git-annex 10.20220127 → 10.20220222
raw patch · 23 files changed
+299/−168 lines, 23 files
Files
- Annex/Content.hs +15/−10
- Annex/Link.hs +3/−3
- Annex/Queue.hs +4/−4
- CHANGELOG +19/−0
- Command/FromKey.hs +7/−4
- Command/Info.hs +65/−35
- Command/RegisterUrl.hs +26/−34
- Command/Unlock.hs +9/−5
- Command/UnregisterUrl.hs +5/−5
- Command/Unused.hs +4/−6
- Database/Keys.hs +3/−0
- Git/Queue.hs +46/−41
- Logs/Transitions.hs +3/−1
- NEWS +9/−0
- Remote/Adb.hs +12/−8
- Test.hs +36/−0
- Types/GitConfig.hs +1/−1
- doc/git-annex-drop.mdwn +2/−1
- doc/git-annex-info.mdwn +5/−6
- doc/git-annex-registerurl.mdwn +10/−0
- doc/git-annex-unregisterurl.mdwn +13/−0
- doc/git-annex.mdwn +1/−3
- git-annex.cabal +1/−1
Annex/Content.hs view
@@ -43,6 +43,7 @@ moveBad, KeyLocation(..), listKeys,+ listKeys', saveState, downloadUrl, preseedTmp,@@ -653,22 +654,26 @@ - .git/annex/objects, whether or not the content is present. -} listKeys :: KeyLocation -> Annex [Key]-listKeys keyloc = do+listKeys keyloc = listKeys' keyloc (const (pure True))++{- Due to use of unsafeInterleaveIO, the passed filter action+ - will be run in a copy of the Annex state, so any changes it+ - makes to the state will not be preserved. -}+listKeys' :: KeyLocation -> (Key -> Annex Bool) -> Annex [Key]+listKeys' keyloc want = do dir <- fromRepo gitAnnexObjectDir- {- In order to run Annex monad actions within unsafeInterleaveIO,- - the current state is taken and reused. No changes made to this- - state will be preserved. - -} s <- Annex.getState id+ r <- Annex.getRead id depth <- gitAnnexLocationDepth <$> Annex.getGitConfig- liftIO $ walk s depth (fromRawFilePath dir)+ liftIO $ walk (s, r) depth (fromRawFilePath dir) where walk s depth dir = do contents <- catchDefaultIO [] (dirContents dir) if depth < 2 then do- contents' <- filterM (present s) contents- let keys = mapMaybe (fileKey . P.takeFileName . toRawFilePath) contents'+ contents' <- filterM present contents+ keys <- filterM (Annex.eval s . want) $+ mapMaybe (fileKey . P.takeFileName . toRawFilePath) contents' continue keys [] else do let deeper = walk s (depth - 1)@@ -683,8 +688,8 @@ InAnywhere -> True _ -> False - present _ _ | inanywhere = pure True- present _ d = presentInAnnex d+ present _ | inanywhere = pure True+ present d = presentInAnnex d presentInAnnex = doesFileExist . contentfile contentfile d = d </> takeFileName d
Annex/Link.hs view
@@ -190,7 +190,7 @@ -- fails on "../../repo/path/file" when cwd is not in the repo -- being acted on. Avoid these problems with an absolute path. absf <- liftIO $ absPath f- Annex.Queue.addInternalAction runner [(absf, isunmodified tsd, inodeCacheFileSize orig)]+ Annex.Queue.addFlushAction runner [(absf, isunmodified tsd, inodeCacheFileSize orig)] where isunmodified tsd = genInodeCache f tsd >>= return . \case Nothing -> False@@ -202,8 +202,8 @@ -- on all still-unmodified files, using a copy of the index file, -- to bypass the lock. Then replace the old index file with the new -- updated index file.- runner :: Git.Queue.InternalActionRunner Annex- runner = Git.Queue.InternalActionRunner "restagePointerFile" $ \r l -> do+ runner :: Git.Queue.FlushActionRunner Annex+ runner = Git.Queue.FlushActionRunner "restagePointerFile" $ \r l -> do -- Flush any queued changes to the keys database, so they -- are visible to child processes. -- The database is closed because that may improve behavior
Annex/Queue.hs view
@@ -9,7 +9,7 @@ module Annex.Queue ( addCommand,- addInternalAction,+ addFlushAction, addUpdateIndex, flush, flushWhenFull,@@ -31,11 +31,11 @@ store =<< flushWhenFull =<< (Git.Queue.addCommand commonparams command params files q =<< gitRepo) -addInternalAction :: Git.Queue.InternalActionRunner Annex -> [(RawFilePath, IO Bool, FileSize)] -> Annex ()-addInternalAction runner files = do+addFlushAction :: Git.Queue.FlushActionRunner Annex -> [(RawFilePath, IO Bool, FileSize)] -> Annex ()+addFlushAction runner files = do q <- get store =<< flushWhenFull =<<- (Git.Queue.addInternalAction runner files q =<< gitRepo)+ (Git.Queue.addFlushAction runner files q =<< gitRepo) {- Adds an update-index stream to the queue. -} addUpdateIndex :: Git.UpdateIndex.Streamer -> Annex ()
CHANGELOG view
@@ -1,3 +1,22 @@+git-annex (10.20220222) upstream; urgency=medium++ * annex.skipunknown now defaults to false, so commands like+ `git annex get foo*` will not silently skip over files/dirs that are+ not checked into git.+ * info: Allow using matching options in more situations. File matching+ options like --include will be rejected in situations where there is+ no filename to match against.+ * adb: Avoid find failing with "Argument list too long"+ * Fix git-annex forget propagation between repositories.+ (reversion introduced in version 7.20190122)+ * registerurl, unregisterurl: Improved output when reading from stdin+ to be more like other batch commands.+ * registerurl, unregisterurl: Added --json and --json-error-messages options.+ * Avoid git status taking a long time after git-annex unlock of many files.+ * Pass --no-textconv when running git diff internally.++ -- Joey Hess <id@joeyh.name> Tue, 22 Feb 2022 13:01:20 -0400+ git-annex (10.20220127) upstream; urgency=medium * New v10 repository version (with v9 as a stepping-stone to it).
Command/FromKey.hs view
@@ -86,12 +86,15 @@ -- the uri scheme, to see if it looks like the prefix of a key. This relies -- on key backend names never containing a ':'. keyOpt :: String -> Key-keyOpt s = case parseURI s of+keyOpt = either giveup id . keyOpt'++keyOpt' :: String -> Either String Key+keyOpt' s = case parseURI s of Just u | not (isKeyPrefix (uriScheme u)) ->- Backend.URL.fromUrl s Nothing+ Right $ Backend.URL.fromUrl s Nothing _ -> case deserializeKey s of- Just k -> k- Nothing -> giveup $ "bad key/url " ++ s+ Just k -> Right k+ Nothing -> Left $ "bad key/url " ++ s perform :: AddUnlockedMatcher -> Key -> RawFilePath -> CommandPerform perform matcher key file = lookupKeyNotHidden file >>= \case
Command/Info.hs view
@@ -1,6 +1,6 @@ {- git-annex command -- - Copyright 2011-2021 Joey Hess <id@joeyh.name>+ - Copyright 2011-2022 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -132,7 +132,6 @@ globalInfo :: InfoOptions -> Annex () globalInfo o = do- disallowMatchingOptions u <- getUUID whenM ((==) DeadTrusted <$> lookupTrust u) $ earlyWarning "Warning: This repository is currently marked as dead."@@ -145,7 +144,6 @@ itemInfo o (si, p) = ifM (isdir p) ( dirInfo o p si , do- disallowMatchingOptions v <- Remote.byName' p case v of Right r -> remoteInfo o r si@@ -168,10 +166,6 @@ showNote $ "not a directory or an annexed file or a treeish or a remote or a uuid" showEndFail -disallowMatchingOptions :: Annex ()-disallowMatchingOptions = whenM Limit.limited $- giveup "File matching options can only be used when getting info on a directory."- dirInfo :: InfoOptions -> FilePath -> SeekInput -> Annex () dirInfo o dir si = showCustom (unwords ["info", dir]) si $ do stats <- selStats@@ -197,9 +191,13 @@ tostats = map (\s -> s t) fileInfo :: InfoOptions -> FilePath -> SeekInput -> Key -> Annex ()-fileInfo o file si k = showCustom (unwords ["info", file]) si $ do- evalStateT (mapM_ showStat (file_stats file k)) (emptyStatInfo o)- return True+fileInfo o file si k = do+ matcher <- Limit.getMatcher+ let file' = toRawFilePath file+ whenM (matcher $ MatchingFile $ FileInfo file' file' (Just k)) $+ showCustom (unwords ["info", file]) si $ do+ evalStateT (mapM_ showStat (file_stats file k)) (emptyStatInfo o)+ return True remoteInfo :: InfoOptions -> Remote -> SeekInput -> Annex () remoteInfo o r si = showCustom (unwords ["info", Remote.name r]) si $ do@@ -404,7 +402,7 @@ bad_data_size = staleSize "bad keys size" gitAnnexBadDir key_size :: Key -> Stat-key_size k = simpleStat "size" $ showSizeKeys $ foldKeys [k]+key_size k = simpleStat "size" $ showSizeKeys $ addKey k emptyKeyInfo key_name :: Key -> Stat key_name k = simpleStat "key" $ pure $ serializeKey k@@ -525,7 +523,9 @@ case presentData s of Just v -> return v Nothing -> do- v <- foldKeys <$> lift (listKeys InAnnex)+ matcher <- lift getKeyOnlyMatcher+ v <- foldl' (flip addKey) emptyKeyInfo+ <$> lift (listKeys' InAnnex (matchOnKey matcher)) put s { presentData = Just v } return v @@ -535,9 +535,13 @@ case M.lookup u (repoData s) of Just v -> return (Right v) Nothing -> do+ matcher <- lift getKeyOnlyMatcher let combinedata d uk = finishCheck uk >>= \case Nothing -> return d- Just k -> return $ addKey k d+ Just k -> ifM (matchOnKey matcher k)+ ( return (addKey k d)+ , return d+ ) lift (loggedKeysFor' u) >>= \case Just (ks, cleanup) -> do v <- lift $ foldM combinedata emptyKeyInfo ks@@ -552,8 +556,13 @@ case referencedData s of Just v -> return v Nothing -> do+ matcher <- lift getKeyOnlyMatcher+ let combinedata k _f d = ifM (matchOnKey matcher k)+ ( return (addKey k d)+ , return d+ ) !v <- lift $ Command.Unused.withKeysReferenced- emptyKeyInfo addKey+ emptyKeyInfo combinedata put s { referencedData = Just v } return v @@ -596,11 +605,16 @@ getTreeStatInfo :: InfoOptions -> Git.Ref -> Annex (Maybe StatInfo) getTreeStatInfo o r = do fast <- Annex.getState Annex.fast+ -- git lstree filenames start with a leading "./" that prevents+ -- matching, and also things like --include are supposed to+ -- match relative to the current directory, which does not make+ -- sense when matching against files in some arbitrary tree.+ matcher <- getKeyOnlyMatcher (ls, cleanup) <- inRepo $ LsTree.lsTree LsTree.LsTreeRecursive (LsTree.LsTreeLong False) r- (presentdata, referenceddata, repodata) <- go fast ls initial+ (presentdata, referenceddata, repodata) <- go fast matcher ls initial ifM (liftIO cleanup) ( return $ Just $ StatInfo (Just presentdata) (Just referenceddata) repodata Nothing o@@ -608,23 +622,25 @@ ) where initial = (emptyKeyInfo, emptyKeyInfo, M.empty)- go _ [] vs = return vs- go fast (l:ls) vs@(presentdata, referenceddata, repodata) = do- mk <- catKey (LsTree.sha l)- case mk of- Nothing -> go fast ls vs- Just key -> do- !presentdata' <- ifM (inAnnex key)- ( return $ addKey key presentdata- , return presentdata- )- let !referenceddata' = addKey key referenceddata- !repodata' <- if fast- then return repodata- else do- locs <- Remote.keyLocations key- return (updateRepoData key locs repodata)- go fast ls $! (presentdata', referenceddata', repodata')+ go _ _ [] vs = return vs+ go fast matcher (l:ls) vs@(presentdata, referenceddata, repodata) =+ catKey (LsTree.sha l) >>= \case+ Nothing -> go fast matcher ls vs+ Just key -> ifM (matchOnKey matcher key)+ ( do+ !presentdata' <- ifM (inAnnex key)+ ( return $ addKey key presentdata+ , return presentdata+ )+ let !referenceddata' = addKey key referenceddata+ !repodata' <- if fast+ then return repodata+ else do+ locs <- Remote.keyLocations key+ return (updateRepoData key locs repodata)+ go fast matcher ls $! (presentdata', referenceddata', repodata')+ , go fast matcher ls vs+ ) emptyKeyInfo :: KeyInfo emptyKeyInfo = KeyInfo 0 0 0 M.empty@@ -632,9 +648,6 @@ emptyNumCopiesStats :: NumCopiesStats emptyNumCopiesStats = NumCopiesStats M.empty -foldKeys :: [Key] -> KeyInfo-foldKeys = foldl' (flip addKey) emptyKeyInfo- addKey :: Key -> KeyInfo -> KeyInfo addKey key (KeyInfo count size unknownsize backends) = KeyInfo count' size' unknownsize' backends'@@ -700,3 +713,20 @@ ( return (const $ const show) , return roughSize )+ +getKeyOnlyMatcher :: Annex (MatchInfo -> Annex Bool)+getKeyOnlyMatcher = do+ whenM (Limit.introspect matchNeedsFileName) $ do+ warning "File matching options cannot be applied when getting this info."+ giveup "Unable to continue."+ Limit.getMatcher++matchOnKey :: (MatchInfo -> Annex Bool) -> Key -> Annex Bool+matchOnKey matcher k = matcher $ MatchingInfo $ ProvidedInfo+ { providedFilePath = Nothing+ , providedKey = Just k+ , providedFileSize = Nothing+ , providedMimeType = Nothing+ , providedMimeEncoding = Nothing+ , providedLinkType = Nothing+ }
Command/RegisterUrl.hs view
@@ -1,21 +1,19 @@ {- git-annex command -- - Copyright 2015-2018 Joey Hess <id@joeyh.name>+ - Copyright 2015-2022 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -} -{-# LANGUAGE BangPatterns #-}- module Command.RegisterUrl where import Command import Logs.Web-import Command.FromKey (keyOpt)+import Command.FromKey (keyOpt, keyOpt') import qualified Remote cmd :: Command-cmd = command "registerurl"+cmd = withGlobalOptions [jsonOptions] $ command "registerurl" SectionPlumbing "registers an url for a key" (paramPair paramKey paramUrl) (seek <$$> optParser)@@ -32,45 +30,39 @@ seek :: RegisterUrlOptions -> CommandSeek seek o = case (batchOption o, keyUrlPairs o) of- (Batch (BatchFormat sep _), _) -> batchOnly Nothing (keyUrlPairs o) $- commandAction $ startMass setUrlPresent sep+ (Batch fmt, _) -> seekBatch setUrlPresent o fmt -- older way of enabling batch input, does not support BatchNull- (NoBatch, []) -> commandAction $ startMass setUrlPresent BatchLine- (NoBatch, ps) -> withWords (commandAction . start setUrlPresent) ps+ (NoBatch, []) -> seekBatch setUrlPresent o (BatchFormat BatchLine (BatchKeys False))+ (NoBatch, ps) -> commandAction (start setUrlPresent ps) +seekBatch :: (Key -> URLString -> Annex ()) -> RegisterUrlOptions -> BatchFormat -> CommandSeek+seekBatch a o fmt = batchOnly Nothing (keyUrlPairs o) $+ batchInput fmt (pure . parsebatch) $+ batchCommandAction . start' a+ where+ parsebatch l = + let (keyname, u) = separate (== ' ') l+ in if null u+ then Left "no url provided"+ else case keyOpt' keyname of+ Left e -> Left e+ Right k -> Right (k, u)+ start :: (Key -> URLString -> Annex ()) -> [String] -> CommandStart-start a (keyname:url:[]) = - starting "registerurl" ai si $- perform a (keyOpt keyname) url+start a (keyname:url:[]) = start' a (si, (keyOpt keyname, url)) where- ai = ActionItemOther (Just url) si = SeekInput [keyname, url] start _ _ = giveup "specify a key and an url" -startMass :: (Key -> URLString -> Annex ()) -> BatchSeparator -> CommandStart-startMass a sep =- starting "registerurl" (ActionItemOther (Just "stdin")) (SeekInput []) $- performMass a sep--performMass :: (Key -> URLString -> Annex ()) -> BatchSeparator -> CommandPerform-performMass a sep = go True =<< map (separate (== ' ')) <$> batchLines fmt+start' :: (Key -> URLString -> Annex ()) -> (SeekInput, (Key, URLString)) -> CommandStart+start' a (si, (key, url)) =+ starting "registerurl" ai si $+ perform a key url where- fmt = BatchFormat sep (BatchKeys False)- go status [] = next $ return status- go status ((keyname,u):rest) | not (null keyname) && not (null u) = do- let key = keyOpt keyname- ok <- perform' a key u- let !status' = status && ok- go status' rest- go _ _ = giveup "Expected pairs of key and url on stdin, but got something else."+ ai = ActionItemOther (Just url) perform :: (Key -> URLString -> Annex ()) -> Key -> URLString -> CommandPerform perform a key url = do- ok <- perform' a key url- next $ return ok--perform' :: (Key -> URLString -> Annex ()) -> Key -> URLString -> Annex Bool-perform' a key url = do r <- Remote.claimingUrl url a key (setDownloader' url r)- return True+ next $ return True
Command/Unlock.hs view
@@ -1,6 +1,6 @@ {- git-annex command -- - Copyright 2010-2016 Joey Hess <id@joeyh.name>+ - Copyright 2010-2022 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -12,6 +12,8 @@ import Annex.Perms import Annex.Link import Annex.ReplaceFile+import Annex.InodeSentinal+import Utility.InodeCache import Git.FilePath import qualified Database.Keys import qualified Utility.RawFilePath as R@@ -47,7 +49,7 @@ perform :: RawFilePath -> Key -> CommandPerform perform dest key = do destmode <- liftIO $ catchMaybeIO $ fileMode <$> R.getFileStatus dest- replaceWorkTreeFile (fromRawFilePath dest) $ \tmp ->+ destic <- replaceWorkTreeFile (fromRawFilePath dest) $ \tmp -> do ifM (inAnnex key) ( do r <- linkFromAnnex' key (toRawFilePath tmp) destmode@@ -57,10 +59,12 @@ LinkAnnexFailed -> error "unlock failed" , liftIO $ writePointerFile (toRawFilePath tmp) key destmode )- next $ cleanup dest key destmode+ withTSDelta (liftIO . genInodeCache (toRawFilePath tmp))+ next $ cleanup dest destic key destmode -cleanup :: RawFilePath -> Key -> Maybe FileMode -> CommandCleanup-cleanup dest key destmode = do+cleanup :: RawFilePath -> Maybe InodeCache -> Key -> Maybe FileMode -> CommandCleanup+cleanup dest destic key destmode = do stagePointerFile dest destmode =<< hashPointerFile key+ maybe noop (restagePointerFile (Restage True) dest) destic Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath dest) return True
Command/UnregisterUrl.hs view
@@ -1,6 +1,6 @@ {- git-annex command -- - Copyright 2015-2021 Joey Hess <id@joeyh.name>+ - Copyright 2015-2022 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -11,18 +11,18 @@ import Command import Logs.Web-import Command.RegisterUrl (start, startMass, optParser, RegisterUrlOptions(..))+import Command.RegisterUrl (seekBatch, start, optParser, RegisterUrlOptions(..)) cmd :: Command-cmd = command "unregisterurl"+cmd = withGlobalOptions [jsonOptions] $ command "unregisterurl" SectionPlumbing "unregisters an url for a key" (paramPair paramKey paramUrl) (seek <$$> optParser) seek :: RegisterUrlOptions -> CommandSeek seek o = case (batchOption o, keyUrlPairs o) of- (Batch (BatchFormat sep _), _) -> commandAction $ startMass unregisterUrl sep- (NoBatch, ps) -> withWords (commandAction . start unregisterUrl) ps+ (Batch fmt, _) -> seekBatch unregisterUrl o fmt+ (NoBatch, ps) -> commandAction (start unregisterUrl ps) unregisterUrl :: Key -> String -> Annex () unregisterUrl key url = do
Command/Unused.hs view
@@ -183,12 +183,10 @@ runfilter a l = a l runbloomfilter a = runfilter $ \l -> bloomFilter l <$> genBloomFilter a -{- Given an initial value, folds it with each key referenced by- - files in the working tree. -}-withKeysReferenced :: v -> (Key -> v -> v) -> Annex v-withKeysReferenced initial a = withKeysReferenced' Nothing initial folda- where- folda k _ v = return $ a k v+{- Given an initial value, accumulates the value over each key+ - referenced by files in the working tree. -}+withKeysReferenced :: v -> (Key -> RawFilePath -> v -> Annex v) -> Annex v+withKeysReferenced initial = withKeysReferenced' Nothing initial {- Runs an action on each referenced key in the working tree. -} withKeysReferencedM :: (Key -> Annex ()) -> Annex ()
Database/Keys.hs view
@@ -342,6 +342,9 @@ , Param "--no-renames" -- Avoid other complications. , Param "--ignore-submodules=all"+ -- Avoid using external textconv command, which would be slow+ -- and possibly wrong.+ , Param "--no-textconv" , Param "--no-ext-diff" ]
Git/Queue.hs view
@@ -1,6 +1,6 @@ {- git repository command queue -- - Copyright 2010-2021 Joey Hess <id@joeyh.name>+ - Copyright 2010-2022 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -13,8 +13,8 @@ defaultTimelimit, addCommand, addUpdateIndex,- addInternalAction,- InternalActionRunner(..),+ addFlushAction,+ FlushActionRunner(..), size, full, flush,@@ -48,30 +48,34 @@ -- ^ parameters that come after the git subcommand , getFiles :: [CommandParam] } - {- An internal action to run, on a list of files that can be added- - to as the queue grows. -}- | InternalAction- { getRunner :: InternalActionRunner m- , getInternalFiles :: [(RawFilePath, IO Bool, FileSize)]+ {- A FlushAction can be added along with CommandActions or+ - UpdateIndexActions, and when the queue later gets flushed,+ - those will be run before the FlushAction is. -}+ | FlushAction+ { getFlushActionRunner :: FlushActionRunner m+ , getFlushActionFiles :: [(RawFilePath, IO Bool, FileSize)] } -{- The String must be unique for each internal action. -}-data InternalActionRunner m = InternalActionRunner String (Repo -> [(RawFilePath, IO Bool, FileSize)] -> m ())+{- The String must be unique for each flush action. -}+data FlushActionRunner m = FlushActionRunner String (Repo -> [(RawFilePath, IO Bool, FileSize)] -> m ()) -instance Eq (InternalActionRunner m) where- InternalActionRunner s1 _ == InternalActionRunner s2 _ = s1 == s2+instance Eq (FlushActionRunner m) where+ FlushActionRunner s1 _ == FlushActionRunner s2 _ = s1 == s2 -{- A key that can uniquely represent an action in a Map. -}+{- A key that can uniquely represent an action in a Map.+ -+ - The ordering controls what order the actions are run in when flushing+ - the queue. -} data ActionKey = UpdateIndexActionKey | CommandActionKey [CommandParam] String [CommandParam]- | InternalActionKey String+ | FlushActionKey String deriving (Eq, Ord) actionKey :: Action m -> ActionKey actionKey (UpdateIndexAction _) = UpdateIndexActionKey actionKey CommandAction { getCommonParams = c, getSubcommand = s, getParams = p } = CommandActionKey c s p-actionKey InternalAction { getRunner = InternalActionRunner s _ } = InternalActionKey s+actionKey FlushAction { getFlushActionRunner = FlushActionRunner s _ } = FlushActionKey s {- A queue of actions to perform (in any order) on a git repository, - with lists of files to perform them on. This allows coalescing @@ -120,7 +124,7 @@ -} addCommand :: MonadIO m => [CommandParam] -> String -> [CommandParam] -> [FilePath] -> Queue m -> Repo -> m (Queue m) addCommand commonparams subcommand params files q repo =- updateQueue action different (length files) q repo+ updateQueue action conflicting (length files) q repo where action = CommandAction { getCommonParams = commonparams@@ -129,36 +133,37 @@ , getFiles = map File files } - different (CommandAction { getSubcommand = s }) = s /= subcommand- different _ = True+ conflicting (CommandAction { getSubcommand = s }) = s /= subcommand+ conflicting (FlushAction {}) = False+ conflicting _ = True -{- Adds an internal action to the queue. -}-addInternalAction :: MonadIO m => InternalActionRunner m -> [(RawFilePath, IO Bool, FileSize)] -> Queue m -> Repo -> m (Queue m)-addInternalAction runner files q repo =- updateQueue action different (length files) q repo+{- Adds an flush action to the queue. This can co-exist with anything else+ - that gets added to the queue, and when the queue is eventually flushed,+ - it will be run after the other things in the queue. -}+addFlushAction :: MonadIO m => FlushActionRunner m -> [(RawFilePath, IO Bool, FileSize)] -> Queue m -> Repo -> m (Queue m)+addFlushAction runner files q repo =+ updateQueue action (const False) (length files) q repo where- action = InternalAction- { getRunner = runner- , getInternalFiles = files+ action = FlushAction+ { getFlushActionRunner = runner+ , getFlushActionFiles = files }- - different (InternalAction { getRunner = r }) = r /= runner- different _ = True {- Adds an update-index streamer to the queue. -} addUpdateIndex :: MonadIO m => Git.UpdateIndex.Streamer -> Queue m -> Repo -> m (Queue m) addUpdateIndex streamer q repo =- updateQueue action different 1 q repo+ updateQueue action conflicting 1 q repo where -- the list is built in reverse order action = UpdateIndexAction [streamer] - different (UpdateIndexAction _) = False- different _ = True+ conflicting (UpdateIndexAction _) = False+ conflicting (FlushAction {}) = False+ conflicting _ = True {- Updates or adds an action in the queue. -- - If the queue already contains a different action, it will be flushed+ - If the queue already contains a conflicting action, it will be flushed - before adding the action; this is to ensure that conflicting actions, - like add and rm, are run in the right order. -@@ -166,19 +171,19 @@ - and the action will be run right away. -} updateQueue :: MonadIO m => Action m -> (Action m -> Bool) -> Int -> Queue m -> Repo -> m (Queue m)-updateQueue !action different sizeincrease q repo = do+updateQueue !action conflicting sizeincrease q repo = do now <- liftIO getPOSIXTime if now - (_lastchanged q) > _timelimit q- then if isdifferent+ then if isconflicting then do q' <- flush q repo flush (mk q') repo else flush (mk q) repo- else if isdifferent+ else if isconflicting then mk <$> flush q repo else return $ mk (q { _lastchanged = now }) where- isdifferent = not (null (filter different (M.elems (items q))))+ isconflicting = not (null (filter conflicting (M.elems (items q)))) mk q' = newq where !newq = q'@@ -196,8 +201,8 @@ CommandAction cps2 sc2 ps2 (fs1++fs2) combineNewOld (UpdateIndexAction s1) (UpdateIndexAction s2) = UpdateIndexAction (s1++s2)-combineNewOld (InternalAction _r1 fs1) (InternalAction r2 fs2) =- InternalAction r2 (fs1++fs2)+combineNewOld (FlushAction _r1 fs1) (FlushAction r2 fs2) =+ FlushAction r2 (fs1++fs2) combineNewOld anew _aold = anew {- Merges the contents of the second queue into the first.@@ -257,6 +262,6 @@ forceSuccessProcess p pid go _ _ _ _ _ = error "internal" #endif-runAction repo action@(InternalAction {}) =- let InternalActionRunner _ runner = getRunner action- in runner repo (getInternalFiles action)+runAction repo action@(FlushAction {}) =+ let FlushActionRunner _ runner = getFlushActionRunner action+ in runner repo (getFlushActionFiles action)
Logs/Transitions.hs view
@@ -25,6 +25,7 @@ import qualified Data.Set as S import Data.Either+import Data.Char import Data.ByteString (ByteString) import Data.ByteString.Builder import qualified Data.ByteString.Lazy as L@@ -82,7 +83,7 @@ transitionLineParser :: A.Parser TransitionLine transitionLineParser = do- t <- (parsetransition <$> A.takeByteString)+ t <- parsetransition <$> A.takeTill (== sp) _ <- A8.char ' ' c <- vectorClockParser return $ TransitionLine c t@@ -90,6 +91,7 @@ parsetransition b = case readish (decodeBS b) of Just t -> Right t Nothing -> Left b+ sp = fromIntegral (ord ' ') combineTransitions :: [Transitions] -> Transitions combineTransitions = S.unions
NEWS view
@@ -1,3 +1,12 @@+git-annex (10.20220218) upstream; urgency=medium++ Transition notice: Commands like `git-annex get foo*` have changed to error+ out when some of files are not checked into the repository. To get back the+ previous behavior of silently skipping unknown files, use git config+ to set annex.skipunknown to true.++ -- Joey Hess <id@joeyh.name> Fri, 18 Feb 2022 13:12:21 -0400+ git-annex (8.20211028) upstream; urgency=medium This version of git-annex removes support for communicating with git-annex
Remote/Adb.hs view
@@ -307,11 +307,15 @@ -- won't recurse into the directory , File $ fromAndroidPath adir ++ "/" , Param "-type", Param "f"- , Param "-exec", Param "stat"- , Param "-c", Param statformat- , Param "{}", Param "+"+ , Param "-printf", Param "%p\\0" ] - (if ignorefinderror then "|| true" else "")+ (\s -> concat+ [ "set -o pipefail; "+ , s+ , "| xargs -0 stat -c " ++ shellEscape statformat ++ " --"+ , if ignorefinderror then " || true" else ""+ ]+ ) ignorefinderror = fromMaybe False (getRemoteConfigValue ignorefinderrorField c) @@ -399,11 +403,11 @@ -- -- Any stdout from the command is returned, separated into lines. adbShell :: AndroidSerial -> [CommandParam] -> Annex (Maybe [String])-adbShell serial cmd = adbShell' serial cmd ""+adbShell serial cmd = adbShell' serial cmd id -adbShell' :: AndroidSerial -> [CommandParam] -> String -> Annex (Maybe [String])-adbShell' serial cmd extra = adbShellRaw serial $- (unwords $ map shellEscape (toCommand cmd)) ++ extra+adbShell' :: AndroidSerial -> [CommandParam] -> (String -> String) -> Annex (Maybe [String])+adbShell' serial cmd f = adbShellRaw serial $+ f (unwords $ map shellEscape (toCommand cmd)) adbShellBool :: AndroidSerial -> [CommandParam] -> Annex Bool adbShellBool serial cmd =
Test.hs view
@@ -360,6 +360,7 @@ , testCase "union merge regression" test_union_merge_regression , testCase "adjusted branch merge regression" test_adjusted_branch_merge_regression , testCase "adjusted branch subtree regression" test_adjusted_branch_subtree_regression+ , testCase "transition propagation" test_transition_propagation_reversion , testCase "conflict resolution" test_conflict_resolution , testCase "conflict resolution (adjusted branch)" test_conflict_resolution_adjusted_branch , testCase "conflict resolution movein regression" test_conflict_resolution_movein_regression@@ -2051,3 +2052,38 @@ -- Make sure that import did not import the file to the top -- of the repo. checkdoesnotexist annexedfile++test_transition_propagation_reversion :: Assertion+test_transition_propagation_reversion =+ withtmpclonerepo $ \r1 ->+ withtmpclonerepo $ \r2 -> do+ pair r1 r2+ indir r1 $ do+ disconnectOrigin+ writecontent wormannexedfile $ content wormannexedfile+ git_annex "add" [wormannexedfile, "--backend=WORM"] "add"+ git_annex "sync" [] "sync"+ indir r2 $ do+ disconnectOrigin+ git_annex "sync" [] "sync"+ indir r1 $ do+ git_annex "sync" [] "sync"+ indir r2 $ do+ git_annex "get" [wormannexedfile] "get"+ git_annex "drop" [wormannexedfile] "drop"+ git_annex "get" [wormannexedfile] "get"+ git_annex "drop" [wormannexedfile] "drop"+ indir r1 $ do+ git_annex "drop" ["--force", wormannexedfile] "drop"+ git_annex "sync" [] "sync"+ git_annex "forget" ["--force"] "forget"+ git_annex "sync" [] "sync"+ emptylog+ indir r2 $ do+ git_annex "sync" [] "sync"+ emptylog+ indir r1 $ do+ git_annex "sync" [] "sync"+ emptylog+ where+ emptylog = git_annex_expectoutput "log" [wormannexedfile] []
Types/GitConfig.hs view
@@ -233,7 +233,7 @@ , annexCommitMode = if getbool (annexConfig "allowsign") False then ManualCommit else AutomaticCommit- , annexSkipUnknown = getbool (annexConfig "skipunknown") True+ , annexSkipUnknown = getbool (annexConfig "skipunknown") False , annexAdjustedBranchRefresh = fromMaybe -- parse as bool if it's not a number (if getbool "adjustedbranchrefresh" False then 1 else 0)
doc/git-annex-drop.mdwn view
@@ -45,7 +45,8 @@ * `--auto` Rather than trying to drop all specified files, drop only those that- are not preferred content of the repository.+ are not preferred content of the repository, and avoid trying to drop+ files when there are not enough other copies for the drop to be possible. See [[git-annex-preferred-content]](1) * `--force`
doc/git-annex-info.mdwn view
@@ -11,9 +11,9 @@ Displays statistics and other information for the specified item, which can be a directory, or a file, or a treeish, or a remote, or the description or uuid of a repository.- + When no item is specified, displays statistics and information-for the local repository and all known annexed files.+for the local repository and all annexed content. # OPTIONS @@ -45,11 +45,10 @@ Makes the `--batch` input be delimited by nulls instead of the usual newlines. -* file matching options+* matching options - When a directory is specified, the [[git-annex-matching-options]](1)- can be used to select the files in the directory that are included- in the statistics.+ The [[git-annex-matching-options]](1) can be used to select what+ to include in the statistics. * Also the [[git-annex-common-options]](1) can be used.
doc/git-annex-registerurl.mdwn view
@@ -37,6 +37,16 @@ (Note that for this to be used, you have to explicitly enable batch mode with `--batch`) +* `--json`++ Enable JSON output. This is intended to be parsed by programs that use+ git-annex. Each line of output is a JSON object.++* `--json-error-messages`++ Messages that would normally be output to standard error are included in+ the json instead.+ * Also the [[git-annex-common-options]](1) can be used. # SEE ALSO
doc/git-annex-unregisterurl.mdwn view
@@ -14,6 +14,9 @@ Unregistering a key's last web url will make git-annex no longer treat content as being present in the web special remote. +Normally the key is a git-annex formatted key. However, if the key cannot be+parsed as a key, and is a valid url, an URL key is constructed from the url.+ # OPTIONS * `--batch`@@ -25,6 +28,16 @@ When in batch mode, the input is delimited by nulls instead of the usual newlines.++* `--json`++ Enable JSON output. This is intended to be parsed by programs that use+ git-annex. Each line of output is a JSON object.++* `--json-error-messages`++ Messages that would normally be output to standard error are included in+ the json instead. * Also the [[git-annex-common-options]](1) can be used.
doc/git-annex.mdwn view
@@ -836,9 +836,7 @@ Set to false to make it an error for commands like "git-annex get" to be asked to operate on files that are not checked into git.-- The default is currently true, but is planned to change to false in a- release in 2022.+ (This is the default in recent versions of git-annex.) Note that, when annex.skipunknown is false, a command like "git-annex get ." will fail if no files in the current directory are checked into git,
git-annex.cabal view
@@ -1,5 +1,5 @@ Name: git-annex-Version: 10.20220127+Version: 10.20220222 Cabal-Version: >= 1.10 License: AGPL-3 Maintainer: Joey Hess <id@joeyh.name>