git-annex 8.20200309 → 8.20200330
raw patch · 17 files changed
+153/−109 lines, 17 files
Files
- Annex.hs +5/−1
- Annex/AdjustedBranch.hs +0/−1
- Annex/Locations.hs +0/−5
- Annex/Ssh.hs +1/−1
- Assistant/WebApp/Configurators/WebDAV.hs +4/−4
- Backend/Hash.hs +2/−1
- CHANGELOG +19/−0
- CmdLine/GitAnnex/Options.hs +5/−2
- Command/Add.hs +2/−2
- Command/PreCommit.hs +1/−5
- Git/Tree.hs +6/−2
- Remote/Helper/Hooks.hs +0/−2
- Remote/WebDAV.hs +100/−76
- Test.hs +6/−3
- Utility/Directory.hs +1/−2
- doc/git-annex-add.mdwn +0/−1
- git-annex.cabal +1/−1
Annex.hs view
@@ -325,7 +325,11 @@ } {- Adds an adjustment to the Repo data. Adjustments persist across reloads- - of the repo's config. -}+ - of the repo's config.+ -+ - Note that the action may run more than once, and should avoid eg,+ - appending the same value to a repo's config when run repeatedly.+ -} adjustGitRepo :: (Git.Repo -> IO Git.Repo) -> Annex () adjustGitRepo a = do changeState $ \s -> s { repoadjustment = \r -> repoadjustment s r >>= a }
Annex/AdjustedBranch.hs view
@@ -57,7 +57,6 @@ import Annex.GitOverlay import Utility.Tmp.Dir import Utility.CopyFile-import Utility.Directory import qualified Database.Keys import Config
Annex/Locations.hs view
@@ -66,7 +66,6 @@ gitAnnexJournalDir', gitAnnexJournalLock, gitAnnexGitQueueLock,- gitAnnexPreCommitLock, gitAnnexMergeLock, gitAnnexIndex, gitAnnexIndexStatus,@@ -468,10 +467,6 @@ - other git state that should only have one writer at a time. -} gitAnnexGitQueueLock :: Git.Repo -> FilePath gitAnnexGitQueueLock r = fromRawFilePath $ gitAnnexDir r P.</> "gitqueue.lck"--{- Lock file for the pre-commit hook. -}-gitAnnexPreCommitLock :: Git.Repo -> FilePath-gitAnnexPreCommitLock r = fromRawFilePath $ gitAnnexDir r P.</> "precommit.lck" {- Lock file for direct mode merge. -} gitAnnexMergeLock :: Git.Repo -> FilePath
Annex/Ssh.hs view
@@ -37,8 +37,8 @@ import Types.Concurrency import Git.Env import Git.Ssh-#ifndef mingw32_HOST_OS import Annex.Perms+#ifndef mingw32_HOST_OS import Annex.LockPool #endif
Assistant/WebApp/Configurators/WebDAV.hs view
@@ -15,7 +15,7 @@ import qualified Remote.WebDAV as WebDAV import Assistant.WebApp.MakeRemote import qualified Remote-import Types.Remote (RemoteConfig)+import Types.Remote (RemoteConfig, config) import Types.StandardGroups import Logs.Remote import Git.Types (RemoteName)@@ -89,16 +89,16 @@ #ifdef WITH_WEBDAV makeWebDavRemote :: SpecialRemoteMaker -> RemoteName -> CredPair -> RemoteConfig -> Handler ()-makeWebDavRemote maker name creds config = +makeWebDavRemote maker name creds c = setupCloudRemote TransferGroup Nothing $- maker name WebDAV.remote (Just creds) config+ maker name WebDAV.remote (Just creds) c {- Only returns creds previously used for the same hostname. -} previouslyUsedWebDAVCreds :: String -> Annex (Maybe CredPair) previouslyUsedWebDAVCreds hostname = previouslyUsedCredPair WebDAV.davCreds WebDAV.remote samehost where- samehost url = case urlHost =<< WebDAV.configUrl url of+ samehost r = case urlHost =<< WebDAV.configUrl (config r) of Nothing -> False Just h -> h == hostname #endif
Backend/Hash.hs view
@@ -157,7 +157,8 @@ validInExtension :: Word8 -> Bool validInExtension c | isAlphaNum (chr (fromIntegral c)) = True- | c <= 127 = False -- other ascii, spaces, punctuation, control chars+ | fromIntegral c == ord '.' = True+ | c <= 127 = False -- other ascii: spaces, punctuation, control chars | otherwise = True -- utf8 is allowed, also other encodings {- Upgrade keys that have the \ prefix on their hash due to a bug, or
CHANGELOG view
@@ -1,3 +1,22 @@+git-annex (8.20200330) upstream; urgency=medium++ * fsck: Fix reversion in 8.20200226 that made it incorrectly warn+ that hashed keys with an extension should be upgraded.+ * add --force-small: Fix a bug that, when adding a symbolic link,+ checked in the content of the file the symlink pointed to.+ Thanks, Kyle Meyer for the patch.+ * add --force-small: Fix failure when passed a modified submodule.+ Thanks, Kyle Meyer for the patch.+ * When syncing changes back from an adjusted branch to the basis branch,+ include changes to submodules.+ Thanks, Kyle Meyer for the patch.+ * webdav: Made exporttree remotes faster by caching connection to the+ server.+ * Fix a minor bug that caused options provided with -c to be passed+ multiple times to git.++ -- Joey Hess <id@joeyh.name> Mon, 30 Mar 2020 12:14:50 -0400+ git-annex (8.20200309) upstream; urgency=medium * Fix bug that caused unlocked annexed dotfiles to be added to git by the
CmdLine/GitAnnex/Options.hs view
@@ -93,8 +93,11 @@ where setnumcopies n = Annex.changeState $ \s -> s { Annex.forcenumcopies = Just $ NumCopies n } setuseragent v = Annex.changeState $ \s -> s { Annex.useragent = Just v }- setgitconfig v = Annex.adjustGitRepo $ \r -> Git.Config.store (encodeBS' v) $ - r { gitGlobalOpts = gitGlobalOpts r ++ [Param "-c", Param v] }+ setgitconfig v = Annex.adjustGitRepo $ \r -> + if Param v `elem` gitGlobalOpts r+ then return r+ else Git.Config.store (encodeBS' v) $ + r { gitGlobalOpts = gitGlobalOpts r ++ [Param "-c", Param v] } setdesktopnotify v = Annex.changeState $ \s -> s { Annex.desktopnotify = Annex.desktopnotify s <> v } {- Parser that accepts all non-option params. -}
Command/Add.hs view
@@ -107,8 +107,8 @@ addSmallOverridden file = do showNote "adding content to git repository" let file' = fromRawFilePath file- s <- liftIO $ getFileStatus file'- if isSymbolicLink s+ s <- liftIO $ getSymbolicLinkStatus file'+ if not (isRegularFile s) then addFile file else do -- Can't use addFile because the clean filter will
Command/PreCommit.hs view
@@ -32,7 +32,7 @@ (withParams seek) seek :: CmdParams -> CommandSeek-seek ps = lockPreCommitHook $ do+seek ps = do l <- workTreeItems ps -- fix symlinks to files being committed flip withFilesToBeCommitted l $ \f -> commandAction $@@ -74,7 +74,3 @@ showset v | isSet v = "+" | otherwise = "-"--{- Takes exclusive lock; blocks until available. -}-lockPreCommitHook :: Annex a -> Annex a-lockPreCommitHook = withExclusiveLock gitAnnexPreCommitLock
Git/Tree.hs view
@@ -237,8 +237,12 @@ let !modified' = modified || slmodified || wasmodified go h modified' (subtree : c) depth intree is' Just CommitObject -> do- let ti = TreeCommit (LsTree.file i) (LsTree.mode i) (LsTree.sha i)- go h wasmodified (ti:c) depth intree is+ let ti = TreeItem (LsTree.file i) (LsTree.mode i) (LsTree.sha i)+ v <- adjusttreeitem ti+ let commit = tc $ fromMaybe ti v+ go h wasmodified (commit:c) depth intree is+ where+ tc (TreeItem f m s) = TreeCommit f m s _ -> error ("unexpected object type \"" ++ decodeBS (LsTree.typeobj i) ++ "\"") | otherwise = return (c, wasmodified, i:is)
Remote/Helper/Hooks.hs view
@@ -17,9 +17,7 @@ import qualified Annex import Annex.LockFile import Annex.LockPool-#ifndef mingw32_HOST_OS import Annex.Perms-#endif {- Modifies a remote's access functions to first run the - annex-start-command hook, and trigger annex-stop-command on shutdown.
Remote/WebDAV.hs view
@@ -22,6 +22,7 @@ import Control.Monad.Catch import Control.Monad.IO.Class (MonadIO) import System.Log.Logger (debugM)+import Control.Concurrent.STM hiding (check) import Annex.Common import Types.Remote@@ -64,15 +65,18 @@ davcredsField = Accepted "davcreds" gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> RemoteStateHandle -> Annex (Maybe Remote)-gen r u rc gc rs = new- <$> parsedRemoteConfig remote rc- <*> remoteCost gc expensiveRemoteCost+gen r u rc gc rs = do+ c <- parsedRemoteConfig remote rc+ new+ <$> pure c+ <*> remoteCost gc expensiveRemoteCost+ <*> mkDavHandleVar c gc u where- new c cst = Just $ specialRemote c- (prepareDAV this $ store chunkconfig)- (prepareDAV this $ retrieve chunkconfig)- (prepareDAV this $ remove)- (prepareDAV this $ checkKey this chunkconfig)+ new c cst hdl = Just $ specialRemote c+ (simplyPrepare $ store hdl chunkconfig)+ (simplyPrepare $ retrieve hdl chunkconfig)+ (simplyPrepare $ remove hdl)+ (simplyPrepare $ checkKey hdl this chunkconfig) this where this = Remote@@ -90,13 +94,13 @@ , checkPresent = checkPresentDummy , checkPresentCheap = False , exportActions = ExportActions- { storeExport = storeExportDav this- , retrieveExport = retrieveExportDav this- , checkPresentExport = checkPresentExportDav this- , removeExport = removeExportDav this+ { storeExport = storeExportDav hdl+ , retrieveExport = retrieveExportDav hdl+ , checkPresentExport = checkPresentExportDav hdl this+ , removeExport = removeExportDav hdl , removeExportDirectory = Just $- removeExportDirectoryDav this- , renameExport = renameExportDav this+ removeExportDirectoryDav hdl+ , renameExport = renameExportDav hdl } , importActions = importUnsupported , whereisKey = Nothing@@ -133,18 +137,20 @@ c'' <- setRemoteCredPair encsetup c' gc (davCreds u) creds return (c'', u) -prepareDAV :: Remote -> (Maybe DavHandle -> helper) -> Preparer helper-prepareDAV = resourcePrepare . const . withDAVHandle--store :: ChunkConfig -> Maybe DavHandle -> Storer-store _ Nothing = byteStorer $ \_k _b _p -> return False-store (LegacyChunks chunksize) (Just dav) = fileStorer $ \k f p -> liftIO $- withMeteredFile f p $ storeLegacyChunked chunksize k dav-store _ (Just dav) = httpStorer $ \k reqbody -> liftIO $ goDAV dav $ do- let tmp = keyTmpLocation k- let dest = keyLocation k- storeHelper dav tmp dest reqbody- return True+store :: DavHandleVar -> ChunkConfig -> Storer+store hv (LegacyChunks chunksize) = fileStorer $ \k f p -> + withDavHandle hv $ \case+ Nothing -> return False+ Just dav -> liftIO $+ withMeteredFile f p $ storeLegacyChunked chunksize k dav+store hv _ = httpStorer $ \k reqbody -> + withDavHandle hv $ \case+ Nothing -> return False+ Just dav -> liftIO $ goDAV dav $ do+ let tmp = keyTmpLocation k+ let dest = keyLocation k+ storeHelper dav tmp dest reqbody+ return True storeHelper :: DavHandle -> DavLocation -> DavLocation -> RequestBody -> DAVT IO () storeHelper dav tmp dest reqbody = do@@ -164,11 +170,14 @@ retrieveCheap :: Key -> AssociatedFile -> FilePath -> Annex Bool retrieveCheap _ _ _ = return False -retrieve :: ChunkConfig -> Maybe DavHandle -> Retriever-retrieve _ Nothing = giveup "unable to connect"-retrieve (LegacyChunks _) (Just dav) = retrieveLegacyChunked dav-retrieve _ (Just dav) = fileRetriever $ \d k p -> liftIO $- goDAV dav $ retrieveHelper (keyLocation k) d p+retrieve :: DavHandleVar -> ChunkConfig -> Retriever+retrieve hv cc = fileRetriever $ \d k p ->+ withDavHandle hv $ \case+ Nothing -> giveup "unable to connect"+ Just dav -> case cc of+ LegacyChunks _ -> retrieveLegacyChunked d k p dav+ _ -> liftIO $+ goDAV dav $ retrieveHelper (keyLocation k) d p retrieveHelper :: DavLocation -> FilePath -> MeterUpdate -> DAVT IO () retrieveHelper loc d p = do@@ -176,12 +185,13 @@ inLocation loc $ withContentM $ httpBodyRetriever d p -remove :: Maybe DavHandle -> Remover-remove Nothing _ = return False-remove (Just dav) k = liftIO $ goDAV dav $- -- Delete the key's whole directory, including any- -- legacy chunked files, etc, in a single action.- removeHelper (keyDir k)+remove :: DavHandleVar -> Remover+remove hv k = withDavHandle hv $ \case+ Nothing -> return False+ Just dav -> liftIO $ goDAV dav $+ -- Delete the key's whole directory, including any+ -- legacy chunked files, etc, in a single action.+ removeHelper (keyDir k) removeHelper :: DavLocation -> DAVT IO Bool removeHelper d = do@@ -195,20 +205,21 @@ Right False -> return True _ -> return False -checkKey :: Remote -> ChunkConfig -> Maybe DavHandle -> CheckPresent-checkKey r _ Nothing _ = giveup $ name r ++ " not configured"-checkKey r chunkconfig (Just dav) k = do- showChecking r- case chunkconfig of- LegacyChunks _ -> checkKeyLegacyChunked dav k- _ -> do- v <- liftIO $ goDAV dav $- existsDAV (keyLocation k)- either giveup return v+checkKey :: DavHandleVar -> Remote -> ChunkConfig -> CheckPresent+checkKey hv r chunkconfig k = withDavHandle hv $ \case+ Nothing -> giveup $ name r ++ " not configured"+ Just dav -> do+ showChecking r+ case chunkconfig of+ LegacyChunks _ -> checkKeyLegacyChunked dav k+ _ -> do+ v <- liftIO $ goDAV dav $+ existsDAV (keyLocation k)+ either giveup return v -storeExportDav :: Remote -> FilePath -> Key -> ExportLocation -> MeterUpdate -> Annex Bool-storeExportDav r f k loc p = case exportLocation loc of- Right dest -> withDAVHandle r $ \mh -> runExport mh $ \dav -> do+storeExportDav :: DavHandleVar -> FilePath -> Key -> ExportLocation -> MeterUpdate -> Annex Bool+storeExportDav hdl f k loc p = case exportLocation loc of+ Right dest -> withDavHandle hdl $ \mh -> runExport mh $ \dav -> do reqbody <- liftIO $ httpBodyStorer f p storeHelper dav (keyTmpLocation k) dest reqbody return True@@ -216,25 +227,25 @@ warning err return False -retrieveExportDav :: Remote -> Key -> ExportLocation -> FilePath -> MeterUpdate -> Annex Bool-retrieveExportDav r _k loc d p = case exportLocation loc of- Right src -> withDAVHandle r $ \mh -> runExport mh $ \_dav -> do+retrieveExportDav :: DavHandleVar -> Key -> ExportLocation -> FilePath -> MeterUpdate -> Annex Bool+retrieveExportDav hdl _k loc d p = case exportLocation loc of+ Right src -> withDavHandle hdl $ \mh -> runExport mh $ \_dav -> do retrieveHelper src d p return True Left _err -> return False -checkPresentExportDav :: Remote -> Key -> ExportLocation -> Annex Bool-checkPresentExportDav r _k loc = case exportLocation loc of- Right p -> withDAVHandle r $ \case+checkPresentExportDav :: DavHandleVar -> Remote -> Key -> ExportLocation -> Annex Bool+checkPresentExportDav hdl r _k loc = case exportLocation loc of+ Right p -> withDavHandle hdl $ \case Nothing -> giveup $ name r ++ " not configured" Just h -> liftIO $ do v <- goDAV h $ existsDAV p either giveup return v Left err -> giveup err -removeExportDav :: Remote -> Key -> ExportLocation -> Annex Bool-removeExportDav r _k loc = case exportLocation loc of- Right p -> withDAVHandle r $ \mh -> runExport mh $ \_dav ->+removeExportDav :: DavHandleVar-> Key -> ExportLocation -> Annex Bool+removeExportDav hdl _k loc = case exportLocation loc of+ Right p -> withDavHandle hdl $ \mh -> runExport mh $ \_dav -> removeHelper p -- When the exportLocation is not legal for webdav, -- the content is certianly not stored there, so it's ok for@@ -243,16 +254,16 @@ -- this will be called to make sure it's gone. Left _err -> return True -removeExportDirectoryDav :: Remote -> ExportDirectory -> Annex Bool-removeExportDirectoryDav r dir = withDAVHandle r $ \mh -> runExport mh $ \_dav -> do+removeExportDirectoryDav :: DavHandleVar -> ExportDirectory -> Annex Bool+removeExportDirectoryDav hdl dir = withDavHandle hdl $ \mh -> runExport mh $ \_dav -> do let d = fromRawFilePath $ fromExportDirectory dir debugDav $ "delContent " ++ d safely (inLocation d delContentM) >>= maybe (return False) (const $ return True) -renameExportDav :: Remote -> Key -> ExportLocation -> ExportLocation -> Annex (Maybe Bool)-renameExportDav r _k src dest = case (exportLocation src, exportLocation dest) of- (Right srcl, Right destl) -> withDAVHandle r $ \case+renameExportDav :: DavHandleVar -> Key -> ExportLocation -> ExportLocation -> Annex (Maybe Bool)+renameExportDav hdl _k src dest = case (exportLocation src, exportLocation dest) of+ (Right srcl, Right destl) -> withDavHandle hdl $ \case Just h -- box.com's DAV endpoint has buggy handling of renames, -- so avoid renaming when using it.@@ -270,8 +281,8 @@ runExport Nothing _ = return False runExport (Just h) a = fromMaybe False <$> liftIO (goDAV h $ safely (a h)) -configUrl :: Remote -> Maybe URLString-configUrl r = fixup <$> getRemoteConfigValue urlField (config r)+configUrl :: ParsedRemoteConfig -> Maybe URLString+configUrl c = fixup <$> getRemoteConfigValue urlField c where -- box.com DAV url changed fixup = replace "https://www.box.com/dav/" boxComUrl@@ -407,15 +418,28 @@ data DavHandle = DavHandle DAVContext DavUser DavPass URLString -withDAVHandle :: Remote -> (Maybe DavHandle -> Annex a) -> Annex a-withDAVHandle r a = do- mcreds <- getCreds (config r) (gitconfig r) (uuid r)- case (mcreds, configUrl r) of- (Just (user, pass), Just baseurl) ->- withDAVContext baseurl $ \ctx ->- a (Just (DavHandle ctx (toDavUser user) (toDavPass pass) baseurl))- _ -> a Nothing+type DavHandleVar = TVar (Either (Annex (Maybe DavHandle)) (Maybe DavHandle)) +{- Prepares a DavHandle for later use. Does not connect to the server or do+ - anything else expensive. -}+mkDavHandleVar :: ParsedRemoteConfig -> RemoteGitConfig -> UUID -> Annex DavHandleVar+mkDavHandleVar c gc u = liftIO $ newTVarIO $ Left $ do+ mcreds <- getCreds c gc u+ case (mcreds, configUrl c) of+ (Just (user, pass), Just baseurl) -> do+ ctx <- mkDAVContext baseurl+ let h = DavHandle ctx (toDavUser user) (toDavPass pass) baseurl+ return (Just h)+ _ -> return Nothing++withDavHandle :: DavHandleVar -> (Maybe DavHandle -> Annex a) -> Annex a+withDavHandle hv a = liftIO (readTVarIO hv) >>= \case+ Right hdl -> a hdl+ Left mkhdl -> do+ hdl <- mkhdl+ liftIO $ atomically $ writeTVar hv (Right hdl)+ a hdl+ goDAV :: DavHandle -> DAVT IO a -> IO a goDAV (DavHandle ctx user pass _) a = choke $ run $ prettifyExceptions $ do prepDAV user pass@@ -464,8 +488,8 @@ tmp = addTrailingPathSeparator $ keyTmpLocation k dest = keyLocation k -retrieveLegacyChunked :: DavHandle -> Retriever-retrieveLegacyChunked dav = fileRetriever $ \d k p -> liftIO $+retrieveLegacyChunked :: FilePath -> Key -> MeterUpdate -> DavHandle -> Annex ()+retrieveLegacyChunked d k p dav = liftIO $ withStoredFilesLegacyChunked k dav onerr $ \locs -> Legacy.meteredWriteFileChunks p d locs $ \l -> goDAV dav $ do
Test.hs view
@@ -1574,10 +1574,13 @@ where gpgcmd = Utility.Gpg.mkGpgCmd Nothing testscheme scheme = do- gpgtmp <- (</> "gpgtest") <$> absPath tmpdir+ abstmp <- absPath tmpdir+ testscheme' scheme abstmp+ testscheme' scheme abstmp = intmpclonerepo $ whenM (Utility.Path.inPath (Utility.Gpg.unGpgCmd gpgcmd)) $ do+ -- Use a relative path to avoid too long path to gpg's+ -- agent socket.+ gpgtmp <- (</> "gpgtmp") <$> relPathCwdToFile abstmp createDirectoryIfMissing False gpgtmp- testscheme' scheme gpgtmp- testscheme' scheme gpgtmp = intmpclonerepo $ whenM (Utility.Path.inPath (Utility.Gpg.unGpgCmd gpgcmd)) $ do Utility.Gpg.testTestHarness gpgtmp gpgcmd @? "test harness self-test failed" Utility.Gpg.testHarness gpgtmp gpgcmd $ do
Utility/Directory.hs view
@@ -14,12 +14,12 @@ module Utility.SystemDirectory ) where -import System.IO.Error import Control.Monad import System.FilePath import System.PosixCompat.Files import Control.Applicative import Control.Monad.IO.Class+import Control.Monad.IfElse import System.IO.Unsafe (unsafeInterleaveIO) import System.IO.Error import Data.Maybe@@ -27,7 +27,6 @@ #ifndef mingw32_HOST_OS import Utility.SafeCommand-import Control.Monad.IfElse #endif import Utility.SystemDirectory
doc/git-annex-add.mdwn view
@@ -25,7 +25,6 @@ modification of their content unless unlocked by [[git-annex-unlock]](1). (This is not the case however when a repository is in a filesystem not supporting symlinks.)-To add a file to the annex in unlocked form, `git add` can be used instead. This command can also be used to add symbolic links, both symlinks to annexed content, and other symlinks.
git-annex.cabal view
@@ -1,5 +1,5 @@ Name: git-annex-Version: 8.20200309+Version: 8.20200330 Cabal-Version: >= 1.8 License: AGPL-3 Maintainer: Joey Hess <id@joeyh.name>