update-nix-fetchgit 0.2.9 → 0.2.11
raw patch · 14 files changed
+540/−493 lines, 14 filesdep ~github-restdep ~hnix
Dependency ranges changed: github-rest, hnix
Files
- CHANGELOG.md +6/−0
- LICENSE +2/−2
- app/Main.hs +3/−2
- package.yaml +6/−8
- src/Nix/Comments.hs +31/−28
- src/Nix/Match.hs +99/−100
- src/Nix/Match/Typed.hs +162/−144
- src/Update/Nix/FetchGit.hs +80/−75
- src/Update/Nix/FetchGit/Prefetch.hs +5/−5
- src/Update/Nix/FetchGit/Utils.hs +89/−84
- src/Update/Span.hs +38/−25
- tests/Samples.hs +8/−7
- tests/fakeRepo.sh +4/−4
- update-nix-fetchgit.cabal +7/−9
CHANGELOG.md view
@@ -2,6 +2,12 @@ ## WIP +## [0.2.11] - 2022-12-06+- Changes for hnix-0.16++## [0.2.10] - 2022-03-20+- Bump github-rest+ ## [0.2.9] - 2021-07-21 - Fix dotgit / deepClone test sha256
LICENSE view
@@ -1,4 +1,4 @@-Copyright Joe Hermaszewski (c) 2016+Copyright Ellie Hermaszewska (c) 2016 Copyright David Grayson (c) 2016 All rights reserved.@@ -14,7 +14,7 @@ disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Joe Hermaszewski nor the names of other+ * Neither the name of Ellie Hermaszewska nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission.
app/Main.hs view
@@ -62,9 +62,10 @@ , 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"+ :: w ::: [Regex] <?> "Pattern (POSIX regex) to limit updates to expressions under matching names in attrsets and let bindings. Combined using inclusive or, if this isn't specified then no expressions will be filtered by attribute name" , dryRun :: w ::: Bool <!> "False" <?> "Don't modify the file"- , onlyCommented :: w ::: Bool <!> "False" <?> "Only update from Git sources which have a comment on the 'rev' (or 'url' for fetchTarball from GitHub) attribute"+ , onlyCommented+ :: w ::: Bool <!> "False" <?> "Only update from Git sources which have a comment on the 'rev' (or 'url' for fetchTarball from GitHub) attribute" } deriving stock Generic
package.yaml view
@@ -1,14 +1,14 @@ name: update-nix-fetchgit-version: "0.2.9"+version: "0.2.11" 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+author: Ellie Hermaszewska+maintainer: Ellie Hermaszewska <haskell@monoid.al>+copyright: 2020 Ellie Hermaszewska github: expipiplus1/update-nix-fetchgit extra-source-files: - package.yaml@@ -45,8 +45,8 @@ - async >= 2.1 - bytestring >= 0.10 - data-fix- - github-rest- - hnix >= 0.13.1+ - github-rest >= 1.1+ - hnix >= 0.16 && < 0.17 - monad-validate - mtl - process >= 1.2@@ -62,8 +62,6 @@ update-nix-fetchgit-samples: source-dirs: tests main: Driver.hs- build-tools:- - tasty-discover dependencies: - base >= 4.7 && < 5 - directory
src/Nix/Comments.hs view
@@ -1,18 +1,20 @@ module Nix.Comments- ( annotateWithComments- , Comment- , NExprCommentsF- , NExprComments- ) where+ ( annotateWithComments,+ Comment,+ NExprCommentsF,+ NExprComments,+ )+where -import Data.Text ( Text )-import Data.Vector ( (!?)- , Vector- )-import Data.Fix-import Nix.Expr-import qualified Data.Text as T-import Data.Char ( isSpace )+import Data.Char (isSpace)+import Data.Fix+import Data.Text (Text)+import qualified Data.Text as T+import Data.Vector+ ( Vector,+ (!?),+ )+import Nix.Expr type Comment = Text @@ -38,22 +40,23 @@ -- [(1 + { a = 2; },Just "baz"),(1,Just "foo"),({ a = 2; },Just "baz"),(2,Just "bar")] annotateWithComments :: Vector Text -> NExprLoc -> NExprComments annotateWithComments sourceLines = go- where- go :: NExprLoc -> NExprComments- go = Fix . go' . fmap go . unFix+ where+ go :: NExprLoc -> NExprComments+ go = Fix . go' . fmap go . unFix - go' :: NExprLocF f -> NExprCommentsF f- go' e =- let- comment = case spanEnd . annotation . getCompose $ e of- SourcePos _ line col -> do- theLine <- sourceLines !? (unPos line - 1)- theLineAfterExpression <- dropMaybe (unPos col - 1) theLine- let theLineAfterCruft = T.dropWhile (\c -> isSpace c || (c == ';'))- theLineAfterExpression- ('#', theComment) <- T.uncons theLineAfterCruft- pure (T.strip theComment)- in Compose (Ann comment e)+ go' :: NExprLocF f -> NExprCommentsF f+ go' e =+ let comment = case spanEnd . annotation . getCompose $ e of+ SourcePos _ line col -> do+ theLine <- sourceLines !? (unPos line - 1)+ theLineAfterExpression <- dropMaybe (unPos col - 1) theLine+ let theLineAfterCruft =+ T.dropWhile+ (\c -> isSpace c || (c == ';'))+ theLineAfterExpression+ ('#', theComment) <- T.uncons theLineAfterCruft+ pure (T.strip theComment)+ in Compose (AnnUnit comment e) ---------------------------------------------------------------- -- Utils
src/Nix/Match.hs view
@@ -1,30 +1,32 @@ {-# LANGUAGE UndecidableInstances #-}+ -- | A set of functions for matching on Nix expression trees and extracting the -- values of sub-trees. module Nix.Match- ( match- , findMatches- , Matchable(..)- , GMatchable(..)- , WithHoles(..)- , addHoles- , addHolesLoc- , isOptionalPath- ) where+ ( match,+ findMatches,+ Matchable (..),+ GMatchable (..),+ WithHoles (..),+ addHoles,+ addHolesLoc,+ isOptionalPath,+ )+where -import Control.Category ( (>>>) )-import Control.Monad ( void )-import Data.Data-import Data.Fix-import Data.Foldable-import Data.List.NonEmpty ( NonEmpty )-import Data.Maybe-import Data.Monoid hiding ( All )-import Data.Text ( Text )-import qualified Data.Text as T-import GHC.Base ( NonEmpty((:|)) )-import GHC.Generics-import Nix+import Control.Category ((>>>))+import Control.Monad (void)+import Data.Data+import Data.Fix+import Data.Foldable+import Data.List.NonEmpty (NonEmpty)+import Data.Maybe+import Data.Monoid hiding (All)+import Data.Text (Text)+import qualified Data.Text as T+import GHC.Base (NonEmpty ((:|)))+import GHC.Generics+import Nix -- | Like 'Fix' but each layer could instead be a 'Hole' data WithHoles t v@@ -45,12 +47,12 @@ -- Just [("bar",Fix (NStr (DoubleQuoted [Plain "world"]))),("foo",Fix (NStr (DoubleQuoted [Plain "hello"])))] match :: Matchable t => WithHoles t v -> Fix t -> Maybe [(v, Fix t)] match = fmap (`appEndo` []) .: go- where- go = \case- Hole v -> \t -> Just (Endo ((v, t) :))- Term s -> \(Fix t) -> do- m <- zipMatchLeft s t- fmap fold . traverse (uncurry go) . toList $ m+ where+ go = \case+ Hole v -> \t -> Just (Endo ((v, t) :))+ Term s -> \(Fix t) -> do+ m <- zipMatchLeft s t+ fmap fold . traverse (uncurry go) . toList $ m -- | Find all the needles in a haystack, returning the matched expression as -- well as their filled holes. Results are returned productively in preorder.@@ -60,31 +62,33 @@ -- >>> pretty = prettyNix *** (fmap @[] (fmap @((,) Text) prettyNix)) -- >>> pretty <$> findMatches (addHoles [nix|{x=^x;}|]) [nix|{x=1;a={x=2;};}|] -- [({ x = 1; a = { x = 2; }; },[("x",1)]),({ x = 2; },[("x",2)])]-findMatches- :: Matchable t- => WithHoles t v- -- ^ Needle- -> Fix t- -- ^ Haystack- -> [(Fix t, [(v, Fix t)])]+findMatches ::+ Matchable t =>+ -- | Needle+ WithHoles t v ->+ -- | Haystack+ Fix t ->+ [(Fix t, [(v, Fix t)])] findMatches needle haystack =- [ (s, r) | s <- fixUniverse haystack, Just r <- pure $ match needle s ]+ [(s, r) | s <- fixUniverse haystack, Just r <- pure $ match needle s] -- | Get every @f@ in a @Fix f@ in preorder. fixUniverse :: Foldable f => Fix f -> [Fix f] fixUniverse e = e : (fixUniverse =<< toList (unFix e)) -- | Make syntactic holes into 'Hole's-addHoles :: NExpr -> WithHoles NExprF Text-addHoles = unFix >>> \case- NSynHole n -> Hole n- e -> Term . fmap addHoles $ e+addHoles :: NExpr -> WithHoles NExprF VarName+addHoles =+ unFix >>> \case+ NSynHole n -> Hole n+ e -> Term . fmap addHoles $ e -- | Make syntactic holes into 'Hole's-addHolesLoc :: NExprLoc -> WithHoles NExprLocF Text-addHolesLoc = unFix >>> \case- Compose (Ann _ (NSynHole n)) -> Hole n- e -> Term . fmap addHolesLoc $ e+addHolesLoc :: NExprLoc -> WithHoles NExprLocF VarName+addHolesLoc =+ unFix >>> \case+ Compose (AnnUnit _ (NSynHole n)) -> Hole n+ e -> Term . fmap addHolesLoc $ e ---------------------------------------------------------------- -- Matchable@@ -99,17 +103,17 @@ -- Unlike the @Unifiable@ class in the "unification-fd" package, this doesn't -- have to be a commutative operation, the needle will always be the first -- parameter and instances are free to treat if differently if appropriate.- zipMatchLeft :: t a -> t b -> Maybe (t (a,b))- default zipMatchLeft- :: (Generic1 t, GMatchable (Rep1 t))- => t a- -> t b- -> Maybe (t (a, b))+ zipMatchLeft :: t a -> t b -> Maybe (t (a, b))+ default zipMatchLeft ::+ (Generic1 t, GMatchable (Rep1 t)) =>+ t a ->+ t b ->+ Maybe (t (a, b)) zipMatchLeft l r = to1 <$> gZipMatchLeft (from1 l) (from1 r) -- | Match a composition of 'Matchable' things-zipMatchLeft2- :: (Matchable f, Matchable t) => t (f a) -> t (f b) -> Maybe (t (f (a, b)))+zipMatchLeft2 ::+ (Matchable f, Matchable t) => t (f a) -> t (f b) -> Maybe (t (f (a, b))) zipMatchLeft2 a b = zipMatchLeft a b >>= traverse (uncurry zipMatchLeft) ----------------------------------------------------------------@@ -131,19 +135,17 @@ -- - If a function in the needle has @_@ as its parameter, it matches -- everything, so @_@ acts as a wildcard pattern. instance Matchable NExprF where- zipMatchLeft (NSet _ bs1) (NSet _ bs2) = do (bs1', bs2') <- unzip <$> reduceBindings bs1 bs2- to1 <$> gZipMatchLeft (from1 (NSet NNonRecursive bs1'))- (from1 (NSet NNonRecursive bs2'))-+ to1+ <$> gZipMatchLeft+ (from1 (NSet NonRecursive bs1'))+ (from1 (NSet NonRecursive bs2')) zipMatchLeft (NLet bs1 e1) (NLet bs2 e2) = do (bs1', bs2') <- unzip <$> reduceBindings bs1 bs2 to1 <$> gZipMatchLeft (from1 (NLet bs1' e1)) (from1 (NLet bs2' e2))- zipMatchLeft (NAbs (Param "_") e1) (NAbs _ e2) = do pure $ NAbs (Param "_") (e1, e2)- zipMatchLeft l r = to1 <$> gZipMatchLeft (from1 l) (from1 r) -- | Bindings are compared on top level structure only.@@ -159,9 +161,8 @@ -- match them up correctly. reduceBindings :: [Binding q] -> [Binding r] -> Maybe [(Binding q, Binding r)] reduceBindings needle matchee =- let- -- A binding is optional if the lhs starts with a '_', return the same- -- binding but without the '_'+ let -- A binding is optional if the lhs starts with a '_', return the same+ -- binding but without the '_' isOptional = \case NamedVar p e l | Just p' <- isOptionalPath p -> Just (NamedVar p' e l) _ -> Nothing@@ -169,51 +170,50 @@ -- Get a representation of the left hand side which has an Eq instance -- This will represent some things the samelike "${a}" and "${b}" getLHS = \case- NamedVar p _ _ -> Left (fmap void p)- Inherit r ps _ -> Right (void r, fmap void ps)- in sequence- [ (n', ) <$> m- | -- For each binding in the needle- n <- needle- , let opt = isOptional n- -- | Use the optional demangled version if present- n' = fromMaybe n opt- lhs = getLHS n'- -- Find the first matching binding in the matchee- m = find ((lhs ==) . getLHS) matchee- , -- Skip this element if it is not present in the matchee and is optional in the needle- isNothing opt || isJust m+ NamedVar p _ _ -> Left (fmap void p)+ Inherit r ps _ -> Right (void r, ps)+ in sequence+ [ (n',) <$> m+ | -- For each binding in the needle+ n <- needle,+ let opt = isOptional n+ -- \| Use the optional demangled version if present+ n' = fromMaybe n opt+ lhs = getLHS n'+ -- Find the first matching binding in the matchee+ m = find ((lhs ==) . getLHS) matchee,+ -- Skip this element if it is not present in the matchee and is optional in the needle+ isNothing opt || isJust m ] -- | Basically: does the path begin with an underscore, if so return it removed -- without the underscore. isOptionalPath :: NAttrPath r -> Maybe (NAttrPath r) isOptionalPath = \case- StaticKey n :| [] | Just ('_', t) <- T.uncons n -> Just (StaticKey t :| [])+ StaticKey (VarName n) :| [] | Just ('_', t) <- T.uncons n -> Just (StaticKey (VarName t) :| []) DynamicKey (Plain (DoubleQuoted [Plain n])) :| rs- | Just ('_', t) <- T.uncons n -> Just- (DynamicKey (Plain (DoubleQuoted [Plain t])) :| rs)+ | Just ('_', t) <- T.uncons n ->+ Just+ (DynamicKey (Plain (DoubleQuoted [Plain t])) :| rs) _ -> Nothing -- -- hnix types -- -instance Matchable NString where+instance Matchable NString -instance Matchable (Antiquoted Text) where+instance Matchable (Antiquoted Text) -- | The matched pair uses the source location of the first argument instance Matchable Binding where zipMatchLeft (NamedVar p1 v1 _) (NamedVar p2 v2 l) = do p <- zipMatchLeft2 p1 p2 pure (NamedVar p (v1, v2) l)-- zipMatchLeft (Inherit x1 ys1 l) (Inherit x2 ys2 _) = do- x <- zipMatchLeft x1 x2- ys <- zipMatchLeft2 ys1 ys2- pure (Inherit x ys l)-+ zipMatchLeft (Inherit x1 ys1 l) (Inherit x2 ys2 _)+ | ys1 == ys2 = do+ x <- zipMatchLeft x1 x2+ pure (Inherit x ys1 l) zipMatchLeft _ _ = Nothing -- | No Generic1 instance@@ -228,26 +228,25 @@ pure $ DynamicKey (Antiquoted (k1, k2)) zipMatchLeft _ _ = Nothing -instance Matchable Params where+instance Matchable Params -- | Doesn't require the annotations to match, returns the second annotation.-instance Matchable (Ann ann) where- zipMatchLeft (Ann _ a1) (Ann ann2 a2) = Just $ Ann ann2 (a1, a2)+instance Matchable (AnnUnit ann) where+ zipMatchLeft (AnnUnit _ a1) (AnnUnit ann2 a2) = Just $ AnnUnit ann2 (a1, a2) -- -- base types -- -instance Matchable [] where--instance Matchable NonEmpty where+instance Matchable [] -instance Matchable Maybe where+instance Matchable NonEmpty -instance Eq a => Matchable ((,) a) where+instance Matchable Maybe -instance (Matchable f, Matchable g)=> Matchable (Compose f g) where+instance Eq a => Matchable ((,) a) +instance (Matchable f, Matchable g) => Matchable (Compose f g) ---------------------------------------------------------------- -- Generic Instance for Matchable@@ -255,7 +254,7 @@ -- | A class used in the @default@ definition for 'zipMatchLeft' class (Traversable t, Generic1 t) => GMatchable t where- gZipMatchLeft :: t a -> t b -> Maybe (t (a,b))+ gZipMatchLeft :: t a -> t b -> Maybe (t (a, b)) instance GMatchable t => GMatchable (M1 m i t) where gZipMatchLeft (M1 l) (M1 r) = M1 <$> gZipMatchLeft l r@@ -264,8 +263,9 @@ gZipMatchLeft _ _ = Just U1 instance Eq c => GMatchable (K1 m c) where- gZipMatchLeft (K1 l) (K1 r) | l == r = Just (K1 l)- | otherwise = Nothing+ gZipMatchLeft (K1 l) (K1 r)+ | l == r = Just (K1 l)+ | otherwise = Nothing instance GMatchable Par1 where gZipMatchLeft (Par1 l) (Par1 r) = Just . Par1 $ (l, r)@@ -276,7 +276,7 @@ instance (GMatchable l, GMatchable r) => GMatchable (l :+: r) where gZipMatchLeft (L1 l) (L1 r) = L1 <$> gZipMatchLeft l r gZipMatchLeft (R1 l) (R1 r) = R1 <$> gZipMatchLeft l r- gZipMatchLeft _ _ = Nothing+ gZipMatchLeft _ _ = Nothing instance (GMatchable l, GMatchable r) => GMatchable (l :*: r) where gZipMatchLeft (l1 :*: l2) (r1 :*: r2) =@@ -286,7 +286,6 @@ gZipMatchLeft (Comp1 l) (Comp1 r) = do x <- zipMatchLeft l r >>= traverse (uncurry gZipMatchLeft) pure (Comp1 x)- ---------------------------------------------------------------- -- Utils
src/Nix/Match/Typed.hs view
@@ -1,60 +1,66 @@ {-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-}+ -- | A more strongly typed alternative to 'Nix.Match' module Nix.Match.Typed- ( matchNix- , matchNixLoc- , TypedMatcher(..)- , TypedMatch(..)- , get- , getOptional- , matchTyped- , findMatchesTyped- ) where+ ( matchNix,+ matchNixLoc,+ TypedMatcher (..),+ TypedMatch (..),+ get,+ getOptional,+ matchTyped,+ findMatchesTyped,+ )+where -import Control.Category ( (>>>) )-import Data.Coerce ( coerce )-import Data.Data-import Data.Fix-import Data.Generics.Aliases-import Data.Kind ( Constraint )-import Data.Maybe-import qualified Data.Text as T-import Data.Type.Equality ( type (==) )-import GHC.TypeLits ( ErrorMessage(..)- , KnownSymbol- , Symbol- , TypeError- , symbolVal- )-import Language.Haskell.TH ( Exp(AppE, VarE)- , ExpQ- , Pat(..)- , PatQ- , Q- , TyLit(StrTyLit)- , Type(..)- , appTypeE- , litT- , mkName- , newName- , strTyLit- , tupE- , tupP- , varE- , varP- )-import Language.Haskell.TH.Lib ( appE- , conE- )-import Language.Haskell.TH.Quote ( QuasiQuoter(..) )-import Language.Haskell.TH.Syntax ( dataToExpQ- , liftString- )-import Nix hiding ( TypeError )-import Nix.Match-import Nix.TH+import Control.Category ((>>>))+import Data.Coerce (coerce)+import Data.Data+import Data.Fix+import Data.Generics.Aliases+import Data.Kind (Constraint)+import Data.Maybe+import qualified Data.Text as T+import Data.Type.Equality (type (==))+import GHC.TypeLits+ ( ErrorMessage (..),+ KnownSymbol,+ Symbol,+ TypeError,+ symbolVal,+ )+import Language.Haskell.TH+ ( Exp (AppE, VarE),+ ExpQ,+ Pat (..),+ PatQ,+ Q,+ TyLit (StrTyLit),+ Type (..),+ appTypeE,+ litT,+ mkName,+ newName,+ strTyLit,+ tupE,+ tupP,+ varE,+ varP,+ )+import Language.Haskell.TH.Lib+ ( appE,+ conE,+ )+import Language.Haskell.TH.Quote (QuasiQuoter (..))+import Language.Haskell.TH.Syntax+ ( dataToExpQ,+ liftString,+ )+import Nix+import Nix.Match+import Nix.TH ---------------------------------------------------------------- -- Typed matching@@ -81,11 +87,13 @@ -- >>> :t (a, b) -- (a, b) :: (Fix NExprF, Maybe (Fix NExprF)) matchNix :: QuasiQuoter-matchNix = QuasiQuoter { quoteExp = typedMatcherExp- , quotePat = typedMatcherPat- , quoteDec = error "No dec quoter for typedMatcher"- , quoteType = error "No type quoter for typedMatcher"- }+matchNix =+ QuasiQuoter+ { quoteExp = typedMatcherExp,+ quotePat = typedMatcherPat,+ quoteDec = error "No dec quoter for typedMatcher",+ quoteType = error "No type quoter for typedMatcher"+ } -- | A QuasiQuoter for safely generating 'TypedMatcher's from nix source along -- with source location annotations@@ -100,17 +108,17 @@ -- the holes present in the expression. These will have type 'NExprLoc' if they -- are required, and @Maybe 'NExprLoc'@ if they are optional. matchNixLoc :: QuasiQuoter-matchNixLoc = QuasiQuoter- { quoteExp = typedMatcherLocExp- , quotePat = typedMatcherLocPat- , quoteDec = error "No dec quoter for typedMatcherLoc"- , quoteType = error "No type quoter for typedMatcherLoc"- }+matchNixLoc =+ QuasiQuoter+ { quoteExp = typedMatcherLocExp,+ quotePat = typedMatcherLocPat,+ quoteDec = error "No dec quoter for typedMatcherLoc",+ quoteType = error "No type quoter for typedMatcherLoc"+ } -- | A matcher with the names of the required and optional holes encoded at the -- type level.-newtype TypedMatcher (opts :: [Symbol]) (reqs :: [Symbol]) t- = TypedMatcher {unTypedMatcher :: WithHoles t T.Text}+newtype TypedMatcher (opts :: [Symbol]) (reqs :: [Symbol]) t = TypedMatcher {unTypedMatcher :: WithHoles t VarName} -- | The results of matching with a 'TypedMatcher'. The values in the required -- list are guaranteed to be present. The values in the optional list may be@@ -119,37 +127,37 @@ = TypedMatch [(T.Text, a)] -- | Extract a required key from a match-get- :: forall x opts reqs a- . (Elem "Required" x reqs, KnownSymbol x)- => TypedMatch opts reqs a- -> a+get ::+ forall x opts reqs a.+ (Elem "Required" x reqs, KnownSymbol x) =>+ TypedMatch opts reqs a ->+ a get (TypedMatch ms) =- fromMaybe (error "Required key not present in TypedMatch")- $ lookup (T.pack (symbolVal (Proxy @x))) ms+ fromMaybe (error "Required key not present in TypedMatch") $+ lookup (T.pack (symbolVal (Proxy @x))) ms -- | Maybe extract an optional key from a match-getOptional- :: forall x opts reqs a- . (Elem "Optional" x opts, KnownSymbol x)- => TypedMatch opts reqs a- -> Maybe a+getOptional ::+ forall x opts reqs a.+ (Elem "Optional" x opts, KnownSymbol x) =>+ TypedMatch opts reqs a ->+ Maybe a getOptional (TypedMatch ms) = lookup (T.pack (symbolVal (Proxy @x))) ms -- | A typed version of 'match'-matchTyped- :: Matchable t- => TypedMatcher opts reqs t- -> Fix t- -> Maybe (TypedMatch opts reqs (Fix t))+matchTyped ::+ Matchable t =>+ TypedMatcher opts reqs t ->+ Fix t ->+ Maybe (TypedMatch opts reqs (Fix t)) matchTyped = coerce match -- | A typed version of 'findMatches'-findMatchesTyped- :: Matchable t- => TypedMatcher opts reqs t- -> Fix t- -> [(Fix t, TypedMatch opts reqs (Fix t))]+findMatchesTyped ::+ Matchable t =>+ TypedMatcher opts reqs t ->+ Fix t ->+ [(Fix t, TypedMatch opts reqs (Fix t))] findMatchesTyped = coerce findMatches typedMatcherExp :: String -> ExpQ@@ -159,10 +167,11 @@ typedMatcherLocExp :: String -> ExpQ typedMatcherLocExp = fmap snd- . typedMatcherGen parseNixTextLoc- collectHolesLoc- addHolesLoc- stripAnnotation+ . typedMatcherGen+ parseNixTextLoc+ collectHolesLoc+ addHolesLoc+ stripAnnotation typedMatcherPat :: String -> PatQ typedMatcherPat = typedMatcherPatGen parseNixText collectHoles addHoles id@@ -171,48 +180,53 @@ typedMatcherLocPat = typedMatcherPatGen parseNixTextLoc collectHolesLoc addHolesLoc stripAnnotation -typedMatcherPatGen- :: Data a- => (T.Text -> Result t)- -> (t -> ([T.Text], [T.Text]))- -> (t -> a)- -> (t -> NExpr)- -> String- -> Q Pat+typedMatcherPatGen ::+ Data a =>+ (T.Text -> Result t) ->+ (t -> ([VarName], [VarName])) ->+ (t -> a) ->+ (t -> NExpr) ->+ String ->+ Q Pat typedMatcherPatGen parseNix collect add strip s = do ((opt, req), matcher) <- typedMatcherGen parseNix collect add strip s -- e' <- [|fmap (\x -> $()) . matchTyped $(pure matcher)|]- x <- newName "x"- let pat = tupP (varP . mkName . T.unpack <$> (req <> opt))- textSymbol = litT . strTyLit . T.unpack- getters = tupE- ( ((\r -> [|get @($r) $(varE x)|]) . textSymbol <$> req)- <> ((\o -> [|getOptional @($o) $(varE x)|]) . textSymbol <$> opt)- )+ x <- newName "x"+ let pat = tupP (varP . mkName . T.unpack . unVarName <$> (req <> opt))+ textSymbol = litT . strTyLit . T.unpack . unVarName+ getters =+ tupE+ ( ((\r -> [|get @($r) $(varE x)|]) . textSymbol <$> req)+ <> ((\o -> [|getOptional @($o) $(varE x)|]) . textSymbol <$> opt)+ ) [p|(fmap (\ $(varP x) -> $getters) . matchTyped $(pure matcher) -> Just $pat)|] -typedMatcherGen- :: Data a- => (T.Text -> Result t)- -> (t -> ([T.Text], [T.Text]))- -> (t -> a)- -> (t -> NExpr)- -> String- -> Q (([T.Text], [T.Text]), Exp)+unVarName :: VarName -> T.Text+unVarName (VarName x) = x++typedMatcherGen ::+ Data a =>+ (T.Text -> Result t) ->+ (t -> ([VarName], [VarName])) ->+ (t -> a) ->+ (t -> NExpr) ->+ String ->+ Q (([VarName], [VarName]), Exp) typedMatcherGen parseNix collect add strip s = do expr <- case parseNix (T.pack s) of Left err -> fail $ show err- Right e -> pure e+ Right e -> pure e let (opt, req) = collect expr- optT = symbolList opt- reqT = symbolList req- holed = add expr- exprExp = dataToExpQ- ( const Nothing- `extQ` metaExp (freeVars (strip expr))- `extQ` (Just . liftText)- )- holed+ optT = symbolList opt+ reqT = symbolList req+ holed = add expr+ exprExp =+ dataToExpQ+ ( const Nothing+ `extQ` metaExp (getFreeVars (strip expr))+ `extQ` (Just . liftText)+ )+ holed e <- conE 'TypedMatcher `appTypeE` pure optT `appTypeE` pure reqT `appE` exprExp pure ((opt, req), e)@@ -221,33 +235,37 @@ liftText txt = AppE (VarE 'T.pack) <$> liftString (T.unpack txt) -- | Make a list of promoted strings-symbolList :: [T.Text] -> Type-symbolList = foldr- (\n -> (PromotedConsT `AppT` LitT (StrTyLit (T.unpack n)) `AppT`))- PromotedNilT+symbolList :: [VarName] -> Type+symbolList =+ foldr+ (\(VarName n) -> (PromotedConsT `AppT` LitT (StrTyLit (T.unpack n)) `AppT`))+ PromotedNilT -- | Collect optional and required holes-collectHoles :: NExpr -> ([T.Text], [T.Text])-collectHoles = unFix >>> \case- NSynHole n -> ([], [n])- NSet _ bs -> foldMap (bindingHoles collectHoles) bs- NLet bs e -> collectHoles e <> foldMap (bindingHoles collectHoles) bs- e -> foldMap collectHoles e+collectHoles :: NExpr -> ([VarName], [VarName])+collectHoles =+ unFix >>> \case+ NSynHole n -> ([], [n])+ NSet _ bs -> foldMap (bindingHoles collectHoles) bs+ NLet bs e -> collectHoles e <> foldMap (bindingHoles collectHoles) bs+ e -> foldMap collectHoles e -- | Collect optional and required holes-collectHolesLoc :: NExprLoc -> ([T.Text], [T.Text])-collectHolesLoc = unFix >>> \case- Compose (Ann _ (NSynHole n)) -> ([], [n])- Compose (Ann _ (NSet _ bs )) -> foldMap (bindingHoles collectHolesLoc) bs- Compose (Ann _ (NLet bs e)) ->- collectHolesLoc e <> foldMap (bindingHoles collectHolesLoc) bs- e -> foldMap collectHolesLoc e+collectHolesLoc :: NExprLoc -> ([VarName], [VarName])+collectHolesLoc =+ unFix >>> \case+ Compose (AnnUnit _ (NSynHole n)) -> ([], [n])+ Compose (AnnUnit _ (NSet _ bs)) -> foldMap (bindingHoles collectHolesLoc) bs+ Compose (AnnUnit _ (NLet bs e)) ->+ collectHolesLoc e <> foldMap (bindingHoles collectHolesLoc) bs+ e -> foldMap collectHolesLoc e -- | Find the optional and required holees in a binding bindingHoles :: (r -> ([a], [a])) -> Binding r -> ([a], [a]) bindingHoles f = \case- b@(NamedVar p _ _) | isJust (isOptionalPath p) ->- let (opt, req) = foldMap f b in (opt <> req, [])+ b@(NamedVar p _ _)+ | isJust (isOptionalPath p) ->+ let (opt, req) = foldMap f b in (opt <> req, []) b -> foldMap f b ----------------------------------------------------------------@@ -260,4 +278,4 @@ type family Elem n x ys :: Constraint where Elem n x '[] = TypeError ('Text n ':<>: 'Text " key \"" ':<>: 'Text x ':<>: 'Text "\" not found in TypedMatch")- Elem n x (y:ys) = Bool' (Elem n x ys) (() :: Constraint) (x == y)+ Elem n x (y : ys) = Bool' (Elem n x ys) (() :: Constraint) (x == y)
src/Update/Nix/FetchGit.hs view
@@ -1,34 +1,36 @@ {-# LANGUAGE QuasiQuotes #-} module Update.Nix.FetchGit- ( processFile- , processText- , updatesFromText- ) where+ ( processFile,+ processText,+ updatesFromText,+ )+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- )-import qualified Data.Text as T+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,+ )+import qualified Data.Text as T import qualified Data.Text.IO-import Data.Time ( Day )-import qualified Data.Vector as V-import Nix.Comments-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 Data.Time (Day)+import qualified Data.Vector as V+import Nix.Comments+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 -------------------------------------------------------------------------------- -- Tying it all together@@ -37,7 +39,7 @@ -- | Provided FilePath, update Nix file in-place processFile :: Env -> FilePath -> IO () processFile env filename = do- t <- Data.Text.IO.readFile filename+ t <- Data.Text.IO.readFile filename t' <- processText env t -- If updates are needed, write to the file. when (t /= t') $ Data.Text.IO.writeFile filename t'@@ -62,9 +64,9 @@ findUpdates (getComment nixLines) expr us <- evalUpdates =<< filterUpdates tree case us of- [] -> logVerbose "Made no updates"+ [] -> logVerbose "Made no updates" [_] -> logVerbose "Made 1 update"- _ -> logVerbose ("Made " <> T.pack (show (length us)) <> " updates")+ _ -> logVerbose ("Made " <> T.pack (show (length us)) <> " updates") pure us ----------------------------------------------------------------@@ -80,27 +82,29 @@ if not (null updateLocations || any (containsPosition e) updateLocations) then pure $ Node Nothing [] else- let- updaters = ($ e) <$> fetchers onlyCommented 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; }|] | 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))+ let updaters = ($ e) <$> fetchers onlyCommented 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; }|]+ | NSetAnnF _ _ bs <- unFix e ->+ Node version . concat <$> traverse bindingTrees bs+ [matchNixLoc|let _version = ^version; in ^x|]+ | NLetAnnF _ 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@@ -111,37 +115,38 @@ -- 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- ]+ 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- go :: FetchTree -> M (Maybe Day, [SpanUpdate])- go = \case- UpdaterNode (Updater u) -> u- Node versionExpr cs -> do- -- Run over all children- (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- ( latestDate- , [ SpanUpdate (exprSpan v)- (quoteString . ("unstable-" <>) . pack . show $ d)- | Just d <- pure latestDate- , Just v <- pure versionExpr- ]- <> concat ss- )+ where+ go :: FetchTree -> M (Maybe Day, [SpanUpdate])+ go = \case+ UpdaterNode (Updater u) -> u+ Node versionExpr cs -> do+ -- Run over all children+ (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+ ( latestDate,+ [ SpanUpdate+ (exprSpan v)+ (quoteString . ("unstable-" <>) . pack . show $ d)+ | Just d <- pure latestDate,+ Just v <- pure versionExpr+ ]+ <> concat ss+ ) ---------------------------------------------------------------- -- Utils
src/Update/Nix/FetchGit/Prefetch.hs view
@@ -141,11 +141,11 @@ pure $ ref .: "commit" .: "committer" .: "date" fromEither $ parseISO8601DateToDay dateString -ghState :: GitHubState-ghState = GitHubState { token = Nothing- , userAgent = "expipiplus1/update-nix-fetchgit"- , apiVersion = "v3"- }+ghState :: GitHubSettings+ghState = GitHubSettings { token = Nothing+ , userAgent = "expipiplus1/update-nix-fetchgit"+ , apiVersion = "v3"+ } ---------------------------------------------------------------- -- Utils
src/Update/Nix/FetchGit/Utils.hs view
@@ -1,59 +1,64 @@- module Update.Nix.FetchGit.Utils- ( RepoLocation(..)- , ourParseNixText- , ourParseNixFile- , extractUrlString- , prettyRepoLocation- , quoteString- , extractFuncName- , pathText- , exprText- , exprBool- , exprSpan- , containsPosition- , parseISO8601DateToDay- , formatWarning- , fromEither- , note- , refute1- , logVerbose- , logNormal- ) where+ ( RepoLocation (..),+ ourParseNixText,+ ourParseNixFile,+ extractUrlString,+ prettyRepoLocation,+ quoteString,+ extractFuncName,+ pathText,+ exprText,+ exprBool,+ exprSpan,+ containsPosition,+ parseISO8601DateToDay,+ formatWarning,+ fromEither,+ note,+ refute1,+ logVerbose,+ logNormal,+ )+where -import Control.Monad.IO.Class ( MonadIO(liftIO) )-import Control.Monad.Reader ( MonadReader(ask) )-import Control.Monad.Validate-import Data.Fix-import Data.List.NonEmpty as NE-import Data.Monoid-import Data.Text ( Text- , splitOn- , unpack- )-import qualified Data.Text as T-import Data.Time ( Day- , defaultTimeLocale- , parseTimeM- )-import Nix.Atoms ( NAtom(NBool) )-import Nix.Expr hiding ( SourcePos )-import Nix.Parser ( parseNixFileLoc- , parseNixTextLoc- )-import Update.Nix.FetchGit.Types-import Update.Nix.FetchGit.Warning-import Update.Span+import Control.Monad.IO.Class (MonadIO (liftIO))+import Control.Monad.Reader (MonadReader (ask))+import Control.Monad.Validate+import Data.Fix+import Data.List.NonEmpty as NE+import Data.Monoid+import Data.Text+ ( Text,+ splitOn,+ unpack,+ )+import qualified Data.Text as T+import Data.Time+ ( Day,+ defaultTimeLocale,+ parseTimeM,+ )+import Nix.Atoms (NAtom (NBool))+import Nix.Expr hiding (SourcePos)+import Nix.Parser+ ( parseNixFileLoc,+ parseNixTextLoc,+ )+import Nix.Utils (Path (..))+import Update.Nix.FetchGit.Types+import Update.Nix.FetchGit.Warning+import Update.Span ourParseNixText :: Text -> Either Warning NExprLoc ourParseNixText t = case parseNixTextLoc t of Left parseError -> Left (CouldNotParseInput (tShow parseError))- Right expr -> pure expr+ Right expr -> pure expr ourParseNixFile :: FilePath -> M NExprLoc-ourParseNixFile f = liftIO (parseNixFileLoc f) >>= \case- Left parseError -> refute1 (CouldNotParseInput (tShow parseError))- Right expr -> pure expr+ourParseNixFile f =+ liftIO (parseNixFileLoc (Path f)) >>= \case+ Left parseError -> refute1 (CouldNotParseInput (tShow parseError))+ Right expr -> pure expr -- | Get the url from either a nix expression for the url or a repo and owner -- expression.@@ -65,7 +70,7 @@ prettyRepoLocation :: RepoLocation -> Text prettyRepoLocation = \case- URL u -> u+ URL u -> u GitHub o r -> o <> "/" <> r GitLab o r -> o <> "/" <> r @@ -80,57 +85,57 @@ -- TODO: Use 'evalExpr' here exprText :: NExprLoc -> Either Warning Text exprText = \case- (AnnE _ (NStr (DoubleQuoted [Plain t]))) -> pure t+ (Ann _ (NStr (DoubleQuoted [Plain t]))) -> pure t e -> Left (NotAString e) exprBool :: NExprLoc -> Either Warning Bool exprBool = \case- (AnnE _ (NConstant (NBool b))) -> pure b- e -> Left (NotABool e)+ (Ann _ (NConstant (NBool b))) -> pure b+ e -> Left (NotABool e) -- | Get the 'SrcSpan' covering a particular expression. exprSpan :: NExprLoc -> SrcSpan-exprSpan (AnnE s _) = s+exprSpan (Ann s _) = s -- | Given an expression that is supposed to represent a function, -- extracts the name of the function. If we cannot figure out the -- function name, returns Nothing.-extractFuncName :: NExprLoc -> Maybe Text-extractFuncName (AnnE _ (NSym name)) = Just name-extractFuncName (AnnE _ (NSelect _ (NE.last -> StaticKey name) _)) = Just name+extractFuncName :: NExprLoc -> Maybe VarName+extractFuncName (Ann _ (NSym name)) = Just name+extractFuncName (Ann _ (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-+ where+ e :: NKeyName r -> Maybe Text+ e = \case+ StaticKey (VarName 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 = let justDate = (unpack . Prelude.head . splitOn "T") t- in maybe (Left $ InvalidDateString t)- Right- (parseTimeM False defaultTimeLocale "%Y-%m-%d" justDate)+ in maybe+ (Left $ InvalidDateString t)+ Right+ (parseTimeM False defaultTimeLocale "%Y-%m-%d" justDate) formatWarning :: Warning -> Text formatWarning (CouldNotParseInput doc) = doc@@ -179,9 +184,9 @@ ---------------------------------------------------------------- containsPosition :: NExprLoc -> (Int, Int) -> Bool-containsPosition (Fix (Compose (Ann (SrcSpan begin end) _))) p =+containsPosition (Fix (Compose (AnnUnit (SrcSpan begin end) _))) p = let unSourcePos (SourcePos _ l c) = (unPos l, unPos c)- in p >= unSourcePos begin && p < unSourcePos end+ in p >= unSourcePos begin && p < unSourcePos end ---------------------------------------------------------------- -- Errors@@ -189,7 +194,7 @@ fromEither :: Either Warning a -> M a fromEither = \case- Left e -> refute1 e+ Left e -> refute1 e Right a -> pure a note :: Warning -> Maybe a -> M a@@ -206,7 +211,7 @@ logVerbose :: Text -> M () logVerbose t = do- Env{..} <- ask+ Env {..} <- ask liftIO $ sayLog Verbose t logNormal :: Text -> M ()
src/Update/Span.hs view
@@ -14,38 +14,46 @@ , split ) where -import Control.Exception (assert)-import Data.Data (Data)-import Data.Int (Int64)-import Data.List (genericTake, sortOn)-import Data.Text (Text, length, lines, splitAt)-import Prelude hiding (length, lines, splitAt)-import Nix.Expr.Types.Annotated+import Control.Exception ( assert )+import Data.Data ( Data )+import Data.Int ( Int64 )+import Data.List ( genericTake+ , sortOn+ )+import Data.Text ( Text+ , length+ , lines+ , splitAt+ )+import Nix.Expr.Types.Annotated+import Prelude hiding ( length+ , lines+ , splitAt+ ) -- | A span and some text to replace it with. -- They don't have to be the same length.-data SpanUpdate = SpanUpdate{ spanUpdateSpan :: SrcSpan- , spanUpdateContents :: Text- }+data SpanUpdate = SpanUpdate+ { spanUpdateSpan :: SrcSpan+ , spanUpdateContents :: Text+ } deriving (Show, Data) -- | Update many spans in a file. They must be non-overlapping. updateSpans :: [SpanUpdate] -> Text -> Text updateSpans us t = let sortedSpans = sortOn (spanBegin . spanUpdateSpan) us- anyOverlap = any (uncurry overlaps)- (zip <*> tail $ spanUpdateSpan <$> sortedSpans)- in- assert (not anyOverlap)- (foldr updateSpan t sortedSpans)+ anyOverlap =+ any (uncurry overlaps) (zip <*> tail $ spanUpdateSpan <$> sortedSpans)+ in assert (not anyOverlap) (foldr updateSpan t sortedSpans) -- | Update a single span of characters inside a text value. If you're updating -- multiples spans it's best to use 'updateSpans'. updateSpan :: SpanUpdate -> Text -> Text updateSpan (SpanUpdate (SrcSpan b e) r) t =- let (before, _) = split b t- (_, end) = split e t- in before <> r <> end+ let (before, _ ) = split b t+ (_ , end) = split e t+ in before <> r <> end -- | Do two spans overlap overlaps :: SrcSpan -> SrcSpan -> Bool@@ -56,7 +64,10 @@ split :: SourcePos -> Text -> (Text, Text) split (SourcePos _ row col) t = splitAt (fromIntegral- (linearizeSourcePos t (fromIntegral (unPos row - 1)) (fromIntegral (unPos col - 1)))+ (linearizeSourcePos t+ (fromIntegral (unPos row - 1))+ (fromIntegral (unPos col - 1))+ ) ) t @@ -64,13 +75,15 @@ -- the beginning of the text. -- -- This probably fails on crazy texts with multi character line breaks.-linearizeSourcePos :: Text -- ^ The string to linearize in- -> Int64 -- ^ The line offset- -> Int64 -- ^ The column offset- -> Int64 -- ^ The character offset+linearizeSourcePos+ :: Text -- ^ The string to linearize in+ -> Int64 -- ^ The line offset+ -> Int64 -- ^ The column offset+ -> Int64 -- ^ The character offset linearizeSourcePos t l c = fromIntegral lineCharOffset + c- where lineCharOffset = sum . fmap ((+1) . length) . genericTake l . lines $ t+ where+ lineCharOffset = sum . fmap ((+ 1) . length) . genericTake l . lines $ t prettyPrintSourcePos :: SourcePos -> String prettyPrintSourcePos (SourcePos _ row column) =- "line " <> show row <> " column " <> show column+ show (unPos row) <> ":" <> show (unPos column)
tests/Samples.hs view
@@ -42,24 +42,25 @@ inBase = System.FilePath.takeBaseName inFile System.Directory.copyFile inFile (dir </> inBase)-- System.Directory.copyFile "tests/fakeRepo.sh" (dir </> "fakeRepo.sh")+ testScript <- System.Directory.makeAbsolute "tests/fakeRepo.sh" - _ <- System.Process.readCreateProcess- ((System.Process.shell (dir </> "fakeRepo.sh")) { System.Process.cwd = Just dir })- mempty+ _ <- System.Process.waitForProcess =<< System.Process.runProcess+ "bash"+ [testScript] (Just dir)+ Nothing+ Nothing Nothing Nothing replaceFile (dir </> inBase) "/tmp/nix-update-fetchgit-test" (Data.Text.pack dir) System.Environment.setEnv "NIX_STATE_DIR" $ storeDir </> "state"- System.Environment.setEnv "NIX_STORE_DIR" $ storeDir+ System.Environment.setEnv "NIX_STORE_DIR" storeDir -- work around race condition https://github.com/NixOS/nix/issues/2706 System.Directory.createDirectoryIfMissing True $ storeDir </> "state/gcroots" -- and another - error: SQLite database storeDir </> 'state/db/db.sqlite' is busy _ <- System.Process.readCreateProcess- (System.Process.shell ("nix-store --init"))+ (System.Process.shell "nix-store --init") mempty let env = Env (const (Data.Text.IO.hPutStrLn System.IO.stderr)) [] [] Wet False
tests/fakeRepo.sh view
@@ -1,9 +1,9 @@-#!/bin/sh+#!/usr/bin/env bash # Prepares git repositories on the local machine that we will use for # testing. -set -ex+set -e # Make sure the commit hashes are predictable. export GIT_AUTHOR_DATE='1466974421 +0200'@@ -15,7 +15,7 @@ export XDG_CONFIG_DIRS= export HOME= -git init repo1+git init repo1 --initial-branch=main cd repo1 echo hi > test.txt git add test.txt@@ -31,7 +31,7 @@ export GIT_AUTHOR_DATE='1468031426 -0700' export GIT_COMMITTER_DATE='1468031426 -0700'-git init repo2+git init repo2 --initial-branch=main cd repo2 echo hi > test.txt git add test.txt
update-nix-fetchgit.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.4.+-- This file has been generated from package.yaml by hpack version 0.34.7. -- -- see: https://github.com/sol/hpack name: update-nix-fetchgit-version: 0.2.9+version: 0.2.11 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@@ -13,9 +13,9 @@ category: Nix homepage: https://github.com/expipiplus1/update-nix-fetchgit#readme bug-reports: https://github.com/expipiplus1/update-nix-fetchgit/issues-author: Joe Hermaszewski-maintainer: Joe Hermaszewski <haskell@monoid.al>-copyright: 2020 Joe Hermaszewski+author: Ellie Hermaszewska+maintainer: Ellie Hermaszewska <haskell@monoid.al>+copyright: 2020 Ellie Hermaszewska license: BSD3 license-file: LICENSE build-type: Simple@@ -107,8 +107,8 @@ , base >=4.7 && <5 , bytestring >=0.10 , data-fix- , github-rest- , hnix >=0.13.1+ , github-rest >=1.1+ , hnix ==0.16.* , monad-validate , mtl , process >=1.2@@ -195,8 +195,6 @@ TypeOperators ViewPatterns ghc-options: -Wall- build-tool-depends:- tasty-discover:tasty-discover build-depends: base >=4.7 && <5 , directory