summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Annex.hs9
-rw-r--r--Annex/Drop.hs2
-rw-r--r--Annex/NumCopies.hs (renamed from Config/NumCopies.hs)68
-rw-r--r--CmdLine/Action.hs9
-rw-r--r--CmdLine/Seek.hs5
-rw-r--r--Command/Add.hs5
-rw-r--r--Command/Copy.hs2
-rw-r--r--Command/Drop.hs69
-rw-r--r--Command/DropUnused.hs2
-rw-r--r--Command/Fsck.hs2
-rw-r--r--Command/Get.hs2
-rw-r--r--Command/Import.hs24
-rw-r--r--Command/Info.hs2
-rw-r--r--Command/Mirror.hs2
-rw-r--r--Command/NumCopies.hs2
-rw-r--r--Limit.hs2
-rw-r--r--Messages.hs15
-rw-r--r--Remote.hs4
-rw-r--r--debian/changelog7
-rw-r--r--doc/bugs/clean-duplicates_causes_data_loss.mdwn3
-rw-r--r--doc/bugs/regression:_behavior_when_files_to_add_do_not_exist/comment_4_42481bb2f6f625a9891e59ec97574164._comment9
-rw-r--r--doc/devblog/day_280__slow_week.mdwn16
-rw-r--r--doc/install/Debian.mdwn4
23 files changed, 181 insertions, 84 deletions
diff --git a/Annex.hs b/Annex.hs
index 1c8618cc0..07da2a17b 100644
--- a/Annex.hs
+++ b/Annex.hs
@@ -5,7 +5,7 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, PackageImports #-}
+{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, PackageImports, BangPatterns #-}
module Annex (
Annex,
@@ -32,6 +32,7 @@ module Annex (
getRemoteGitConfig,
withCurrentState,
changeDirectory,
+ incError,
) where
import Common
@@ -309,3 +310,9 @@ changeDirectory d = do
liftIO $ setCurrentDirectory d
r' <- liftIO $ Git.relPath r
changeState $ \s -> s { repo = r' }
+
+incError :: Annex ()
+incError = changeState $ \s ->
+ let ! c = errcounter s + 1
+ ! s' = s { errcounter = c }
+ in s'
diff --git a/Annex/Drop.hs b/Annex/Drop.hs
index 6f3b95615..a99a1edff 100644
--- a/Annex/Drop.hs
+++ b/Annex/Drop.hs
@@ -9,7 +9,7 @@ module Annex.Drop where
import Common.Annex
import Logs.Trust
-import Config.NumCopies
+import Annex.NumCopies
import Types.Remote (uuid)
import Types.Key (key2file)
import qualified Remote
diff --git a/Config/NumCopies.hs b/Annex/NumCopies.hs
index 50dcdf684..879513927 100644
--- a/Config/NumCopies.hs
+++ b/Annex/NumCopies.hs
@@ -1,11 +1,11 @@
-{- git-annex numcopies configuration
+{- git-annex numcopies configuration and checking
-
- - Copyright 2014 Joey Hess <id@joeyh.name>
+ - Copyright 2014-2015 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
-module Config.NumCopies (
+module Annex.NumCopies (
module Types.NumCopies,
module Logs.NumCopies,
getFileNumCopies,
@@ -15,6 +15,8 @@ module Config.NumCopies (
defaultNumCopies,
numCopiesCheck,
numCopiesCheck',
+ verifyEnoughCopies,
+ knownCopies,
) where
import Common.Annex
@@ -24,6 +26,8 @@ import Logs.NumCopies
import Logs.Trust
import Annex.CheckAttr
import qualified Remote
+import Annex.UUID
+import Annex.Content
defaultNumCopies :: NumCopies
defaultNumCopies = NumCopies 1
@@ -83,3 +87,61 @@ numCopiesCheck' :: FilePath -> (Int -> Int -> v) -> [UUID] -> Annex v
numCopiesCheck' file vs have = do
NumCopies needed <- getFileNumCopies file
return $ length have `vs` needed
+
+{- Verifies that enough copies of a key exist amoung the listed remotes,
+ - priting an informative message if not.
+ -}
+verifyEnoughCopies
+ :: String -- message to print when there are no known locations
+ -> Key
+ -> NumCopies
+ -> [UUID] -- repos to skip (generally untrusted remotes)
+ -> [UUID] -- repos that are trusted or already verified to have it
+ -> [Remote] -- remotes to check to see if they have it
+ -> Annex Bool
+verifyEnoughCopies nolocmsg key need skip trusted tocheck =
+ helper [] [] (nub trusted) (nub tocheck)
+ where
+ helper bad missing have []
+ | NumCopies (length have) >= need = return True
+ | otherwise = do
+ notEnoughCopies key need have (skip++missing) bad nolocmsg
+ return False
+ helper bad missing have (r:rs)
+ | NumCopies (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 -> NumCopies -> [UUID] -> [UUID] -> [Remote] -> String -> Annex ()
+notEnoughCopies key need have skip bad nolocmsg = do
+ showNote "unsafe"
+ showLongNote $
+ "Could only verify the existence of " ++
+ show (length have) ++ " out of " ++ show (fromNumCopies need) ++
+ " necessary copies"
+ Remote.showTriedRemotes bad
+ Remote.showLocations True key (have++skip) nolocmsg
+
+{- Cost ordered lists of remotes that the location log indicates
+ - may have a key.
+ -
+ - Also returns a list of UUIDs that are trusted to have the key
+ - (some may not have configured remotes). If the current repository
+ - currently has the key, and is not untrusted, it is included in this list.
+ -}
+knownCopies :: Key -> Annex ([Remote], [UUID])
+knownCopies key = do
+ (remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key
+ u <- getUUID
+ trusteduuids' <- ifM (inAnnex key <&&> (<= SemiTrusted) <$> lookupTrust u)
+ ( pure (u:trusteduuids)
+ , pure trusteduuids
+ )
+ return (remotes, trusteduuids')
diff --git a/CmdLine/Action.hs b/CmdLine/Action.hs
index 57e1fa60b..b566621bb 100644
--- a/CmdLine/Action.hs
+++ b/CmdLine/Action.hs
@@ -5,8 +5,6 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE BangPatterns #-}
-
module CmdLine.Action where
import Common.Annex
@@ -45,14 +43,11 @@ commandAction a = account =<< tryIO go
account (Right True) = return True
account (Right False) = incerr
account (Left err) = do
- showErr err
+ toplevelWarning True (show err)
showEndFail
incerr
incerr = do
- Annex.changeState $ \s ->
- let ! c = Annex.errcounter s + 1
- ! s' = s { Annex.errcounter = c }
- in s'
+ Annex.incError
return False
{- Runs a single command action through the start, perform and cleanup
diff --git a/CmdLine/Seek.hs b/CmdLine/Seek.hs
index 1db075ec3..96076261f 100644
--- a/CmdLine/Seek.hs
+++ b/CmdLine/Seek.hs
@@ -218,8 +218,9 @@ seekHelper a params = do
ll <- inRepo $ \g -> concat <$> forM (segmentXargsOrdered params)
(runSegmentPaths (\fs -> Git.Command.leaveZombie <$> a fs g))
forM_ (map fst $ filter (null . snd) $ zip params ll) $ \p ->
- unlessM (isJust <$> liftIO (catchMaybeIO $ getSymbolicLinkStatus p)) $
- error $ p ++ " not found"
+ unlessM (isJust <$> liftIO (catchMaybeIO $ getSymbolicLinkStatus p)) $ do
+ toplevelWarning False (p ++ " not found")
+ Annex.incError
return $ concat ll
notSymlink :: FilePath -> IO Bool
diff --git a/Command/Add.hs b/Command/Add.hs
index c461c4d56..d53ba91ad 100644
--- a/Command/Add.hs
+++ b/Command/Add.hs
@@ -116,7 +116,10 @@ start file = ifAnnexed file addpresent add
- Lockdown can fail if a file gets deleted, and Nothing will be returned.
-}
lockDown :: FilePath -> Annex (Maybe KeySource)
-lockDown = either (\e -> showErr e >> return Nothing) (return . Just) <=< lockDown'
+lockDown = either
+ (\e -> warning (show e) >> return Nothing)
+ (return . Just)
+ <=< lockDown'
lockDown' :: FilePath -> Annex (Either IOException KeySource)
lockDown' file = ifM crippledFileSystem
diff --git a/Command/Copy.hs b/Command/Copy.hs
index 1b9b2aac8..5cfdabb4e 100644
--- a/Command/Copy.hs
+++ b/Command/Copy.hs
@@ -12,7 +12,7 @@ import Command
import qualified Command.Move
import qualified Remote
import Annex.Wanted
-import Config.NumCopies
+import Annex.NumCopies
cmd :: [Command]
cmd = [withOptions copyOptions $ command "copy" paramPaths seek
diff --git a/Command/Drop.hs b/Command/Drop.hs
index 63b9ccb7f..a3ac87633 100644
--- a/Command/Drop.hs
+++ b/Command/Drop.hs
@@ -15,7 +15,7 @@ import Annex.UUID
import Logs.Location
import Logs.Trust
import Logs.PreferredContent
-import Config.NumCopies
+import Annex.NumCopies
import Annex.Content
import Annex.Wanted
import Annex.Notification
@@ -72,7 +72,7 @@ performLocal key afile numcopies knownpresentremote = lockContent key $ \content
(remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key
let trusteduuids' = case knownpresentremote of
Nothing -> trusteduuids
- Just r -> nub (Remote.uuid r:trusteduuids)
+ Just r -> Remote.uuid r:trusteduuids
untrusteduuids <- trustGet UnTrusted
let tocheck = Remote.remotesWithoutUUID remotes (trusteduuids'++untrusteduuids)
u <- getUUID
@@ -91,17 +91,9 @@ performRemote key afile 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,
- -- as long asthe local repo is not untrusted.
- (remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key
- present <- inAnnex key
- u <- getUUID
- trusteduuids' <- if present
- then ifM ((<= SemiTrusted) <$> lookupTrust u)
- ( pure (u:trusteduuids)
- , pure trusteduuids
- )
- else pure trusteduuids
- let have = filter (/= uuid) trusteduuids'
+ -- as long as the local repo is not untrusted.
+ (remotes, trusteduuids) <- knownCopies key
+ let have = filter (/= uuid) trusteduuids
untrusteduuids <- trustGet UnTrusted
let tocheck = filter (/= remote) $
Remote.remotesWithoutUUID remotes (have++untrusteduuids)
@@ -131,45 +123,20 @@ cleanupRemote key remote ok = do
- --force overrides and always allows dropping.
-}
canDrop :: UUID -> Key -> AssociatedFile -> NumCopies -> [UUID] -> [Remote] -> [UUID] -> Annex Bool
-canDrop dropfrom key afile numcopies have check skip = ifM (Annex.getState Annex.force)
- ( return True
- , checkRequiredContent dropfrom key afile
- <&&>
- findCopies key numcopies skip have check
- )
-
-findCopies :: Key -> NumCopies -> [UUID] -> [UUID] -> [Remote] -> Annex Bool
-findCopies key need skip = helper [] []
- where
- helper bad missing have []
- | NumCopies (length have) >= need = return True
- | otherwise = notEnoughCopies key need have (skip++missing) bad
- helper bad missing have (r:rs)
- | NumCopies (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 -> NumCopies -> [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 (fromNumCopies need) ++
- " necessary copies"
- Remote.showTriedRemotes bad
- Remote.showLocations True key (have++skip)
- "Rather than dropping this file, try using: git annex move"
- hint
- return False
+canDrop dropfrom key afile numcopies have check skip =
+ ifM (Annex.getState Annex.force)
+ ( return True
+ , ifM (checkRequiredContent dropfrom key afile
+ <&&> verifyEnoughCopies nolocmsg key numcopies skip have check
+ )
+ ( return True
+ , do
+ hint
+ return False
+ )
+ )
where
- unsafe = showNote "unsafe"
+ nolocmsg = "Rather than dropping this file, try using: git annex move"
hint = showLongNote "(Use --force to override this check, or adjust numcopies.)"
checkRequiredContent :: UUID -> Key -> AssociatedFile -> Annex Bool
diff --git a/Command/DropUnused.hs b/Command/DropUnused.hs
index 36ff49720..d441a4bd2 100644
--- a/Command/DropUnused.hs
+++ b/Command/DropUnused.hs
@@ -14,7 +14,7 @@ import qualified Command.Drop
import qualified Remote
import qualified Git
import Command.Unused (withUnusedMaps, UnusedMaps(..), startUnused)
-import Config.NumCopies
+import Annex.NumCopies
cmd :: [Command]
cmd = [withOptions [Command.Drop.dropFromOption] $
diff --git a/Command/Fsck.hs b/Command/Fsck.hs
index eea0ebc11..46d7c2e77 100644
--- a/Command/Fsck.hs
+++ b/Command/Fsck.hs
@@ -24,7 +24,7 @@ import Annex.Link
import Logs.Location
import Logs.Trust
import Logs.Activity
-import Config.NumCopies
+import Annex.NumCopies
import Annex.UUID
import Utility.DataUnits
import Config
diff --git a/Command/Get.hs b/Command/Get.hs
index 922aee06a..7e95493eb 100644
--- a/Command/Get.hs
+++ b/Command/Get.hs
@@ -12,7 +12,7 @@ import Command
import qualified Remote
import Annex.Content
import Annex.Transfer
-import Config.NumCopies
+import Annex.NumCopies
import Annex.Wanted
import qualified Command.Move
diff --git a/Command/Import.hs b/Command/Import.hs
index 261bd7b8e..eb21faea2 100644
--- a/Command/Import.hs
+++ b/Command/Import.hs
@@ -17,6 +17,9 @@ import Remote
import Types.KeySource
import Types.Key
import Annex.CheckIgnore
+import Annex.NumCopies
+import Types.TrustLevel
+import Logs.Trust
cmd :: [Command]
cmd = [withOptions opts $ notBareRepo $ command "import" paramPaths seek
@@ -76,8 +79,14 @@ start mode (srcfile, destfile) =
where
deletedup k = do
showNote $ "duplicate of " ++ key2file k
- liftIO $ removeFile srcfile
- next $ return True
+ ifM (verifiedExisting k destfile)
+ ( do
+ liftIO $ removeFile srcfile
+ next $ return True
+ , do
+ warning "Could not verify that the content is still present in the annex; not removing from the import location."
+ stop
+ )
importfile = do
ignored <- not <$> Annex.getState Annex.force <&&> checkIgnored destfile
if ignored
@@ -120,3 +129,14 @@ start mode (srcfile, destfile) =
CleanDuplicates -> checkdup (Just deletedup) Nothing
SkipDuplicates -> checkdup Nothing (Just importfile)
_ -> return (Just importfile)
+
+verifiedExisting :: Key -> FilePath -> Annex Bool
+verifiedExisting key destfile = do
+ -- Look up the numcopies setting for the file that it would be
+ -- imported to, if it were imported.
+ need <- getFileNumCopies destfile
+
+ (remotes, trusteduuids) <- knownCopies key
+ untrusteduuids <- trustGet UnTrusted
+ let tocheck = Remote.remotesWithoutUUID remotes (trusteduuids++untrusteduuids)
+ verifyEnoughCopies [] key need trusteduuids [] tocheck
diff --git a/Command/Info.hs b/Command/Info.hs
index b7cb3232f..1c2dd2fb2 100644
--- a/Command/Info.hs
+++ b/Command/Info.hs
@@ -30,7 +30,7 @@ import Types.Key
import Logs.UUID
import Logs.Trust
import Logs.Location
-import Config.NumCopies
+import Annex.NumCopies
import Remote
import Config
import Utility.Percentage
diff --git a/Command/Mirror.hs b/Command/Mirror.hs
index a04efb89b..14f70d3b6 100644
--- a/Command/Mirror.hs
+++ b/Command/Mirror.hs
@@ -14,7 +14,7 @@ import qualified Command.Drop
import qualified Command.Get
import qualified Remote
import Annex.Content
-import Config.NumCopies
+import Annex.NumCopies
cmd :: [Command]
cmd = [withOptions mirrorOptions $ command "mirror" paramPaths seek
diff --git a/Command/NumCopies.hs b/Command/NumCopies.hs
index 6c69b2166..1e710f561 100644
--- a/Command/NumCopies.hs
+++ b/Command/NumCopies.hs
@@ -10,7 +10,7 @@ module Command.NumCopies where
import Common.Annex
import qualified Annex
import Command
-import Config.NumCopies
+import Annex.NumCopies
import Types.Messages
cmd :: [Command]
diff --git a/Limit.hs b/Limit.hs
index 030ee6a5f..c412637bb 100644
--- a/Limit.hs
+++ b/Limit.hs
@@ -15,7 +15,7 @@ import qualified Backend
import Annex.Content
import Annex.UUID
import Logs.Trust
-import Config.NumCopies
+import Annex.NumCopies
import Types.TrustLevel
import Types.Key
import Types.Group
diff --git a/Messages.hs b/Messages.hs
index 0e83a7243..5dffbd8de 100644
--- a/Messages.hs
+++ b/Messages.hs
@@ -19,7 +19,7 @@ module Messages (
showEndOk,
showEndFail,
showEndResult,
- showErr,
+ toplevelWarning,
warning,
warningIO,
indent,
@@ -117,15 +117,16 @@ showEndResult ok = handleMessage (JSON.end ok) $ putStrLn msg
| ok = "ok"
| otherwise = "failed"
-showErr :: (Show a) => a -> Annex ()
-showErr e = warning' $ "git-annex: " ++ show e
+toplevelWarning :: Bool -> String -> Annex ()
+toplevelWarning makeway s = warning' makeway ("git-annex: " ++ s)
warning :: String -> Annex ()
-warning = warning' . indent
+warning = warning' True . indent
-warning' :: String -> Annex ()
-warning' w = do
- handleMessage q $ putStr "\n"
+warning' :: Bool -> String -> Annex ()
+warning' makeway w = do
+ when makeway $
+ handleMessage q $ putStr "\n"
liftIO $ do
hFlush stdout
hPutStrLn stderr w
diff --git a/Remote.hs b/Remote.hs
index 8a03f757d..90cc6008e 100644
--- a/Remote.hs
+++ b/Remote.hs
@@ -282,7 +282,9 @@ showLocations separateuntrusted key exclude nolocmsg = do
let uuidsskipped = filteruuids uuids (u:exclude++uuidswanted)
ppuuidswanted <- prettyPrintUUIDs "wanted" uuidswanted
ppuuidsskipped <- prettyPrintUUIDs "skipped" uuidsskipped
- showLongNote $ message ppuuidswanted ppuuidsskipped
+ let msg = message ppuuidswanted ppuuidsskipped
+ unless (null msg) $
+ showLongNote msg
ignored <- filter (remoteAnnexIgnore . gitconfig) <$> remoteList
unless (null ignored) $
showLongNote $ "(Note that these git remotes have annex-ignore set: " ++ unwords (map name ignored) ++ ")"
diff --git a/debian/changelog b/debian/changelog
index 2db52813e..38db4ee67 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -18,6 +18,13 @@ git-annex (5.20150421) UNRELEASED; urgency=medium
* Improve integration with KDE's file manager to work with dolphin
version 14.12.3 while still being compatable with 4.14.2.
Thanks, silvio.
+ * import: Before removing a duplicate file in --deduplicate or
+ --clean-duplicates mode, verify that enough copies of its content still
+ exist.
+ * Improve behavior when a git-annex command is told to operate
+ on a file that doesn't exist. It will now continue to other
+ files specified after that on the command line, and only error out at
+ the end.
-- Joey Hess <id@joeyh.name> Tue, 21 Apr 2015 15:54:10 -0400
diff --git a/doc/bugs/clean-duplicates_causes_data_loss.mdwn b/doc/bugs/clean-duplicates_causes_data_loss.mdwn
index df1f7e131..c5d545420 100644
--- a/doc/bugs/clean-duplicates_causes_data_loss.mdwn
+++ b/doc/bugs/clean-duplicates_causes_data_loss.mdwn
@@ -25,3 +25,6 @@ g-a import --clean-duplicates ~/tmp/importme (containing a, b and c) into 'impor
### Please provide any additional information below.
I can provide the script if it is wanted (coded in Perl, couple of non-core dependencies).
+
+> Decided to go ahead and make it check remotes like drop does, so [[done]]
+> --[[Joey]]
diff --git a/doc/bugs/regression:_behavior_when_files_to_add_do_not_exist/comment_4_42481bb2f6f625a9891e59ec97574164._comment b/doc/bugs/regression:_behavior_when_files_to_add_do_not_exist/comment_4_42481bb2f6f625a9891e59ec97574164._comment
new file mode 100644
index 000000000..4755498c1
--- /dev/null
+++ b/doc/bugs/regression:_behavior_when_files_to_add_do_not_exist/comment_4_42481bb2f6f625a9891e59ec97574164._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2015-04-30T18:56:31Z"
+ content="""
+Regression or not, it would be useful if git-annex continued past such
+not-existing files to process the rest of the specified files, and only
+set the error flag.
+"""]]
diff --git a/doc/devblog/day_280__slow_week.mdwn b/doc/devblog/day_280__slow_week.mdwn
new file mode 100644
index 000000000..0c49b33bc
--- /dev/null
+++ b/doc/devblog/day_280__slow_week.mdwn
@@ -0,0 +1,16 @@
+Reduced activity this week (didn't work on the assistant after all),
+but several things got done:
+
+Monday: Fixed `fsck --fast --from remote` to not fail when the remote
+didn't support fast copy mode. And dealt with an incompatability in S3 bucket
+names; the old hS3 library supported upper-case bucket names but the new
+one needs them all in lower case.
+
+Wednesday: Caught up on most recent backlog, made some improvements
+to error handling in `import`, and improved integration with KDE's file
+manager to work with newer versions.
+
+Today: Made `import --deduplicate/--clean-duplicates` actively
+verify that enough copies of a file exist before deleting it. And,
+thinking about some options for batch mode access to git-annex plumbing,
+to speed up things that use it a lot.
diff --git a/doc/install/Debian.mdwn b/doc/install/Debian.mdwn
index c71d4d244..3401afded 100644
--- a/doc/install/Debian.mdwn
+++ b/doc/install/Debian.mdwn
@@ -2,6 +2,10 @@
sudo apt-get install git-annex
+## Debian 8.0 "jessie"
+
+ sudo apt-get install git-annex
+
## Debian 7.0 "wheezy":
sudo apt-get install git-annex