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:
parent
6fb6913168
commit
e227e8f683
2 changed files with 48 additions and 28 deletions
|
@ -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
2
debian/changelog
vendored
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue