sync: Fix automatic resolution of merge conflicts where one side is an annexed file, and the other side is a non-annexed file, or a directory.

Note that this case is only fully automatically resolved in direct mode.
In indirect mode, git merge moves the file to file~HEAD, and replaces it
with the directory, and leaves the file in unmerged state, and sync doesn't
yet change that.
This commit is contained in:
Joey Hess 2013-10-16 14:48:51 -04:00
parent 6fb6913168
commit e227e8f683
2 changed files with 48 additions and 28 deletions

View file

@ -257,11 +257,16 @@ mergeFrom branch = do
- -
- This uses the Keys pointed to by the files to construct new - This uses the Keys pointed to by the files to construct new
- filenames. So when both sides modified file foo, - filenames. So when both sides modified file foo,
- it will be deleted, and replaced with files foo.KEYA and foo.KEYB. - it will be deleted, and replaced with files foo.variant-A and
- foo.variant-B.
- -
- On the other hand, when one side deleted foo, and the other modified it, - On the other hand, when one side deleted foo, and the other modified it,
- it will be deleted, and the modified version stored as file - it will be deleted, and the modified version stored as file
- foo.KEYA (or KEYB). - foo.variant-A (or B).
-
- It's also possible that one side has foo as an annexed file, and
- the other as a directory or non-annexed file. The annexed file
- is renamed to resolve the merge, and the other object is preserved as-is.
-} -}
resolveMerge :: Annex Bool resolveMerge :: Annex Bool
resolveMerge = do resolveMerge = do
@ -286,42 +291,55 @@ resolveMerge = do
resolveMerge' :: LsFiles.Unmerged -> Annex Bool resolveMerge' :: LsFiles.Unmerged -> Annex Bool
resolveMerge' u resolveMerge' u
| issymlink LsFiles.valUs && issymlink LsFiles.valThem = | issymlink LsFiles.valUs && issymlink LsFiles.valThem = do
withKey LsFiles.valUs $ \keyUs -> kus <- getKey LsFiles.valUs
withKey LsFiles.valThem $ \keyThem -> do kthem <- getKey LsFiles.valThem
ifM isDirect case (kus, kthem) of
( maybe noop (`removeDirect` file) keyUs -- Both sides of conflict are annexed files
, liftIO $ nukeFile file (Just keyUs, Just keyThem) -> do
) removeoldfile keyUs
Annex.Queue.addCommand "rm" [Params "--quiet -f --"] [file] if keyUs == keyThem
go keyUs keyThem then makelink keyUs
else do
makelink keyUs
makelink keyThem
return True
-- Our side is annexed, other side is not.
(Just keyUs, Nothing) -> do
removeoldfile keyUs
makelink keyUs
-- Move newly added non-annexed object
-- out of merge directory.
whenM isDirect $ do
d <- fromRepo gitAnnexMergeDir
liftIO $ rename (d </> file) file
return True
-- Our side is not annexed, other side is.
(Nothing, Just keyThem) -> do
makelink keyThem
return True
-- Neither side is annexed; cannot resolve.
(Nothing, Nothing) -> return False
| otherwise = return False | otherwise = return False
where where
go keyUs keyThem
| keyUs == keyThem = do
makelink keyUs
return True
| otherwise = do
makelink keyUs
makelink keyThem
return True
file = LsFiles.unmergedFile u file = LsFiles.unmergedFile u
issymlink select = select (LsFiles.unmergedBlobType u) `elem` [Just SymlinkBlob, Nothing] issymlink select = select (LsFiles.unmergedBlobType u) `elem` [Just SymlinkBlob, Nothing]
makelink (Just key) = do makelink key = do
let dest = mergeFile file key let dest = mergeFile file key
l <- inRepo $ gitAnnexLink dest key l <- inRepo $ gitAnnexLink dest key
replaceFile dest $ makeAnnexLink l replaceFile dest $ makeAnnexLink l
stageSymlink dest =<< hashSymlink l stageSymlink dest =<< hashSymlink l
whenM isDirect $ whenM isDirect $
toDirect key dest toDirect key dest
makelink _ = noop removeoldfile keyUs = do
withKey select a = do ifM isDirect
let msha = select $ LsFiles.unmergedSha u ( removeDirect keyUs file
case msha of , liftIO $ nukeFile file
Nothing -> a Nothing )
Just sha -> do Annex.Queue.addCommand "rm" [Params "--quiet -f --"] [file]
key <- catKey sha symLinkMode getKey select = case select (LsFiles.unmergedSha u) of
maybe (return False) (a . Just) key Nothing -> return Nothing
Just sha -> catKey sha symLinkMode
{- The filename to use when resolving a conflicted merge of a file, {- The filename to use when resolving a conflicted merge of a file,
- that points to a key. - that points to a key.

2
debian/changelog vendored
View file

@ -23,6 +23,8 @@ git-annex (4.20131003) UNRELEASED; urgency=low
* Deal with git check-attr -z output format change in git 1.8.5. * Deal with git check-attr -z output format change in git 1.8.5.
* Work around sed output difference that led to version containing a newline * Work around sed output difference that led to version containing a newline
on OSX. on OSX.
* sync: Fix automatic resolution of merge conflicts where one side is an
annexed file, and the other side is a non-annexed file, or a directory.
-- Joey Hess <joeyh@debian.org> Thu, 03 Oct 2013 15:41:24 -0400 -- Joey Hess <joeyh@debian.org> Thu, 03 Oct 2013 15:41:24 -0400