summaryrefslogtreecommitdiff
path: root/Command/Drop.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Command/Drop.hs')
-rw-r--r--Command/Drop.hs161
1 files changed, 161 insertions, 0 deletions
diff --git a/Command/Drop.hs b/Command/Drop.hs
new file mode 100644
index 000000000..5d642ed3a
--- /dev/null
+++ b/Command/Drop.hs
@@ -0,0 +1,161 @@
+{- git-annex command
+ -
+ - Copyright 2010 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Command.Drop where
+
+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
+import qualified Option
+import Annex.Wanted
+
+def :: [Command]
+def = [withOptions [fromOption] $ command "drop" paramPaths seek
+ SectionCommon "indicate content of files not currently wanted"]
+
+fromOption :: Option
+fromOption = Option.field ['f'] "from" paramRemote "drop content from a remote"
+
+seek :: [CommandSeek]
+seek = [withField fromOption Remote.byNameWithUUID $ \from ->
+ withFilesInGit $ whenAnnexed $ start from]
+
+start :: Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart
+start from file (key, _) = checkDropAuto from file key $ \numcopies ->
+ stopUnless (checkAuto $ wantDrop False (Remote.uuid <$> from) (Just file)) $
+ case from of
+ Nothing -> startLocal file numcopies key Nothing
+ Just remote -> do
+ u <- getUUID
+ if Remote.uuid remote == u
+ then startLocal file numcopies key Nothing
+ else startRemote file numcopies key remote
+
+startLocal :: FilePath -> Maybe Int -> Key -> Maybe Remote -> CommandStart
+startLocal file numcopies key knownpresentremote = stopUnless (inAnnex key) $ do
+ showStart "drop" file
+ next $ performLocal key numcopies knownpresentremote
+
+startRemote :: FilePath -> Maybe Int -> Key -> Remote -> CommandStart
+startRemote file numcopies key remote = do
+ showStart ("drop " ++ Remote.name remote) file
+ next $ performRemote key numcopies remote
+
+performLocal :: Key -> Maybe Int -> Maybe Remote -> CommandPerform
+performLocal key numcopies knownpresentremote = lockContent key $ do
+ (remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key
+ let trusteduuids' = case knownpresentremote of
+ Nothing -> trusteduuids
+ Just r -> nub (Remote.uuid r:trusteduuids)
+ untrusteduuids <- trustGet UnTrusted
+ let tocheck = Remote.remotesWithoutUUID remotes (trusteduuids'++untrusteduuids)
+ stopUnless (canDropKey key numcopies trusteduuids' tocheck []) $ do
+ removeAnnex key
+ next $ cleanupLocal key
+
+performRemote :: Key -> Maybe Int -> Remote -> CommandPerform
+performRemote key numcopies remote = lockContent key $ 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)
+ stopUnless (canDropKey key numcopies have tocheck [uuid]) $ do
+ ok <- Remote.removeKey remote key
+ next $ cleanupRemote key remote ok
+ where
+ uuid = Remote.uuid remote
+
+cleanupLocal :: Key -> CommandCleanup
+cleanupLocal key = do
+ logStatus key InfoMissing
+ return True
+
+cleanupRemote :: Key -> Remote -> Bool -> CommandCleanup
+cleanupRemote key remote ok = do
+ when ok $
+ Remote.logStatus remote key InfoMissing
+ 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] -> [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
+ need <- getNumCopies numcopiesM
+ findCopies key need skip have check
+
+findCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote] -> Annex Bool
+findCopies key need skip = helper [] []
+ where
+ helper bad missing have []
+ | length have >= need = return True
+ | otherwise = notEnoughCopies key need have (skip++missing) bad
+ helper bad missing 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) -> helper bad missing (u:have) rs
+ (False, Left _) -> helper (r:bad) missing have rs
+ (False, Right False) -> helper bad (u:missing) have rs
+ _ -> helper bad missing have rs
+
+notEnoughCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote] -> 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)
+ "Rather than dropping this file, try using: git annex move"
+ hint
+ return False
+ where
+ unsafe = showNote "unsafe"
+ hint = showLongNote "(Use --force to override this check, or adjust annex.numcopies.)"
+
+{- In auto mode, only runs the action if there are enough
+ - copies on other semitrusted repositories.
+ -
+ - Passes any numcopies attribute of the file on to the action as an
+ - optimisation. -}
+checkDropAuto :: Maybe Remote -> FilePath -> Key -> (Maybe Int -> CommandStart) -> CommandStart
+checkDropAuto mremote file key a = do
+ numcopiesattr <- numCopies file
+ Annex.getState Annex.auto >>= auto numcopiesattr
+ where
+ auto numcopiesattr False = a numcopiesattr
+ auto numcopiesattr True = do
+ needed <- getNumCopies numcopiesattr
+ locs <- Remote.keyLocations key
+ uuid <- getUUID
+ let remoteuuid = fromMaybe uuid $ Remote.uuid <$> mremote
+ locs' <- trustExclude UnTrusted $ filter (/= remoteuuid) locs
+ if length locs' >= needed
+ then a numcopiesattr
+ else stop