1
1
mirror of https://github.com/nmattia/niv.git synced 2024-09-18 19:07:19 +03:00

Merge pull request #45 from nmattia/nm-fix-nixpkgs-fetch

Fix infinite recursion and empty nixpkgs
This commit is contained in:
Nicolas Mattia 2019-04-10 23:14:43 +02:00 committed by GitHub
commit 29e351ce67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 61 deletions

View File

@ -1,4 +1,5 @@
{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
@ -11,6 +12,7 @@ import Control.Monad
import Control.Monad.State import Control.Monad.State
import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey) import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)
import Data.Char (isSpace, toUpper) import Data.Char (isSpace, toUpper)
import Data.FileEmbed (embedFile)
import Data.Functor ((<&>)) import Data.Functor ((<&>))
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import Data.Maybe (mapMaybe, fromMaybe) import Data.Maybe (mapMaybe, fromMaybe)
@ -23,6 +25,7 @@ import UnliftIO
import qualified Data.Aeson as Aeson import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Encode.Pretty as AesonPretty import qualified Data.Aeson.Encode.Pretty as AesonPretty
import qualified Data.ByteString as B import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy as L
import qualified Data.HashMap.Strict as HMap import qualified Data.HashMap.Strict as HMap
import qualified Data.Text as T import qualified Data.Text as T
@ -319,7 +322,7 @@ cmdInit = do
if shouldUpdateNixSourcesNix content if shouldUpdateNixSourcesNix content
then do then do
putStrLn "Updating sources.nix" putStrLn "Updating sources.nix"
writeFile path initNixSourcesNixContent B.writeFile path initNixSourcesNixContent
else putStrLn "Not updating sources.nix" else putStrLn "Not updating sources.nix"
) )
, ( pathNixSourcesJson , ( pathNixSourcesJson
@ -336,14 +339,14 @@ cmdInit = do
, \path _content -> dontCreateFile path) , \path _content -> dontCreateFile path)
] $ \(path, onCreate, onUpdate) -> do ] $ \(path, onCreate, onUpdate) -> do
exists <- Dir.doesFileExist path exists <- Dir.doesFileExist path
if exists then readFile path >>= onUpdate path else onCreate path if exists then B.readFile path >>= onUpdate path else onCreate path
where where
createFile :: FilePath -> String -> IO () createFile :: FilePath -> B.ByteString -> IO ()
createFile path content = do createFile path content = do
let dir = takeDirectory path let dir = takeDirectory path
Dir.createDirectoryIfMissing True dir Dir.createDirectoryIfMissing True dir
putStrLn $ "Creating " <> path putStrLn $ "Creating " <> path
writeFile path content B.writeFile path content
dontCreateFile :: FilePath -> IO () dontCreateFile :: FilePath -> IO ()
dontCreateFile path = putStrLn $ "Not creating " <> path dontCreateFile path = putStrLn $ "Not creating " <> path
@ -611,24 +614,24 @@ nixPrefetchURL unpack url =
-- | Checks if content is different than default and if it does /not/ contain -- | Checks if content is different than default and if it does /not/ contain
-- a comment line with @niv: no_update@ -- a comment line with @niv: no_update@
shouldUpdateNixSourcesNix :: String -> Bool shouldUpdateNixSourcesNix :: B.ByteString -> Bool
shouldUpdateNixSourcesNix content = shouldUpdateNixSourcesNix content =
content /= initNixSourcesNixContent && content /= initNixSourcesNixContent &&
not (any lineForbids (lines content)) not (any lineForbids (B8.lines content))
where where
lineForbids :: String -> Bool lineForbids :: B8.ByteString -> Bool
lineForbids str = lineForbids str =
case dropWhile isSpace str of case B8.uncons (B8.dropWhile isSpace str) of
'#':rest -> case dropWhile isSpace rest of Just ('#',rest) -> case B8.stripPrefix "niv:" (B8.dropWhile isSpace rest) of
'n':'i':'v':':':rest' -> case dropWhile isSpace rest' of Just rest' -> case B8.stripPrefix "no_update" (B8.dropWhile isSpace rest') of
'n':'o':'_':'u':'p':'d':'a':'t':'e':_ -> True Just{} -> True
_ -> False _ -> False
_ -> False _ -> False
_ -> False _ -> False
warnIfOutdated :: IO () warnIfOutdated :: IO ()
warnIfOutdated = do warnIfOutdated = do
tryAny (readFile pathNixSourcesNix) >>= \case tryAny (B.readFile pathNixSourcesNix) >>= \case
Left e -> putStrLn $ unlines Left e -> putStrLn $ unlines
[ "Could not read " <> pathNixSourcesNix [ "Could not read " <> pathNixSourcesNix
, "Error: " <> show e , "Error: " <> show e
@ -650,51 +653,15 @@ pathNixSourcesNix :: FilePath
pathNixSourcesNix = "nix" </> "sources.nix" pathNixSourcesNix = "nix" </> "sources.nix"
-- | Glue code between nix and sources.json -- | Glue code between nix and sources.json
initNixSourcesNixContent :: String initNixSourcesNixContent :: B.ByteString
initNixSourcesNixContent = [s| initNixSourcesNixContent = $(embedFile "nix/sources.nix")
# This file has been generated by Niv.
# A record, from name to path, of the third-party packages
with rec
{
pkgs = import <nixpkgs> {};
sources = builtins.fromJSON (builtins.readFile ./sources.json);
mapAttrs = builtins.mapAttrs or
(f: set: with builtins;
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)));
getFetcher = spec:
let fetcherName =
if builtins.hasAttr "type" spec
then builtins.getAttr "type" spec
else "tarball";
in builtins.getAttr fetcherName {
"tarball" = pkgs.fetchzip;
"file" = pkgs.fetchurl;
};
};
# NOTE: spec must _not_ have an "outPath" attribute
mapAttrs (_: spec:
if builtins.hasAttr "outPath" spec
then abort
"The values in sources.json should not have an 'outPath' attribute"
else
if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec
then
spec //
{ outPath = getFetcher spec { inherit (spec) url sha256; } ; }
else spec
) sources
|]
-- | @nix/sources.json" -- | @nix/sources.json"
pathNixSourcesJson :: FilePath pathNixSourcesJson :: FilePath
pathNixSourcesJson = "nix" </> "sources.json" pathNixSourcesJson = "nix" </> "sources.json"
-- | Empty JSON map -- | Empty JSON map
initNixSourcesJsonContent :: String initNixSourcesJsonContent :: B.ByteString
initNixSourcesJsonContent = "{}" initNixSourcesJsonContent = "{}"
------------------------------------------------------------------------------- -------------------------------------------------------------------------------

