summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Annex/AutoMerge.hs46
-rw-r--r--Annex/CatFile.hs15
-rw-r--r--Annex/Link.hs7
-rw-r--r--debian/changelog2
-rw-r--r--doc/bugs/Merge_involving_symlink_yields_unexpected_results.mdwn2
5 files changed, 54 insertions, 18 deletions
diff --git a/Annex/AutoMerge.hs b/Annex/AutoMerge.hs
index b5c4b911d..1c463003e 100644
--- a/Annex/AutoMerge.hs
+++ b/Annex/AutoMerge.hs
@@ -110,11 +110,11 @@ resolveMerge' (Just us) them u = do
makelink keyUs
-- Our side is annexed file, other side is not.
(Just keyUs, Nothing) -> resolveby $ do
- graftin them file
+ graftin them file LsFiles.valThem LsFiles.valThem
makelink keyUs
-- Our side is not annexed file, other side is.
(Nothing, Just keyThem) -> resolveby $ do
- graftin us file
+ graftin us file LsFiles.valUs LsFiles.valUs
makelink keyThem
-- Neither side is annexed file; cannot resolve.
(Nothing, Nothing) -> return Nothing
@@ -131,17 +131,41 @@ resolveMerge' (Just us) them u = do
makelink key = do
let dest = variantFile file key
l <- inRepo $ gitAnnexLink dest key
- ifM isDirect
- ( do
- d <- fromRepo gitAnnexMergeDir
- replaceFile (d </> dest) $ makeAnnexLink l
- , replaceFile dest $ makeAnnexLink l
- )
+ replacewithlink dest l
stageSymlink dest =<< hashSymlink l
- {- stage a graft of a directory or file from a branch -}
- graftin b item = Annex.Queue.addUpdateIndex
- =<< fromRepo (UpdateIndex.lsSubTree b item)
+ replacewithlink file link = ifM isDirect
+ ( do
+ d <- fromRepo gitAnnexMergeDir
+ replaceFile (d </> file) $ makeGitLink link
+ , replaceFile file $ makeGitLink link
+ )
+
+ {- Stage a graft of a directory or file from a branch.
+ -
+ - When there is a conflicted merge where one side is a directory
+ - or file, and the other side is a symlink, git merge always
+ - updates the work tree to contain the non-symlink. So, the
+ - directory or file will already be in the work tree correctly,
+ - and they just need to be staged into place. Do so by copying the
+ - index. (Note that this is also better than calling git-add
+ - because on a crippled filesystem, it preserves any symlink
+ - bits.)
+ -
+ - It's also possible for the branch to have a symlink in it,
+ - which is not a git-annex symlink. In this special case,
+ - git merge does not update the work tree to contain the symlink
+ - from the branch, so we have to do so manually.
+ -}
+ graftin b item select select' = do
+ Annex.Queue.addUpdateIndex
+ =<< fromRepo (UpdateIndex.lsSubTree b item)
+ when (select (LsFiles.unmergedBlobType u) == Just SymlinkBlob) $
+ case select' (LsFiles.unmergedSha u) of
+ Nothing -> noop
+ Just sha -> do
+ link <- catLink True sha
+ replacewithlink item link
resolveby a = do
{- Remove conflicted file from index so merge can be resolved. -}
diff --git a/Annex/CatFile.hs b/Annex/CatFile.hs
index 6a778db03..2f8c43079 100644
--- a/Annex/CatFile.hs
+++ b/Annex/CatFile.hs
@@ -15,6 +15,7 @@ module Annex.CatFile (
catKey,
catKeyFile,
catKeyFileHEAD,
+ catLink,
) where
import qualified Data.ByteString.Lazy as L
@@ -77,21 +78,25 @@ catFileHandle = do
catKey :: Ref -> FileMode -> Annex (Maybe Key)
catKey = catKey' True
-catKey' :: Bool -> Ref -> FileMode -> Annex (Maybe Key)
-catKey' modeguaranteed ref mode
+catKey' :: Bool -> Sha -> FileMode -> Annex (Maybe Key)
+catKey' modeguaranteed sha mode
| isSymLink mode = do
- l <- fromInternalGitPath . decodeBS <$> get
+ l <- catLink modeguaranteed sha
return $ if isLinkToAnnex l
then fileKey $ takeFileName l
else Nothing
| otherwise = return Nothing
+
+{- Gets a symlink target. -}
+catLink :: Bool -> Sha -> Annex String
+catLink modeguaranteed sha = fromInternalGitPath . decodeBS <$> get
where
-- If the mode is not guaranteed to be correct, avoid
-- buffering the whole file content, which might be large.
-- 8192 is enough if it really is a symlink.
get
- | modeguaranteed = catObject ref
- | otherwise = L.take 8192 <$> catObject ref
+ | modeguaranteed = catObject sha
+ | otherwise = L.take 8192 <$> catObject sha
{- Looks up the key corresponding to the Ref using the running cat-file.
-
diff --git a/Annex/Link.hs b/Annex/Link.hs
index 26991e911..25166bff5 100644
--- a/Annex/Link.hs
+++ b/Annex/Link.hs
@@ -68,6 +68,9 @@ getAnnexLinkTarget file = ifM (coreSymlinks <$> Annex.getGitConfig)
then ""
else s
+makeAnnexLink :: LinkTarget -> FilePath -> Annex ()
+makeAnnexLink = makeGitLink
+
{- Creates a link on disk.
-
- On a filesystem that does not support symlinks, writes the link target
@@ -75,8 +78,8 @@ getAnnexLinkTarget file = ifM (coreSymlinks <$> Annex.getGitConfig)
- it's staged as such, so use addAnnexLink when adding a new file or
- modified link to git.
-}
-makeAnnexLink :: LinkTarget -> FilePath -> Annex ()
-makeAnnexLink linktarget file = ifM (coreSymlinks <$> Annex.getGitConfig)
+makeGitLink :: LinkTarget -> FilePath -> Annex ()
+makeGitLink linktarget file = ifM (coreSymlinks <$> Annex.getGitConfig)
( liftIO $ do
void $ tryIO $ removeFile file
createSymbolicLink linktarget file
diff --git a/debian/changelog b/debian/changelog
index 39ce9ca11..6d151ee08 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,8 @@
git-annex (5.20140708) UNRELEASED; urgency=medium
* Fix git version that supported --no-gpg-sign.
+ * Fix bug in automatic merge conflict resolution, when one side is an
+ annexed symlink, and the other side is a non-annexed symlink.
-- Joey Hess <joeyh@debian.org> Tue, 08 Jul 2014 12:44:42 -0400
diff --git a/doc/bugs/Merge_involving_symlink_yields_unexpected_results.mdwn b/doc/bugs/Merge_involving_symlink_yields_unexpected_results.mdwn
index d8cd3d1e3..1ebd4039b 100644
--- a/doc/bugs/Merge_involving_symlink_yields_unexpected_results.mdwn
+++ b/doc/bugs/Merge_involving_symlink_yields_unexpected_results.mdwn
@@ -47,3 +47,5 @@ git-annex 5.20140613
[[!tag confirmed]]
+
+> [[fixed|done]] --[[Joey]]