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:
parent
148bd0dbfd
commit
8e22114735
4 changed files with 43 additions and 16 deletions
|
@ -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
|
||||
|
|
|
@ -2,6 +2,8 @@ git-annex (6.20161013) UNRELEASED; urgency=medium
|
|||
|
||||
* lock, smudge: Fix edge cases where data loss could occur in v6 mode
|
||||
when the keys database was not populated.
|
||||
* upgrade: Handle upgrade to v6 when the repository already contains
|
||||
v6 unlocked files whose content is already present.
|
||||
|
||||
-- Joey Hess <id@joeyh.name> Mon, 17 Oct 2016 12:46:54 -0400
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ performNew dest key = do
|
|||
case r of
|
||||
LinkAnnexOk -> return ()
|
||||
LinkAnnexNoop -> return ()
|
||||
_ -> error "unlock failed"
|
||||
LinkAnnexFailed -> error "unlock failed"
|
||||
, liftIO $ writePointerFile tmp key destmode
|
||||
)
|
||||
next $ cleanupNew dest key destmode
|
||||
|
|
|
@ -35,4 +35,13 @@ $> ./v6-push.sh 6 2>&1 | grep '>>>'
|
|||
>
|
||||
> I am not sure yet why the keys database lacked an entry for the file;
|
||||
> perhaps something to do with it being a v6 unlocked file in a v5
|
||||
> repository. --[[Joey]]
|
||||
> repository.
|
||||
>
|
||||
> Ok.. Seems that cloning to a v5 repository, and then copying/getting
|
||||
> objects into it, and then upgrading to v6 reproduces the problem with the
|
||||
> keys database. The inode cache does not get populated for unlocked files
|
||||
> on upgrade. Also, unlocked files stay as pointer files even when their
|
||||
> content is present in annex/objects. Fixed the upgrade process to handle
|
||||
> this case.
|
||||
>
|
||||
> [[fixed|done]]] --[[Joey]]
|
||||
|
|
Loading…
Reference in a new issue