git-annex 8.20210621 → 8.20210630
raw patch · 27 files changed
+277/−137 lines, 27 files
Files
- Annex/Content.hs +19/−7
- Annex/CopyFile.hs +3/−1
- Annex/Drop.hs +2/−3
- Annex/Init.hs +27/−17
- Annex/Perms.hs +31/−25
- Annex/Transfer.hs +2/−7
- Annex/TransferrerPool.hs +2/−6
- Build/Configure.hs +12/−1
- CHANGELOG +24/−0
- Command/AddUrl.hs +17/−6
- Command/Drop.hs +37/−21
- Command/DropUnused.hs +3/−2
- Command/ImportFeed.hs +5/−4
- Command/Mirror.hs +3/−2
- Command/Move.hs +3/−3
- Command/Sync.hs +11/−4
- Git/Repair.hs +29/−16
- Messages/Serialized.hs +1/−1
- Remote/Git.hs +13/−7
- Test.hs +3/−1
- Types/GitConfig.hs +4/−0
- doc/git-annex-addurl.mdwn +6/−0
- doc/git-annex-dead.mdwn +1/−1
- doc/git-annex-dropunused.mdwn +1/−1
- doc/git-annex-importfeed.mdwn +7/−0
- doc/git-annex.mdwn +10/−0
- git-annex.cabal +1/−1
Annex/Content.hs view
@@ -1,6 +1,6 @@ {- git-annex file content managing -- - Copyright 2010-2020 Joey Hess <id@joeyh.name>+ - Copyright 2010-2021 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -36,6 +36,7 @@ linkOrCopy', sendAnnex, prepSendAnnex,+ prepSendAnnex', removeAnnex, moveBad, KeyLocation(..),@@ -446,14 +447,15 @@ - The rollback action should remove the data that was transferred. -} sendAnnex :: Key -> Annex () -> (FilePath -> Annex a) -> Annex a-sendAnnex key rollback sendobject = go =<< prepSendAnnex key+sendAnnex key rollback sendobject = go =<< prepSendAnnex' key where- go (Just (f, checksuccess)) = do+ go (Just (f, check)) = do r <- sendobject f- unlessM checksuccess $ do- rollback- giveup "content changed while it was being sent"- return r+ check >>= \case+ Nothing -> return r+ Just err -> do+ rollback+ giveup err go Nothing = giveup "content not available to send" {- Returns a file that contains an object's content,@@ -482,6 +484,16 @@ return $ if null cache' then Nothing else Just (fromRawFilePath f, sameInodeCache f cache')++prepSendAnnex' :: Key -> Annex (Maybe (FilePath, Annex (Maybe String)))+prepSendAnnex' key = prepSendAnnex key >>= \case+ Just (f, checksuccess) -> + let checksuccess' = ifM checksuccess+ ( return Nothing+ , return (Just "content changed while it was being sent")+ )+ in return (Just (f, checksuccess'))+ Nothing -> return Nothing cleanObjectLoc :: Key -> Annex () -> Annex () cleanObjectLoc key cleaner = do
Annex/CopyFile.hs view
@@ -113,7 +113,9 @@ ( case iv of Just x -> ifM (liftIO $ finalizeIncremental x) ( return (True, Verified)- , return (False, UnVerified)+ , do+ warning "verification of content failed"+ return (False, UnVerified) ) Nothing -> return (True, UnVerified) , return (False, UnVerified)
Annex/Drop.hs view
@@ -10,7 +10,6 @@ module Annex.Drop where import Annex.Common-import qualified Annex import Logs.Trust import Annex.NumCopies import Types.Remote (uuid, appendonly, config, remotetype, thirdPartyPopulated)@@ -119,10 +118,10 @@ dropl fs n = checkdrop fs n Nothing $ \pcc numcopies mincopies -> stopUnless (inAnnex key) $- Command.Drop.startLocal pcc afile ai si numcopies mincopies key preverified+ Command.Drop.startLocal pcc afile ai si numcopies mincopies key preverified (Command.Drop.DroppingUnused False) dropr fs r n = checkdrop fs n (Just $ Remote.uuid r) $ \pcc numcopies mincopies ->- Command.Drop.startRemote pcc afile ai si numcopies mincopies key r+ Command.Drop.startRemote pcc afile ai si numcopies mincopies key (Command.Drop.DroppingUnused False) r ai = mkActionItem (key, afile)
Annex/Init.hs view
@@ -1,6 +1,6 @@ {- git-annex repository initialization -- - Copyright 2011-2020 Joey Hess <id@joeyh.name>+ - Copyright 2011-2021 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -51,14 +51,15 @@ import Utility.UserInfo import qualified Utility.RawFilePath as R import Utility.ThreadScheduler-#ifndef mingw32_HOST_OS import Annex.Perms+#ifndef mingw32_HOST_OS import Utility.FileMode import System.Posix.User import qualified Utility.LockFile.Posix as Posix #endif import qualified Data.Map as M+import Control.Monad.IO.Class (MonadIO) #ifndef mingw32_HOST_OS import Data.Either import qualified System.FilePath.ByteString as P@@ -241,32 +242,40 @@ - or removing write access from files. -} probeCrippledFileSystem :: Annex Bool probeCrippledFileSystem = withEventuallyCleanedOtherTmp $ \tmp -> do- (r, warnings) <- liftIO $ probeCrippledFileSystem' tmp+ (r, warnings) <- probeCrippledFileSystem' tmp+ (Just freezeContent)+ (Just thawContent) mapM_ warning warnings return r -probeCrippledFileSystem' :: RawFilePath -> IO (Bool, [String])+probeCrippledFileSystem'+ :: (MonadIO m, MonadCatch m)+ => RawFilePath+ -> Maybe (RawFilePath -> m ())+ -> Maybe (RawFilePath -> m ())+ -> m (Bool, [String]) #ifdef mingw32_HOST_OS-probeCrippledFileSystem' _ = return (True, [])+probeCrippledFileSystem' _ _ _ = return (True, []) #else-probeCrippledFileSystem' tmp = do- let f = fromRawFilePath (tmp P.</> "gaprobe")- writeFile f ""- r <- probe f- void $ tryIO $ allowWrite (toRawFilePath f)- removeFile f+probeCrippledFileSystem' tmp freezecontent thawcontent = do+ let f = tmp P.</> "gaprobe"+ let f' = fromRawFilePath f+ liftIO $ writeFile f' ""+ r <- probe f'+ void $ tryNonAsync $ (fromMaybe (liftIO . allowWrite) thawcontent) f+ liftIO $ removeFile f' return r where probe f = catchDefaultIO (True, []) $ do let f2 = f ++ "2"- removeWhenExistsWith R.removeLink (toRawFilePath f2)- createSymbolicLink f f2- removeWhenExistsWith R.removeLink (toRawFilePath f2)- preventWrite (toRawFilePath f)+ liftIO $ removeWhenExistsWith R.removeLink (toRawFilePath f2)+ liftIO $ createSymbolicLink f f2+ liftIO $ removeWhenExistsWith R.removeLink (toRawFilePath f2)+ (fromMaybe (liftIO . preventWrite) freezecontent) (toRawFilePath f) -- Should be unable to write to the file, unless -- running as root, but some crippled -- filesystems ignore write bit removals.- ifM ((== 0) <$> getRealUserID)+ liftIO $ ifM ((== 0) <$> getRealUserID) ( return (False, []) , do r <- catchBoolIO $ do@@ -283,7 +292,8 @@ warning "Detected a crippled filesystem." setCrippledFileSystem True - {- Normally git disables core.symlinks itself when the+ {- Normally git disables core.symlinks itself when the:w+ - - filesystem does not support them. But, even if symlinks are - supported, we don't use them by default in a crippled - filesystem. -}
Annex/Perms.hs view
@@ -1,6 +1,6 @@ {- git-annex file permissions -- - Copyright 2012-2020 Joey Hess <id@joeyh.name>+ - Copyright 2012-2021 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -17,7 +17,6 @@ freezeContent, isContentWritePermOk, thawContent,- chmodContent, createContentDir, freezeContentDir, thawContentDir,@@ -132,8 +131,9 @@ - owned by another user, so failure to set this mode is ignored. -} freezeContent :: RawFilePath -> Annex ()-freezeContent file = unlessM crippledFileSystem $+freezeContent file = unlessM crippledFileSystem $ do withShared go+ freezeHook file where go GroupShared = liftIO $ void $ tryIO $ modifyFileMode file $ addModes [ownerReadMode, groupReadMode, ownerWriteMode, groupWriteMode]@@ -157,22 +157,10 @@ Nothing -> True Just havemode -> havemode == combineModes (havemode:wantmode) -{- Adjusts read mode of annexed file per core.sharedRepository setting. -}-chmodContent :: RawFilePath -> Annex ()-chmodContent file = unlessM crippledFileSystem $- withShared go- where- go GroupShared = liftIO $ void $ tryIO $ modifyFileMode file $- addModes [ownerReadMode, groupReadMode]- go AllShared = liftIO $ void $ tryIO $ modifyFileMode file $- addModes readModes- go _ = liftIO $ modifyFileMode file $- addModes [ownerReadMode]- {- Allows writing to an annexed file that freezeContent was called on - before. -} thawContent :: RawFilePath -> Annex ()-thawContent file = thawPerms $ withShared go+thawContent file = thawPerms (withShared go) (thawHook file) where go GroupShared = liftIO $ void $ tryIO $ groupWriteRead file go AllShared = liftIO $ void $ tryIO $ groupWriteRead file@@ -180,11 +168,12 @@ {- Runs an action that thaws a file's permissions. This will probably - fail on a crippled filesystem. But, if file modes are supported on a- - crippled filesystem, the file may be frozen, so try to thaw it. -}-thawPerms :: Annex () -> Annex ()-thawPerms a = ifM crippledFileSystem- ( void $ tryNonAsync a- , a+ - crippled filesystem, the file may be frozen, so try to thaw its+ - permissions. -}+thawPerms :: Annex () -> Annex () -> Annex ()+thawPerms a hook = ifM crippledFileSystem+ ( void (tryNonAsync a)+ , hook >> a ) {- Blocks writing to the directory an annexed file is in, to prevent the@@ -193,8 +182,9 @@ - file. -} freezeContentDir :: RawFilePath -> Annex ()-freezeContentDir file = unlessM crippledFileSystem $+freezeContentDir file = unlessM crippledFileSystem $ do withShared go+ freezeHook dir where dir = parentDir file go GroupShared = liftIO $ void $ tryIO $ groupWriteRead dir@@ -202,8 +192,9 @@ go _ = liftIO $ preventWrite dir thawContentDir :: RawFilePath -> Annex ()-thawContentDir file = - thawPerms $ liftIO $ allowWrite $ parentDir file+thawContentDir file = thawPerms (liftIO $ allowWrite dir) (thawHook dir)+ where+ dir = parentDir file {- Makes the directory tree to store an annexed file's content, - with appropriate permissions on each level. -}@@ -212,7 +203,8 @@ unlessM (liftIO $ R.doesPathExist dir) $ createAnnexDirectory dir -- might have already existed with restricted perms- unlessM crippledFileSystem $+ unlessM crippledFileSystem $ do+ thawHook dir liftIO $ allowWrite dir where dir = parentDir dest@@ -226,3 +218,17 @@ v <- tryNonAsync a freezeContentDir f either throwM return v++freezeHook :: RawFilePath -> Annex ()+freezeHook p = maybe noop go =<< annexFreezeContentCommand <$> Annex.getGitConfig+ where+ go basecmd = void $ liftIO $+ boolSystem "sh" [Param "-c", Param $ gencmd basecmd]+ gencmd = massReplace [ ("%path", shellEscape (fromRawFilePath p)) ]++thawHook :: RawFilePath -> Annex ()+thawHook p = maybe noop go =<< annexThawContentCommand <$> Annex.getGitConfig+ where+ go basecmd = void $ liftIO $+ boolSystem "sh" [Param "-c", Param $ gencmd basecmd]+ gencmd = massReplace [ ("%path", shellEscape (fromRawFilePath p)) ]
Annex/Transfer.hs view
@@ -205,13 +205,8 @@ , return observeFailure ) - getbytescomplete metervar- | transferDirection t == Upload =- liftIO $ maybe 0 fromBytesProcessed - <$> readTVarIO metervar- | otherwise = do- f <- fromRepo $ gitAnnexTmpObjectLocation (transferKey t)- liftIO $ catchDefaultIO 0 $ getFileSize f+ getbytescomplete metervar = liftIO $+ maybe 0 fromBytesProcessed <$> readTVarIO metervar detectStallsAndSuggestConfig :: Maybe StallDetection -> TVar (Maybe BytesProcessed) -> Annex a -> Annex a detectStallsAndSuggestConfig Nothing _ a = a
Annex/TransferrerPool.hs view
@@ -133,12 +133,8 @@ ifM (catchBoolIO $ bracket setup cleanup (go bpv)) ( return (Right ()) , do- n <- case transferDirection t of- Upload -> liftIO $ atomically $ - fromBytesProcessed <$> readTVar bpv- Download -> do- f <- runannex $ fromRepo $ gitAnnexTmpObjectLocation (transferKey t)- liftIO $ catchDefaultIO 0 $ getFileSize f+ n <- liftIO $ atomically $+ fromBytesProcessed <$> readTVar bpv return $ Left $ info { bytesComplete = Just n } ) where
Build/Configure.hs view
@@ -1,6 +1,7 @@ {- Checks system configuration and generates Build/SysConfig and Build/Version. -} {-# OPTIONS_GHC -fno-warn-tabs #-}+{-# LANGUAGE CPP #-} module Build.Configure where @@ -23,7 +24,7 @@ , testCp "cp_a" "-a" , testCp "cp_p" "-p" , testCp "cp_preserve_timestamps" "--preserve=timestamps"- , testCp "cp_reflink_supported" "--reflink=auto"+ , testCpReflinkAuto , TestCase "xargs -0" $ testCmd "xargs_0" "xargs -0 </dev/null" , TestCase "rsync" $ testCmd "rsync" "rsync --version >/dev/null" , TestCase "curl" $ testCmd "curl" "curl --version >/dev/null"@@ -50,6 +51,16 @@ where cmd = "cp " ++ option cmdline = cmd ++ " " ++ testFile ++ " " ++ testFile ++ ".new"++testCpReflinkAuto :: TestCase+#ifdef mingw32_HOST_OS+-- Windows does not support reflink so don't even try to use the option.+testCpReflinkAuto = TestCase k (Config k (BoolConfig False))+#else+testCpReflinkAuto = testCp k "--reflink=auto"+#endif+ where+ k = "cp_reflink_supported" getUpgradeLocation :: Test getUpgradeLocation = do
CHANGELOG view
@@ -1,3 +1,27 @@+git-annex (8.20210630) upstream; urgency=medium++ * Fixed bug that interrupting git-annex repair (or assistant) while+ it was fixing repository corruption would lose objects that were+ contained in pack files. Also the assistant might sometimes have+ crashed with the same result.+ * repair: Fix reversion in version 8.20200522 that prevented fetching+ missing objects from remotes.+ * sync: Partly work around github behavior that first branch to be pushed+ to a new repository is assumed to be the head branch, by not pushing+ synced/git-annex first.+ * Added annex.freezecontent-command and annex.thawcontent-command+ configs.+ * Improve display of errors when transfers fail.+ * Dropping an unused object with drop --unused or dropunused will+ mark it as dead, preventing fsck --all from complaining about it+ after it's been dropped from all repositories.+ * addurl, importfeed: Added --no-raw option that forces download+ with youtube-dl or a special remote. In particular this can avoid+ falling back to raw download when youtube-dl is blocked for some+ reason.++ -- Joey Hess <id@joeyh.name> Wed, 30 Jun 2021 11:48:16 -0400+ git-annex (8.20210621) upstream; urgency=medium * New matching options --excludesamecontent and --includesamecontent
Command/AddUrl.hs view
@@ -1,6 +1,6 @@ {- git-annex command -- - Copyright 2011-2020 Joey Hess <id@joeyh.name>+ - Copyright 2011-2021 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -54,6 +54,7 @@ data DownloadOptions = DownloadOptions { relaxedOption :: Bool , rawOption :: Bool+ , noRawOption :: Bool , fileOption :: Maybe FilePath , preserveFilenameOption :: Bool , checkGitIgnoreOption :: CheckGitIgnore@@ -91,6 +92,10 @@ ( long "raw" <> help "disable special handling for torrents, youtube-dl, etc" )+ <*> switch+ ( long "no-raw"+ <> help "prevent downloading raw url content, must use special handling"+ ) <*> (if withfileoptions then optional (strOption ( long "file" <> metavar paramFile@@ -265,7 +270,7 @@ addurl = addUrlChecked o url file webUUID $ \k -> ifM (pure (not (rawOption (downloadOptions o))) <&&> youtubeDlSupported url) ( return (True, True, setDownloader url YoutubeDownloader)- , return (Url.urlExists urlinfo, Url.urlSize urlinfo == fromKey keySize k, url)+ , checkRaw (downloadOptions o) $ return (Url.urlExists urlinfo, Url.urlSize urlinfo == fromKey keySize k, url) ) {- Check that the url exists, and has the same size as the key,@@ -326,7 +331,7 @@ in ifAnnexed f (alreadyannexed (fromRawFilePath f)) (dl f)- Left _ -> normalfinish tmp+ Left _ -> checkRaw o (normalfinish tmp) where dl dest = withTmpWorkDir mediakey $ \workdir -> do let cleanuptmp = pruneTmpWorkDirBefore tmp (liftIO . removeWhenExistsWith R.removeLink)@@ -340,7 +345,7 @@ showDestinationFile (fromRawFilePath dest) addWorkTree canadd addunlockedmatcher webUUID mediaurl dest mediakey (Just (toRawFilePath mediafile)) return $ Just mediakey- Right Nothing -> normalfinish tmp+ Right Nothing -> checkRaw o (normalfinish tmp) Left msg -> do cleanuptmp warning msg@@ -356,6 +361,11 @@ else do warning $ dest ++ " already exists; not overwriting" return Nothing+ +checkRaw :: DownloadOptions -> Annex a -> Annex a+checkRaw o a+ | noRawOption o = giveup "Unable to use youtube-dl or a special remote and --no-raw was specified."+ | otherwise = a {- The destination file is not known at start time unless the user provided - a filename. It's not displayed then for output consistency, @@ -464,8 +474,9 @@ nodownloadWeb addunlockedmatcher o url urlinfo file | Url.urlExists urlinfo = if rawOption o then nomedia- else either (const nomedia) (usemedia . toRawFilePath)- =<< youtubeDlFileName url+ else youtubeDlFileName url >>= \case+ Right mediafile -> usemedia (toRawFilePath mediafile)+ Left _ -> checkRaw o nomedia | otherwise = do warning $ "unable to access url: " ++ url return Nothing
Command/Drop.hs view
@@ -86,29 +86,32 @@ checkDropAuto (autoMode o) from afile key $ \numcopies mincopies -> stopUnless wantdrop $ case from of- Nothing -> startLocal pcc afile ai si numcopies mincopies key []- Just remote -> startRemote pcc afile ai si numcopies mincopies key remote+ Nothing -> startLocal pcc afile ai si numcopies mincopies key [] ud+ Just remote -> startRemote pcc afile ai si numcopies mincopies key ud remote where wantdrop | autoMode o = wantDrop False (Remote.uuid <$> from) (Just key) afile Nothing | otherwise = return True pcc = PreferredContentChecked (autoMode o)+ ud = case (batchOption o, keyOptions o) of+ (NoBatch, Just WantUnusedKeys) -> DroppingUnused True+ _ -> DroppingUnused False startKeys :: DropOptions -> Maybe Remote -> (SeekInput, Key, ActionItem) -> CommandStart startKeys o from (si, key, ai) = start' o from key (AssociatedFile Nothing) ai si -startLocal :: PreferredContentChecked -> AssociatedFile -> ActionItem -> SeekInput -> NumCopies -> MinCopies -> Key -> [VerifiedCopy] -> CommandStart-startLocal pcc afile ai si numcopies mincopies key preverified =+startLocal :: PreferredContentChecked -> AssociatedFile -> ActionItem -> SeekInput -> NumCopies -> MinCopies -> Key -> [VerifiedCopy] -> DroppingUnused -> CommandStart+startLocal pcc afile ai si numcopies mincopies key preverified ud = starting "drop" (OnlyActionOn key ai) si $- performLocal pcc key afile numcopies mincopies preverified+ performLocal pcc key afile numcopies mincopies preverified ud -startRemote :: PreferredContentChecked -> AssociatedFile -> ActionItem -> SeekInput -> NumCopies -> MinCopies -> Key -> Remote -> CommandStart-startRemote pcc afile ai si numcopies mincopies key remote = +startRemote :: PreferredContentChecked -> AssociatedFile -> ActionItem -> SeekInput -> NumCopies -> MinCopies -> Key -> DroppingUnused -> Remote -> CommandStart+startRemote pcc afile ai si numcopies mincopies key ud remote = starting ("drop " ++ Remote.name remote) (OnlyActionOn key ai) si $- performRemote pcc key afile numcopies mincopies remote+ performRemote pcc key afile numcopies mincopies remote ud -performLocal :: PreferredContentChecked -> Key -> AssociatedFile -> NumCopies -> MinCopies -> [VerifiedCopy] -> CommandPerform-performLocal pcc key afile numcopies mincopies preverified = lockContentForRemoval key fallback $ \contentlock -> do+performLocal :: PreferredContentChecked -> Key -> AssociatedFile -> NumCopies -> MinCopies -> [VerifiedCopy] -> DroppingUnused -> CommandPerform+performLocal pcc key afile numcopies mincopies preverified ud = lockContentForRemoval key fallback $ \contentlock -> do u <- getUUID (tocheck, verified) <- verifiableCopies key [u] doDrop pcc u (Just contentlock) key afile numcopies mincopies [] (preverified ++ verified) tocheck@@ -120,7 +123,7 @@ ] removeAnnex contentlock notifyDrop afile True- next $ cleanupLocal key+ next $ cleanupLocal key ud , do notifyDrop afile False stop@@ -131,10 +134,10 @@ -- is present, but due to buffering, may find it present for the -- second file before the first is dropped. If so, nothing remains -- to be done except for cleaning up.- fallback = next $ cleanupLocal key+ fallback = next $ cleanupLocal key ud -performRemote :: PreferredContentChecked -> Key -> AssociatedFile -> NumCopies -> MinCopies -> Remote -> CommandPerform-performRemote pcc key afile numcopies mincopies remote = do+performRemote :: PreferredContentChecked -> Key -> AssociatedFile -> NumCopies -> MinCopies -> Remote -> DroppingUnused -> CommandPerform+performRemote pcc key afile numcopies mincopies remote ud = do -- Filter the uuid it's being dropped from out of the lists of -- places assumed to have the key, and places to check. (tocheck, verified) <- verifiableCopies key [uuid]@@ -147,22 +150,35 @@ , show proof ] ok <- Remote.action (Remote.removeKey remote key)- next $ cleanupRemote key remote ok+ next $ cleanupRemote key remote ud ok , stop ) where uuid = Remote.uuid remote -cleanupLocal :: Key -> CommandCleanup-cleanupLocal key = do- logStatus key InfoMissing+cleanupLocal :: Key -> DroppingUnused -> CommandCleanup+cleanupLocal key ud = do+ logStatus key (dropStatus ud) return True -cleanupRemote :: Key -> Remote -> Bool -> CommandCleanup-cleanupRemote key remote ok = do+cleanupRemote :: Key -> Remote -> DroppingUnused -> Bool -> CommandCleanup+cleanupRemote key remote ud ok = do when ok $- Remote.logStatus remote key InfoMissing+ Remote.logStatus remote key (dropStatus ud) return ok++{- Set when the user explicitly chose to operate on unused content.+ - Presumably the user still expects the last git-annex unused to be+ - correct at this point. -}+newtype DroppingUnused = DroppingUnused Bool++{- When explicitly dropping unused content, mark the key as dead, at least+ - in the repository it was dropped from. It may still be in other+ - repositories, and will not be treated as dead until dropped from all of+ - them. -}+dropStatus :: DroppingUnused -> LogStatus+dropStatus (DroppingUnused False) = InfoMissing+dropStatus (DroppingUnused True) = InfoDead {- Before running the dropaction, checks specified remotes to - verify that enough copies of a key exist to allow it to be
Command/DropUnused.hs view
@@ -49,7 +49,7 @@ perform from numcopies mincopies key = case from of Just r -> do showAction $ "from " ++ Remote.name r- Command.Drop.performRemote pcc key (AssociatedFile Nothing) numcopies mincopies r+ Command.Drop.performRemote pcc key (AssociatedFile Nothing) numcopies mincopies r ud Nothing -> ifM (inAnnex key) ( droplocal , ifM (objectFileExists key)@@ -63,8 +63,9 @@ ) ) where- droplocal = Command.Drop.performLocal pcc key (AssociatedFile Nothing) numcopies mincopies []+ droplocal = Command.Drop.performLocal pcc key (AssociatedFile Nothing) numcopies mincopies [] ud pcc = Command.Drop.PreferredContentChecked False+ ud = Command.Drop.DroppingUnused True performOther :: (Key -> Git.Repo -> RawFilePath) -> Key -> CommandPerform performOther filespec key = do
Command/ImportFeed.hs view
@@ -42,7 +42,7 @@ import Logs.MetaData import Annex.MetaData import Annex.FileMatcher-import Command.AddUrl (addWorkTree)+import Command.AddUrl (addWorkTree, checkRaw) import Annex.UntrustedFilePath import qualified Annex.Branch import Logs@@ -185,7 +185,7 @@ let f' = fromRawFilePath f r <- Remote.claimingUrl url if Remote.uuid r == webUUID || rawOption (downloadOptions opts)- then do+ then checkRaw (downloadOptions opts) $ do let dlopts = (downloadOptions opts) -- force using the filename -- chosen here@@ -326,8 +326,9 @@ , downloadlink ) where- downloadlink = performDownload addunlockedmatcher opts cache todownload- { location = Enclosure linkurl }+ downloadlink = checkRaw (downloadOptions opts) $+ performDownload addunlockedmatcher opts cache todownload+ { location = Enclosure linkurl } addmediafast linkurl mediaurl mediakey = ifM (pure (not (rawOption (downloadOptions opts)))
Command/Mirror.hs view
@@ -69,7 +69,8 @@ ( Command.Move.toStart Command.Move.RemoveNever afile key ai si =<< getParsed r , do (numcopies, mincopies) <- getSafestNumMinCopies afile key- Command.Drop.startRemote pcc afile ai si numcopies mincopies key =<< getParsed r+ Command.Drop.startRemote pcc afile ai si numcopies mincopies key (Command.Drop.DroppingUnused False)+ =<< getParsed r ) FromRemote r -> checkFailedTransferDirection ai Download $ do haskey <- flip Remote.hasKey key =<< getParsed r@@ -82,7 +83,7 @@ Right False -> ifM (inAnnex key) ( do (numcopies, mincopies) <- getSafestNumMinCopies afile key- Command.Drop.startLocal pcc afile ai si numcopies mincopies key []+ Command.Drop.startLocal pcc afile ai si numcopies mincopies key [] (Command.Drop.DroppingUnused False) , stop ) where
Command/Move.hs view
@@ -186,7 +186,7 @@ removeAnnex contentlock next $ do () <- setpresentremote- Command.Drop.cleanupLocal key+ Command.Drop.cleanupLocal key (Command.Drop.DroppingUnused False) faileddrophere setpresentremote = do showLongNote "(Use --force to override this check, or adjust numcopies.)" showLongNote "Content not dropped from here."@@ -199,7 +199,7 @@ -- is present, but due to buffering, may find it present for the -- second file before the first is dropped. If so, nothing remains -- to be done except for cleaning up.- lockfailed = next $ Command.Drop.cleanupLocal key+ lockfailed = next $ Command.Drop.cleanupLocal key (Command.Drop.DroppingUnused False) fromStart :: RemoveWhen -> AssociatedFile -> Key -> ActionItem -> SeekInput -> Remote -> CommandStart fromStart removewhen afile key ai si src = @@ -262,7 +262,7 @@ , "(" ++ reason ++ ")" ] ok <- Remote.action (Remote.removeKey src key)- next $ Command.Drop.cleanupRemote key src ok+ next $ Command.Drop.cleanupRemote key src (Command.Drop.DroppingUnused False) ok faileddropremote = do showLongNote "(Use --force to override this check, or adjust numcopies.)"
Command/Sync.hs view
@@ -604,8 +604,15 @@ - direct push is tried, with stderr discarded, to update the branch ref - on the remote. -- - The sync push forces the update of the remote synced/git-annex branch.- - This is necessary if a transition has rewritten the git-annex branch.+ - The sync push first sends the synced/master branch,+ - and then forces the update of the remote synced/git-annex branch.+ -+ - Since some providers like github may treat the first branch sent+ - as the default branch, it's better to make that be synced/master than+ - synced/git-annex. (Although neither is ideal, it's the best that+ - can be managed given the constraints on order.)+ -+ - The forcing is necessary if a transition has rewritten the git-annex branch. - Normally any changes to the git-annex branch get pulled and merged before - this push, so this forcing is unlikely to overwrite new data pushed - in from another repository that is also syncing.@@ -618,8 +625,8 @@ pushBranch remote mbranch g = directpush `after` annexpush `after` syncpush where syncpush = flip Git.Command.runBool g $ pushparams $ catMaybes- [ Just $ Git.Branch.forcePush $ refspec Annex.Branch.name- , (refspec . fromAdjustedBranch) <$> mbranch+ [ (refspec . fromAdjustedBranch) <$> mbranch+ , Just $ Git.Branch.forcePush $ refspec Annex.Branch.name ] annexpush = void $ tryIO $ flip Git.Command.runQuiet g $ pushparams [ Git.fromRef $ Git.Ref.base $ Annex.Branch.name ]
Git/Repair.hs view
@@ -1,6 +1,6 @@ {- git repository recovery -- - Copyright 2013-2014 Joey Hess <id@joeyh.name>+ - Copyright 2013-2021 Joey Hess <id@joeyh.name> - - Licensed under the GNU AGPL version 3 or higher. -}@@ -29,6 +29,7 @@ import Git.Types import Git.Fsck import Git.Index+import Git.Env import qualified Git.Config as Config import qualified Git.Construct as Construct import qualified Git.LsTree as LsTree@@ -61,15 +62,14 @@ whenM (isMissing s r) $ removeLoose s -{- Explodes all pack files, and deletes them.- -- - First moves all pack files to a temp dir, before unpacking them each in- - turn.+{- Explodes all pack files to loose objects, and deletes the pack files. -- - This is because unpack-objects will not unpack a pack file if it's in the- - git repo.+ - git unpack-objects will not unpack objects from a pack file that are+ - in the git repo. So, GIT_OBJECT_DIRECTORY is pointed to a temporary+ - directory, and the loose objects then are moved into place, before+ - deleting the pack files. -- - Also, this prevents unpack-objects from possibly looking at corrupt+ - Also, that prevents unpack-objects from possibly looking at corrupt - pack files to see if they contain an object, while unpacking a - non-corrupt pack file. -}@@ -78,18 +78,28 @@ where go [] = return False go packs = withTmpDir "packs" $ \tmpdir -> do+ r' <- addGitEnv r "GIT_OBJECT_DIRECTORY" tmpdir putStrLn "Unpacking all pack files." forM_ packs $ \packfile -> do- moveFile packfile (tmpdir </> takeFileName packfile)- removeWhenExistsWith R.removeLink- (packIdxFile (toRawFilePath packfile))- forM_ packs $ \packfile -> do- let tmp = tmpdir </> takeFileName packfile- allowRead (toRawFilePath tmp)+ -- Just in case permissions are messed up.+ allowRead (toRawFilePath packfile) -- May fail, if pack file is corrupt. void $ tryIO $- pipeWrite [Param "unpack-objects", Param "-r"] r $ \h ->- L.hPut h =<< L.readFile tmp+ pipeWrite [Param "unpack-objects", Param "-r"] r' $ \h ->+ L.hPut h =<< L.readFile packfile+ objs <- dirContentsRecursive tmpdir+ forM_ objs $ \objfile -> do+ f <- relPathDirToFile+ (toRawFilePath tmpdir)+ (toRawFilePath objfile)+ let dest = objectsDir r P.</> f+ createDirectoryIfMissing True+ (fromRawFilePath (parentDir dest))+ moveFile objfile (fromRawFilePath dest)+ forM_ packs $ \packfile -> do+ let f = toRawFilePath packfile+ removeWhenExistsWith R.removeLink f+ removeWhenExistsWith R.removeLink (packIdxFile f) return True {- Try to retrieve a set of missing objects, from the remotes of a@@ -106,6 +116,9 @@ unlessM (boolSystem "git" [Param "init", File tmpdir]) $ error $ "failed to create temp repository in " ++ tmpdir tmpr <- Config.read =<< Construct.fromPath (toRawFilePath tmpdir)+ let repoconfig r' = fromRawFilePath (localGitDir r' P.</> "config")+ whenM (doesFileExist (repoconfig r)) $+ L.readFile (repoconfig r) >>= L.writeFile (repoconfig tmpr) rs <- Construct.fromRemotes r stillmissing <- pullremotes tmpr rs fetchrefstags missing if S.null (knownMissing stillmissing)
Messages/Serialized.hs view
@@ -32,7 +32,7 @@ -> (SerializedOutputResponse -> m ()) -- ^ Send response to child process. -> (Maybe BytesProcessed -> m ())- -- ^ When a progress meter is running, is updated with+ -- ^ When a progress meter is running, it is updated with -- progress meter values sent by the process. -- When a progress meter is stopped, Nothing is sent. -> (forall a. Annex a -> m a)
Remote/Git.hs view
@@ -549,8 +549,11 @@ u <- getUUID hardlink <- wantHardLink -- run copy from perspective of remote- onLocalFast st $ Annex.Content.prepSendAnnex key >>= \case- Just (object, checksuccess) -> do+ onLocalFast st $ Annex.Content.prepSendAnnex' key >>= \case+ Just (object, check) -> do+ let checksuccess = check >>= \case+ Just err -> giveup err+ Nothing -> return True let verify = Annex.Content.RemoteVerify r copier <- mkFileCopier hardlink st (ok, v) <- runTransfer (Transfer Download u (fromKey id key))@@ -673,7 +676,7 @@ copyToRemote' repo r st@(State connpool duc _ _ _) key file meterupdate | not $ Git.repoIsUrl repo = ifM duc ( guardUsable repo (giveup "cannot access remote") $ commitOnCleanup repo r st $- copylocal =<< Annex.Content.prepSendAnnex key+ copylocal =<< Annex.Content.prepSendAnnex' key , giveup "remote does not have expected annex.uuid value" ) | Git.repoIsSsh repo = commitOnCleanup repo r st $@@ -684,11 +687,11 @@ | otherwise = giveup "copying to non-ssh repo not supported" where copylocal Nothing = giveup "content not available"- copylocal (Just (object, checksuccess)) = do- -- The checksuccess action is going to be run in+ copylocal (Just (object, check)) = do+ -- The check action is going to be run in -- the remote's Annex, but it needs access to the local -- Annex monad's state.- checksuccessio <- Annex.withCurrentState checksuccess+ checkio <- Annex.withCurrentState check u <- getUUID hardlink <- wantHardLink -- run copy from perspective of remote@@ -698,9 +701,12 @@ let verify = Annex.Content.RemoteVerify r copier <- mkFileCopier hardlink st let rsp = RetrievalAllKeysSecure+ let checksuccess = liftIO checkio >>= \case+ Just err -> giveup err+ Nothing -> return True res <- logStatusAfter key $ Annex.Content.getViaTmp rsp verify key file $ \dest -> metered (Just (combineMeterUpdate meterupdate p)) key $ \_ p' -> - copier object (fromRawFilePath dest) key p' (liftIO checksuccessio) verify+ copier object (fromRawFilePath dest) key p' checksuccess verify Annex.Content.saveState True return res )
Test.hs view
@@ -142,7 +142,9 @@ exitWith exitcode runsubprocesstests (Just _) = isolateGitConfig $ do ensuretmpdir- crippledfilesystem <- fst <$> Annex.Init.probeCrippledFileSystem' (toRawFilePath tmpdir)+ crippledfilesystem <- fst <$> Annex.Init.probeCrippledFileSystem'+ (toRawFilePath tmpdir)+ Nothing Nothing adjustedbranchok <- Annex.AdjustedBranch.isGitVersionSupported case tryIngredients ingredients (tastyOptionSet opts) (tests crippledfilesystem adjustedbranchok opts) of Nothing -> error "No tests found!?"
Types/GitConfig.hs view
@@ -104,6 +104,8 @@ , annexFsckNudge :: Bool , annexAutoUpgrade :: AutoUpgrade , annexExpireUnused :: Maybe (Maybe Duration)+ , annexFreezeContentCommand :: Maybe String+ , annexThawContentCommand :: Maybe String , annexSecureEraseCommand :: Maybe String , annexGenMetaData :: Bool , annexListen :: Maybe String@@ -191,6 +193,8 @@ getmaybe (annexConfig "autoupgrade") , annexExpireUnused = either (const Nothing) Just . parseDuration <$> getmaybe (annexConfig "expireunused")+ , annexFreezeContentCommand = getmaybe (annexConfig "freezecontent-command")+ , annexThawContentCommand = getmaybe (annexConfig "thawcontent-command") , annexSecureEraseCommand = getmaybe (annexConfig "secure-erase-command") , annexGenMetaData = getbool (annexConfig "genmetadata") False , annexListen = getmaybe (annexConfig "listen")
doc/git-annex-addurl.mdwn view
@@ -49,6 +49,12 @@ special remotes. This will for example, make addurl download the .torrent file and not the contents it points to. +* `--no-raw`++ Require content pointed to by the url to be downloaded using youtube-dl+ or a special remote, rather than the raw content of the url. if that+ cannot be done, the add will fail.+ * `--file=name` Use with a filename that does not yet exist to add a new file
doc/git-annex-dead.mdwn view
@@ -18,7 +18,7 @@ When a key is specified, indicates that the content of that key has been irretrievably lost. This prevents commands like `git annex fsck --all`-from complaining about it; `--all` will not operate on the key anymore.+from complaining about it. (To undo, add the key's content back to the repository, by using eg, `git-annex reinject`.)
doc/git-annex-dropunused.mdwn view
@@ -9,7 +9,7 @@ # DESCRIPTION Drops the data corresponding to the numbers, as listed by the last-git annex unused`+`git annex unused` You can also specify ranges of numbers, such as "1-1000". Or, specify "all" to drop all unused data.
doc/git-annex-importfeed.mdwn view
@@ -58,6 +58,13 @@ special remotes. This will for example, make importfeed download a .torrent file and not the contents it points to. +* `--no-raw`++ Require content pointed to by the url to be downloaded using youtube-dl+ or a special remote, rather than the raw content of the url. if that+ cannot be done, the import will fail, and the next import of the feed+ will retry.+ * `--template` Controls where the files are stored.
doc/git-annex.mdwn view
@@ -1213,6 +1213,16 @@ For example, to use the wipe command, set it to `wipe -f %file`. +* `annex.freezecontent-command`, `annex.thawcontent-command`++ Usually the write permission bits are unset to protect annexed objects+ from being modified or deleted. The freezecontent-command is run after+ git-annex has removed the write bit. The thawcontent-command should undo+ its effect, and is run before git-annex restores the write bit.++ In the command line, %path is replaced with the file or directory to+ operate on.+ * `annex.tune.objecthash1`, `annex.tune.objecthashlower`, `annex.tune.branchhash1` These can be passed to `git annex init` to tune the repository.
git-annex.cabal view
@@ -1,5 +1,5 @@ Name: git-annex-Version: 8.20210621+Version: 8.20210630 Cabal-Version: >= 1.10 License: AGPL-3 Maintainer: Joey Hess <id@joeyh.name>