1
1
mirror of https://github.com/nmattia/niv.git synced 2024-11-29 09:42:35 +03:00

Allow JSON attributes values with -a foo=bar

This commit is contained in:
Nicolas Mattia 2019-11-24 20:21:35 +01:00
parent d9e35d67d8
commit 271677ec6e
2 changed files with 41 additions and 22 deletions

View File

@ -227,13 +227,17 @@ Examples:
niv add my-package -v alpha-0.1 -t http://example.com/archive/<version>.zip
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] | [-T|--type TYPE])
[-s|--string-attribute KEY=VAL] | [-b|--branch BRANCH] |
[-o|--owner OWNER] | [-r|--repo REPO] | [-v|--version VERSION] |
[-t|--template URL] | [-T|--type TYPE])
Add dependency
Available options:
-n,--name NAME Set the package name to <NAME>
-a,--attribute KEY=VAL Set the package spec attribute <KEY> to <VAL>
-a,--attribute KEY=VAL Set the package spec attribute <KEY> to <VAL>, where
<VAL> may be JSON.
-s,--string-attribute KEY=VAL
Set the package spec attribute <KEY> to <VAL>.
-b,--branch BRANCH Equivalent to --attribute branch=<BRANCH>
-o,--owner OWNER Equivalent to --attribute owner=<OWNER>
-r,--repo REPO Equivalent to --attribute repo=<REPO>
@ -256,13 +260,17 @@ Examples:
niv update nixpkgs # update nixpkgs
niv update my-package -v beta-0.2 # update my-package to version "beta-0.2"
Usage: niv update [PACKAGE] ([-a|--attribute KEY=VAL] | [-b|--branch BRANCH] |
Usage: niv update [PACKAGE] ([-a|--attribute KEY=VAL] |
[-s|--string-attribute KEY=VAL] | [-b|--branch BRANCH] |
[-o|--owner OWNER] | [-r|--repo REPO] | [-v|--version VERSION]
| [-t|--template URL] | [-T|--type TYPE])
Update dependencies
Available options:
-a,--attribute KEY=VAL Set the package spec attribute <KEY> to <VAL>
-a,--attribute KEY=VAL Set the package spec attribute <KEY> to <VAL>, where
<VAL> may be JSON.
-s,--string-attribute KEY=VAL
Set the package spec attribute <KEY> to <VAL>.
-b,--branch BRANCH Equivalent to --attribute branch=<BRANCH>
-o,--owner OWNER Equivalent to --attribute owner=<OWNER>
-r,--repo REPO Equivalent to --attribute repo=<REPO>

View File

@ -11,6 +11,8 @@ module Niv.Cli where
import Control.Applicative
import Control.Monad
import Data.Aeson ((.=))
import Data.Bifunctor
import Data.Maybe
import Data.Char (isSpace)
import Data.Functor
import Data.HashMap.Strict.Extended
@ -70,45 +72,57 @@ parsePackageName = PackageName <$>
parsePackageSpec :: Opts.Parser PackageSpec
parsePackageSpec =
(PackageSpec . HMS.fromList . fmap fixupAttributes) <$>
(PackageSpec . HMS.fromList) <$>
many parseAttribute
where
parseAttribute :: Opts.Parser (T.Text, T.Text)
parseAttribute :: Opts.Parser (T.Text, Aeson.Value)
parseAttribute =
Opts.option (Opts.maybeReader parseKeyVal)
Opts.option (Opts.maybeReader parseKeyValJSON)
( Opts.long "attribute" <>
Opts.short 'a' <>
Opts.metavar "KEY=VAL" <>
Opts.help "Set the package spec attribute <KEY> to <VAL>"
) <|> shortcutAttributes <|>
(("url_template",) <$> Opts.strOption
Opts.help "Set the package spec attribute <KEY> to <VAL>, where <VAL> may be JSON."
) <|>
Opts.option (Opts.maybeReader (parseKeyVal (Aeson.String . T.pack)))
( Opts.long "string-attribute" <>
Opts.short 's' <>
Opts.metavar "KEY=VAL" <>
Opts.help "Set the package spec attribute <KEY> to <VAL>."
) <|>
shortcutAttributes <|>
((\x -> ("url_template",Aeson.String x)) <$> Opts.strOption
( Opts.long "template" <>
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
((\x -> ("type", Aeson.String x)) <$> 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")
parseKeyVal :: String -> Maybe (T.Text, T.Text)
parseKeyVal str = case span (/= '=') str of
(key, '=':val) -> Just (T.pack key, T.pack val)
parseKeyValJSON = parseKeyVal $ \x ->
fromMaybe (Aeson.String $ T.pack x) (Aeson.decodeStrict (B8.pack x))
-- Parse "key=val" into ("key", val)
parseKeyVal
:: (String -> Aeson.Value) -- ^ how to convert to JSON
-> String -> Maybe (T.Text, Aeson.Value)
parseKeyVal toJSON str = case span (/= '=') str of
(key, '=':val) -> Just (T.pack key, toJSON val)
_ -> Nothing
-- Shortcuts for common attributes
shortcutAttributes :: Opts.Parser (T.Text, T.Text)
shortcutAttributes :: Opts.Parser (T.Text, Aeson.Value)
shortcutAttributes = foldr (<|>) empty $ mkShortcutAttribute <$>
[ "branch", "owner", "repo", "version" ]
-- TODO: infer those shortcuts from 'Update' keys
mkShortcutAttribute :: T.Text -> Opts.Parser (T.Text, T.Text)
mkShortcutAttribute :: T.Text -> Opts.Parser (T.Text, Aeson.Value)
mkShortcutAttribute = \case
attr@(T.uncons -> Just (c,_)) -> (attr,) <$> Opts.strOption
attr@(T.uncons -> Just (c,_)) -> fmap (second Aeson.String) $ (attr,) <$> Opts.strOption
( Opts.long (T.unpack attr) <>
Opts.short c <>
Opts.metavar (T.unpack $ T.toUpper attr) <>
@ -120,9 +134,6 @@ parsePackageSpec =
)
_ -> empty
fixupAttributes :: (T.Text, T.Text) -> (T.Text, Aeson.Value)
fixupAttributes (k, v) = (k, Aeson.String v)
parsePackage :: Opts.Parser (PackageName, PackageSpec)
parsePackage = (,) <$> parsePackageName <*> parsePackageSpec