update-nix-fetchgit 0.2.2 → 0.2.3
raw patch · 9 files changed
+122/−29 lines, 9 filesdep +regex-tdfadep ~base
Dependencies added: regex-tdfa
Dependency ranges changed: base
Files
- CHANGELOG.md +6/−0
- app/Main.hs +25/−5
- package.yaml +5/−2
- src/Update/Nix/FetchGit.hs +47/−12
- src/Update/Nix/FetchGit/Types.hs +4/−2
- src/Update/Nix/FetchGit/Utils.hs +26/−1
- src/Update/Nix/FetchGit/Warning.hs +0/−1
- tests/Samples.hs +4/−4
- update-nix-fetchgit.cabal +5/−2
CHANGELOG.md view
@@ -2,6 +2,12 @@ ## WIP +## [0.2.3] - 2020-11-06++- Implement filtering updates based on binding name+- Better error message output on parse failure+- Drop support for GHC 8.6+ ## [0.2.2] - 2020-11-03 - Require hnix version 0.11 with several important bugfixes
app/Main.hs view
@@ -1,5 +1,8 @@+{-# OPTIONS_GHC -Wno-orphans #-} -module Main where+module Main+ ( main+ ) where import Data.Foldable import qualified Data.Text.IO as T@@ -14,6 +17,7 @@ , readS_to_P , sepBy )+import Text.Regex.TDFA import Update.Nix.FetchGit import Update.Nix.FetchGit.Types @@ -43,7 +47,8 @@ Normal -> sayErr Quiet -> sayErr updateLocations = [ (l, c) | Position l c <- location ]- in Env { .. }+ attrPatterns = attribute+ in Env { .. } ---------------------------------------------------------------- -- Options@@ -52,7 +57,9 @@ data Options w = Options { verbose :: w ::: Bool <!> "False" , quiet :: w ::: Bool <!> "False"- , location :: w ::: [Position] <?> "Source location to limit updates to"+ , location :: w ::: [Position] <?> "Source location to limit updates to, Combined using inclusive or"+ , attribute+ :: w ::: [Regex] <?> "Pattern (POSIX regex) to limit updates to expressions under matching names in attrsets and let bindings. Combined using inclusing or, if this isn't specified then no expressions will be filtered by attribute name" } deriving stock Generic @@ -70,7 +77,9 @@ versionOption <*> ( (,) <$> (unwrap <$> parseRecordWithModifiers defaultModifiers- { shortNameModifier = firstLetter+ { shortNameModifier = \case+ "attribute" -> Just 'A'+ n -> firstLetter n } ) <*> many@@ -88,7 +97,6 @@ (long "version" <> help ("print " <> versionString)) instance ParseRecord (Options Wrapped)-deriving instance Show (Options Unwrapped) data Position = Position Int Int deriving Show@@ -101,3 +109,15 @@ instance ParseField Position where metavar _ = "LINE:COL"++instance Read Regex where+ readsPrec _ s = case makeRegexM s of+ Nothing -> []+ Just r -> [(r, "")]++instance ParseField Regex where+ metavar _ = "REGEX"+ readField = eitherReader makeRegexM++instance (e ~ String) => MonadFail (Either e) where+ fail = Left
package.yaml view
@@ -1,10 +1,11 @@ name: update-nix-fetchgit-version: "0.2.2"+version: "0.2.3" synopsis: A program to update fetchgit values in Nix expressions description: | This command-line utility is meant to be used by people maintaining Nix expressions that fetch files from Git repositories. It automates the process of keeping such expressions up-to-date with the latest upstream sources.+category: Nix author: Joe Hermaszewski maintainer: Joe Hermaszewski <haskell@monoid.al> copyright: 2020 Joe Hermaszewski@@ -28,9 +29,10 @@ source-dirs: app ghc-options: -threaded -rtsopts -with-rtsopts=-N dependencies:- - base+ - base >= 4.13 - optparse-applicative - optparse-generic >= 1.4.2+ - regex-tdfa - say - text >= 1.2 - update-nix-fetchgit@@ -48,6 +50,7 @@ - monad-validate - mtl - process >= 1.2+ - regex-tdfa - syb - template-haskell - text >= 1.2
src/Update/Nix/FetchGit.hs view
@@ -7,8 +7,11 @@ ) where import Control.Monad ( when )+import Control.Monad.Reader ( MonadReader(ask) )+import Control.Monad.Validate ( MonadValidate(tolerate) ) import Data.Fix import Data.Foldable+import Data.Functor import Data.Maybe import Data.Text ( Text , pack@@ -21,13 +24,11 @@ import Nix.Expr import Nix.Match.Typed import System.Exit+import Text.Regex.TDFA import Update.Nix.FetchGit.Types import Update.Nix.FetchGit.Utils import Update.Nix.Updater import Update.Span-import Control.Monad.Validate ( MonadValidate(tolerate) )-import Data.Functor-import Control.Monad.Reader ( MonadReader(ask) ) -------------------------------------------------------------------------------- -- Tying it all together@@ -57,7 +58,7 @@ tree <- do expr <- fromEither $ ourParseNixText t findUpdates (getComment nixLines) expr- us <- evalUpdates tree+ us <- evalUpdates =<< filterUpdates tree case us of [] -> logVerbose "Made no updates" [_] -> logVerbose "Made 1 update"@@ -71,20 +72,54 @@ findUpdates :: (NExprLoc -> Maybe Comment) -> NExprLoc -> M FetchTree findUpdates getComment e = do Env {..} <- ask+ -- First of all, if this expression doesn't enclose the requested position,+ -- return an empty tree+ -- Then check against all the updaters, if they match we have a leaf if not (null updateLocations || any (containsPosition e) updateLocations) then pure $ Node Nothing [] else- let updaters = ($ e) <$> fetchers getComment+ let+ updaters = ($ e) <$> fetchers getComment+ bindingTrees = \case+ NamedVar p e' _ | Just t <- pathText p ->+ (: []) . (Just t, ) <$> findUpdates getComment e'+ b ->+ traverse (fmap (Nothing, ) . findUpdates getComment) . toList $ b in case asum updaters of Just u -> UpdaterNode <$> u Nothing -> case e of- [matchNixLoc|{ _version = ^version; }|] ->- Node version- <$> traverse (findUpdates getComment) (toList (unFix e))- _ -> Node Nothing- <$> traverse (findUpdates getComment) (toList (unFix e))+ [matchNixLoc|{ _version = ^version; }|] | NSet_ _ _ bs <- unFix e ->+ Node version . concat <$> traverse bindingTrees bs+ [matchNixLoc|let _version = ^version; in ^x|]+ | NLet_ _ bs _ <- unFix e -> do+ bs' <- concat <$> traverse bindingTrees bs+ x' <- findUpdates getComment x+ pure $ Node version ((Nothing, x') : bs')+ _ -> Node Nothing <$> traverse+ (fmap (Nothing, ) . findUpdates getComment)+ (toList (unFix e)) +filterUpdates :: FetchTree -> M FetchTree+filterUpdates t = do+ Env {..} <- ask+ let matches s = any (`match` s) attrPatterns+ -- If we're in a branch, include any bindings which match unconditionally,+ -- otherwise recurse+ -- If we reach a leaf, return empty because it hasn't been included by a+ -- binding yet+ let go = \case+ Node v cs -> Node+ v+ [ (n, c')+ | (n, c) <- cs+ , let c' = if maybe False matches n then c else go c+ ]+ UpdaterNode _ -> Node Nothing []+ -- If there are no patterns, don't do any filtering+ pure $ if null attrPatterns then t else go t++ evalUpdates :: FetchTree -> M [SpanUpdate] evalUpdates = fmap snd . go where@@ -92,7 +127,7 @@ go = \case UpdaterNode (Updater u) -> u Node versionExpr cs -> do- (ds, ss) <- unzip . catMaybes <$> traverse (tolerate . go) cs+ (ds, ss) <- unzip . catMaybes <$> traverse (tolerate . go . snd) cs -- Update version string with the maximum of versions in the children let latestDate = maximumMay (catMaybes ds) pure@@ -101,7 +136,7 @@ | Just d <- pure latestDate , Just v <- pure versionExpr ]- <> concat ss+ <> concat ss ) ----------------------------------------------------------------
src/Update/Nix/FetchGit/Types.hs view
@@ -11,6 +11,7 @@ import Data.Text ( Text ) import Data.Time ( Day ) import Nix.Expr ( NExprLoc )+import Text.Regex.TDFA ( Regex ) import Update.Nix.FetchGit.Warning import Update.Span @@ -28,8 +29,9 @@ Right (MNothing, a) -> (mempty, Just a) data Env = Env- { sayLog :: Verbosity -> Text -> IO ()+ { sayLog :: Verbosity -> Text -> IO () , updateLocations :: [(Int, Int)]+ , attrPatterns :: [Regex] } data Verbosity@@ -45,7 +47,7 @@ -- parsing, but which only contains the information we care about. data FetchTree = Node { nodeVersionExpr :: Maybe NExprLoc- , nodeChildren :: [FetchTree]+ , nodeChildren :: [(Maybe Text, FetchTree)] } | UpdaterNode Updater
src/Update/Nix/FetchGit/Utils.hs view
@@ -7,6 +7,7 @@ , prettyRepoLocation , quoteString , extractFuncName+ , pathText , exprText , exprBool , exprSpan@@ -101,6 +102,30 @@ extractFuncName (AnnE _ (NSelect _ (NE.last -> StaticKey name) _)) = Just name extractFuncName _ = Nothing +pathText :: NAttrPath r -> Maybe Text+pathText = fmap (T.concat . toList) . traverse e+ where+ e :: NKeyName r -> Maybe Text+ e = \case+ StaticKey s -> Just s+ DynamicKey (Plain s) -> t s+ DynamicKey EscapedNewline -> Just "\n"+ DynamicKey (Antiquoted _) -> Nothing+ t :: NString r -> Maybe Text+ t =+ fmap T.concat+ . traverse a+ . (\case+ DoubleQuoted as -> as+ Indented _ as -> as+ )+ a :: Antiquoted Text r -> Maybe Text+ a = \case+ Plain s -> pure s+ EscapedNewline -> pure "\n"+ Antiquoted _ -> Nothing++ -- Takes an ISO 8601 date and returns just the day portion. parseISO8601DateToDay :: Text -> Either Warning Day parseISO8601DateToDay t =@@ -110,7 +135,7 @@ (parseTimeM False defaultTimeLocale "%Y-%m-%d" justDate) formatWarning :: Warning -> Text-formatWarning (CouldNotParseInput doc) = tShow doc+formatWarning (CouldNotParseInput doc) = doc formatWarning (MissingAttr attrName) = "Error: The \"" <> attrName <> "\" attribute is missing." formatWarning (DuplicateAttrs attrName) =
src/Update/Nix/FetchGit/Warning.hs view
@@ -4,7 +4,6 @@ import Data.Text import Nix.Expr-import Data.Void data Warning = CouldNotParseInput Text | MissingAttr Text
tests/Samples.hs view
@@ -5,7 +5,6 @@ import Test.Tasty (TestTree, testGroup) import Test.Tasty.Golden (goldenVsFile) import System.FilePath ((</>))-import Data.Bool (bool) import Data.Maybe (mapMaybe) import qualified Data.List@@ -30,6 +29,7 @@ -- * perform update -- * adjust @url@ to point to the expected one -- * copy file back to @tests/test_rec_sets.out.nix@ so it be compared to @expected.nix@+runTest :: String -> IO () runTest f = System.IO.Temp.withSystemTempDirectory "test-update-nix-fetchgit" $ \dir -> System.IO.Temp.withSystemTempDirectory "test-update-nix-fetchgit-store" $ \storeDir -> do@@ -60,15 +60,15 @@ (System.Process.shell ("nix-store --init")) mempty - let env = Env (const (Data.Text.IO.hPutStrLn System.IO.stderr)) []+ let env = Env (const (Data.Text.IO.hPutStrLn System.IO.stderr)) [] [] Update.Nix.FetchGit.processFile env (dir </> inBase) replaceFile (dir </> inBase) (Data.Text.pack dir) "/tmp/nix-update-fetchgit-test" System.Directory.copyFile (dir </> inBase) f where- replaceFile f what with =- Data.Text.IO.readFile f >>= Data.Text.IO.writeFile f . Data.Text.replace what with+ replaceFile f' what with =+ Data.Text.IO.readFile f' >>= Data.Text.IO.writeFile f' . Data.Text.replace what with test_derivation :: IO TestTree test_derivation = do
update-nix-fetchgit.cabal view
@@ -5,11 +5,12 @@ -- see: https://github.com/sol/hpack name: update-nix-fetchgit-version: 0.2.2+version: 0.2.3 synopsis: A program to update fetchgit values in Nix expressions description: This command-line utility is meant to be used by people maintaining Nix expressions that fetch files from Git repositories. It automates the process of keeping such expressions up-to-date with the latest upstream sources.+category: Nix homepage: https://github.com/expipiplus1/update-nix-fetchgit#readme bug-reports: https://github.com/expipiplus1/update-nix-fetchgit/issues author: Joe Hermaszewski@@ -86,6 +87,7 @@ , monad-validate , mtl , process >=1.2+ , regex-tdfa , syb , template-haskell , text >=1.2@@ -103,9 +105,10 @@ default-extensions: DataKinds DefaultSignatures DeriveAnyClass DeriveDataTypeable DeriveGeneric DerivingStrategies FlexibleContexts FlexibleInstances GADTs LambdaCase MultiParamTypeClasses OverloadedStrings PolyKinds RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving TemplateHaskellQuotes TupleSections TypeApplications TypeFamilies TypeOperators ViewPatterns ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N build-depends:- base+ base >=4.13 , optparse-applicative , optparse-generic >=1.4.2+ , regex-tdfa , say , text >=1.2 , update-nix-fetchgit