packages feed

git-annex 6.20180926 → 6.20181011

raw patch · 106 files changed

+384/−289 lines, 106 files

Files

Annex/Export.hs view
@@ -12,9 +12,11 @@ import Types.Key import Types.Remote import qualified Git+import Config  import qualified Data.Map as M import Control.Applicative+import Data.Maybe import Prelude  -- An export includes both annexed files and files stored in git.@@ -40,6 +42,4 @@ 		}  exportTree :: RemoteConfig -> Bool-exportTree c = case M.lookup "exporttree" c of-	Just "yes" -> True-	_ -> False+exportTree c = fromMaybe False $ yesNo =<< M.lookup "exporttree" c
Annex/Url.hs view
@@ -59,8 +59,8 @@ 			-- it from accessing specific IP addresses. 			curlopts <- map Param . annexWebOptions <$> Annex.getGitConfig 			let urldownloader = if null curlopts-				then U.DownloadWithCurl curlopts-				else U.DownloadWithConduit+				then U.DownloadWithConduit+				else U.DownloadWithCurl curlopts 			manager <- liftIO $ U.newManager U.managerSettings 			return (urldownloader, manager) 		allowedaddrs -> do
Assistant/Threads/Exporter.hs view
@@ -64,6 +64,7 @@ 			Annex.changeState $ \st -> st { Annex.errcounter = 0 } 			start <- liftIO getCurrentTime 			void $ Command.Sync.seekExportContent rs+				=<< join Command.Sync.getCurrBranch 			-- Look at command error counter to see if the export 			-- didn't work. 			failed <- (> 0) <$> Annex.getState Annex.errcounter
Assistant/Upgrade.hs view
@@ -83,7 +83,7 @@   where 	go Nothing = debug ["Skipping redundant upgrade"] 	go (Just dest) = do-		liftAnnex $ setUrlPresent webUUID k u+		liftAnnex $ setUrlPresent k u 		hook <- asIO1 $ distributionDownloadComplete d dest cleanup 		modifyDaemonStatus_ $ \s -> s 			{ transferHook = M.insert k hook (transferHook s) }@@ -100,7 +100,7 @@ 		} 	cleanup = liftAnnex $ do 		lockContentForRemoval k removeAnnex-		setUrlMissing webUUID k u+		setUrlMissing k u 		logStatus k InfoMissing  {- Called once the download is done.
CHANGELOG view
@@ -1,3 +1,26 @@+git-annex (6.20181011) upstream; urgency=medium++  * sync: Warn when a remote's export is not updated to the current+    tree because export tracking is not configured.+  * Improve display when git config download from a http remote fails.+  * Added annex.jobs setting, which is like using the -J option.+  * Fix reversion in support of annex.web-options.+  * rmurl: Fix a case where removing the last url left git-annex thinking+    content was still present in the web special remote.+  * SETURLPRESENT, SETURIPRESENT, SETURLMISSING, and SETURIMISSING+    used to update the presence information of the external special remote+    that called them; this was not documented behavior and is no longer done.+  * export: Fix false positive in export conflict detection, that occurred+    when the same tree was exported by multiple clones.+  * Fix potential crash in exporttree database due to failure to honor+    uniqueness constraint.+  * Fix crash when exporttree is set to a bad value.+  * Linux standalone: Avoid using bundled cp before envionment is fully set up.+  * Added arm64 Linux standalone build.+  * Improved termux installation process.++ -- Joey Hess <id@joeyh.name>  Thu, 11 Oct 2018 13:41:10 -0400+ git-annex (6.20180926) upstream; urgency=medium    [ Joey Hess ]
CmdLine/Action.hs view
@@ -78,6 +78,9 @@ 	go NonConcurrent = run 	run = void $ includeCommandAction a +commandActions :: [CommandStart] -> Annex ()+commandActions = mapM_ commandAction+ {- Waits for any forked off command actions to finish.  -  - Merge together the cleanup actions of all the AnnexStates used by@@ -167,20 +170,32 @@ {- Do concurrent output when that has been requested. -} allowConcurrentOutput :: Annex a -> Annex a #ifdef WITH_CONCURRENTOUTPUT-allowConcurrentOutput a = go =<< Annex.getState Annex.concurrency+allowConcurrentOutput a = do+	fromcmdline <- Annex.getState Annex.concurrency+	fromgitcfg <- annexJobs <$> Annex.getGitConfig+	case (fromcmdline, fromgitcfg) of+		(NonConcurrent, NonConcurrent) -> a+		(Concurrent n, _) -> goconcurrent n+		(NonConcurrent, Concurrent n) -> do+			Annex.changeState $ +				\c -> c { Annex.concurrency = fromgitcfg }+			goconcurrent n   where-	go NonConcurrent = a-	go (Concurrent _) = ifM (liftIO concurrentOutputSupported)-		( Regions.displayConsoleRegions $-			goconcurrent True-		, goconcurrent False-		)-	goconcurrent b = bracket_ (setup b) cleanup a-	setup = setconcurrentenabled+	goconcurrent n = do+		c <- liftIO getNumCapabilities+		when (n > c) $+			liftIO $ setNumCapabilities n+		ifM (liftIO concurrentOutputSupported)+			( Regions.displayConsoleRegions $+				goconcurrent' True+			, goconcurrent' False+			)+	goconcurrent' b = bracket_ (setup b) cleanup a+	setup = setconcurrentoutputenabled 	cleanup = do 		finishCommandActions-		setconcurrentenabled False-	setconcurrentenabled b = Annex.changeState $ \s ->+		setconcurrentoutputenabled False+	setconcurrentoutputenabled b = Annex.changeState $ \s -> 		s { Annex.output = (Annex.output s) { concurrentOutputEnabled = b } } #else allowConcurrentOutput = id
CmdLine/GitAnnex/Options.hs view
@@ -13,7 +13,6 @@ #if ! MIN_VERSION_optparse_applicative(0,14,1) import Options.Applicative.Builder.Internal #endif-import Control.Concurrent import qualified Data.Map as M  import Annex.Common@@ -370,11 +369,7 @@ 			) 	]   where-	set n = do-		Annex.changeState $ \s -> s { Annex.concurrency = Concurrent n }-		c <- liftIO getNumCapabilities-		when (n > c) $-			liftIO $ setNumCapabilities n+	set n = Annex.changeState $ \s -> s { Annex.concurrency = Concurrent n }  timeLimitOption :: [GlobalOption] timeLimitOption = 
CmdLine/Seek.hs view
@@ -22,7 +22,6 @@ import Git.FilePath import qualified Limit import CmdLine.GitAnnex.Options-import CmdLine.Action import Logs.Location import Logs.Unused import Types.Transfer@@ -34,11 +33,11 @@ import Annex.InodeSentinal import qualified Database.Keys -withFilesInGit :: (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withFilesInGit :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withFilesInGit a l = seekActions $ prepFiltered a $ 	seekHelper LsFiles.inRepo l -withFilesInGitNonRecursive :: String -> (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withFilesInGitNonRecursive :: String -> (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withFilesInGitNonRecursive needforce a l = ifM (Annex.getState Annex.force) 	( withFilesInGit a l 	, if null l@@ -58,7 +57,7 @@ 				getfiles c ps 			_ -> giveup needforce -withFilesNotInGit :: Bool -> (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withFilesNotInGit :: Bool -> (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withFilesNotInGit skipdotfiles a l 	| skipdotfiles = do 		{- dotfiles are not acted on unless explicitly listed -}@@ -78,7 +77,7 @@ 	go fs = seekActions $ prepFiltered a $ 		return $ concat $ segmentPaths (map (\(WorkTreeItem f) -> f) l) fs -withFilesInRefs :: (FilePath -> Key -> CommandStart) -> [Git.Ref] -> CommandSeek+withFilesInRefs :: ((FilePath, Key) -> CommandSeek) -> [Git.Ref] -> CommandSeek withFilesInRefs a = mapM_ go   where 	go r = do	@@ -89,16 +88,17 @@ 			catKey (LsTree.sha i) >>= \case 				Nothing -> noop 				Just k -> whenM (matcher $ MatchingKey k) $-					commandAction $ a f k+					a (f, k) 		liftIO $ void cleanup -withPathContents :: ((FilePath, FilePath) -> CommandStart) -> CmdParams -> CommandSeek+withPathContents :: ((FilePath, FilePath) -> CommandSeek) -> CmdParams -> CommandSeek withPathContents a params = do 	matcher <- Limit.getMatcher 	forM_ params $ \p -> do 		fs <- liftIO $ get p-		forM fs $ \f -> whenM (checkmatch matcher f) $-			commandAction (a f)	+		forM fs $ \f ->+			whenM (checkmatch matcher f) $+				a f   where 	get p = ifM (isDirectory <$> getFileStatus p) 		( map (\f -> (f, makeRelative (parentDir p) f))@@ -110,24 +110,24 @@ 		, matchFile = relf 		} -withWords :: ([String] -> CommandStart) -> CmdParams -> CommandSeek+withWords :: ([String] -> CommandSeek) -> CmdParams -> CommandSeek withWords a params = seekActions $ return [a params] -withStrings :: (String -> CommandStart) -> CmdParams -> CommandSeek+withStrings :: (String -> CommandSeek) -> CmdParams -> CommandSeek withStrings a params = seekActions $ return $ map a params -withPairs :: ((String, String) -> CommandStart) -> CmdParams -> CommandSeek+withPairs :: ((String, String) -> CommandSeek) -> CmdParams -> CommandSeek withPairs a params = seekActions $ return $ map a $ pairs [] params   where 	pairs c [] = reverse c 	pairs c (x:y:xs) = pairs ((x,y):c) xs 	pairs _ _ = giveup "expected pairs" -withFilesToBeCommitted :: (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withFilesToBeCommitted :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withFilesToBeCommitted a l = seekActions $ prepFiltered a $ 	seekHelper LsFiles.stagedNotDeleted l -withFilesOldUnlocked :: (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withFilesOldUnlocked :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withFilesOldUnlocked = withFilesOldUnlocked' LsFiles.typeChanged  {- Unlocked files before v6 have changed type from a symlink to a regular file.@@ -135,7 +135,7 @@  - Furthermore, unlocked files used to be a git-annex symlink,  - not some other sort of symlink.  -}-withFilesOldUnlocked' :: ([FilePath] -> Git.Repo -> IO ([FilePath], IO Bool)) -> (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withFilesOldUnlocked' :: ([FilePath] -> Git.Repo -> IO ([FilePath], IO Bool)) -> (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withFilesOldUnlocked' typechanged a l = seekActions $ 	prepFiltered a unlockedfiles   where@@ -145,12 +145,12 @@ isOldUnlocked f = liftIO (notSymlink f) <&&>  	(isJust <$> catKeyFile f <||> isJust <$> catKeyFileHEAD f) -withFilesOldUnlockedToBeCommitted :: (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withFilesOldUnlockedToBeCommitted :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withFilesOldUnlockedToBeCommitted = withFilesOldUnlocked' LsFiles.typeChangedStaged  {- v6 unlocked pointer files that are staged, and whose content has not been  - modified-}-withUnmodifiedUnlockedPointers :: (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withUnmodifiedUnlockedPointers :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withUnmodifiedUnlockedPointers a l = seekActions $ 	prepFiltered a unlockedfiles   where@@ -163,17 +163,17 @@ 	Just k -> sameInodeCache f =<< Database.Keys.getInodeCaches k  {- Finds files that may be modified. -}-withFilesMaybeModified :: (FilePath -> CommandStart) -> [WorkTreeItem] -> CommandSeek+withFilesMaybeModified :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek withFilesMaybeModified a params = seekActions $ 	prepFiltered a $ seekHelper LsFiles.modified params -withKeys :: (Key -> CommandStart) -> CmdParams -> CommandSeek+withKeys :: (Key -> CommandSeek) -> CmdParams -> CommandSeek withKeys a l = seekActions $ return $ map (a . parse) l   where 	parse p = fromMaybe (giveup "bad key") $ file2key p -withNothing :: CommandStart -> CmdParams -> CommandSeek-withNothing a [] = seekActions $ return [a]+withNothing :: CommandSeek -> CmdParams -> CommandSeek+withNothing a [] = a withNothing _ _ = giveup "This command takes no parameters."  {- Handles the --all, --branch, --unused, --failed, --key, and@@ -183,11 +183,12 @@  - In a bare repo, --all is the default.  -  - Otherwise falls back to a regular CommandSeek action on- - whatever params were passed. -}+ - whatever params were passed.+ -} withKeyOptions  	:: Maybe KeyOptions 	-> Bool-	-> (Key -> ActionItem -> CommandStart)+	-> ((Key, ActionItem) -> CommandSeek) 	-> ([WorkTreeItem] -> CommandSeek) 	-> [WorkTreeItem] 	-> CommandSeek@@ -195,14 +196,14 @@   where 	mkkeyaction = do 		matcher <- Limit.getMatcher-		return $ \k i ->-			whenM (matcher $ MatchingKey k) $-				commandAction $ keyaction k i+		return $ \v ->+			whenM (matcher $ MatchingKey $ fst v) $+				keyaction v  withKeyOptions'  	:: Maybe KeyOptions 	-> Bool-	-> Annex (Key -> ActionItem -> Annex ())+	-> Annex ((Key, ActionItem) -> Annex ()) 	-> ([WorkTreeItem] -> CommandSeek) 	-> [WorkTreeItem] 	-> CommandSeek@@ -231,14 +232,14 @@ 		keyaction <- mkkeyaction 		ks <- getks 		forM_ ks $ checker >=> maybe noop -			(\k -> keyaction k (mkActionItem k))+			(\k -> keyaction (k, mkActionItem k)) 	runbranchkeys bs = do 		keyaction <- mkkeyaction 		forM_ bs $ \b -> do 			(l, cleanup) <- inRepo $ LsTree.lsTree b 			forM_ l $ \i -> do 				let bfp = mkActionItem $ BranchFilePath b (LsTree.file i)-				maybe noop (\k -> keyaction k bfp)+				maybe noop (\k -> keyaction (k, bfp)) 					=<< catKey (LsTree.sha i) 			unlessM (liftIO cleanup) $ 				error ("git ls-tree " ++ Git.fromRef b ++ " failed")@@ -247,18 +248,17 @@ 		rs <- remoteList 		ts <- concat <$> mapM (getFailedTransfers . Remote.uuid) rs 		forM_ ts $ \(t, i) ->-			keyaction (transferKey t) (mkActionItem (t, i))+			keyaction (transferKey t, mkActionItem (t, i)) -prepFiltered :: (FilePath -> CommandStart) -> Annex [FilePath] -> Annex [CommandStart]+prepFiltered :: (FilePath -> CommandSeek) -> Annex [FilePath] -> Annex [CommandSeek] prepFiltered a fs = do 	matcher <- Limit.getMatcher 	map (process matcher) <$> fs   where-	process matcher f = ifM (matcher $ MatchingFile $ FileInfo f f)-		( a f , return Nothing )+	process matcher f = whenM (matcher $ MatchingFile $ FileInfo f f) $ a f -seekActions :: Annex [CommandStart] -> Annex ()-seekActions gen = mapM_ commandAction =<< gen+seekActions :: Annex [CommandSeek] -> Annex ()+seekActions gen = sequence_ =<< gen  seekHelper :: ([FilePath] -> Git.Repo -> IO ([FilePath], IO Bool)) -> [WorkTreeItem] -> Annex [FilePath] seekHelper a l = inRepo $ \g ->
Command/Add.hs view
@@ -65,7 +65,7 @@ 			| otherwise -> batchFilesMatching fmt gofile 		NoBatch -> do 			l <- workTreeItems (addThese o)-			let go a = a gofile l+			let go a = a (commandAction . gofile) l 			unless (updateOnly o) $ 				go (withFilesNotInGit (not $ includeDotFiles o)) 			go withFilesMaybeModified
Command/AddUrl.hs view
@@ -233,7 +233,8 @@ 			(exists, samesize, url') <- checkexistssize key 			if exists && (samesize || relaxedOption (downloadOptions o)) 				then do-					setUrlPresent u key url'+					setUrlPresent key url'+					logChange key u InfoPresent 					next $ return True 				else do 					warning $ "while adding a new url to an already annexed file, " ++ if exists@@ -397,7 +398,8 @@   where 	go = do 		maybeShowJSON $ JSONChunk [("key", key2file key)]-		setUrlPresent u key url+		setUrlPresent key url+		logChange key u InfoPresent 		ifM (addAnnexedFile file key mtmp) 			( do 				when (isJust mtmp) $
Command/Commit.hs view
@@ -17,7 +17,7 @@ 	paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = next $ next $ do
Command/ConfigList.hs view
@@ -23,7 +23,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = do
Command/Copy.hs view
@@ -50,8 +50,8 @@ 		Batch fmt -> batchFilesMatching fmt go 		NoBatch -> withKeyOptions 			(keyOptions o) (autoMode o)-			(Command.Move.startKey (fromToOptions o) Command.Move.RemoveNever)-			(withFilesInGit go)+			(commandAction . Command.Move.startKey (fromToOptions o) Command.Move.RemoveNever)+			(withFilesInGit $ commandAction . go) 			=<< workTreeItems (copyFiles o)  {- A copy is just a move that does not delete the source file.
Command/Dead.hs view
@@ -29,7 +29,7 @@  seek :: DeadOptions -> CommandSeek seek (DeadRemotes rs) = trustCommand "dead" DeadTrusted rs-seek (DeadKeys ks) = seekActions $ pure $ map startKey ks+seek (DeadKeys ks) = commandActions $ map startKey ks  startKey :: Key -> CommandStart startKey key = do
Command/Describe.hs view
@@ -18,7 +18,7 @@ 	(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start (name:description) = do
Command/DiffDriver.hs view
@@ -19,7 +19,7 @@ 		("-- cmd --") (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start opts = do
Command/Direct.hs view
@@ -21,7 +21,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = ifM versionSupportsDirectMode
Command/Drop.hs view
@@ -56,8 +56,8 @@ 	case batchOption o of 		Batch fmt -> batchFilesMatching fmt go 		NoBatch -> withKeyOptions (keyOptions o) (autoMode o)-			(startKeys o)-			(withFilesInGit go)+			(commandAction . startKeys o)+			(withFilesInGit (commandAction . go)) 			=<< workTreeItems (dropFiles o)   where 	go = whenAnnexed $ start o@@ -84,8 +84,8 @@ 			| autoMode o = wantDrop False (Remote.uuid <$> from) (Just key) afile 			| otherwise = return True -startKeys :: DropOptions -> Key -> ActionItem -> CommandStart-startKeys o key = start' o key (AssociatedFile Nothing)+startKeys :: DropOptions -> (Key, ActionItem) -> CommandStart+startKeys o (key, ai) = start' o key (AssociatedFile Nothing) ai  startLocal :: AssociatedFile -> ActionItem -> NumCopies -> Key -> [VerifiedCopy] -> CommandStart startLocal afile ai numcopies key preverified = stopUnless (inAnnex key) $ do
Command/DropKey.hs view
@@ -33,7 +33,7 @@ seek o = do 	unlessM (Annex.getState Annex.force) $ 		giveup "dropkey can cause data loss; use --force if you're sure you want to do this"-	withKeys start (toDrop o)+	withKeys (commandAction . start) (toDrop o) 	case batchOption o of 		Batch fmt -> batchInput fmt parsekey $ batchCommandAction . start 		NoBatch -> noop
Command/EnableRemote.hs view
@@ -32,7 +32,7 @@ 	(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start [] = unknownNameError "Specify the remote to enable."
Command/EnableTor.hs view
@@ -36,7 +36,7 @@ 		"uid" (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  -- This runs as root, so avoid making any commits or initializing -- git-annex, or doing other things that create root-owned files.
Command/Expire.hs view
@@ -53,7 +53,7 @@ 	u <- getUUID 	us <- filter (/= u) . M.keys <$> uuidMap 	descs <- uuidMap-	seekActions $ pure $ map (start expire (noActOption o) actlog descs) us+	commandActions $ map (start expire (noActOption o) actlog descs) us  start :: Expire -> Bool -> Log Activity -> M.Map UUID String -> UUID -> CommandStart start (Expire expire) noact actlog descs u =
Command/Export.hs view
@@ -99,10 +99,12 @@ 	-- the next block of code below may have renamed some files to 	-- temp files. Diff from the incomplete tree to the new tree, 	-- and delete any temp files that the new tree can't use.+	let recover diff = commandAction $+		startRecoverIncomplete r ea db+			(Git.DiffTree.srcsha diff)+			(Git.DiffTree.file diff) 	forM_ (concatMap incompleteExportedTreeish old) $ \incomplete ->-		mapdiff (\diff -> startRecoverIncomplete r ea db (Git.DiffTree.srcsha diff) (Git.DiffTree.file diff))-			incomplete-			new+		mapdiff recover incomplete new  	-- Diff the old and new trees, and delete or rename to new name all 	-- changed files in the export. After this, every file that remains@@ -111,17 +113,18 @@ 	-- When there was an export conflict, this resolves it. 	-- 	-- The ExportTree is also updated here to reflect the new tree.-	case map exportedTreeish old of+	case nub (map exportedTreeish old) of 		[] -> updateExportTree db emptyTree new 		[oldtreesha] -> do 			diffmap <- mkDiffMap oldtreesha new db-			let seekdiffmap a = seekActions $ pure $ map a (M.toList diffmap)+			let seekdiffmap a = commandActions $ +				map a (M.toList diffmap) 			-- Rename old files to temp, or delete. 			seekdiffmap $ \(ek, (moldf, mnewf)) -> do 				case (moldf, mnewf) of 					(Just oldf, Just _newf) -> 						startMoveToTempName r ea db oldf ek-					(Just oldf, Nothing) -> +					(Just oldf, Nothing) -> 						startUnexport' r ea db oldf ek 					_ -> stop 			-- Rename from temp to new files.@@ -144,7 +147,7 @@ 				-- Don't rename to temp, because the 				-- content is unknown; delete instead. 				mapdiff-					(\diff -> startUnexport r ea db (Git.DiffTree.file diff) (unexportboth diff))+					(\diff -> commandAction $ startUnexport r ea db (Git.DiffTree.file diff) (unexportboth diff)) 					oldtreesha new 			updateExportTree db emptyTree new 	liftIO $ recordExportTreeCurrent db new@@ -194,7 +197,7 @@ fillExport r ea db new = do 	(l, cleanup) <- inRepo $ Git.LsTree.lsTree new 	cvar <- liftIO $ newMVar False-	seekActions $ pure $ map (startExport r ea db cvar) l+	commandActions $ map (startExport r ea db cvar) l 	void $ liftIO $ cleanup 	liftIO $ takeMVar cvar 
Command/Find.hs view
@@ -50,7 +50,8 @@  seek :: FindOptions -> CommandSeek seek o = case batchOption o of-	NoBatch -> withFilesInGit go =<< workTreeItems (findThese o)+	NoBatch -> withFilesInGit (commandAction . go)+		=<< workTreeItems (findThese o) 	Batch fmt -> batchFilesMatching fmt go   where 	go = whenAnnexed $ start o
Command/FindRef.hs view
@@ -18,4 +18,5 @@ 		paramRef (seek <$$> Find.optParser)  seek :: Find.FindOptions -> CommandSeek-seek o = Find.start o `withFilesInRefs` (map Git.Ref $ Find.findThese o)+seek o = (commandAction . uncurry (Find.start o))+	`withFilesInRefs` (map Git.Ref $ Find.findThese o)
Command/Fix.hs view
@@ -34,8 +34,9 @@ 		( return FixAll 		, return FixSymlinks 		)-	l <- workTreeItems ps-	flip withFilesInGit l $ whenAnnexed $ start fixwhat+	withFilesInGit+		(commandAction . (whenAnnexed $ start fixwhat))+		=<< workTreeItems ps  data FixWhat = FixSymlinks | FixAll 
Command/FromKey.hs view
@@ -35,12 +35,12 @@  seek :: FromKeyOptions -> CommandSeek seek o = case (batchOption o, keyFilePairs o) of-	(Batch fmt, _) -> withNothing (startMass fmt) []+	(Batch fmt, _) -> commandAction $ startMass fmt 	-- older way of enabling batch input, does not support BatchNull-	(NoBatch, []) -> withNothing (startMass BatchLine) []+	(NoBatch, []) -> commandAction $ startMass BatchLine 	(NoBatch, ps) -> do 		force <- Annex.getState Annex.force-		withPairs (start force) ps+		withPairs (commandAction . start force) ps  start :: Bool -> (String, FilePath) -> CommandStart start force (keyname, file) = do
Command/Fsck.hs view
@@ -94,8 +94,8 @@ 	checkDeadRepo u 	i <- prepIncremental u (incrementalOpt o) 	withKeyOptions (keyOptions o) False-		(\k ai -> startKey from i k ai =<< getNumCopies)-		(withFilesInGit $ whenAnnexed $ start from i)+		(\kai -> commandAction . startKey from i kai =<< getNumCopies)+		(withFilesInGit $ commandAction . (whenAnnexed (start from i))) 		=<< workTreeItems (fsckFiles o) 	cleanupIncremental i 	void $ tryIO $ recordActivity Fsck u@@ -183,8 +183,8 @@ 		) 	dummymeter _ = noop -startKey :: Maybe Remote -> Incremental -> Key -> ActionItem -> NumCopies -> CommandStart-startKey from inc key ai numcopies =+startKey :: Maybe Remote -> Incremental -> (Key, ActionItem) -> NumCopies -> CommandStart+startKey from inc (key, ai) numcopies = 	case Backend.maybeLookupBackendVariety (keyVariety key) of 		Nothing -> stop 		Just backend -> runFsck inc ai key $
Command/FuzzTest.hs view
@@ -26,7 +26,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = do
Command/GCryptSetup.hs view
@@ -19,7 +19,7 @@ 		paramValue (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withStrings start+seek = withStrings (commandAction . start)  start :: String -> CommandStart start gcryptid = next $ next $ do
Command/Get.hs view
@@ -44,8 +44,8 @@ 	case batchOption o of 		Batch fmt -> batchFilesMatching fmt go 		NoBatch -> withKeyOptions (keyOptions o) (autoMode o)-			(startKeys from)-			(withFilesInGit go)+			(commandAction . startKeys from)+			(withFilesInGit (commandAction . go)) 			=<< workTreeItems (getFiles o)  start :: GetOptions -> Maybe Remote -> FilePath -> Key -> CommandStart@@ -57,8 +57,8 @@ 			<||> wantGet False (Just key) afile 		| otherwise = return True -startKeys :: Maybe Remote -> Key -> ActionItem -> CommandStart-startKeys from key ai = checkFailedTransferDirection ai Download $+startKeys :: Maybe Remote -> (Key, ActionItem) -> CommandStart+startKeys from (key, ai) = checkFailedTransferDirection ai Download $ 	start' (return True) from key (AssociatedFile Nothing) ai  start' :: Annex Bool -> Maybe Remote -> Key -> AssociatedFile -> ActionItem -> CommandStart
Command/Group.hs view
@@ -19,7 +19,7 @@ 	(paramPair paramRemote paramDesc) (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start (name:g:[]) = do
Command/GroupWanted.hs view
@@ -18,7 +18,7 @@ 	(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start (g:[]) = next $ performGet groupPreferredContentMapRaw g
Command/Help.hs view
@@ -27,7 +27,7 @@ 	parseparams = withParams  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start params = do
Command/Import.hs view
@@ -73,7 +73,8 @@ 	unless (null inrepops) $ do 		giveup $ "cannot import files from inside the working tree (use git annex add instead): " ++ unwords inrepops 	largematcher <- largeFilesMatcher-	withPathContents (start largematcher (duplicateMode o)) (importFiles o)+	(commandAction . start largematcher (duplicateMode o))+		`withPathContents` importFiles o  start :: GetFileMatcher -> DuplicateMode -> (FilePath, FilePath) -> CommandStart start largematcher mode (srcfile, destfile) =
Command/ImportFeed.hs view
@@ -67,7 +67,7 @@ seek :: ImportFeedOptions -> CommandSeek seek o = do 	cache <- getCache (templateOption o)-	withStrings (start o cache) (feedUrls o)+	withStrings (commandAction . start o cache) (feedUrls o)  start :: ImportFeedOptions -> Cache -> URLString -> CommandStart start opts cache url = do
Command/InAnnex.hs view
@@ -18,7 +18,7 @@ 		(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withKeys start+seek = withKeys (commandAction . start)  start :: Key -> CommandStart start key = inAnnexSafe key >>= dispatch
Command/Indirect.hs view
@@ -27,7 +27,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = ifM isDirect
Command/Info.hs view
@@ -132,7 +132,7 @@  seek :: InfoOptions -> CommandSeek seek o = case batchOption o of-	NoBatch -> withWords (start o) (infoFor o)+	NoBatch -> withWords (commandAction . start o) (infoFor o) 	Batch fmt -> batchInput fmt Right (itemInfo o)  start :: InfoOptions -> [String] -> CommandStart
Command/InitRemote.hs view
@@ -24,7 +24,7 @@ 	(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start [] = giveup "Specify a name for the remote."
Command/Inprogress.hs view
@@ -38,7 +38,8 @@ 		then forM_ ts $ commandAction . start' 		else do 			let s = S.fromList ts-			withFilesInGit (whenAnnexed (start s))+			withFilesInGit+				(commandAction . (whenAnnexed (start s))) 				=<< workTreeItems (inprogressFiles o)  start :: S.Set Key -> FilePath -> Key -> CommandStart
Command/List.hs view
@@ -44,7 +44,8 @@ seek o = do 	list <- getList o 	printHeader list-	withFilesInGit (whenAnnexed $ start list)+	withFilesInGit+		(commandAction . (whenAnnexed $ start list)) 		=<< workTreeItems (listThese o)  getList :: ListOptions -> Annex [(UUID, RemoteName, TrustLevel)]
Command/Lock.hs view
@@ -32,10 +32,10 @@ seek ps = do 	l <- workTreeItems ps 	ifM versionSupportsUnlockedPointers-		( withFilesInGit (whenAnnexed startNew) l+		( withFilesInGit (commandAction . (whenAnnexed startNew)) l 		, do-			withFilesOldUnlocked startOld l-			withFilesOldUnlockedToBeCommitted startOld l+			withFilesOldUnlocked (commandAction . startOld) l+			withFilesOldUnlockedToBeCommitted (commandAction . startOld) l 		)  startNew :: FilePath -> Key -> CommandStart
Command/LockContent.hs view
@@ -20,7 +20,7 @@ 		(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  -- First, lock the content, then print out "OK".  -- Wait for the caller to send a line before dropping the lock.
Command/Log.hs view
@@ -91,7 +91,8 @@ 	zone <- liftIO getCurrentTimeZone 	let outputter = mkOutputter m zone o 	case (logFiles o, allOption o) of-		(fs, False) -> withFilesInGit (whenAnnexed $ start o outputter) +		(fs, False) -> withFilesInGit+			(commandAction . (whenAnnexed $ start o outputter))  			=<< workTreeItems fs 		([], True) -> commandAction (startAll o outputter) 		(_, True) -> giveup "Cannot specify both files and --all"
Command/Map.hs view
@@ -37,7 +37,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = do
Command/MetaData.hs view
@@ -80,8 +80,8 @@ 			Set _ -> withFilesInGitNonRecursive 				"Not recursively setting metadata. Use --force to do that." 		withKeyOptions (keyOptions o) False-			(startKeys c o)-			(seeker $ whenAnnexed $ start c o)+			(commandAction . startKeys c o)+			(seeker (commandAction . (whenAnnexed (start c o)))) 			=<< workTreeItems (forFiles o) 	Batch fmt -> withMessageState $ \s -> case outputType s of 		JSONOutput _ -> ifM limited@@ -92,12 +92,12 @@ 		_ -> giveup "--batch is currently only supported in --json mode"  start :: VectorClock -> MetaDataOptions -> FilePath -> Key -> CommandStart-start c o file k = startKeys c o k (mkActionItem afile)+start c o file k = startKeys c o (k, mkActionItem afile)   where 	afile = AssociatedFile (Just file) -startKeys :: VectorClock -> MetaDataOptions -> Key -> ActionItem -> CommandStart-startKeys c o k ai = case getSet o of+startKeys :: VectorClock -> MetaDataOptions -> (Key, ActionItem) -> CommandStart+startKeys c o (k, ai) = case getSet o of 	Get f -> do 		l <- S.toList . currentMetaDataValues f <$> getCurrentMetaData k 		liftIO $ forM_ l $
Command/Migrate.hs view
@@ -17,7 +17,6 @@ import qualified Annex import Logs.MetaData import Logs.Web-import qualified Remote  cmd :: Command cmd = notDirect $ withGlobalOptions [annexedMatchingOptions] $@@ -26,7 +25,7 @@ 		paramPaths (withParams seek)  seek :: CmdParams -> CommandSeek-seek ps = withFilesInGit (whenAnnexed start) =<< workTreeItems ps+seek = withFilesInGit (commandAction . (whenAnnexed start)) <=< workTreeItems  start :: FilePath -> Key -> CommandStart start file key = do@@ -78,9 +77,8 @@ 			-- If the old key had some associated urls, record them for 			-- the new key as well. 			urls <- getUrls oldkey-			forM_ urls $ \url -> do-				r <- Remote.claimingUrl url-				setUrlPresent (Remote.uuid r) newkey url+			forM_ urls $ \url ->+				setUrlPresent newkey url 			next $ Command.ReKey.cleanup file oldkey newkey 		, error "failed" 		)
Command/Mirror.hs view
@@ -43,17 +43,17 @@ seek :: MirrorOptions -> CommandSeek seek o = allowConcurrentOutput $  	withKeyOptions (keyOptions o) False-		(startKey o (AssociatedFile Nothing))-		(withFilesInGit $ whenAnnexed $ start o)+		(commandAction . startKey o (AssociatedFile Nothing))+		(withFilesInGit (commandAction . (whenAnnexed $ start o))) 		=<< workTreeItems (mirrorFiles o)  start :: MirrorOptions -> FilePath -> Key -> CommandStart-start o file k = startKey o afile k (mkActionItem afile)+start o file k = startKey o afile (k, mkActionItem afile)   where 	afile = AssociatedFile (Just file) -startKey :: MirrorOptions -> AssociatedFile -> Key -> ActionItem -> CommandStart-startKey o afile key ai = onlyActionOn key $ case fromToOptions o of+startKey :: MirrorOptions -> AssociatedFile -> (Key, ActionItem) -> CommandStart+startKey o afile (key, ai) = onlyActionOn key $ case fromToOptions o of 	ToRemote r -> checkFailedTransferDirection ai Upload $ ifM (inAnnex key) 		( Command.Move.toStart Command.Move.RemoveNever afile key ai =<< getParsed r 		, do
Command/Move.hs view
@@ -59,8 +59,8 @@ 	case batchOption o of 		Batch fmt -> batchFilesMatching fmt go 		NoBatch -> withKeyOptions (keyOptions o) False-			(startKey (fromToOptions o) (removeWhen o))-			(withFilesInGit go)+			(commandAction . startKey (fromToOptions o) (removeWhen o))+			(withFilesInGit (commandAction . go)) 			=<< workTreeItems (moveFiles o)  start :: FromToHereOptions -> RemoveWhen -> FilePath -> Key -> CommandStart@@ -69,8 +69,9 @@   where 	afile = AssociatedFile (Just f) -startKey :: FromToHereOptions -> RemoveWhen -> Key -> ActionItem -> CommandStart-startKey fromto removewhen = start' fromto removewhen (AssociatedFile Nothing)+startKey :: FromToHereOptions -> RemoveWhen -> (Key, ActionItem) -> CommandStart+startKey fromto removewhen = +	uncurry $ start' fromto removewhen (AssociatedFile Nothing)  start' :: FromToHereOptions -> RemoveWhen -> AssociatedFile -> Key -> ActionItem -> CommandStart start' fromto removewhen afile key ai = onlyActionOn key $
Command/NotifyChanges.hs view
@@ -21,7 +21,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = go =<< watchChangedRefs
Command/NumCopies.hs view
@@ -17,7 +17,7 @@ 	paramNumber (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start [] = startGet
Command/PreCommit.hs view
@@ -39,7 +39,7 @@ seek ps = lockPreCommitHook $ ifM isDirect 	( do 		-- update direct mode mappings for committed files-		withWords startDirect ps+		withWords (commandAction . startDirect) ps 		runAnnexHook preCommitAnnexHook 	, do 		ifM (not <$> versionSupportsUnlockedPointers <&&> liftIO Git.haveFalseIndex)@@ -51,14 +51,14 @@ 			, do 				l <- workTreeItems ps 				-- fix symlinks to files being committed-				flip withFilesToBeCommitted l $ \f -> +				flip withFilesToBeCommitted l $ \f -> commandAction $ 					maybe stop (Command.Fix.start Command.Fix.FixSymlinks f) 						=<< isAnnexLink f 				-- inject unlocked files into the annex 				-- (not needed when repo version uses 				-- unlocked pointer files) 				unlessM versionSupportsUnlockedPointers $-					withFilesOldUnlockedToBeCommitted startInjectUnlocked l+					withFilesOldUnlockedToBeCommitted (commandAction . startInjectUnlocked) l 			) 		runAnnexHook preCommitAnnexHook 		-- committing changes to a view updates metadata
Command/Proxy.hs view
@@ -27,7 +27,7 @@ 		("-- git command") (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start [] = giveup "Did not specify command to run."
Command/ReKey.hs view
@@ -50,7 +50,7 @@ seek :: ReKeyOptions -> CommandSeek seek o = case batchOption o of 	Batch fmt -> batchInput fmt batchParser (batchCommandAction . start)-	NoBatch -> withPairs (start . parsekey) (reKeyThese o)+	NoBatch -> withPairs (commandAction . start . parsekey) (reKeyThese o)   where 	parsekey (file, skey) = 		(file, fromMaybe (giveup "bad key") (file2key skey))
Command/ReadPresentKey.hs view
@@ -18,7 +18,7 @@ 		(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start (ks:us:[]) = do
Command/RecvKey.hs view
@@ -23,7 +23,7 @@ 	paramKey (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withKeys start+seek = withKeys (commandAction . start)  start :: Key -> CommandStart start key = fieldTransfer Download key $ \_p -> do
Command/RegisterUrl.hs view
@@ -33,10 +33,10 @@  seek :: RegisterUrlOptions -> CommandSeek seek o = case (batchOption o, keyUrlPairs o) of-	(Batch fmt, _) -> withNothing (startMass fmt) []+	(Batch fmt, _) -> commandAction $ startMass fmt 	-- older way of enabling batch input, does not support BatchNull-	(NoBatch, []) -> withNothing (startMass BatchLine) []-	(NoBatch, ps) -> withWords start ps+	(NoBatch, []) -> commandAction $ startMass BatchLine+	(NoBatch, ps) -> withWords (commandAction . start) ps  start :: [String] -> CommandStart start (keyname:url:[]) = do@@ -69,5 +69,5 @@ perform' :: Key -> URLString -> Annex Bool perform' key url = do 	r <- Remote.claimingUrl url-	setUrlPresent (Remote.uuid r) key (setDownloader' url r)+	setUrlPresent key (setDownloader' url r) 	return True
Command/Reinit.hs view
@@ -21,7 +21,7 @@ 		(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start ws = do
Command/Reinject.hs view
@@ -35,8 +35,8 @@  seek :: ReinjectOptions -> CommandSeek seek os-	| knownOpt os = withStrings startKnown (params os)-	| otherwise = withWords startSrcDest (params os)+	| knownOpt os = withStrings (commandAction . startKnown) (params os)+	| otherwise = withWords (commandAction . startSrcDest) (params os)  startSrcDest :: [FilePath] -> CommandStart startSrcDest (src:dest:[])
Command/Repair.hs view
@@ -22,7 +22,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = next $ next $ runRepair =<< Annex.getState Annex.force
Command/ResolveMerge.hs view
@@ -19,7 +19,7 @@ 	paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = do
Command/RmUrl.hs view
@@ -31,7 +31,7 @@ seek :: RmUrlOptions -> CommandSeek seek o = case batchOption o of 	Batch fmt -> batchInput fmt batchParser (batchCommandAction . start)-	NoBatch -> withPairs start (rmThese o)+	NoBatch -> withPairs (commandAction . start) (rmThese o)  -- Split on the last space, since a FilePath can contain whitespace, -- but a url should not.@@ -49,5 +49,5 @@ cleanup :: String -> Key -> CommandCleanup cleanup url key = do 	r <- Remote.claimingUrl url-	setUrlMissing (Remote.uuid r) key (setDownloader' url r)+	setUrlMissing key (setDownloader' url r) 	return True
Command/Schedule.hs view
@@ -20,7 +20,7 @@ 	(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start = parse
Command/SendKey.hs view
@@ -24,7 +24,7 @@ 		paramKey (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withKeys start+seek = withKeys (commandAction . start)  start :: Key -> CommandStart start key = do
Command/SetKey.hs view
@@ -17,7 +17,7 @@ 	(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start (keyname:file:[]) = do
Command/Status.hs view
@@ -37,7 +37,7 @@ 		))  seek :: StatusOptions -> CommandSeek-seek o = withWords (start o) (statusFiles o)+seek o = withWords (commandAction . start o) (statusFiles o) 	 start :: StatusOptions -> [FilePath] -> CommandStart start o locs = do
Command/Sync.hs view
@@ -189,7 +189,7 @@ 			 			whenM shouldsynccontent $ do 				syncedcontent <- seekSyncContent o dataremotes-				exportedcontent <- seekExportContent exportremotes+				exportedcontent <- withbranch $ seekExportContent exportremotes 				-- Transferring content can take a while, 				-- and other changes can be pushed to the 				-- git-annex branch on the remotes in the@@ -595,7 +595,7 @@   where 	seekworktree mvar l bloomfeeder = seekHelper LsFiles.inRepo l >>= 		mapM_ (\f -> ifAnnexed f (go (Right bloomfeeder) mvar (AssociatedFile (Just f))) noop)-	seekkeys mvar bloom k _ = go (Left bloom) mvar (AssociatedFile Nothing) k+	seekkeys mvar bloom (k, _) = go (Left bloom) mvar (AssociatedFile Nothing) k 	go ebloom mvar af k = commandAction $ do 		whenM (syncFile ebloom rs af k) $ 			void $ liftIO $ tryPutMVar mvar ()@@ -680,22 +680,39 @@  -   - Returns True if any file transfers were made.  -}-seekExportContent :: [Remote] -> Annex Bool-seekExportContent rs = or <$> forM rs go+seekExportContent :: [Remote] -> CurrBranch -> Annex Bool+seekExportContent rs (currbranch, _) = or <$> forM rs go   where 	go r = withExclusiveLock (gitAnnexExportLock (Remote.uuid r)) $ do 		db <- Export.openDb (Remote.uuid r) 		ea <- Remote.exportActions r 		exported <- case remoteAnnexExportTracking (Remote.gitconfig r) of-			Nothing -> getExport (Remote.uuid r)+			Nothing -> nontracking r 			Just b -> do 				mcur <- inRepo $ Git.Ref.tree b 				case mcur of-					Nothing -> getExport (Remote.uuid r)+					Nothing -> nontracking r 					Just cur -> do 						Command.Export.changeExport r ea db cur 						return [Exported cur []] 		Export.closeDb db `after` fillexport r ea db exported+		+	nontracking r = do+		exported <- getExport (Remote.uuid r)+		maybe noop (warnnontracking r exported) currbranch+		return exported+	+	warnnontracking r exported currb = inRepo (Git.Ref.tree currb) >>= \case+		Just currt | not (any (\ex -> exportedTreeish ex == currt) exported) ->+			showLongNote $ unwords+				[ "Not updating export to " ++ Remote.name r+				, "to reflect changes to the tree, because export"+				, "tracking is not enabled. "+				, "(Use git-annex export's --tracking option"+				, "to enable it.)"+				]+		_ -> noop+  	fillexport _ _ _ [] = return False 	fillexport r ea db (Exported { exportedTreeish = t }:[]) =
Command/TransferInfo.hs view
@@ -22,7 +22,7 @@ 		paramKey (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  {- Security:  - 
Command/TransferKey.hs view
@@ -42,7 +42,7 @@ 		<*> pure (fileOption v)  seek :: TransferKeyOptions -> CommandSeek-seek o = withKeys (start o) (keyOptions o)+seek o = withKeys (commandAction . start o) (keyOptions o)  start :: TransferKeyOptions -> Key -> CommandStart start o key = case fromToOptions o of
Command/TransferKeys.hs view
@@ -25,7 +25,7 @@ 	paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = do
Command/Trust.hs view
@@ -23,7 +23,7 @@ seek = trustCommand "trust" Trusted  trustCommand :: String -> TrustLevel -> CmdParams -> CommandSeek-trustCommand c level = withWords start+trustCommand c level = withWords (commandAction . start)   where 	start ws = do 		let name = unwords ws
Command/Unannex.hs view
@@ -31,7 +31,7 @@  seek :: CmdParams -> CommandSeek seek ps = wrapUnannex $ -	(withFilesInGit $ whenAnnexed start) =<< workTreeItems ps+	(withFilesInGit $ commandAction . whenAnnexed start) =<< workTreeItems ps  wrapUnannex :: Annex a -> Annex a wrapUnannex a = ifM (versionSupportsUnlockedPointers <||> isDirect)
Command/Undo.hs view
@@ -43,7 +43,7 @@ 	void $ Command.Sync.commitStaged Git.Branch.ManualCommit 		"commit before undo" 	-	withStrings start ps+	withStrings (commandAction . start) ps  start :: FilePath -> CommandStart start p = do
Command/Ungroup.hs view
@@ -19,7 +19,7 @@ 	(paramPair paramRemote paramDesc) (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start (name:g:[]) = do
Command/Uninit.hs view
@@ -41,9 +41,9 @@ seek :: CmdParams -> CommandSeek seek ps = do 	l <- workTreeItems ps-	withFilesNotInGit False (whenAnnexed startCheckIncomplete) l+	withFilesNotInGit False (commandAction . whenAnnexed startCheckIncomplete) l 	Annex.changeState $ \s -> s { Annex.fast = True }-	withFilesInGit (whenAnnexed Command.Unannex.start) l+	withFilesInGit (commandAction . whenAnnexed Command.Unannex.start) l 	finish  {- git annex symlinks that are not checked into git could be left by an
Command/Unlock.hs view
@@ -30,7 +30,7 @@ 		command n SectionCommon d paramPaths (withParams seek)  seek :: CmdParams -> CommandSeek-seek ps = withFilesInGit (whenAnnexed start) =<< workTreeItems ps+seek ps = withFilesInGit (commandAction . whenAnnexed start) =<< workTreeItems ps  {- Before v6, the unlock subcommand replaces the symlink with a copy of  - the file's content. In v6 and above, it converts the file from a symlink
Command/Unused.hs view
@@ -303,8 +303,7 @@ 	unusedtmp <- readUnusedMap "tmp" 	let m = unused `M.union` unusedbad `M.union` unusedtmp 	let unusedmaps = UnusedMaps unused unusedbad unusedtmp-	seekActions $ return $ map (a unusedmaps) $-		concatMap (unusedSpec m) params+	commandActions $ map (a unusedmaps) $ concatMap (unusedSpec m) params  unusedSpec :: UnusedMap -> String -> [Int] unusedSpec m spec
Command/Upgrade.hs view
@@ -19,7 +19,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = do
Command/VAdd.hs view
@@ -19,7 +19,7 @@ 		(withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start params = do
Command/VCycle.hs view
@@ -20,7 +20,7 @@ 		paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start ::CommandStart start = go =<< currentView
Command/VFilter.hs view
@@ -17,7 +17,7 @@ 		paramView (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start params = do
Command/VPop.hs view
@@ -21,7 +21,7 @@ 		paramNumber (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start ps = go =<< currentView
Command/Vicfg.hs view
@@ -37,7 +37,7 @@ 	paramNothing (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withNothing start+seek = withNothing (commandAction start)  start :: CommandStart start = do
Command/View.hs view
@@ -25,7 +25,7 @@ 		paramView (withParams seek)  seek :: CmdParams -> CommandSeek-seek = withWords start+seek = withWords (commandAction . start)  start :: [String] -> CommandStart start [] = giveup "Specify metadata to include in view"
Command/Wanted.hs view
@@ -30,7 +30,7 @@   where 	pdesc = paramPair paramRemote (paramOptional paramExpression) -	seek = withWords start+	seek = withWords (commandAction . start)  	start (rname:[]) = go rname (performGet getter) 	start (rname:expr:[]) = go rname $ \uuid -> do
Command/Whereis.hs view
@@ -43,17 +43,17 @@ 		Batch fmt -> batchFilesMatching fmt go 		NoBatch ->  			withKeyOptions (keyOptions o) False-				(startKeys m)-				(withFilesInGit go)+				(commandAction . startKeys m)+				(withFilesInGit (commandAction . go)) 				=<< workTreeItems (whereisFiles o)  start :: M.Map UUID Remote -> FilePath -> Key -> CommandStart-start remotemap file key = startKeys remotemap key (mkActionItem afile)+start remotemap file key = startKeys remotemap (key, mkActionItem afile)   where 	afile = AssociatedFile (Just file) -startKeys :: M.Map UUID Remote -> Key -> ActionItem -> CommandStart-startKeys remotemap key ai = do+startKeys :: M.Map UUID Remote -> (Key, ActionItem) -> CommandStart+startKeys remotemap (key, ai) = do 	showStartKey "whereis" key ai 	next $ perform remotemap key 
Config.hs view
@@ -102,3 +102,8 @@ setCrippledFileSystem b = do 	setConfig (annexConfig "crippledfilesystem") (Git.Config.boolConfig b) 	Annex.changeGitConfig $ \c -> c { annexCrippledFileSystem = b }++yesNo :: String -> Maybe Bool+yesNo "yes" = Just True+yesNo "no" = Just False+yesNo _ = Nothing
Database/Export.hs view
@@ -126,10 +126,10 @@ 	let edirs = map 		(\ed -> ExportedDirectory (toSFilePath (fromExportDirectory ed)) ef) 		(exportDirectories el)-#if MIN_VERSION_persistent(2,1,0)-	insertMany_ edirs+#if MIN_VERSION_persistent(2,8,1)+	putMany edirs #else-	void $ insertMany edirs+	mapM_ insertUnique edirs #endif   where 	ik = toIKey k@@ -208,7 +208,7 @@ 		| sha == nullSha = return Nothing 		| otherwise = Just <$> exportKey sha -updateExportTree' :: ExportHandle -> Maybe ExportKey -> Maybe ExportKey -> Git.DiffTree.DiffTreeItem-> Annex ()+updateExportTree' :: ExportHandle -> Maybe ExportKey -> Maybe ExportKey -> Git.DiffTree.DiffTreeItem -> Annex () updateExportTree' h srcek dstek i = do 	case srcek of 		Nothing -> return ()
Logs/Web.hs view
@@ -56,20 +56,32 @@ 	. map (fst . getDownloader) 	<$> getUrls key -setUrlPresent :: UUID -> Key -> URLString -> Annex ()-setUrlPresent uuid key url = do+setUrlPresent :: Key -> URLString -> Annex ()+setUrlPresent key url = do 	us <- getUrls key 	unless (url `elem` us) $ do 		config <- Annex.getGitConfig 		addLog (urlLogFile config key) =<< logNow InfoPresent url-	logChange key uuid InfoPresent+	-- If the url does not have an OtherDownloader, it must be present+	-- in the web.+	case snd (getDownloader url) of+		OtherDownloader -> return ()+		_ -> logChange key webUUID InfoPresent -setUrlMissing :: UUID -> Key -> URLString -> Annex ()-setUrlMissing uuid key url = do+setUrlMissing :: Key -> URLString -> Annex ()+setUrlMissing key url = do 	config <- Annex.getGitConfig 	addLog (urlLogFile config key) =<< logNow InfoMissing url-	whenM (null <$> getUrls key) $-		logChange key uuid InfoMissing+	-- If the url was a web url (not OtherDownloader) and none of+	-- the remaining urls for the key are web urls, the key must not+	-- be present in the web.+	when (isweb url) $+		whenM (null . filter isweb <$> getUrls key) $+			logChange key webUUID InfoMissing+  where+	isweb u = case snd (getDownloader u) of+		OtherDownloader -> False+		_ -> True  {- Finds all known urls. -} knownUrls :: Annex [(Key, URLString)]
Remote/BitTorrent.hs view
@@ -112,7 +112,7 @@  dropKey :: Key -> Annex Bool dropKey k = do-	mapM_ (setUrlMissing bitTorrentUUID k) =<< getBitTorrentUrls k+	mapM_ (setUrlMissing k) =<< getBitTorrentUrls k 	return True  {- We punt and don't try to check if a torrent has enough seeders
Remote/External.hs view
@@ -416,9 +416,9 @@ 			<$> getRemoteState (externalUUID external) key 		send $ VALUE state 	handleRemoteRequest (SETURLPRESENT key url) =-		setUrlPresent (externalUUID external) key url+		setUrlPresent key url 	handleRemoteRequest (SETURLMISSING key url) =-		setUrlMissing (externalUUID external) key url+		setUrlMissing key url 	handleRemoteRequest (SETURIPRESENT key uri) = 		withurl (SETURLPRESENT key) uri 	handleRemoteRequest (SETURIMISSING key uri) =
Remote/Git.hs view
@@ -254,7 +254,7 @@ 		v <- liftIO $ withTmpFile "git-annex.tmp" $ \tmpfile h -> do 			hClose h 			let url = Git.repoLocation r ++ "/config"-			ifM (Url.download nullMeterUpdate url tmpfile uo)+			ifM (Url.downloadQuiet nullMeterUpdate url tmpfile uo) 				( Just <$> pipedconfig "git" [Param "config", Param "--null", Param "--list", Param "--file", File tmpfile] 				, return Nothing 				)
Remote/Helper/Encryptable.hs view
@@ -25,6 +25,7 @@  import Annex.Common import Types.Remote+import Config import Crypto import Types.Crypto import qualified Annex@@ -128,11 +129,9 @@  - Not when a shared cipher is used.  -} embedCreds :: RemoteConfig -> Bool-embedCreds c-	| M.lookup "embedcreds" c == Just "yes" = True-	| M.lookup "embedcreds" c == Just "no" = False-	| isJust (M.lookup "cipherkeys" c) && isJust (M.lookup "cipher" c) = True-	| otherwise = False+embedCreds c = case yesNo =<< M.lookup "embedcreds" c of+	Just v -> v+	Nothing -> isJust (M.lookup "cipherkeys" c) && isJust (M.lookup "cipher" c)  {- Gets encryption Cipher, and key encryptor. -} cipherKey :: RemoteConfig -> RemoteGitConfig -> Annex (Maybe (Cipher, EncKey))
Remote/Helper/Export.hs view
@@ -17,6 +17,7 @@ import Remote.Helper.Encryptable (isEncrypted) import Database.Export import Annex.Export+import Config  import qualified Data.Map as M import Control.Concurrent.STM@@ -69,13 +70,16 @@ -- remote to be an export. adjustExportable :: Remote -> Annex Remote adjustExportable r = case M.lookup "exporttree" (config r) of-	Just "yes" -> ifM (isExportSupported r)-		( isexport-		, notexport-		) 	Nothing -> notexport-	Just "no" -> notexport-	Just _ -> error "bad exporttree value"+	Just c -> case yesNo c of+		Just True -> ifM (isExportSupported r)+			( isexport+			, notexport+			)+		Just False -> notexport+		Nothing -> do+			warning $ "bad exporttree value for " ++ name r ++ ", assuming not an export"+			notexport   where 	notexport = return $ r  		{ exportActions = exportUnsupported
Remote/Rsync.hs view
@@ -114,7 +114,7 @@ 	, rsyncOptions = transport ++ opts [] 	, rsyncUploadOptions = transport ++ opts (remoteAnnexRsyncUploadOptions gc) 	, rsyncDownloadOptions = transport ++ opts (remoteAnnexRsyncDownloadOptions gc)-	, rsyncShellEscape = M.lookup "shellescape" c /= Just "no"+	, rsyncShellEscape = (yesNo =<< M.lookup "shellescape" c) /= Just False 	}   where 	opts specificopts = map Param $ filter safe $
Remote/S3.hs view
@@ -195,7 +195,7 @@ 	void $ storeHelper info h f (T.pack $ bucketObject info k) p 	-- Store public URL to item in Internet Archive. 	when (isIA info && not (isChunkKey k)) $-		setUrlPresent webUUID k (iaPublicUrl info (bucketObject info k))+		setUrlPresent k (iaPublicUrl info (bucketObject info k)) 	return True  storeHelper :: S3Info -> S3Handle -> FilePath -> S3.Object -> MeterUpdate -> Annex (Maybe S3VersionID)@@ -605,9 +605,7 @@ 		, host = M.lookup "host" c 		}   where-	boolcfg k = case M.lookup k c of-		Just "yes" -> True-		_ -> False+	boolcfg k = fromMaybe False $ yesNo =<< M.lookup k c  putObject :: S3Info -> T.Text -> RequestBody -> S3.PutObject putObject info file rbody = (S3.putObject (bucket info) file rbody)
Remote/Tahoe.hs view
@@ -104,7 +104,7 @@ 	u <- maybe (liftIO genUUID) return mu 	configdir <- liftIO $ defaultTahoeConfigDir u 	scs <- liftIO $ tahoeConfigure configdir furl (M.lookup scsk c)-	let c' = if M.lookup "embedcreds" c == Just "yes"+	let c' = if (yesNo =<< M.lookup "embedcreds" c) == Just True 		then flip M.union c $ M.fromList 			[ (furlk, furl) 			, (scsk, scs)
Remote/Web.hs view
@@ -100,7 +100,7 @@  dropKey :: Key -> Annex Bool dropKey k = do-	mapM_ (setUrlMissing webUUID k) =<< getWebUrls k+	mapM_ (setUrlMissing k) =<< getWebUrls k 	return True  checkKey :: Key -> Annex Bool
Types/GitConfig.hs view
@@ -26,6 +26,7 @@ import Types.UUID import Types.Distribution import Types.Availability+import Types.Concurrency import Types.NumCopies import Types.Difference import Types.RefSpec@@ -99,6 +100,7 @@ 	, annexAllowedHttpAddresses :: String 	, annexAllowUnverifiedDownloads :: Bool 	, annexMaxExtensionLength :: Maybe Int+	, annexJobs :: Concurrency 	, coreSymlinks :: Bool 	, coreSharedRepository :: SharedRepository 	, receiveDenyCurrentBranch :: DenyCurrentBranch@@ -173,6 +175,7 @@ 	, annexAllowUnverifiedDownloads = (== Just "ACKTHPPT") $ 		getmaybe (annex "security.allow-unverified-downloads") 	, annexMaxExtensionLength = getmayberead (annex "maxextensionlength")+	, annexJobs = maybe NonConcurrent Concurrent $ getmayberead (annex "jobs") 	, coreSymlinks = getbool "core.symlinks" True 	, coreSharedRepository = getSharedRepository r 	, receiveDenyCurrentBranch = getDenyCurrentBranch r
Utility/Url.hs view
@@ -29,6 +29,7 @@ 	getUrlInfo, 	assumeUrlExists, 	download,+	downloadQuiet, 	sinkResponseFile, 	downloadPartial, 	parseURIRelaxed,@@ -139,19 +140,21 @@ 		] 	schemelist = map fromScheme $ S.toList $ allowedSchemes uo -checkPolicy :: UrlOptions -> URI -> a -> IO a -> IO a-checkPolicy uo u onerr a+checkPolicy :: UrlOptions -> URI -> a -> (String -> IO b) -> IO a -> IO a+checkPolicy uo u onerr displayerror a 	| allowedScheme uo u = a 	| otherwise = do-		hPutStrLn stderr $ +		void $ displayerror $ 			"Configuration does not allow accessing " ++ show u-		hFlush stderr 		return onerr -unsupportedUrlScheme :: URI -> IO ()-unsupportedUrlScheme u = do-	hPutStrLn stderr $ -		"Unsupported url scheme " ++ show u+unsupportedUrlScheme :: URI -> (String -> IO a) -> IO a+unsupportedUrlScheme u displayerror =+	displayerror $ "Unsupported url scheme " ++ show u++warnError :: String -> IO ()+warnError msg = do+	hPutStrLn stderr msg 	hFlush stderr  allowedScheme :: UrlOptions -> URI -> Bool@@ -192,15 +195,15 @@  - also returning its size and suggested filename if available. -} getUrlInfo :: URLString -> UrlOptions -> IO UrlInfo getUrlInfo url uo = case parseURIRelaxed url of-	Just u -> checkPolicy uo u dne $-		case (urlDownloader uo, parseUrlConduit (show u)) of+	Just u -> checkPolicy uo u dne warnError $+		case (urlDownloader uo, parseUrlRequest (show u)) of 			(DownloadWithConduit, Just req) -> 				existsconduit req 					`catchNonAsync` (const $ return dne) 			(DownloadWithConduit, Nothing) 				| isfileurl u -> existsfile u 				| otherwise -> do-					unsupportedUrlScheme u+					unsupportedUrlScheme u warnError 					return dne 			(DownloadWithCurl _, _)  				| isfileurl u -> existsfile u@@ -294,42 +297,46 @@  - Displays error message on stderr when download failed.  -} download :: MeterUpdate -> URLString -> FilePath -> UrlOptions -> IO Bool-download meterupdate url file uo =+download = download' False++{- Avoids displaying any error message. -}+downloadQuiet :: MeterUpdate -> URLString -> FilePath -> UrlOptions -> IO Bool+downloadQuiet = download' True++download' :: Bool -> MeterUpdate -> URLString -> FilePath -> UrlOptions -> IO Bool+download' noerror meterupdate url file uo = 	catchJust matchHttpException go showhttpexception-		`catchNonAsync` showerr+		`catchNonAsync` (dlfailed . show)   where 	go = case parseURIRelaxed url of-		Just u -> checkPolicy uo u False $-			case (urlDownloader uo, parseUrlConduit (show u)) of+		Just u -> checkPolicy uo u False dlfailed $+			case (urlDownloader uo, parseUrlRequest (show u)) of 				(DownloadWithConduit, Just req) -> 					downloadconduit req 				(DownloadWithConduit, Nothing) 					| isfileurl u -> downloadfile u-					| otherwise -> do-						unsupportedUrlScheme u-						return False+					| otherwise -> unsupportedUrlScheme u dlfailed 				(DownloadWithCurl _, _) 					| isfileurl u -> downloadfile u 					| otherwise -> downloadcurl 		Nothing -> do 			liftIO $ debugM "url" url-			hPutStrLn stderr "download failed: invalid url"-			return False+			dlfailed "invalid url" 	 	isfileurl u = uriScheme u == "file:"  	downloadconduit req = catchMaybeIO (getFileSize file) >>= \case 		Nothing -> runResourceT $ do 			liftIO $ debugM "url" (show req')-			resp <- http (applyRequest uo req') (httpManager uo)+			resp <- http req' (httpManager uo) 			if responseStatus resp == ok200 				then store zeroBytesProcessed WriteMode resp 				else showrespfailure resp 		Just sz -> resumeconduit req' sz 	  where-		-- Override http-client's default decompression of gzip-		-- compressed files. We want the unmodified file content.-		req' = req+		req' = applyRequest uo $ req+			-- Override http-client's default decompression of gzip+			-- compressed files. We want the unmodified file content. 			{ requestHeaders = (hAcceptEncoding, "identity") : 				filter ((/= hAcceptEncoding) . fst) 					(requestHeaders req)@@ -361,11 +368,8 @@ 					then store zeroBytesProcessed WriteMode resp 					else showrespfailure resp 	-	showrespfailure resp = liftIO $ do-		hPutStrLn stderr $ B8.toString $-			statusMessage $ responseStatus resp-		hFlush stderr-		return False+	showrespfailure = liftIO . dlfailed . B8.toString +		. statusMessage . responseStatus 	showhttpexception he = do #if MIN_VERSION_http_client(0,5,0) 		let msg = case he of@@ -383,13 +387,13 @@ 				B8.toString (statusMessage status) 			_ -> show he #endif-		hPutStrLn stderr $ "download failed: " ++ msg-		hFlush stderr-		return False-	showerr e = do-		hPutStrLn stderr (show e)-		hFlush stderr-		return False+		dlfailed msg+	dlfailed msg+		| noerror = return False+		| otherwise = do+			hPutStrLn stderr $ "download failed: " ++ msg+			hFlush stderr+			return False 	 	store initialp mode resp = do 		sinkResponseFile meterupdate initialp file mode resp@@ -401,13 +405,15 @@ 		unlessM (doesFileExist file) $ 			writeFile file "" 		let ps = curlParams uo-			[ Param "-sS"+			[ if noerror+				then Param "-S"+				else Param "-sS" 			, Param "-f" 			, Param "-L" 			, Param "-C", Param "-" 			] 		boolSystem "curl" (ps ++ [Param "-o", File file, File url])-					+	 	downloadfile u = do 		let src = unEscapeString (uriPath u) 		withMeteredFile src meterupdate $@@ -455,36 +461,23 @@ 	Nothing -> return Nothing 	Just u -> go u `catchNonAsync` const (return Nothing)   where-	go u = case parseUrlConduit (show u) of+	go u = case parseUrlRequest (show u) of 		Nothing -> return Nothing 		Just req -> do 			let req' = applyRequest uo req 			liftIO $ debugM "url" (show req') 			withResponse req' (httpManager uo) $ \resp -> 				if responseStatus resp == ok200-					then Just <$> brread n [] (responseBody resp)+					then Just <$> brReadSome (responseBody resp) n 					else return Nothing -	-- could use brReadSome here, needs newer http-client dependency-	brread n' l rb-		| n' <= 0 = return (L.fromChunks (reverse l))-		| otherwise = do-			bs <- brRead rb-			if B.null bs-				then return (L.fromChunks (reverse l))-				else brread (n' - B.length bs) (bs:l) rb- {- Allows for spaces and other stuff in urls, properly escaping them. -} parseURIRelaxed :: URLString -> Maybe URI parseURIRelaxed s = maybe (parseURIRelaxed' s) Just $ 	parseURI $ escapeURIString isAllowedInURI s -parseUrlConduit :: URLString -> Maybe Request-#if MIN_VERSION_http_client(0,4,30)-parseUrlConduit = parseUrlThrow-#else-parseUrlConduit = parseUrl-#endif+parseUrlRequest :: URLString -> Maybe Request+parseUrlRequest = parseUrlThrow  {- Some characters like '[' are allowed in eg, the address of  - an uri, but cannot appear unescaped further along in the uri.
doc/git-annex-export.mdwn view
@@ -43,7 +43,7 @@ that, it can be used as a key/value store and the limitations in the above paragraph do not appy. Note that dropping content from such a remote is not supported. See individual special remotes' documentation for-details of how to  enable such versioning.+details of how to enable such versioning.  # OPTIONS @@ -55,7 +55,11 @@    This makes the export track changes that are committed to   the branch. `git annex sync --content` and the git-annex assistant-  will update exports when it commits to the branch they are tracking.+  will update exports with commits made to the branch.++  This is a local configuration setting, similar to a git remote's tracking+  branch. You'll need to run `git annex export --tracking` in each+  repository you want the export to track.  * `--fast` 
doc/git-annex-metadata.mdwn view
@@ -23,11 +23,17 @@ automatically.  Note that the metadata is attached to the particular content of a file,-not to a particular filename on a particular git branch. -All files with the same content share the same metadata, which is+not to a particular filename on a particular git branch.  More precisely,+metadata is attached to the key used for the file, which can reflect+file contents and/or name, depending on the key-value backend used for the file.+All files with the same key share the same metadata, which is stored in the git-annex branch. If a file is edited, old-metadata will be copied to the new contents when you [[git-annex-add]]-the edited file. +metadata will be copied to the new key when you [[git-annex-add]]+the edited file.  Note also that changes to a file's git-annex metadata will+not be reflected in the git log of the file, since they are stored on the +git-annex branch. To attach metadata to a particular path,+rather than a particular key, use .gitattributes .+  # OPTIONS 
doc/git-annex-rmurl.mdwn view
@@ -10,6 +10,9 @@  Record that the file is no longer available at the url. +Removing the last url will make git-annex no longer treat content as being+present in the web special remote.+ # OPTIONS  * `--batch`
doc/git-annex.mdwn view
@@ -935,6 +935,13 @@   This controls which refs `git-annex unused` considers to be used.   See REFSPEC FORMAT in [[git-annex-unused]](1) for details. +* `annex.jobs++  Configure the number of concurrent jobs to run. Default is 1.++  Only git-annex commands that support the --jobs option will+  use this.+ * `annex.queuesize`    git-annex builds a queue of git commands, in order to combine similar
git-annex.cabal view
@@ -1,5 +1,5 @@ Name: git-annex-Version: 6.20180926+Version: 6.20181011 Cabal-Version: >= 1.8 License: GPL-3 Maintainer: Joey Hess <id@joeyh.name>