--batch-keys
authorJoey Hess <joeyh@joeyh.name>
Wed, 25 Aug 2021 18:20:33 +0000 (14:20 -0400)
committerJoey Hess <joeyh@joeyh.name>
Wed, 25 Aug 2021 18:21:12 +0000 (14:21 -0400)
New --batch-keys option added to these commands:  get, drop, move, copy, whereis

git-annex-matching-options had to be reworded since some of its options
can be used to match on keys, not only files.

Sponsored-by: Luke Shumaker on Patreon
33 files changed:
CHANGELOG
CmdLine/Batch.hs
Command/Add.hs
Command/AddUrl.hs
Command/CheckPresentKey.hs
Command/Copy.hs
Command/Drop.hs
Command/DropKey.hs
Command/Find.hs
Command/FromKey.hs
Command/Get.hs
Command/Info.hs
Command/MetaData.hs
Command/Move.hs
Command/ReKey.hs
Command/RegisterUrl.hs
Command/RmUrl.hs
Command/SetPresentKey.hs
Command/UnregisterUrl.hs
Command/Whereis.hs
doc/git-annex-copy.mdwn
doc/git-annex-drop.mdwn
doc/git-annex-find.mdwn
doc/git-annex-fsck.mdwn
doc/git-annex-get.mdwn
doc/git-annex-log.mdwn
doc/git-annex-matching-options.mdwn
doc/git-annex-metadata.mdwn
doc/git-annex-mirror.mdwn
doc/git-annex-move.mdwn
doc/git-annex-whereis.mdwn
doc/todo/git-annex-get_--batch_--key.mdwn
doc/todo/git-annex-get_--batch_--key/comment_5_c778976121cff4e1fbec3acd0cc70648._comment [new file with mode: 0644]

index 9b7d4cf377cd14491d68d71f42766a90d8606569..c59603ba6b723600d4b0096b855bf74a614e3a06 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,8 @@ git-annex (8.20210804) UNRELEASED; urgency=medium
   * unused: Skip the refs/annex/last-index ref that git-annex recently
     started creating.
   * Fix test suite failure on Windows.
+  * New --batch-keys option added to these commands: 
+    get, drop, move, copy, whereis
 
  -- Joey Hess <id@joeyh.name>  Tue, 03 Aug 2021 12:22:45 -0400
 
