packages feed

git-annex 10.20220127 → 10.20220222

raw patch · 23 files changed

+299/−168 lines, 23 files

Files

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>