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:
commit
29e351ce67
69
app/Niv.hs
69
app/Niv.hs
@ -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 = "{}"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user