index 799f586e840eb8f81d37370c77087dcbfa7e181f..15fd89710e0638b26282dfce001ba2515207be1b 100644 (file)
@@ -1,6 +1,6 @@
 {- git-annex batch commands
  -
- - Copyright 2015-2020 Joey Hess <id@joeyh.name>
+ - Copyright 2015-2021 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -24,22 +24,42 @@ import Types.Concurrency
 
 data BatchMode = Batch BatchFormat | NoBatch
 
-data BatchFormat = BatchLine | BatchNull
+data BatchFormat = BatchFormat BatchSeparator BatchKeys
 
-parseBatchOption :: Parser BatchMode
-parseBatchOption = go 
+data BatchSeparator = BatchLine | BatchNull
+
+newtype BatchKeys = BatchKeys Bool
+
+parseBatchOption :: Bool -> Parser BatchMode
+parseBatchOption supportbatchkeysoption = go 
        <$> switch
                ( long "batch"
-               <> help "enable batch mode"
+               <> help batchhelp
                )
-       <*> switch
+       <*> batchkeysswitch
+       <*> flag BatchLine BatchNull
                ( short 'z'
                <> help "null delimited batch input"
                )
   where
-       go True False = Batch BatchLine
-       go True True = Batch BatchNull
-       go False _ = NoBatch
+       go True False batchseparator = 
+               Batch (BatchFormat batchseparator (BatchKeys False))
+       go _ True batchseparator = 
+               Batch (BatchFormat batchseparator (BatchKeys True))
+       go _ _ _ = NoBatch
+
+       batchhelp = "enable batch mode" ++
+               if supportbatchkeysoption
+                       then ", with files input"
+                       else ""
+       batchkeyshelp = "enable batch mode, with keys input"
+
+       batchkeysswitch
+               | supportbatchkeysoption = switch
+                       ( long "batch-keys"
+                       <> help batchkeyshelp
+                       )
+               | otherwise = pure False
 
 -- A batchable command can run in batch mode, or not.
 -- In batch mode, one line at a time is read, parsed, and a reply output to
@@ -52,7 +72,7 @@ batchable handler parser paramdesc = batchseeker <$> batchparser
   where
        batchparser = (,,)
                <$> parser
-               <*> parseBatchOption
+               <*> parseBatchOption False
                <*> cmdParams paramdesc
        
        batchseeker (opts, NoBatch, params) =
@@ -68,7 +88,7 @@ batchable handler parser paramdesc = batchseeker <$> batchparser
 -- mode, exit on bad input.
 batchBadInput :: BatchMode -> Annex ()
 batchBadInput NoBatch = liftIO exitFailure
-batchBadInput (Batch _) = liftIO $ putStrLn ""
+batchBadInput _ = liftIO $ putStrLn ""
 
 -- Reads lines of batch mode input, runs a parser, and passes the result
 -- to the action.
@@ -87,12 +107,12 @@ batchInput fmt parser a = go =<< batchLines fmt
        parseerr s = giveup $ "Batch input parse failure: " ++ s
 
 batchLines :: BatchFormat -> Annex [String]
-batchLines fmt = do
+batchLines (BatchFormat sep _) = do
        checkBatchConcurrency
        enableInteractiveBranchAccess
        liftIO $ splitter <$> getContents
   where
-       splitter = case fmt of
+       splitter = case sep of
                BatchLine -> lines
                BatchNull -> splitc '\0'
 
@@ -116,37 +136,76 @@ batchCommandStart :: CommandStart -> CommandStart
 batchCommandStart a = a >>= \case
        Just v -> return (Just v)
        Nothing -> do
-               batchBadInput (Batch BatchLine)
+               batchBadInput (Batch (BatchFormat BatchLine (BatchKeys False)))
                return Nothing
 
 -- Reads lines of batch input and passes the filepaths to a CommandStart
 -- to handle them.
 --
--- Absolute filepaths are converted to relative, because in non-batch
--- mode, that is done when CmdLine.Seek uses git ls-files.
---
 -- File matching options are checked, and non-matching files skipped.
-batchFilesMatching :: BatchFormat -> ((SeekInput, RawFilePath) -> CommandStart) -> Annex ()
-batchFilesMatching fmt a = do
+batchFiles :: BatchFormat -> ((SeekInput, RawFilePath) -> CommandStart) -> Annex ()
+batchFiles fmt a = batchFilesKeys fmt $ \(si, v) -> case v of
+       Right f -> a (si, f)
+       Left _k -> return Nothing
+
+batchFilesKeys :: BatchFormat -> ((SeekInput, Either Key RawFilePath) -> CommandStart) -> Annex ()
+batchFilesKeys fmt a = do
        matcher <- getMatcher
-       go $ \si f ->
-               let f' = toRawFilePath f
-               in ifM (matcher $ MatchingFile $ FileInfo f' f' Nothing)
-                       ( a (si, f')
-                       , return Nothing
-                       )
+       go $ \si v -> case v of
+               Right f -> 
+                       let f' = toRawFilePath f
+                       in ifM (matcher $ MatchingFile $ FileInfo f' f' Nothing)
+                               ( a (si, Right f')
+                               , return Nothing
+                               )
+               Left k -> a (si, Left k)
   where
-       go a' = batchInput fmt 
-               (Right . fromRawFilePath <$$> liftIO . relPathCwdToFile . toRawFilePath)
-               (batchCommandAction . uncurry a')
-
-batchAnnexedFilesMatching :: BatchFormat -> AnnexedFileSeeker -> Annex ()
-batchAnnexedFilesMatching fmt seeker = batchFilesMatching fmt $ \(si, bf) ->
-       flip whenAnnexed bf $ \f k -> 
-               case checkContentPresent seeker of
-                       Just v -> do
-                               present <- inAnnex k
-                               if present == v
-                                       then startAction seeker si f k
-                                       else return Nothing
-                       Nothing -> startAction seeker si f k
+       go a' = batchInput fmt parser (batchCommandAction . uncurry a')
+       parser = case fmt of
+               -- Absolute filepaths are converted to relative,
+               -- because in non-batch mode, that is done when
+               -- CmdLine.Seek uses git ls-files.
+               BatchFormat _ (BatchKeys False) -> 
+                       Right . Right . fromRawFilePath 
+                               <$$> liftIO . relPathCwdToFile . toRawFilePath
+               BatchFormat _ (BatchKeys True) -> \i ->
+                       pure $ case deserializeKey i of
+                               Just k -> Right (Left k)
+                               Nothing -> Left "not a valid key"
+
+batchAnnexedFiles :: BatchFormat -> AnnexedFileSeeker -> Annex ()
+batchAnnexedFiles fmt seeker = batchAnnexed fmt seeker (const (return Nothing))
+
+-- Reads lines of batch input and passes filepaths to the AnnexedFileSeeker
+-- to handle them. Or, with --batch-keys, passes keys to the keyaction.
+--
+-- Matching options are checked, and non-matching items skipped.
+batchAnnexed :: BatchFormat -> AnnexedFileSeeker -> ((SeekInput, Key, ActionItem) -> CommandStart) -> Annex ()
+batchAnnexed fmt seeker keyaction = do
+       matcher <- getMatcher
+       batchFilesKeys fmt $ \(si, v) ->
+               case v of
+                       Right bf -> flip whenAnnexed bf $ \f k ->
+                               checkpresent k $
+                                       startAction seeker si f k
+                       Left k -> ifM (matcher (MatchingInfo (mkinfo k)))
+                               ( checkpresent k $
+                                       keyaction (si, k, mkActionItem k)
+                               , return Nothing)
+  where
+       checkpresent k cont = case checkContentPresent seeker of
+               Just v -> do
+                       present <- inAnnex k
+                       if present == v
+                               then cont
+                               else return Nothing
+               Nothing -> cont
+       
+       mkinfo k = ProvidedInfo
+               { providedFilePath = Nothing
+               , providedKey = Just k
+               , providedFileSize = Nothing
+               , providedMimeType = Nothing
+               , providedMimeEncoding = Nothing
+               , providedLinkType = Nothing
+               }
index 9398865f74b0087aedc5ff7a7872b47c2c8d7e59..56495825dad027e42b01f1e56961c3546f853002 100644 (file)
@@ -50,7 +50,7 @@ data AddOptions = AddOptions
 optParser :: CmdParamsDesc -> Parser AddOptions
 optParser desc = AddOptions
        <$> cmdParams desc
-       <*> parseBatchOption
+       <*> parseBatchOption False
        <*> switch
                ( long "update"
                <> short 'u'
@@ -95,7 +95,7 @@ seek o = startConcurrency commandStages $ do
                Batch fmt
                        | updateOnly o ->
                                giveup "--update --batch is not supported"
-                       | otherwise -> batchFilesMatching fmt gofile
+                       | otherwise -> batchFiles fmt gofile
                NoBatch -> do
                        -- Avoid git ls-files complaining about files that
                        -- are not known to git yet, since this will add
index 70cc3239f96d8d543d053ff716fe40eb6dcb5faa..eb99119ac4291addc537ad216985233d2f2d58e1 100644 (file)
@@ -76,7 +76,7 @@ optParser desc = AddUrlOptions
                <> help "add a suffix to the filename"
                ))
        <*> parseDownloadOptions True
-       <*> parseBatchOption
+       <*> parseBatchOption False
        <*> switch
                ( long "with-files"
                <> help "parse batch mode lines of the form \"$url $file\""
index 1f6a554e85c97d957edf4894e6efab51a4323547..46211523bf556e2e11bf48c5def28b18b0679604 100644 (file)
@@ -26,7 +26,7 @@ data CheckPresentKeyOptions = CheckPresentKeyOptions
 optParser :: CmdParamsDesc -> Parser CheckPresentKeyOptions
 optParser desc = CheckPresentKeyOptions
        <$> cmdParams desc
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 seek :: CheckPresentKeyOptions -> CommandSeek
 seek o = case batchOption o of
index 15f2ea4f167b485c23a1b140beeee4129c17860a..a6ddf4f80f43e1532b7a9385f2c165ba452f493b 100644 (file)
@@ -33,7 +33,7 @@ optParser desc = CopyOptions
        <*> parseFromToHereOptions
        <*> optional (parseKeyOptions <|> parseFailedTransfersOption)
        <*> parseAutoOption
-       <*> parseBatchOption
+       <*> parseBatchOption True
 
 instance DeferredParseClass CopyOptions where
        finishParse v = CopyOptions
@@ -48,10 +48,10 @@ seek o = startConcurrency commandStages $ do
        case batchOption o of
                NoBatch -> withKeyOptions
                        (keyOptions o) (autoMode o) seeker
-                       (commandAction . Command.Move.startKey (fromToOptions o) Command.Move.RemoveNever)
+                       (commandAction . keyaction)
                        (withFilesInGitAnnex ww seeker)
                        =<< workTreeItems ww (copyFiles o)
-               Batch fmt -> batchAnnexedFilesMatching fmt seeker
+               Batch fmt -> batchAnnexed fmt seeker keyaction
   where
        ww = WarnUnmatchLsFiles
        
@@ -63,6 +63,7 @@ seek o = startConcurrency commandStages $ do
                        Left ToHere -> Just False
                , usesLocationLog = True
                }
+       keyaction = Command.Move.startKey (fromToOptions o) Command.Move.RemoveNever
 
 {- A copy is just a move that does not delete the source file.
  - However, auto mode avoids unnecessary copies, and avoids getting or
index b8c930f6f31ea3c1f3070559d7646983a5258577..a9a4314cac0566cdfd53e837bf744c35bc1e8220 100644 (file)
@@ -41,7 +41,7 @@ optParser desc = DropOptions
        <*> optional parseDropFromOption
        <*> parseAutoOption
        <*> optional parseKeyOptions
-       <*> parseBatchOption
+       <*> parseBatchOption True
 
 parseDropFromOption :: Parser (DeferredParse Remote)
 parseDropFromOption = parseRemoteOption <$> strOption
@@ -67,11 +67,11 @@ seek o = startConcurrency commandStages $ do
                , usesLocationLog = True
                }
        case batchOption o of
-               Batch fmt -> batchAnnexedFilesMatching fmt seeker
                NoBatch -> withKeyOptions (keyOptions o) (autoMode o) seeker
                        (commandAction . startKeys o from)
                        (withFilesInGitAnnex ww seeker)
                        =<< workTreeItems ww (dropFiles o)
+               Batch fmt -> batchAnnexed fmt seeker (startKeys o from)
   where
        ww = WarnUnmatchLsFiles
 
index ddc2bea5f67ef7790414d5930631917fc89bc61f..580c6f1c22dfb0475b29b151fda5c0a7fed2aefc 100644 (file)
@@ -27,7 +27,7 @@ data DropKeyOptions = DropKeyOptions
 optParser :: CmdParamsDesc -> Parser DropKeyOptions
 optParser desc = DropKeyOptions
        <$> cmdParams desc
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 seek :: DropKeyOptions -> CommandSeek
 seek o = do
index 96f1f3b8bc30b0998085689ea9731888ce417ec7..d89ff2b96714dee169f6922ef58bee5b468b4fcb 100644 (file)
@@ -39,7 +39,7 @@ optParser desc = FindOptions
        <$> cmdParams desc
        <*> optional parseFormatOption
        <*> optional parseBranchKeysOption
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 parseFormatOption :: Parser Utility.Format.Format
 parseFormatOption = 
@@ -69,7 +69,7 @@ seek o = do
                        (commandAction . startKeys o)
                        (withFilesInGitAnnex ww seeker)
                        =<< workTreeItems ww (findThese o)
-               Batch fmt -> batchAnnexedFilesMatching fmt seeker
+               Batch fmt -> batchAnnexedFiles fmt seeker
   where
        ww = WarnUnmatchLsFiles
 
index 16ff1693f4bb3db424418da621ed8d498869409d..e4591a184f303c8a5179183881583ee806cb3a25 100644 (file)
@@ -35,7 +35,7 @@ data FromKeyOptions = FromKeyOptions
 optParser :: CmdParamsDesc -> Parser FromKeyOptions
 optParser desc = FromKeyOptions
        <$> cmdParams desc
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 seek :: FromKeyOptions -> CommandSeek
 seek o = do
@@ -43,7 +43,7 @@ seek o = do
        case (batchOption o, keyFilePairs o) of
                (Batch fmt, _) -> seekBatch matcher fmt
                -- older way of enabling batch input, does not support BatchNull
-               (NoBatch, []) -> seekBatch matcher BatchLine
+               (NoBatch, []) -> seekBatch matcher (BatchFormat BatchLine (BatchKeys False))
                (NoBatch, ps) -> do
                        force <- Annex.getState Annex.force
                        withPairs (commandAction . start matcher force) ps
index f443c86bf380c502cdd940ed72433be90986c36a..eef40c4eb349c5db28c799a6da71e1825f9478df 100644 (file)
@@ -34,7 +34,7 @@ optParser desc = GetOptions
        <*> optional (parseRemoteOption <$> parseFromOption)
        <*> parseAutoOption
        <*> optional (parseIncompleteOption <|> parseKeyOptions <|> parseFailedTransfersOption)
-       <*> parseBatchOption
+       <*> parseBatchOption True
 
 seek :: GetOptions -> CommandSeek
 seek o = startConcurrency downloadStages $ do
@@ -49,7 +49,7 @@ seek o = startConcurrency downloadStages $ do
                        (commandAction . startKeys from)
                        (withFilesInGitAnnex ww seeker)
                        =<< workTreeItems ww (getFiles o)
-               Batch fmt -> batchAnnexedFilesMatching fmt seeker
+               Batch fmt -> batchAnnexed fmt seeker (startKeys from)
   where
        ww = WarnUnmatchLsFiles
 
index 2d97603e9be60cd3652dcae39d5a0beae319318d..f4ef0df8000e1e3450de015f5841c357c0593fca 100644 (file)
@@ -114,7 +114,7 @@ optParser desc = InfoOptions
                ( long "bytes"
                <> help "display file sizes in bytes"
                )
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 seek :: InfoOptions -> CommandSeek
 seek o = case batchOption o of
index 56c25df6caa2cc915103cc016f2668b4936be3e7..f2fd87ffbfa4cec8c73b03c5ea6818122a7cd0b4 100644 (file)
@@ -44,7 +44,7 @@ optParser desc = MetaDataOptions
        <$> cmdParams desc
        <*> ((Get <$> getopt) <|> (Set <$> some modopts) <|> pure GetAll)
        <*> optional parseKeyOptions
-       <*> parseBatchOption
+       <*> parseBatchOption False
   where
        getopt = option (eitherReader (mkMetaField . T.pack))
                ( long "get" <> short 'g' <> metavar paramField
index bff099dd2cf3aaeb6aac8c56cda94b6c5f98d1e2..781bdb6138877682485feb2b4ea12e63398032d9 100644 (file)
@@ -44,7 +44,7 @@ optParser desc = MoveOptions
        <*> parseFromToHereOptions
        <*> pure RemoveSafe
        <*> optional (parseKeyOptions <|> parseFailedTransfersOption)
-       <*> parseBatchOption
+       <*> parseBatchOption True
 
 instance DeferredParseClass MoveOptions where
        finishParse v = MoveOptions
@@ -61,10 +61,10 @@ seek :: MoveOptions -> CommandSeek
 seek o = startConcurrency stages $ do
        case batchOption o of
                NoBatch -> withKeyOptions (keyOptions o) False seeker
-                       (commandAction . startKey (fromToOptions o) (removeWhen o))
+                       (commandAction . keyaction)
                        (withFilesInGitAnnex ww seeker)
                        =<< workTreeItems ww (moveFiles o)
-               Batch fmt -> batchAnnexedFilesMatching fmt seeker
+               Batch fmt -> batchAnnexed fmt seeker keyaction
   where
        seeker = AnnexedFileSeeker
                { startAction = start (fromToOptions o) (removeWhen o)
@@ -78,6 +78,7 @@ seek o = startConcurrency stages $ do
                Right (FromRemote _) -> downloadStages
                Right (ToRemote _) -> commandStages
                Left ToHere -> downloadStages
+       keyaction = startKey (fromToOptions o) (removeWhen o)
        ww = WarnUnmatchLsFiles
 
 start :: FromToHereOptions -> RemoveWhen -> SeekInput -> RawFilePath -> Key -> CommandStart
index 077dd5a6286b2ee1708479bf53d69fce9172bd0f..ab2f9fa2411866f892fa80ae3752890d48ea8908 100644 (file)
@@ -33,7 +33,7 @@ data ReKeyOptions = ReKeyOptions
 optParser :: CmdParamsDesc -> Parser ReKeyOptions
 optParser desc = ReKeyOptions
        <$> cmdParams desc
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 -- Split on the last space, since a FilePath can contain whitespace,
 -- but a Key very rarely does.
index 583b170143800ed292c3e994b7a08fe9e7c9e01f..1ec953d02bd4f29ea7c2c2025c7fcbb3369cb717 100644 (file)
@@ -28,11 +28,12 @@ data RegisterUrlOptions = RegisterUrlOptions
 optParser :: CmdParamsDesc -> Parser RegisterUrlOptions
 optParser desc = RegisterUrlOptions
        <$> cmdParams desc
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 seek :: RegisterUrlOptions -> CommandSeek
 seek o = case (batchOption o, keyUrlPairs o) of
-       (Batch fmt, _) -> commandAction $ startMass setUrlPresent fmt
+       (Batch (BatchFormat sep _), _) ->
+               commandAction $ startMass setUrlPresent sep
        -- older way of enabling batch input, does not support BatchNull
        (NoBatch, []) -> commandAction $ startMass setUrlPresent BatchLine
        (NoBatch, ps) -> withWords (commandAction . start setUrlPresent) ps
@@ -46,14 +47,15 @@ start a (keyname:url:[]) =
        si = SeekInput [keyname, url]
 start _ _ = giveup "specify a key and an url"
 
-startMass :: (Key -> URLString -> Annex ()) -> BatchFormat -> CommandStart
-startMass a fmt = 
+startMass :: (Key -> URLString -> Annex ()) -> BatchSeparator -> CommandStart
+startMass a sep =
        starting "registerurl" (ActionItemOther (Just "stdin")) (SeekInput []) $
-               performMass a fmt
+               performMass a sep
 
-performMass :: (Key -> URLString -> Annex ()) -> BatchFormat -> CommandPerform
-performMass a fmt = go True =<< map (separate (== ' ')) <$> batchLines fmt
+performMass :: (Key -> URLString -> Annex ()) -> BatchSeparator -> CommandPerform
+performMass a sep = go True =<< map (separate (== ' ')) <$> batchLines fmt
   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
index 83092800f3bcfdf79e9e36be408fe9e74ec64d74..bd854f64a0fac61b7f19077fa404d39e1e8945e5 100644 (file)
@@ -25,7 +25,7 @@ data RmUrlOptions = RmUrlOptions
 optParser :: CmdParamsDesc -> Parser RmUrlOptions
 optParser desc = RmUrlOptions
        <$> cmdParams desc
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 seek :: RmUrlOptions -> CommandSeek
 seek o = case batchOption o of
index e90f38934811bf76156c5cd9f138e356de917890..50749886e60ba6396d5b9493c56b31d993e0882a 100644 (file)
@@ -26,7 +26,7 @@ data SetPresentKeyOptions = SetPresentKeyOptions
 optParser :: CmdParamsDesc -> Parser SetPresentKeyOptions
 optParser desc = SetPresentKeyOptions
        <$> cmdParams desc
-       <*> parseBatchOption
+       <*> parseBatchOption False
 
 seek :: SetPresentKeyOptions -> CommandSeek
 seek o = case batchOption o of
index 7d4d65beb79e9b943dce86179d1e8dcd0aeb355c..2e2dcc83aed7c161649128c865678b5bc065fdec 100644 (file)
@@ -21,7 +21,7 @@ cmd = command "unregisterurl"
 
 seek :: RegisterUrlOptions -> CommandSeek
 seek o = case (batchOption o, keyUrlPairs o) of
-       (Batch fmt, _) -> commandAction $ startMass unregisterUrl fmt
+       (Batch (BatchFormat sep _), _) -> commandAction $ startMass unregisterUrl sep
        (NoBatch, ps) -> withWords (commandAction . start unregisterUrl) ps
 
 unregisterUrl :: Key -> String -> Annex ()
index 81c297aad1e0d2825c42dcf929abaabe2854d0e0..58f26db1f1ba3f4547643142cb1534569d94719b 100644 (file)
@@ -39,7 +39,7 @@ optParser :: CmdParamsDesc -> Parser WhereisOptions
 optParser desc = WhereisOptions
        <$> cmdParams desc
        <*> optional parseKeyOptions
-       <*> parseBatchOption
+       <*> parseBatchOption True
        <*> optional parseFormatOption
 
 parseFormatOption :: Parser Utility.Format.Format
@@ -62,7 +62,7 @@ seek o = do
                                (commandAction . startKeys o m)
                                (withFilesInGitAnnex ww seeker)
                                =<< workTreeItems ww (whereisFiles o)
-               Batch fmt -> batchAnnexedFilesMatching fmt seeker
+               Batch fmt -> batchAnnexed fmt seeker (startKeys o m)
   where
        ww = WarnUnmatchLsFiles
 
index e77d9a508b36af9e8e682ab4cd4dd7ce78f40a36..5a4e805cdf2ecc755cc1175c2db48b844bdc14d1 100644 (file)
@@ -74,10 +74,10 @@ Paths of files or directories to operate on can be specified.
 
   Use this option to copy a specified key.
 
-* file matching options
+* matching options
 
   The [[git-annex-matching-options]](1)
-  can be used to specify files to copy.
+  can be used to specify what to copy.
 
 * `--batch`
 
@@ -93,10 +93,13 @@ Paths of files or directories to operate on can be specified.
   machine-parseable, you may want to use --json in combination with
   --batch.
 
+* `--batch-keys`
+
+  This is like `--batch` but the lines read from stdin are parsed as keys.
+
 * `-z`
 
-  Makes the `--batch` input be delimited by nulls instead of the usual
-  newlines.
+  Makes batch input be delimited by nulls instead of the usual newlines.
 
 * `--json`
 
index 23f0b70268ef7416a498e11c0ed20488542772f7..482aa9906c01dbf7794bbc23c865d3b5e3c316e6 100644 (file)
@@ -87,10 +87,10 @@ Paths of files or directories to drop can be specified.
   Note that this bypasses checking the .gitattributes annex.numcopies
   setting and required content settings.
 
-* file matching options
+* matching options
 
   The [[git-annex-matching-options]](1)
-  can be used to specify files to drop.
+  can be used to specify what to drop.
 
 * `--jobs=N` `-JN`
 
@@ -110,10 +110,17 @@ Paths of files or directories to drop can be specified.
   match specified matching options, or it is not an annexed file,
   a blank line is output in response instead.
 
+* `--batch-keys`
+
+  This is like `--batch` but the lines read from stdin are parsed as keys.
+
+  Note that this bypasses checking the .gitattributes annex.numcopies
+  setting and required content settings.
+
 * `-z`
 
-  Makes the `--batch` input be delimited by nulls instead of the usual
-  newlines.
+  Makes the batch input be delimited by nulls
+  instead of the usual newlines.
 
 * `--json`
 
index 2decd932b8dfd68d7b446f114646941b203b6a25..e8b5feead243aa2c0b86f6ed9ab940ef012ce96f 100644 (file)
@@ -72,6 +72,10 @@ finds files in the current directory and its subdirectories.
   or otherwise doesn't meet the matching options, an empty line
   will be output instead.
 
+* `--batch-keys`
+
+  This is like `--batch` but the lines read from stdin are parsed as keys.
+
 * `-z`
 
   Makes the `--batch` input be delimited by nulls instead of the usual
index edc0360487c7c5cb2fe6011de238311f4215902b..faa58aaa1c08857bf91ed026b4a871f27703cebf 100644 (file)
@@ -89,10 +89,10 @@ better format.
 
   Use this option to fsck a specified key.
   
-* file matching options
+* matching options
 
   The [[git-annex-matching-options]](1)
-  can be used to specify files to fsck.
+  can be used to control what to fsck.
 
 * `--jobs=N` `-JN`
 
index 44f4fba0ca41229073d447520091620dc450f724..8fe1ab6f3e1a01b479f4425e9781e6c5f3bb1192 100644 (file)
@@ -56,10 +56,10 @@ be specified.
   parallel. (Remotes with lower costs are still preferred over higher cost
   remotes.)
 
-* file matching options
+* matching options
  
   The [[git-annex-matching-options]](1)
-  can be used to specify files to get.
+  can be used to control what to get.
 
 * `--incomplete`
 
@@ -114,9 +114,13 @@ be specified.
   machine-parseable, you may want to use --json in combination with
   --batch.
 
+* `--batch-keys`
+
+  This is like `--batch` but the lines read from stdin are parsed as keys.
+
 * `-z`
 
-  Makes the `--batch` input be delimited by nulls instead of the usual
+  Makes batch input be delimited by nulls instead of the usual
   newlines.
 
 * `--json`
index 053b761ca482deefafd1cc9287c3b125bf24bb0c..68cf79fb18b0626f9da13368cdfb5fc3a2f9751c 100644 (file)
@@ -39,10 +39,10 @@ false, information may not have been committed to the branch yet.
 
   Generates output suitable for the `gource` visualization program.
 
-* file matching options
+* matching options
   
   The [[git-annex-matching-options]](1)
-  can be used to specify files to act on.
+  can be used to control what to act on.
 
 * `--all` `-A`
 
index a2670eb34b9f9941b5b1240bc2df3a9372432ce9..93172165ca3e3938c6d5a3544d1dbc0737a8284c 100644 (file)
@@ -1,11 +1,12 @@
 # NAME
 
-git-annex-matching-options - specifying files to act on
+git-annex-matching-options - specifying what to act on
 
 # DESCRIPTION
 
 Many git-annex commands support using these options to specify which
-files they act on.
+files they act on. Some of these options can also be used by commands to
+specify which keys they act on.
 
 Arbitrarily complicated expressions can be built using these options.
 For example:
@@ -58,8 +59,8 @@ in either of two repositories.
 
 * `--in=repository`
 
-  Matches only files that git-annex believes have their contents present
-  in a repository. Note that it does not check the repository to verify
+  Matches only when git-annex believes that the content is present in a
+  repository. Note that it does not check the repository to verify
   that it still has the content.
 
   The repository should be specified using the name of a configured remote,
@@ -68,8 +69,8 @@ in either of two repositories.
 
 * `--in=repository@{date}`
 
-  Matches files currently in the work tree whose content was present in
-  the repository on the given date.
+  Matches only when the content was present in a repository on the given
+  date.
 
   The date is specified in the same syntax documented in
   gitrevisions(7). Note that this uses the reflog, so dates far in the
@@ -81,13 +82,13 @@ in either of two repositories.
 
 * `--copies=number`
 
-  Matches only files that git-annex believes to have the specified number
+  Matches only when git-annex believes there are the specified number
   of copies, or more. Note that it does not check remotes to verify that
   the copies still exist.
 
 * `--copies=trustlevel:number`
 
-  Matches only files that git-annex believes have the specified number of
+  Matches only when git-annex believes there are the specified number of
   copies, on remotes with the specified trust level. For example,
   `--copies=trusted:2`
 
@@ -96,14 +97,14 @@ in either of two repositories.
 
 * `--copies=groupname:number`
 
-  Matches only files that git-annex believes have the specified number of
+  Matches only when git-annex believes there are the specified number of
   copies, on remotes in the specified group. For example,
   `--copies=archive:2`
 
 * `--lackingcopies=number`
 
-  Matches only files that git-annex believes need the specified number or 
-  more additional copies to be made in order to satisfy their numcopies
+  Matches only when git-annex beleives that the specified number or 
+  more additional copies to be made in order to satisfy numcopies
   settings.
 
 * `--approxlackingcopies=number`
@@ -113,23 +114,23 @@ in either of two repositories.
 
 * `--inbackend=name`
 
-  Matches only files whose content is stored using the specified key-value
+  Matches only when content is stored using the specified key-value
   backend.
 
 * `--securehash`
 
-  Matches only files whose content is hashed using a cryptographically
+  Matches only when content is hashed using a cryptographically
   secure function. 
 
 * `--inallgroup=groupname`
 
-  Matches only files that git-annex believes are present in all repositories
-  in the specified group.
+  Matches only when git-annex believes content is present in
+  all repositories in the specified group.
 
 * `--smallerthan=size`
 * `--largerthan=size`
 
-  Matches only files whose content is smaller than, or larger than the
+  Matches only when the content is is smaller than, or larger than the
   specified size.
 
   The size can be specified with any commonly used units, for example,
@@ -137,14 +138,14 @@ in either of two repositories.
 
 * `--metadata field=glob`
 
-  Matches only files that have a metadata field attached with a value that
+  Matches only when there is a metadata field attached with a value that
   matches the glob. The values of metadata fields are matched case
   insensitively.
 
 * `--metadata field<number` / `--metadata field>number`
 * `--metadata field<=number` / `--metadata field>=number`
 
-  Matches only files that have a metadata field attached with a value that
+  Matches only when there is a metadata field attached with a value that
   is a number and is less than or greater than the specified number.
 
   (Note that you will need to quote the second parameter to avoid
@@ -152,34 +153,34 @@ in either of two repositories.
 
 * `--want-get`
 
-  Matches files that the preferred content settings for the repository
-  make it want to get. Note that this will match even files that are
-  already present, unless limited with e.g., `--not --in .`
+  Matches only when the preferred content settings for the repository
+  make it want to get content. Note that this will match even when
+  the content is already present, unless limited with e.g., `--not --in .`
 
 * `--want-drop`
 
-  Matches files that the preferred content settings for the repository
-  make it want to drop. Note that this will match even files that have
-  already been dropped, unless limited with e.g., `--in .`
+  Matches only when the preferred content settings for the repository
+  make it want to drop content. Note that this will match even when
+  the content is not present, unless limited with e.g., `--in .`
 
-  Files that this matches will not necessarily be dropped by
+  Things that this matches will not necessarily be dropped by
   `git-annex drop --auto`. This does not check that there are enough copies
   to drop. Also the same content may be used by a file that is not wanted
   to be dropped.
 
 * `--accessedwithin=interval`
 
-  Matches files that were accessed recently, within the specified time
+  Matches when the content was accessed recently, within the specified time
   interval.
   
   The interval can be in the form "5m" or "1h" or "2d" or "1y", or a
   combination such as "1h5m".
 
-  So for example, `--accessedwithin=1d` matches files that have been
+  So for example, `--accessedwithin=1d` matches when the content was
   accessed within the past day.
 
   If the OS or filesystem does not support access times, this will not
-  match any files.
+  match anything.
 
 * `--unlocked`
 
@@ -220,8 +221,8 @@ in either of two repositories.
 
 * `--not`
 
-  Inverts the next matching option. For example, to only act on
-  files with less than 3 copies, use `--not --copies=3`
+  Inverts the next matching option. For example, to match
+  when there are less than 3 copies, use `--not --copies=3`
 
 * `--and`
 
index 811b62112828fb5562cbf7ce88a18e7623fe80ec..e5b8b1948ce2d1d90e34e67af042a92a38d85f1d 100644 (file)
@@ -82,10 +82,10 @@ the modified file.
   throughout the files in a directory. This option enables such recursive
   setting.
 
-* file matching options
+* matching options
  
   The [[git-annex-matching-options]](1)
-  can be used to specify files to act on.
+  can be used to control what to act on.
 
 * `--all` `-A`
 
@@ -159,7 +159,7 @@ the modified file.
 
        {"file":"foo","fields":{"author":[]}}
 
-  Note that file matching options do not affect the files that are
+  Note that matching options do not affect the files that are
   processed when in batch mode.
 
 * Also the [[git-annex-common-options]](1) can be used.
index b125050e3f6a2f2c158ed49917b1d4bf597d155e..688d0c3f08143f146375043b552d2b10ab8ab6ff 100644 (file)
@@ -63,10 +63,10 @@ contents. Use [[git-annex-sync]](1) for that.
 
   Operate on files that have recently failed to be transferred.
 
-* file matching options
+* matching options
 
   The [[git-annex-matching-options]](1)
-  can be used to specify files to mirror.
+  can be used to control what to mirror.
 
 * `--json`
 
index 5eeb7a3e268fcacdccd7f90425c6c8a3664fbb65..0fbea84d5887bedae75b369047ce9ad344581e3e 100644 (file)
@@ -74,10 +74,10 @@ Paths of files or directories to operate on can be specified.
   already has content. This can be faster, but might skip moving content
   to the remote in some cases.
 
-* file matching options
+* matching options
 
   The [[git-annex-matching-options]](1)
-  can be used to specify files to move.
+  can be used to control what to move.
 
 * `--batch`
 
@@ -93,10 +93,13 @@ Paths of files or directories to operate on can be specified.
   machine-parseable, you may want to use --json in combination with
   --batch.
 
+* `--batch-keys`
+
+  This is like `--batch` but the lines read from stdin are parsed as keys.
+
 * `-z`
 
-  Makes the `--batch` input be delimited by nulls instead of the usual
-  newlines.
+  Makes batch input be delimited by nulls instead of the usual newlines.
 
 * `--json`
 
index ee6bd89d7b0a98d6e998abb08f11283d48aa826c..032a9ee02b344b4fd9822dc1dd3f88713d4bda3a 100644 (file)
@@ -26,10 +26,10 @@ received from remotes.
 
 # OPTIONS
 
-* file matching options
+* matching options
   
   The [[git-annex-matching-options]](1)
-  can be used to specify files to act on.
+  can be used to control what to act on.
 
 * `--key=keyname`
 
@@ -53,12 +53,16 @@ received from remotes.
   its information displayed, and repeat.
 
   Note that if the file is not an annexed file, or does not match
-  specified file matching options, an empty line will be
+  specified matching options, an empty line will be
   output instead.
 
+* `--batch-keys`
+
+  This is like `--batch` but the lines read from stdin are parsed as keys.
+
 * `-z`
 
-  Makes the `--batch` input be delimited by nulls instead of the usual
+  Makes batch input be delimited by nulls instead of the usual
   newlines.
 
 * `--json`
index a54d5391021d21d6f4c8823f76c0381dcbe0a733..fd4966a0a1dd1ad89df61eae27a97e169304cf3c 100644 (file)
@@ -1,3 +1,3 @@
 Can git-annex-get be extended so that "git-annex-get --batch --key" fetches the keys (rather than filenames) given in the input?
 
-[[!tag needsthought]]
+> [[done]] --[[Joey]]
diff --git a/doc/todo/git-annex-get_--batch_--key/comment_5_c778976121cff4e1fbec3acd0cc70648._comment b/doc/todo/git-annex-get_--batch_--key/comment_5_c778976121cff4e1fbec3acd0cc70648._comment
new file mode 100644 (file)
index 0000000..43719f5
--- /dev/null
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2021-08-25T18:06:29Z"
+ content="""
+I've implemented --batch-keys for the commands: get, drop, move, copy, whereis
+
+That covers everything mentioned here except for dead, but that does not
+support --batch yet, so if batch mode is needed for it, it can just use
+--batch, not --batch-keys. However, after a recent change that makes
+dropping unused keys automatically mark them dead, I suspect there
+will not be a use case for that.
+
+Most of the other commands that use --batch don't make sense to support
+--batch-keys. Eg, add and find can't operate on keys, while 
+fromkey already operates on keys. About the only one that might is 
+rmurl, but it uses a custom batch format so would not be able to use the
+current --batch-keys implementation. If someone needs that or some other
+one, they can open a new todo.
+"""]]