avoid removing old associated file when there is a merge conflict

It makes sense to keep the key used by the old version of an
associated file, until the merge conflict is resolved.

Note that, since in this case git diff is being run with --index, it's
not possible to use -1 or -3, which would let the keys
associated with the new versions of the file also be added. That would
be better, because it's possible that the local modification to the file
that caused the merge conflict has not yet gotten its new key recorded
in the db.

Opened a bug about a case this is thus not able to address.

Sponsored-by: Boyd Stephen Smith Jr. on Patreon
This commit is contained in:
Joey Hess 2021-06-01 11:24:15 -04:00
parent 3155c0d03e
commit 5b7429e73a
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
2 changed files with 40 additions and 8 deletions

View file

@ -309,14 +309,18 @@ reconcileStaged qh = do
procdiff (info:file:rest) changed
| ":" `S.isPrefixOf` info = case S8.words info of
(_colonsrcmode:dstmode:srcsha:dstsha:_change:[]) -> do
removed <- catKey (Ref srcsha) >>= \case
Just oldkey -> do
liftIO $ SQL.removeAssociatedFile oldkey
(asTopFilePath file)
(SQL.WriteHandle qh)
return True
Nothing -> return False
(_colonsrcmode:dstmode:srcsha:dstsha:status:[]) -> do
-- avoid removing associated file when
-- there is a merge conflict
removed <- if status /= "U"
then catKey (Ref srcsha) >>= \case
Just oldkey -> do
liftIO $ SQL.removeAssociatedFile oldkey
(asTopFilePath file)
(SQL.WriteHandle qh)
return True
Nothing -> return False
else return False
added <- catKey (Ref dstsha) >>= \case
Just key -> do
liftIO $ SQL.addAssociatedFile key

View file

@ -0,0 +1,28 @@
Found a case where the associated files in the keys db end up out-of-date.
Make a repo with an unlocked file, clone it to a second repo, and set up a
conflict involving that file in both repos, using git-annex add to add the
conflicting version, and not running other git-annex commands after that,
before pulling the conflicting branch. When the associated files db
gets updated in the conflict situation, only 1 key has the conflicting file
associated with it, rather than 2 or 3.
The original key before the conflict has the file associated with it, but
the new local key and new remote key do not.
The result is that a drop of another file that uses the same key may not
honor the preferred content of the file that is in conflict.
Once the conflict is resolved, git-annex will recover, the problem only
occurs while there's an unmerged conflict, and only when git-annex did not
get a change to notice the local modification before the conflict happened.
This only affected locked files, because when an unlocked file is staged,
git-annex updates the keys db. So, one solution to this bug will be for
git-annex to also update the keys db when staging locked files.
(Unfortunately this would make mass adds somewhat slower.)
Or, possibly, for reconcileStaged to not use git diff --index in this case,
but git diff with -1 and -3. That lets both sides of the merge conflict be
accessed, and it could then add the file to both keys. As well as not
slowing down git-annex add, this would let it honor the preferred content
of the conflicting file for all 3 keys. --[[Joey]]