diff options
author | Joey Hess <joey@kitenet.net> | 2011-10-28 17:26:38 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2011-10-28 17:26:38 -0400 |
commit | 6c31e3a8c3c5ab92ca2e84b4c166f32d02a50f4f (patch) | |
tree | 8f0b857728feca852c7907c2dcb552ff87e8c582 | |
parent | 33e18d3d02865ac0677fc1f22de2352b92f184a8 (diff) |
drop --from is now supported to remove file content from a remote.
-rw-r--r-- | Command/Drop.hs | 125 | ||||
-rw-r--r-- | Command/DropUnused.hs | 5 | ||||
-rw-r--r-- | Command/Move.hs | 25 | ||||
-rw-r--r-- | Remote.hs | 15 | ||||
-rw-r--r-- | debian/changelog | 1 | ||||
-rw-r--r-- | doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn | 1 | ||||
-rw-r--r-- | doc/git-annex.mdwn | 5 |
7 files changed, 114 insertions, 63 deletions
diff --git a/Command/Drop.hs b/Command/Drop.hs index a84d2efcc..27049fc67 100644 --- a/Command/Drop.hs +++ b/Command/Drop.hs @@ -11,76 +11,131 @@ import Common.Annex import Command import qualified Remote import qualified Annex +import Annex.UUID import Logs.Location import Logs.Trust import Annex.Content import Config command :: [Command] -command = [Command "drop" paramPaths defaultChecks seek +command = [Command "drop" paramPaths (noTo >> needsRepo) seek "indicate content of files not currently wanted"] seek :: [CommandSeek] seek = [withNumCopies start] start :: FilePath -> Maybe Int -> CommandStart -start file numcopies = isAnnexed file $ \(key, _) -> do +start file numcopies = isAnnexed file $ \(key, _) -> + autoCopies key (>) numcopies $ do + from <- Annex.getState Annex.fromremote + case from of + Nothing -> startLocal file numcopies key + Just name -> do + remote <- Remote.byName name + u <- getUUID + if Remote.uuid remote == u + then startLocal file numcopies key + else startRemote file numcopies key remote + +startLocal :: FilePath -> Maybe Int -> Key -> CommandStart +startLocal file numcopies key = do present <- inAnnex key if present - then autoCopies key (>) numcopies $ do + then do showStart "drop" file - next $ perform key numcopies + next $ performLocal key numcopies else stop -perform :: Key -> Maybe Int -> CommandPerform -perform key numcopies = do - success <- canDropKey key numcopies +startRemote :: FilePath -> Maybe Int -> Key -> Remote.Remote Annex -> CommandStart +startRemote file numcopies key remote = do + showStart "drop" file + next $ performRemote key numcopies remote + +performLocal :: Key -> Maybe Int -> CommandPerform +performLocal key numcopies = do + (remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key + untrusteduuids <- trustGet UnTrusted + let tocheck = Remote.remotesWithoutUUID remotes (trusteduuids++untrusteduuids) + success <- canDropKey key numcopies trusteduuids tocheck [] if success - then next $ cleanup key + then next $ cleanupLocal key else stop -cleanup :: Key -> CommandCleanup -cleanup key = do +performRemote :: Key -> Maybe Int -> Remote.Remote Annex -> CommandPerform +performRemote key numcopies remote = do + -- Filter the remote it's being dropped from out of the lists of + -- places assumed to have the key, and places to check. + -- When the local repo has the key, that's one additional copy. + (remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key + present <- inAnnex key + u <- getUUID + let have = filter (/= uuid) $ + if present then u:trusteduuids else trusteduuids + untrusteduuids <- trustGet UnTrusted + let tocheck = filter (/= remote) $ + Remote.remotesWithoutUUID remotes (have++untrusteduuids) + success <- canDropKey key numcopies have tocheck [uuid] + if success + then next $ cleanupRemote key remote + else stop + where + uuid = Remote.uuid remote + +cleanupLocal :: Key -> CommandCleanup +cleanupLocal key = do whenM (inAnnex key) $ removeAnnex key logStatus key InfoMissing return True -{- Checks remotes to verify that enough copies of a key exist to allow - - for a key to be safely removed (with no data loss). -} -canDropKey :: Key -> Maybe Int -> Annex Bool -canDropKey key numcopiesM = do +cleanupRemote :: Key -> Remote.Remote Annex -> CommandCleanup +cleanupRemote key remote = do + ok <- Remote.removeKey remote key + -- better safe than sorry: assume the remote dropped the key + -- even if it seemed to fail; the failure could have occurred + -- after it really dropped it + Remote.remoteHasKey remote key False + return ok + +{- Checks specified remotes to verify that enough copies of a key exist to + - allow it to be safely removed (with no data loss). Can be provided with + - some locations where the key is known/assumed to be present. -} +canDropKey :: Key -> Maybe Int -> [UUID] -> [Remote.Remote Annex] -> [UUID] -> Annex Bool +canDropKey key numcopiesM have check skip = do force <- Annex.getState Annex.force if force || numcopiesM == Just 0 then return True else do - (remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key - untrusteduuids <- trustGet UnTrusted - let tocheck = Remote.remotesWithoutUUID remotes (trusteduuids++untrusteduuids) - numcopies <- getNumCopies numcopiesM - findcopies numcopies trusteduuids tocheck [] + need <- getNumCopies numcopiesM + findCopies key need skip have check + +findCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote.Remote Annex] -> Annex Bool +findCopies key need skip = helper [] where - findcopies need have [] bad + helper bad have [] | length have >= need = return True - | otherwise = notEnoughCopies need have bad - findcopies need have (r:rs) bad + | otherwise = notEnoughCopies key need have skip bad + helper bad have (r:rs) | length have >= need = return True | otherwise = do let u = Remote.uuid r let duplicate = u `elem` have haskey <- Remote.hasKey r key case (duplicate, haskey) of - (False, Right True) -> findcopies need (u:have) rs bad - (False, Left _) -> findcopies need have rs (r:bad) - _ -> findcopies need have rs bad - notEnoughCopies need have bad = do - unsafe - showLongNote $ - "Could only verify the existence of " ++ - show (length have) ++ " out of " ++ show need ++ - " necessary copies" - Remote.showTriedRemotes bad - Remote.showLocations key have - hint - return False + (False, Right True) -> helper bad (u:have) rs + (False, Left _) -> helper (r:bad) have rs + _ -> helper bad have rs + +notEnoughCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote.Remote Annex] -> Annex Bool +notEnoughCopies key need have skip bad = do + unsafe + showLongNote $ + "Could only verify the existence of " ++ + show (length have) ++ " out of " ++ show need ++ + " necessary copies" + Remote.showTriedRemotes bad + Remote.showLocations key (have++skip) + hint + return False + where unsafe = showNote "unsafe" hint = showLongNote "(Use --force to override this check, or adjust annex.numcopies.)" diff --git a/Command/DropUnused.hs b/Command/DropUnused.hs index 1236fb823..46f2dc9f7 100644 --- a/Command/DropUnused.hs +++ b/Command/DropUnused.hs @@ -13,7 +13,6 @@ import Common.Annex import Command import qualified Annex import qualified Command.Drop -import qualified Command.Move import qualified Remote import qualified Git import Types.Key @@ -56,8 +55,8 @@ perform key = maybe droplocal dropremote =<< Annex.getState Annex.fromremote dropremote name = do r <- Remote.byName name showAction $ "from " ++ Remote.name r - next $ Command.Move.fromCleanup r True key - droplocal = Command.Drop.perform key (Just 0) -- force drop + next $ Command.Drop.cleanupRemote key r + droplocal = Command.Drop.performLocal key (Just 0) -- force drop performOther :: (Git.Repo -> Key -> FilePath) -> Key -> CommandPerform performOther filespec key = do diff --git a/Command/Move.hs b/Command/Move.hs index ae5e0e1d4..2a7402a0d 100644 --- a/Command/Move.hs +++ b/Command/Move.hs @@ -11,7 +11,6 @@ import Common.Annex import Command import qualified Command.Drop import qualified Annex -import Logs.Location import Annex.Content import qualified Remote import Annex.UUID @@ -49,18 +48,6 @@ showMoveAction :: Bool -> FilePath -> Annex () showMoveAction True file = showStart "move" file showMoveAction False file = showStart "copy" file -{- Used to log a change in a remote's having a key. The change is logged - - in the local repo, not on the remote. The process of transferring the - - key to the remote, or removing the key from it *may* log the change - - on the remote, but this cannot be relied on. -} -remoteHasKey :: Remote.Remote Annex -> Key -> Bool -> Annex () -remoteHasKey remote key present = do - let remoteuuid = Remote.uuid remote - g <- gitRepo - logChange g key remoteuuid status - where - status = if present then InfoPresent else InfoMissing - {- Moves (or copies) the content of an annexed file to a remote. - - If the remote already has the content, it is still removed from @@ -108,9 +95,9 @@ toPerform dest move key = do Right True -> next $ toCleanup dest move key toCleanup :: Remote.Remote Annex -> Bool -> Key -> CommandCleanup toCleanup dest move key = do - remoteHasKey dest key True + Remote.remoteHasKey dest key True if move - then Command.Drop.cleanup key + then Command.Drop.cleanupLocal key else return True {- Moves (or copies) the content of an annexed file from a remote @@ -140,11 +127,5 @@ fromPerform src move key = do then next $ fromCleanup src move key else stop -- fail fromCleanup :: Remote.Remote Annex -> Bool -> Key -> CommandCleanup -fromCleanup src True key = do - ok <- Remote.removeKey src key - -- better safe than sorry: assume the src dropped the key - -- even if it seemed to fail; the failure could have occurred - -- after it really dropped it - remoteHasKey src key False - return ok +fromCleanup src True key = Command.Drop.cleanupRemote key src fromCleanup _ False _ = return True @@ -25,7 +25,8 @@ module Remote ( nameToUUID, showTriedRemotes, showLocations, - forceTrust + forceTrust, + remoteHasKey ) where import qualified Data.Map as M @@ -225,3 +226,15 @@ forceTrust level remotename = do r <- nameToUUID remotename Annex.changeState $ \s -> s { Annex.forcetrust = (r, level):Annex.forcetrust s } + +{- Used to log a change in a remote's having a key. The change is logged + - in the local repo, not on the remote. The process of transferring the + - key to the remote, or removing the key from it *may* log the change + - on the remote, but this cannot always be relied on. -} +remoteHasKey :: Remote Annex -> Key -> Bool -> Annex () +remoteHasKey remote key present = do + let remoteuuid = uuid remote + g <- gitRepo + logChange g key remoteuuid status + where + status = if present then InfoPresent else InfoMissing diff --git a/debian/changelog b/debian/changelog index d100bd4e8..237abb83f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,7 @@ git-annex (3.20111026) UNRELEASED; urgency=low host. * uninit: Add guard against being run with the git-annex branch checked out. * Fail if --from or --to is passed to commands that do not support them. + * drop --from is now supported to remove file content from a remote. -- Joey Hess <joeyh@debian.org> Thu, 27 Oct 2011 13:58:53 -0400 diff --git a/doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn b/doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn index 982f398ae..24cacbf71 100644 --- a/doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn +++ b/doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn @@ -2,6 +2,7 @@ Currently there is no way to drop files, or list what files are available, on a It would be good if "git annex drop" and "git annex find" supported the --from argument. > I agree, drop should support --from. +>> [[done]] --[[Joey]] > > To find files *believed* to be present in a given remote, use > `git annex find --in remote` diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn index 3dcc11705..dc0b49ab2 100644 --- a/doc/git-annex.mdwn +++ b/doc/git-annex.mdwn @@ -80,8 +80,9 @@ subdirectories). Drops the content of annexed files from this repository. git-annex will refuse to drop content if it cannot verify it is - safe to do so. At least one copy of content needs to exist in another - remote. This can be overridden with the --force switch. + safe to do so. This can be overridden with the --force switch. + + To drop content from a remote, specify --from. * move [path ...] |