View File

@ -4,6 +4,8 @@ with rec
[ "^package.yaml$" [ "^package.yaml$"
"^app.*$" "^app.*$"
"^README.md$" "^README.md$"
"^nix$"
"^nix.sources.nix$"
]; ];
haskellPackages = pkgs.haskellPackages.override haskellPackages = pkgs.haskellPackages.override
{ overrides = _: haskellPackages: { overrides = _: haskellPackages:

View File

@ -1,20 +1,58 @@
# This file has been generated by Niv.
# A record, from name to path, of the third-party packages # A record, from name to path, of the third-party packages
with with rec
{ {
pkgs =
if hasNixpkgsPath
then
if hasThisAsNixpkgsPath
then import (builtins_fetchTarball { inherit (sources_nixpkgs) url sha256; }) {}
else import <nixpkgs> {}
else
import (builtins_fetchTarball { inherit (sources_nixpkgs) url sha256; }) {};
sources_nixpkgs =
if builtins.hasAttr "nixpkgs" sources
then sources.nixpkgs
else abort
''
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
add a package called "nixpkgs" to your sources.json.
'';
builtins_fetchTarball =
# fetchTarball version that is compatible between all the versions of
# Nix
{ url, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchTarball;
in
if lessThan nixVersion "1.12" then
fetchTarball { inherit url; }
else
fetchTarball attrs;
hasNixpkgsPath = (builtins.tryEval <nixpkgs>).success;
hasThisAsNixpkgsPath =
(builtins.tryEval <nixpkgs>).success && <nixpkgs> == ./.;
sources = builtins.fromJSON (builtins.readFile ./sources.json); sources = builtins.fromJSON (builtins.readFile ./sources.json);
# fetchTarball version that is compatible between all the sources of Nix
fetchTarball =
{ url, sha256 }:
if builtins.lessThan builtins.nixVersion "1.12" then
builtins.fetchTarball { inherit url; }
else
builtins.fetchTarball { inherit url sha256; };
mapAttrs = builtins.mapAttrs or mapAttrs = builtins.mapAttrs or
(f: set: with builtins; (f: set: with builtins;
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))); listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)));
};
getFetcher = spec:
let fetcherName =
if builtins.hasAttr "type" spec
then builtins.getAttr "type" spec
else "tarball";
in builtins.getAttr fetcherName {
"tarball" = pkgs.fetchzip;
"file" = pkgs.fetchurl;
};
};
# NOTE: spec must _not_ have an "outPath" attribute # NOTE: spec must _not_ have an "outPath" attribute
mapAttrs (_: spec: mapAttrs (_: spec:
if builtins.hasAttr "outPath" spec if builtins.hasAttr "outPath" spec
@ -24,6 +62,6 @@ mapAttrs (_: spec:
if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec
then then
spec // spec //
{ outPath = fetchTarball { inherit (spec) url sha256; } ; } { outPath = getFetcher spec { inherit (spec) url sha256; } ; }
else spec else spec
) sources ) sources

View File

@ -11,6 +11,7 @@ executable:
dependencies: dependencies:
- base - base
- hashable - hashable
- file-embed
- process - process
- text - text
- bytestring - bytestring
@ -24,3 +25,5 @@ executable:
- optparse-applicative - optparse-applicative
- unliftio - unliftio
- unordered-containers - unordered-containers
data-files:
- nix/sources.nix