upgrade: Handle upgrade to v6 when the repository already contains v6 unlocked files whose content is already present.

Closes https://github.com/datalad/datalad/issues/1020

The use of runWriter in scanUnlockedFiles broke due to this change;
it failed with blocked indefinitely in mvar, because the database write
handle was taken while linkFromAnnex needed to also write to it (to update
the inode cache). So, switched to using a separate runWriter for each call
to addAssociatedFileFast. A little less efficient, but not greatly; the
writes should all still be cached.
This commit is contained in:
Joey Hess 2016-10-17 15:19:47 -04:00
parent 148bd0dbfd
commit 8e22114735
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
4 changed files with 43 additions and 16 deletions

View file

@ -11,7 +11,10 @@ import Annex.Common
import Annex.Link
import Annex.CatFile
import Annex.Version
import Annex.Content
import Annex.ReplaceFile
import Config
import Git.FilePath
import qualified Git.Ref
import qualified Git.Branch
import qualified Git.LsTree
@ -54,24 +57,37 @@ ifAnnexed file yes no = maybe no yes =<< lookupFile file
- This is expensive, and so normally the associated files are updated
- incrementally when changes are noticed. So, this only needs to be done
- when initializing/upgrading a v6 mode repository.
-
- Also, the content for the unlocked file may already be present as
- an annex object. If so, make the unlocked file use that content.
-}
scanUnlockedFiles :: Annex ()
scanUnlockedFiles = whenM (isJust <$> inRepo Git.Branch.current) $
Database.Keys.runWriter $ \h -> do
showSideAction "scanning for unlocked files"
liftIO $ Database.Keys.SQL.dropAllAssociatedFiles h
(l, cleanup) <- inRepo $ Git.LsTree.lsTree Git.Ref.headRef
forM_ l $ \i ->
when (isregfile i) $
maybe noop (add h i)
=<< catKey (Git.LsTree.sha i)
liftIO $ void cleanup
scanUnlockedFiles = whenM (isJust <$> inRepo Git.Branch.current) $ do
showSideAction "scanning for unlocked files"
Database.Keys.runWriter $
liftIO . Database.Keys.SQL.dropAllAssociatedFiles
(l, cleanup) <- inRepo $ Git.LsTree.lsTree Git.Ref.headRef
forM_ l $ \i ->
when (isregfile i) $
maybe noop (add i)
=<< catKey (Git.LsTree.sha i)
liftIO $ void cleanup
where
isregfile i = case Git.Types.toBlobType (Git.LsTree.mode i) of
Just Git.Types.FileBlob -> True
Just Git.Types.ExecutableBlob -> True
_ -> False
add h i k = liftIO $ Database.Keys.SQL.addAssociatedFileFast
(toIKey k)
(Git.LsTree.file i)
h
add i k = do
let tf = Git.LsTree.file i
Database.Keys.runWriter $
liftIO . Database.Keys.SQL.addAssociatedFileFast (toIKey k) tf
whenM (inAnnex k) $ do
f <- fromRepo $ fromTopFilePath tf
destmode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus f
replaceFile f $ \tmp -> do
r <- linkFromAnnex k tmp destmode
case r of
LinkAnnexOk -> return ()
LinkAnnexNoop -> return ()
LinkAnnexFailed -> liftIO $
writePointerFile tmp k destmode