* Added an optional cost= configuration to all special remotes.
* adb: Support the remote.name.cost and remote.name.cost-command configs.
* findkeys: New command, very similar to git-annex find but operating on keys.
+ * move, copy: Support combining --from and --to in order to move/copy
+ the content of files that are in one remote to another remote.
-- Joey Hess <id@joeyh.name> Mon, 12 Dec 2022 13:04:54 -0400
{- git-annex command-line option parsing
-
- - Copyright 2010-2021 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2023 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
<> help "don't make changes, but show what would be done"
)
--- | From or To a remote.
+-- | From or To a remote but not both.
data FromToOptions
= FromRemote (DeferredParse Remote)
| ToRemote (DeferredParse Remote)
<> completeRemotes
)
--- | Like FromToOptions, but with a special --to=here
-type FromToHereOptions = Either ToHere FromToOptions
+-- | From or to a remote, or both, or a special --to=here
+data FromToHereOptions
+ = FromOrToRemote FromToOptions
+ | ToHere
+ | FromRemoteToRemote (DeferredParse Remote) (DeferredParse Remote)
-data ToHere = ToHere
-
-parseFromToHereOptions :: Parser FromToHereOptions
-parseFromToHereOptions = parsefrom <|> parseto
+parseFromToHereOptions :: Parser (Maybe FromToHereOptions)
+parseFromToHereOptions = go
+ <$> optional parseFromOption
+ <*> optional parseToOption
where
- parsefrom = Right . FromRemote . parseRemoteOption <$> parseFromOption
- parseto = herespecialcase <$> parseToOption
- where
- herespecialcase "here" = Left ToHere
- herespecialcase "." = Left ToHere
- herespecialcase n = Right $ ToRemote $ parseRemoteOption n
+ go (Just from) (Just to) = Just $ FromRemoteToRemote
+ (parseRemoteOption from)
+ (parseRemoteOption to)
+ go (Just from) Nothing = Just $ FromOrToRemote
+ (FromRemote $ parseRemoteOption from)
+ go Nothing (Just to) = Just $ case to of
+ "here" -> ToHere
+ "." -> ToHere
+ _ -> FromOrToRemote $ ToRemote $ parseRemoteOption to
+ go Nothing Nothing = Nothing
instance DeferredParseClass FromToHereOptions where
- finishParse = either (pure . Left) (Right <$$> finishParse)
+ finishParse (FromOrToRemote v) = FromOrToRemote <$> finishParse v
+ finishParse ToHere = pure ToHere
+ finishParse (FromRemoteToRemote v1 v2) = FromRemoteToRemote
+ <$> finishParse v1
+ <*> finishParse v2
-- Options for acting on keys, rather than work tree files.
data KeyOptions
{- git-annex command
-
- - Copyright 2010 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2023 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
data CopyOptions = CopyOptions
{ copyFiles :: CmdParams
- , fromToOptions :: FromToHereOptions
+ , fromToOptions :: Maybe FromToHereOptions
, keyOptions :: Maybe KeyOptions
, autoMode :: Bool
, batchOption :: BatchMode
instance DeferredParseClass CopyOptions where
finishParse v = CopyOptions
<$> pure (copyFiles v)
- <*> finishParse (fromToOptions v)
+ <*> maybe (pure Nothing) (Just <$$> finishParse)
+ (fromToOptions v)
<*> pure (keyOptions v)
<*> pure (autoMode v)
<*> pure (batchOption v)
seek :: CopyOptions -> CommandSeek
-seek o = startConcurrency commandStages $ do
+seek o = case fromToOptions o of
+ Just fto -> seek' o fto
+ Nothing -> giveup "Specify --from or --to"
+
+seek' :: CopyOptions -> FromToHereOptions -> CommandSeek
+seek' o fto = startConcurrency commandStages $ do
case batchOption o of
NoBatch -> withKeyOptions
(keyOptions o) (autoMode o) seeker
ww = WarnUnmatchLsFiles
seeker = AnnexedFileSeeker
- { startAction = start o
- , checkContentPresent = case fromToOptions o of
- Right (FromRemote _) -> Just False
- Right (ToRemote _) -> Just True
- Left ToHere -> Just False
+ { startAction = start o fto
+ , checkContentPresent = case fto of
+ FromOrToRemote (FromRemote _) -> Just False
+ FromOrToRemote (ToRemote _) -> Just True
+ ToHere -> Just False
+ FromRemoteToRemote _ _ -> Just False
, usesLocationLog = True
}
- keyaction = Command.Move.startKey (fromToOptions o) Command.Move.RemoveNever
+ keyaction = Command.Move.startKey fto 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
- sending non-preferred content. -}
-start :: CopyOptions -> SeekInput -> RawFilePath -> Key -> CommandStart
-start o si file key = stopUnless shouldCopy $
- Command.Move.start (fromToOptions o) Command.Move.RemoveNever si file key
+start :: CopyOptions -> FromToHereOptions -> SeekInput -> RawFilePath -> Key -> CommandStart
+start o fto si file key = stopUnless shouldCopy $
+ Command.Move.start fto Command.Move.RemoveNever si file key
where
shouldCopy
| autoMode o = want <||> numCopiesCheck file key (<)
| otherwise = return True
- want = case fromToOptions o of
- Right (ToRemote dest) ->
+ want = case fto of
+ FromOrToRemote (ToRemote dest) ->
+ (Remote.uuid <$> getParsed dest) >>= checkwantsend
+ FromOrToRemote (FromRemote _) -> checkwantget
+ ToHere -> checkwantget
+ FromRemoteToRemote _ dest ->
(Remote.uuid <$> getParsed dest) >>= checkwantsend
- Right (FromRemote _) -> checkwantget
- Left ToHere -> checkwantget
checkwantsend = wantGetBy False (Just key) (AssociatedFile (Just file))
checkwantget = wantGet False (Just key) (AssociatedFile (Just file))
{- git-annex command
-
- - Copyright 2010-2022 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2023 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
data MoveOptions = MoveOptions
{ moveFiles :: CmdParams
- , fromToOptions :: FromToHereOptions
+ , fromToOptions :: Maybe FromToHereOptions
, removeWhen :: RemoveWhen
, keyOptions :: Maybe KeyOptions
, batchOption :: BatchMode
instance DeferredParseClass MoveOptions where
finishParse v = MoveOptions
<$> pure (moveFiles v)
- <*> finishParse (fromToOptions v)
+ <*> maybe (pure Nothing) (Just <$$> finishParse)
+ (fromToOptions v)
<*> pure (removeWhen v)
<*> pure (keyOptions v)
<*> pure (batchOption v)
deriving (Show, Eq)
seek :: MoveOptions -> CommandSeek
-seek o = startConcurrency stages $ do
+seek o = case fromToOptions o of
+ Just fto -> seek' o fto
+ Nothing -> giveup "Specify --from or --to"
+
+seek' :: MoveOptions -> FromToHereOptions -> CommandSeek
+seek' o fto = startConcurrency stages $ do
case batchOption o of
NoBatch -> withKeyOptions (keyOptions o) False seeker
(commandAction . keyaction)
batchAnnexed fmt seeker keyaction
where
seeker = AnnexedFileSeeker
- { startAction = start (fromToOptions o) (removeWhen o)
- , checkContentPresent = case fromToOptions o of
- Right (FromRemote _) -> Nothing
- Right (ToRemote _) -> Just True
- Left ToHere -> Nothing
+ { startAction = start fto (removeWhen o)
+ , checkContentPresent = case fto of
+ FromOrToRemote (FromRemote _) -> Nothing
+ FromOrToRemote (ToRemote _) -> Just True
+ ToHere -> Nothing
+ FromRemoteToRemote _ _ -> Nothing
, usesLocationLog = True
}
- stages = case fromToOptions o of
- Right (FromRemote _) -> downloadStages
- Right (ToRemote _) -> commandStages
- Left ToHere -> downloadStages
- keyaction = startKey (fromToOptions o) (removeWhen o)
+ stages = case fto of
+ FromOrToRemote (FromRemote _) -> downloadStages
+ FromOrToRemote (ToRemote _) -> commandStages
+ ToHere -> downloadStages
+ FromRemoteToRemote _ _ -> commandStages
+ keyaction = startKey fto (removeWhen o)
ww = WarnUnmatchLsFiles
start :: FromToHereOptions -> RemoveWhen -> SeekInput -> RawFilePath -> Key -> CommandStart
start' :: FromToHereOptions -> RemoveWhen -> AssociatedFile -> SeekInput -> Key -> ActionItem -> CommandStart
start' fromto removewhen afile si key ai =
case fromto of
- Right (FromRemote src) ->
+ FromOrToRemote (FromRemote src) ->
checkFailedTransferDirection ai Download $
fromStart removewhen afile key ai si =<< getParsed src
- Right (ToRemote dest) ->
+ FromOrToRemote (ToRemote dest) ->
checkFailedTransferDirection ai Upload $
toStart removewhen afile key ai si =<< getParsed dest
- Left ToHere ->
+ ToHere ->
checkFailedTransferDirection ai Download $
toHereStart removewhen afile key ai si
Copy the content of files from all reachable remotes to the local
repository.
+* `--from=remote1 --to=remote2`
+
+ Copy the content of files that are in remote1 to remote2. Does not change
+ what is stored in the local repository.
+
+ Note: This may need to store an intermediate copy of the content on disk.
+
* `--jobs=N` `-JN`
Enables parallel transfers with up to the specified number of jobs
Move the content of files from all reachable remotes to the local
repository.
+* `--from=remote1 --to=remote2`
+
+ Move the content of files that are in remote1 to remote2. Does not change
+ what is stored in the local repository.
+
+ Note: This may need to store an intermediate copy of the content on disk.
+
* `--force`
Override numcopies and required content checking, and always remove