summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2014-02-04 15:31:53 -0400
committerGravatar Joey Hess <joey@kitenet.net>2014-02-04 17:24:12 -0400
commitf5ce1a15d7a35b85ffa938ee950f4749bf445939 (patch)
tree5b0b192fc789fa4b6004a4e43144853af7dde812
parentc69cd93af187c55793052db169abe0d3fb33ef60 (diff)
add test case & fix conflict resolution bug on Windows & FAT
Fix bug in automatic merge conflict resolution code when used on a filesystem not supporting symlinks, which resulted in it losing track of the symlink bit of annexed files. This was the underlying bug that was causing another test to fail, which got worked around in f5d0c8f0bf7f018479eb4da7e8c41598b7aacb7d. I've chosen to keep 2 separate test cases since the old test case only detected the problem accidentially. Test suite passes on FAT & in windows, as well as on proper unix systems. This commit was sponsored by Ellis Whitehead.
-rw-r--r--Command/Sync.hs31
-rw-r--r--Test.hs18
-rw-r--r--debian/changelog3
3 files changed, 42 insertions, 10 deletions
diff --git a/Command/Sync.hs b/Command/Sync.hs
index c9493b2a4..331f5d03f 100644
--- a/Command/Sync.hs
+++ b/Command/Sync.hs
@@ -392,14 +392,10 @@ resolveMerge' u
-- Our side is annexed, other side is not.
(Just keyUs, Nothing) -> do
ifM isDirect
- -- Move newly added non-annexed object
- -- out of direct mode merge directory.
( do
removeoldfile keyUs
makelink keyUs
- d <- fromRepo gitAnnexMergeDir
- liftIO $ rename (d </> file) file
- -- cleaup tree after git merge
+ movefromdirectmerge file
, do
unstageoldfile
makelink keyUs
@@ -433,6 +429,31 @@ resolveMerge' u
getKey select = case select (LsFiles.unmergedSha u) of
Nothing -> return Nothing
Just sha -> catKey sha symLinkMode
+
+ {- Move something out of the direct mode merge directory and into
+ - the git work tree.
+ -
+ - On a filesystem not supporting symlinks, this is complicated
+ - because a directory may contain annex links, but just
+ - moving them into the work tree will not let git know they are
+ - symlinks.
+ -
+ - Also, if the content of the file is available, make it available
+ - in direct mode.
+ -}
+ movefromdirectmerge item = do
+ d <- fromRepo gitAnnexMergeDir
+ liftIO $ rename (d </> item) item
+ mapM_ setuplink =<< liftIO (dirContentsRecursive item)
+ setuplink f = do
+ v <- getAnnexLinkTarget f
+ case v of
+ Nothing -> noop
+ Just target -> do
+ unlessM (coreSymlinks <$> Annex.getGitConfig) $
+ addAnnexLink target f
+ maybe noop (flip toDirect f)
+ (fileKey (takeFileName target))
{- git-merge moves conflicting files away to files
- named something like f~HEAD or f~branch, but the
diff --git a/Test.hs b/Test.hs
index 3402b2831..3def4a2ad 100644
--- a/Test.hs
+++ b/Test.hs
@@ -187,8 +187,8 @@ unitTests note getenv = testGroup ("Unit Tests " ++ note)
, check "sync" test_sync
, check "union merge regression" test_union_merge_regression
, check "conflict resolution" test_conflict_resolution_movein_bug
- , check "sync push" test_sync_push
, check "conflict_resolution (mixed directory and file)" test_mixed_conflict_resolution
+ , check "conflict_resolution (mixed directory and file) 2" test_mixed_conflict_resolution2
, check "map" test_map
, check "uninit" test_uninit
, check "uninit (in git-annex branch)" test_uninit_inbranch
@@ -841,11 +841,19 @@ test_mixed_conflict_resolution env = do
any (variantprefix `isPrefixOf`) l
@? (what ++ " conflictor file missing in: " ++ show l )
-{- A windows-specific failure of mixed conflict resolution. -}
-test_sync_push :: TestEnv -> Assertion
-test_sync_push env = check >> check
+{-
+ - During conflict resolution, one of the annexed files in git is
+ - accidentially converted from a symlink to a regular file.
+ - This only happens on crippled filesystems.
+ -
+ - This test case happens to detect the problem when it tries the next
+ - pass of conflict resolution, since it's unable to resolve a conflict
+ - between an annexed and non-annexed file.
+ -}
+test_mixed_conflict_resolution2 :: TestEnv -> Assertion
+test_mixed_conflict_resolution2 env = go >> go
where
- check = withtmpclonerepo env False $ \r1 ->
+ go = withtmpclonerepo env False $ \r1 ->
withtmpclonerepo env False $ \r2 -> do
indir env r1 $ do
writeFile conflictor "conflictor"
diff --git a/debian/changelog b/debian/changelog
index e6607fdde..275bf96b3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -13,6 +13,9 @@ git-annex (5.20140128) UNRELEASED; urgency=medium
Closes: #737480
* sync --content: Drop files from remotes that don't have them after
getting them.
+ * sync: Fix bug in automatic merge conflict resolution code when used
+ on a filesystem not supporting symlinks, which resulted in it losing
+ track of the symlink bit of annexed files.
* Added ways to configure rsync options to be used only when uploading
or downloading from a remote. Useful to eg limit upload bandwidth.
* Document in man page that sshcaching uses ssh ControlMaster.