git-annex/Command/Move.hs

167 lines
5.1 KiB
Haskell
Raw Normal View History

{- git-annex command
-
2013-07-03 17:55:50 +00:00
- Copyright 2010-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Command.Move where
2011-10-05 20:02:51 +00:00
import Common.Annex
import Command
2010-11-11 22:54:52 +00:00
import qualified Command.Drop
import qualified Annex
2011-10-04 04:40:47 +00:00
import Annex.Content
import qualified Remote
import Annex.UUID
import Annex.Transfer
import Logs.Presence
def :: [Command]
2013-07-03 17:55:50 +00:00
def = [withOptions moveOptions $ command "move" paramPaths seek
SectionCommon "move content of files to/from another repository"]
2013-07-03 17:55:50 +00:00
moveOptions :: [Option]
moveOptions = fromToOptions ++ keyOptions
seek :: CommandSeek
seek ps = do
to <- getOptionField toOption Remote.byNameWithUUID
from <- getOptionField fromOption Remote.byNameWithUUID
withKeyOptions
(startKey to from True)
(withFilesInGit $ whenAnnexed $ start to from True)
ps
2010-11-11 22:54:52 +00:00
start :: Maybe Remote -> Maybe Remote -> Bool -> FilePath -> Key -> CommandStart
start to from move file key = start' to from move (Just file) key
2013-07-03 17:55:50 +00:00
startKey :: Maybe Remote -> Maybe Remote -> Bool -> Key -> CommandStart
2013-09-25 07:09:06 +00:00
startKey to from move = start' to from move Nothing
2013-07-03 17:55:50 +00:00
start' :: Maybe Remote -> Maybe Remote -> Bool -> AssociatedFile -> Key -> CommandStart
start' to from move afile key = do
noAuto
case (from, to) of
(Nothing, Nothing) -> error "specify either --from or --to"
2013-07-03 17:55:50 +00:00
(Nothing, Just dest) -> toStart dest move afile key
(Just src, Nothing) -> fromStart src move afile key
_ -> error "only one of --from or --to can be specified"
2012-11-12 05:05:04 +00:00
where
noAuto = when move $ whenM (Annex.getState Annex.auto) $ error
"--auto is not supported for move"
2013-07-03 17:55:50 +00:00
showMoveAction :: Bool -> Key -> AssociatedFile -> Annex ()
2014-01-26 19:53:01 +00:00
showMoveAction move = showStart' (if move then "move" else "copy")
2010-11-27 21:02:53 +00:00
{- Moves (or copies) the content of an annexed file to a remote.
-
- If the remote already has the content, it is still removed from
- the current repository.
-
- Note that unlike drop, this does not honor numcopies.
- A file's content can be moved even if there are insufficient copies to
- allow it to be dropped.
-}
2013-07-03 17:55:50 +00:00
toStart :: Remote -> Bool -> AssociatedFile -> Key -> CommandStart
toStart dest move afile key = do
2011-10-11 18:43:45 +00:00
u <- getUUID
ishere <- inAnnex key
if not ishere || u == Remote.uuid dest
2011-05-15 06:02:46 +00:00
then stop -- not here, so nothing to do
else toStart' dest move afile key
toStart' :: Remote -> Bool -> AssociatedFile -> Key -> CommandStart
toStart' dest move afile key = do
fast <- Annex.getState Annex.fast
if fast && not move && not (Remote.hasKeyCheap dest)
then ifM (expectedPresent dest key)
( stop
, go True (pure $ Right False)
)
else go False (Remote.hasKey dest key)
where
go fastcheck isthere = do
showMoveAction move key afile
next $ toPerform dest move key afile fastcheck =<< isthere
expectedPresent :: Remote -> Key -> Annex Bool
expectedPresent dest key = do
remotes <- Remote.keyPossibilities key
return $ dest `elem` remotes
toPerform :: Remote -> Bool -> Key -> AssociatedFile -> Bool -> Either String Bool -> CommandPerform
toPerform dest move key afile fastcheck isthere = do
case isthere of
Left err -> do
2011-11-11 05:52:58 +00:00
showNote err
2011-05-15 06:02:46 +00:00
stop
Right False -> do
showAction $ "to " ++ Remote.name dest
ok <- notifyTransfer Upload afile $
upload (Remote.uuid dest) key afile noRetry $
Remote.storeKey dest key afile
2010-11-22 21:51:55 +00:00
if ok
then do
Remote.logStatus dest key InfoPresent
finish
else do
when fastcheck $
warning "This could have failed because --fast is enabled."
stop
Right True -> do
unlessM (expectedPresent dest key) $
Remote.logStatus dest key InfoPresent
finish
2012-11-12 05:05:04 +00:00
where
finish
| move = lockContent key $ \contentlock -> do
removeAnnex contentlock
next $ Command.Drop.cleanupLocal key
| otherwise = next $ return True
{- Moves (or copies) the content of an annexed file from a remote
- to the current repository.
-
- If the current repository already has the content, it is still removed
- from the remote.
-}
2013-07-03 17:55:50 +00:00
fromStart :: Remote -> Bool -> AssociatedFile -> Key -> CommandStart
fromStart src move afile key
2011-11-11 05:52:58 +00:00
| move = go
2011-12-09 17:32:09 +00:00
| otherwise = stopUnless (not <$> inAnnex key) go
2012-11-12 05:05:04 +00:00
where
go = stopUnless (fromOk src key) $ do
2013-07-03 17:55:50 +00:00
showMoveAction move key afile
next $ fromPerform src move key afile
2012-11-12 05:05:04 +00:00
2011-12-31 08:11:39 +00:00
fromOk :: Remote -> Key -> Annex Bool
fromOk src key = go =<< Annex.getState Annex.force
2012-11-12 05:05:04 +00:00
where
go True = either (const $ return True) return =<< haskey
go False
| Remote.hasKeyCheap src =
either (const expensive) return =<< haskey
| otherwise = expensive
haskey = Remote.hasKey src key
2012-11-12 05:05:04 +00:00
expensive = do
u <- getUUID
remotes <- Remote.keyPossibilities key
return $ u /= Remote.uuid src && elem src remotes
2013-07-03 17:55:50 +00:00
fromPerform :: Remote -> Bool -> Key -> AssociatedFile -> CommandPerform
fromPerform src move key afile = ifM (inAnnex key)
( dispatch move True
, dispatch move =<< go
)
2012-11-12 05:05:04 +00:00
where
go = notifyTransfer Download afile $
download (Remote.uuid src) key afile noRetry $ \p -> do
showAction $ "from " ++ Remote.name src
getViaTmp key $ \t -> Remote.retrieveKeyFile src key afile t p
dispatch _ False = stop -- failed
dispatch False True = next $ return True -- copy complete
dispatch True True = do -- finish moving
2012-11-12 05:05:04 +00:00
ok <- Remote.removeKey src key
next $ Command.Drop.cleanupRemote key src ok