diff options
-rw-r--r-- | Annex/Direct.hs | 31 | ||||
-rw-r--r-- | debian/changelog | 4 | ||||
-rw-r--r-- | doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn | 2 |
3 files changed, 24 insertions, 13 deletions
diff --git a/Annex/Direct.hs b/Annex/Direct.hs index d4b73860e..366966fc2 100644 --- a/Annex/Direct.hs +++ b/Annex/Direct.hs @@ -138,28 +138,33 @@ mergeDirect d branch g = do - and the commit sha passed in, along with the old sha of the tree - before the merge. Uses git diff-tree to find files that changed between - the two shas, and applies those changes to the work tree. + - + - There are really only two types of changes: An old item can be deleted, + - or a new item added. Two passes are made, first deleting and then + - adding. This is to handle cases where eg, a file is deleted and a + - directory is added. The diff-tree output may list these in the opposite + - order, but we cannot really add the directory until the file with the + - same name is remvoed. -} mergeDirectCleanup :: FilePath -> Git.Ref -> Git.Ref -> Annex () mergeDirectCleanup d oldsha newsha = do (items, cleanup) <- inRepo $ DiffTree.diffTreeRecursive oldsha newsha makeabs <- flip fromTopFilePath <$> gitRepo - forM_ items (updated makeabs) + let fsitems = zip (map (makeabs . DiffTree.file) items) items + forM_ fsitems $ + go DiffTree.srcsha DiffTree.srcmode moveout moveout_raw + forM_ fsitems $ + go DiffTree.dstsha DiffTree.dstmode movein movein_raw void $ liftIO cleanup liftIO $ removeDirectoryRecursive d where - updated makeabs item = do - let f = makeabs (DiffTree.file item) - void $ tryAnnex $ - go f DiffTree.srcsha DiffTree.srcmode moveout moveout_raw - void $ tryAnnex $ - go f DiffTree.dstsha DiffTree.dstmode movein movein_raw - where - go f getsha getmode a araw - | getsha item == nullSha = noop - | otherwise = maybe (araw f) (\k -> void $ a k f) - =<< catKey (getsha item) (getmode item) + go getsha getmode a araw (f, item) + | getsha item == nullSha = noop + | otherwise = void $ + tryAnnex . maybe (araw f) (\k -> void $ a k f) + =<< catKey (getsha item) (getmode item) - moveout = removeDirect + moveout k f = removeDirect k f {- Files deleted by the merge are removed from the work tree. - Empty work tree directories are removed, per git behavior. -} diff --git a/debian/changelog b/debian/changelog index 975818366..86e833eab 100644 --- a/debian/changelog +++ b/debian/changelog @@ -27,6 +27,10 @@ git-annex (5.20131102) UNRELEASED; urgency=low * repair: Handle case where index file is corrupt, but all objects are ok. * assistant: Notice on startup when the index file is corrupt, and auto-repair. + * Fix direct mode merge bug when a direct mode file was deleted and replaced + with a directory. An ordering problem caused the directory to not get + created in this case. + Thanks to Tim for the test cases. -- Joey Hess <joeyh@debian.org> Wed, 06 Nov 2013 16:14:14 -0400 diff --git a/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn b/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn index 46a07ee6a..9b5d52220 100644 --- a/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn +++ b/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn @@ -40,3 +40,5 @@ remote types: git gcrypt S3 bup directory rsync web webdav glacier hook Linux ceilingcat 3.11.6-1-ARCH #1 SMP PREEMPT Fri Oct 18 23:22:36 CEST 2013 x86_64 GNU/Linux """]] + +> [[fixed|done]] --[[Joey]] |