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.Link
|
||||||
import Annex.CatFile
|
import Annex.CatFile
|
||||||
import Annex.Version
|
import Annex.Version
|
||||||
|
import Annex.Content
|
||||||
|
import Annex.ReplaceFile
|
||||||
import Config
|
import Config
|
||||||
|
import Git.FilePath
|
||||||
import qualified Git.Ref
|
import qualified Git.Ref
|
||||||
import qualified Git.Branch
|
import qualified Git.Branch
|
||||||
import qualified Git.LsTree
|
import qualified Git.LsTree
|
||||||
|
@ -54,16 +57,19 @@ ifAnnexed file yes no = maybe no yes =<< lookupFile file
|
||||||
- This is expensive, and so normally the associated files are updated
|
- This is expensive, and so normally the associated files are updated
|
||||||
- incrementally when changes are noticed. So, this only needs to be done
|
- incrementally when changes are noticed. So, this only needs to be done
|
||||||
- when initializing/upgrading a v6 mode repository.
|
- 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 :: Annex ()
|
||||||
scanUnlockedFiles = whenM (isJust <$> inRepo Git.Branch.current) $
|
scanUnlockedFiles = whenM (isJust <$> inRepo Git.Branch.current) $ do
|
||||||
Database.Keys.runWriter $ \h -> do
|
|
||||||
showSideAction "scanning for unlocked files"
|
showSideAction "scanning for unlocked files"
|
||||||
liftIO $ Database.Keys.SQL.dropAllAssociatedFiles h
|
Database.Keys.runWriter $
|
||||||
|
liftIO . Database.Keys.SQL.dropAllAssociatedFiles
|
||||||
(l, cleanup) <- inRepo $ Git.LsTree.lsTree Git.Ref.headRef
|
(l, cleanup) <- inRepo $ Git.LsTree.lsTree Git.Ref.headRef
|
||||||
forM_ l $ \i ->
|
forM_ l $ \i ->
|
||||||
when (isregfile i) $
|
when (isregfile i) $
|
||||||
maybe noop (add h i)
|
maybe noop (add i)
|
||||||
=<< catKey (Git.LsTree.sha i)
|
=<< catKey (Git.LsTree.sha i)
|
||||||
liftIO $ void cleanup
|
liftIO $ void cleanup
|
||||||
where
|
where
|
||||||
|
@ -71,7 +77,17 @@ scanUnlockedFiles = whenM (isJust <$> inRepo Git.Branch.current) $
|
||||||
Just Git.Types.FileBlob -> True
|
Just Git.Types.FileBlob -> True
|
||||||
Just Git.Types.ExecutableBlob -> True
|
Just Git.Types.ExecutableBlob -> True
|
||||||
_ -> False
|
_ -> False
|
||||||
add h i k = liftIO $ Database.Keys.SQL.addAssociatedFileFast
|
add i k = do
|
||||||
(toIKey k)
|
let tf = Git.LsTree.file i
|
||||||
(Git.LsTree.file i)
|
Database.Keys.runWriter $
|
||||||
h
|
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
|
* lock, smudge: Fix edge cases where data loss could occur in v6 mode
|
||||||
when the keys database was not populated.
|
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
|
-- Joey Hess <id@joeyh.name> Mon, 17 Oct 2016 12:46:54 -0400
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ performNew dest key = do
|
||||||
case r of
|
case r of
|
||||||
LinkAnnexOk -> return ()
|
LinkAnnexOk -> return ()
|
||||||
LinkAnnexNoop -> return ()
|
LinkAnnexNoop -> return ()
|
||||||
_ -> error "unlock failed"
|
LinkAnnexFailed -> error "unlock failed"
|
||||||
, liftIO $ writePointerFile tmp key destmode
|
, liftIO $ writePointerFile tmp key destmode
|
||||||
)
|
)
|
||||||
next $ cleanupNew dest 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;
|
> 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
|
> 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…
Add table
Reference in a new issue