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

Add the attribute 'type' to set the package URL type

The main objective is to be able to fetch packages that are just a file
which was not possible.

The value of this attribute is either 'file' or 'tarball'. By default,
the value of this attribute is inferred by using the suffix of the
URL. If the URL ends with 'tar.gz' the type is set to 'tarball',
otherwise it is 'file'.

This attribute is used by the Nix expression to select the appropriate
fetcher ('fetchurl' or 'fetchTarball') and by `nix-prefetch-url` to
set or not the `--unpack` flag.
This commit is contained in:
Antoine Eiche 2019-02-28 22:22:21 +01:00
parent 47cd53f704
commit d23a8626a0
2 changed files with 50 additions and 9 deletions

49
Main.hs
View File

@ -13,6 +13,7 @@ import Control.Monad
import Control.Monad.State
import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)
import Data.Char (toUpper)
import Data.Functor ((<&>))
import Data.Hashable (Hashable)
import Data.Maybe (mapMaybe, fromMaybe)
import Data.String.QQ (s)
@ -100,6 +101,12 @@ parsePackageSpec =
Opts.short 't' <>
Opts.metavar "URL" <>
Opts.help "Used during 'update' when building URL. Occurrences of <foo> are replaced with attribute 'foo'."
)) <|>
(("type",) <$> Opts.strOption
( Opts.long "type" <>
Opts.short 'T' <>
Opts.metavar "TYPE" <>
Opts.help "The type of the URL target. The value can be either 'file' or 'tarball'. If not set, the value is inferred from the suffix of the URL."
))
-- Parse "key=val" into ("key", "val")
@ -153,6 +160,20 @@ updatePackageSpec = execStateT $ do
_ -> pure ()
)
-- If the type attribute is not set, we try to infer its value based on the url suffix
(,) <$> getPackageSpecAttr "type" <*> getPackageSpecAttr "url" >>= \case
-- If an url type is set, we'll use it
(Just _, _) -> pure ()
-- We need an url to infer a url type
(_, Nothing) -> pure ()
(Nothing, Just (Aeson.String url)) -> do
let urlType = if "tar.gz" `T.isSuffixOf` url
then "tarball"
else "file"
setPackageSpecAttr "type" (Aeson.String $ T.pack urlType)
-- If the JSON value is not a string, we ignore it
(_, _) -> pure ()
-- Updates the sha256 based on the URL contents
(,) <$> getPackageSpecAttr "url" <*> getPackageSpecAttr "sha256" >>= \case
-- If no URL is set, we simply can't prefetch
@ -167,7 +188,11 @@ updatePackageSpec = execStateT $ do
prefetch :: Aeson.Value -> StateT PackageSpec IO ()
prefetch = \case
Aeson.String (T.unpack -> url) -> do
sha256 <- liftIO $ nixPrefetchURL url
unpack <- getPackageSpecAttr "type" <&> \case
-- Do not unpack if the url type is 'file'
Just (Aeson.String urlType) -> not $ T.unpack urlType == "file"
_ -> True
sha256 <- liftIO $ nixPrefetchURL unpack url
setPackageSpecAttr "sha256" (Aeson.String $ T.pack sha256)
_ -> pure ()
@ -564,12 +589,13 @@ abort msg = do
putStrLn msg
exitFailure
nixPrefetchURL :: String -> IO String
nixPrefetchURL url =
lines <$> readProcess "nix-prefetch-url" ["--unpack", url] "" >>=
nixPrefetchURL :: Bool -> String -> IO String
nixPrefetchURL unpack url =
lines <$> readProcess "nix-prefetch-url" args "" >>=
\case
(l:_) -> pure l
_ -> abortNixPrefetchExpectedOutput
where args = if unpack then ["--unpack", url] else [url]
-------------------------------------------------------------------------------
-- Files and their content
@ -583,7 +609,7 @@ pathNixSourcesNix = "nix" </> "sources.nix"
initNixSourcesNixContent :: String
initNixSourcesNixContent = [s|
# A record, from name to path, of the third-party packages
with
with rec
{
sources = builtins.fromJSON (builtins.readFile ./sources.json);
@ -597,8 +623,17 @@ with
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" = builtins.fetchTarball;
"file" = builtins.fetchurl;
};
};
# NOTE: spec must _not_ have an "outPath" attribute
mapAttrs (_: spec:
if builtins.hasAttr "outPath" spec
@ -608,7 +643,7 @@ mapAttrs (_: spec:
if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec
then
spec //
{ outPath = fetchTarball { inherit (spec) url sha256; } ; }
{ outPath = getFetcher spec { inherit (spec) url sha256; } ; }
else spec
) sources
|]

View File

@ -214,7 +214,7 @@ Examples:
Usage: niv add [-n|--name NAME] PACKAGE ([-a|--attribute KEY=VAL] |
[-b|--branch BRANCH] | [-o|--owner OWNER] | [-r|--repo REPO] |
[-v|--version VERSION] | [-t|--template URL])
[-v|--version VERSION] | [-t|--template URL] | [-T|--type TYPE])
Add dependency
Available options:
@ -226,6 +226,9 @@ Available options:
-v,--version VERSION Equivalent to --attribute version=<VERSION>
-t,--template URL Used during 'update' when building URL. Occurrences
of <foo> are replaced with attribute 'foo'.
-T,--type TYPE The type of the URL target. The value can be either
'file' or 'tarball'. If not set, the value is
inferred from the suffix of the URL.
-h,--help Show this help text
```
@ -241,7 +244,7 @@ Examples:
Usage: niv update [PACKAGE] ([-a|--attribute KEY=VAL] | [-b|--branch BRANCH] |
[-o|--owner OWNER] | [-r|--repo REPO] | [-v|--version VERSION]
| [-t|--template URL])
| [-t|--template URL] | [-T|--type TYPE])
Update dependencies
Available options:
@ -252,6 +255,9 @@ Available options:
-v,--version VERSION Equivalent to --attribute version=<VERSION>
-t,--template URL Used during 'update' when building URL. Occurrences
of <foo> are replaced with attribute 'foo'.
-T,--type TYPE The type of the URL target. The value can be either
'file' or 'tarball'. If not set, the value is
inferred from the suffix of the URL.
-h,--help Show this help text
```