init: fix data loss bug

Fix bug that lost modifications to unlocked files when init is re-ran in an
already initialized repo.

In retrospect needing scanUnlockedFiles False in the direct mode upgrade
path was a good hint that it was unsafe when used with True.

However, this bug did not affect upgrade from v5. In such an upgrade, an
unlocked file that is modified is left as-is. The only place
scanUnlockedFiles True did overwrite modified unlocked files is during an
git-annex init of a repo that was already initialized by git-annex.

(I also tried a scenario where the repo had not been initialized by
git-annex yet, but was cloned from a v7 repo with an unlocked file, and the
pointer file replaced with some other content, and the data loss did not
occur in that situation.)

Since the fixed scanUnlockedFiles avoids overwriting non-pointer files,
it should be safe to run in any situation, so there's no need any longer
for the parameter.
This commit is contained in:
Joey Hess 2019-11-05 12:41:15 -04:00
parent 3cb2427dbc
commit e2d4c133f5
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 23 additions and 20 deletions

View file

@ -109,7 +109,7 @@ initialize' mversion = checkCanInitialize $ do
setVersion (fromMaybe defaultVersion mversion)
configureSmudgeFilter
showSideAction "scanning for unlocked files"
scanUnlockedFiles True
scanUnlockedFiles
unlessM isBareRepo $ do
hookWrite postCheckoutHook
hookWrite postMergeHook

View file

@ -70,11 +70,12 @@ ifAnnexed file yes no = maybe no yes =<< lookupFile file
- 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
- when replacefiles is True.
- an annex object. If so, populate the pointer file with it.
- But if worktree file does not have a pointer file's content, it is left
- as-is.
-}
scanUnlockedFiles :: Bool -> Annex ()
scanUnlockedFiles replacefiles = whenM (inRepo Git.Ref.headExists) $ do
scanUnlockedFiles :: Annex ()
scanUnlockedFiles = whenM (inRepo Git.Ref.headExists) $ do
Database.Keys.runWriter $
liftIO . Database.Keys.SQL.dropAllAssociatedFiles
(l, cleanup) <- inRepo $ Git.LsTree.lsTree Git.LsTree.LsTreeRecursive Git.Ref.headRef
@ -92,15 +93,18 @@ scanUnlockedFiles replacefiles = whenM (inRepo Git.Ref.headExists) $ do
let tf = Git.LsTree.file i
Database.Keys.runWriter $
liftIO . Database.Keys.SQL.addAssociatedFileFast (toIKey k) tf
whenM (pure replacefiles <&&> inAnnex k) $ do
whenM (inAnnex k) $ do
f <- fromRepo $ fromTopFilePath tf
destmode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus f
ic <- replaceFile f $ \tmp ->
linkFromAnnex k tmp destmode >>= \case
LinkAnnexOk ->
withTSDelta (liftIO . genInodeCache tmp)
LinkAnnexNoop -> return Nothing
LinkAnnexFailed -> liftIO $ do
writePointerFile tmp k destmode
return Nothing
maybe noop (restagePointerFile (Restage True) f) ic
liftIO (isPointerFile f) >>= \case
Just k' | k' == k -> do
destmode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus f
ic <- replaceFile f $ \tmp ->
linkFromAnnex k tmp destmode >>= \case
LinkAnnexOk ->
withTSDelta (liftIO . genInodeCache tmp)
LinkAnnexNoop -> return Nothing
LinkAnnexFailed -> liftIO $ do
writePointerFile tmp k destmode
return Nothing
maybe noop (restagePointerFile (Restage True) f) ic
_ -> noop

View file

@ -1,5 +1,7 @@
git-annex (7.20191025) UNRELEASED; urgency=medium
* init: Fix bug that lost modifications to unlocked files when init is
re-ran in an already initialized repo.
* benchmark: Add --databases to benchmark sqlite databases.
-- Joey Hess <id@joeyh.name> Tue, 29 Oct 2019 15:13:03 -0400

View file

@ -42,13 +42,10 @@ upgrade automatic = flip catchNonAsync (const $ return False) $ do
( do
checkGitVersionForDirectUpgrade
convertDirect
-- Worktree files are already populated, so don't
-- have this try to populate them again.
scanUnlockedFiles False
, do
checkGitVersionForIndirectUpgrade
scanUnlockedFiles True
)
scanUnlockedFiles
configureSmudgeFilter
-- Inode sentinal file was only used in direct mode and when
-- locking down files as they were added. In v6, it's used more