git-annex/Command/Move.hs

140 lines
4.3 KiB
Haskell
Raw Normal View History

{- git-annex command
-
- Copyright 2010 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Command.Move where
2010-11-27 21:02:53 +00:00
import Control.Monad.State (liftIO)
import Command
2010-11-11 22:54:52 +00:00
import qualified Command.Drop
import qualified Annex
import Locations
import LocationLog
import Types
import Core
import qualified GitRepo as Git
import qualified Remotes
import UUID
2010-11-08 19:15:21 +00:00
import Messages
2010-11-11 22:54:52 +00:00
seek :: [SubCmdSeek]
2010-11-27 21:02:53 +00:00
seek = [withFilesInGit $ start True]
2010-11-11 22:54:52 +00:00
2010-11-27 21:02:53 +00:00
{- Move (or copy) a file either --to or --from a repository.
-
- This only operates on the cached file content; it does not involve
- moving data in the key-value backend. -}
2010-11-27 21:02:53 +00:00
start :: Bool -> SubCmdStartString
start move file = do
fromName <- Annex.flagGet "fromrepository"
toName <- Annex.flagGet "torepository"
case (fromName, toName) of
("", "") -> error "specify either --from or --to"
2010-11-27 21:02:53 +00:00
("", _) -> toStart move file
(_ , "") -> fromStart move file
(_ , _) -> error "only one of --from or --to can be specified"
2010-11-27 21:02:53 +00:00
showAction :: Bool -> FilePath -> Annex ()
showAction True file = showStart "move" file
showAction False file = showStart "copy" file
remoteHasKey :: Git.Repo -> Key -> Bool -> Annex ()
remoteHasKey remote key present = do
g <- Annex.gitRepo
remoteuuid <- getUUID remote
logfile <- liftIO $ logChange g key remoteuuid status
Annex.queue "add" ["--"] logfile
where
status = if present then ValuePresent else ValueMissing
{- Moves (or copies) the content of an annexed file to another repository,
- and updates locationlog information on both.
-
2010-11-27 21:02:53 +00:00
- When moving, if the destination already has the content, it is
- still removed from the current repository.
-
- Note that unlike drop, this does not honor annex.numcopies.
- A file's content can be moved even if there are insufficient copies to
- allow it to be dropped.
-}
2010-11-27 21:02:53 +00:00
toStart :: Bool -> SubCmdStartString
toStart move file = isAnnexed file $ \(key, _) -> do
ishere <- inAnnex key
2010-11-22 21:51:55 +00:00
if not ishere
then return Nothing -- not here, so nothing to do
else do
2010-11-27 21:02:53 +00:00
showAction move file
return $ Just $ toPerform move key
toPerform :: Bool -> Key -> SubCmdPerform
toPerform move key = do
-- checking the remote is expensive, so not done in the start step
remote <- Remotes.commandLineRemote
isthere <- Remotes.inAnnex remote key
case isthere of
Left err -> do
showNote $ show err
return Nothing
Right False -> do
2010-11-27 21:02:53 +00:00
showNote $ "to " ++ Git.repoDescribe remote ++ "..."
2010-11-22 21:51:55 +00:00
let tmpfile = annexTmpLocation remote ++ keyFile key
ok <- Remotes.copyToRemote remote key tmpfile
2010-11-22 21:51:55 +00:00
if ok
2010-11-27 21:02:53 +00:00
then return $ Just $ toCleanup move remote key tmpfile
else return Nothing -- failed
Right True -> return $ Just $ Command.Drop.cleanup key
2010-11-27 21:02:53 +00:00
toCleanup :: Bool -> Git.Repo -> Key -> FilePath -> SubCmdCleanup
toCleanup move remote key tmpfile = do
-- Tell remote to use the transferred content.
ok <- Remotes.runCmd remote "git-annex" ["setkey", "--quiet",
2010-11-22 21:51:55 +00:00
"--backend=" ++ backendName key,
"--key=" ++ keyName key,
tmpfile]
if ok
then do
2010-11-27 21:02:53 +00:00
remoteHasKey remote key True
if move
then Command.Drop.cleanup key
else return True
else return False
2010-11-27 21:02:53 +00:00
{- Moves (or copies) the content of an annexed file from another repository
- to the current repository and updates locationlog information on both.
-
- If the current repository already has the content, it is still removed
2010-11-27 21:02:53 +00:00
- from the other repository when moving.
-}
2010-11-27 21:02:53 +00:00
fromStart :: Bool -> SubCmdStartString
fromStart move file = isAnnexed file $ \(key, _) -> do
remote <- Remotes.commandLineRemote
l <- Remotes.keyPossibilities key
2010-11-22 21:51:55 +00:00
if null $ filter (\r -> Remotes.same r remote) l
then return Nothing
else do
2010-11-27 21:02:53 +00:00
showAction move file
return $ Just $ fromPerform move key
fromPerform :: Bool -> Key -> SubCmdPerform
fromPerform move key = do
remote <- Remotes.commandLineRemote
ishere <- inAnnex key
2010-11-22 21:51:55 +00:00
if ishere
2010-11-27 21:02:53 +00:00
then return $ Just $ fromCleanup move remote key
else do
2010-11-27 21:02:53 +00:00
showNote $ "from " ++ Git.repoDescribe remote ++ "..."
2010-11-22 21:51:55 +00:00
ok <- getViaTmp key $ Remotes.copyFromRemote remote key
if ok
2010-11-27 21:02:53 +00:00
then return $ Just $ fromCleanup move remote key
else return Nothing -- fail
2010-11-27 21:02:53 +00:00
fromCleanup :: Bool -> Git.Repo -> Key -> SubCmdCleanup
fromCleanup True remote key = do
ok <- Remotes.runCmd remote "git-annex"
["dropkey", "--quiet", "--force",
2010-11-22 21:51:55 +00:00
"--backend=" ++ backendName key,
keyName key]
2010-11-27 21:02:53 +00:00
remoteHasKey remote key False
return ok
2010-11-27 21:02:53 +00:00
fromCleanup False _ _ = return True