improved direct mode dir/file conflicted merge resultion, using tree grafting

This commit is contained in:
Joey Hess 2014-03-04 15:00:19 -04:00
parent 85214c23fc
commit 8496d8aa63
Failed to extract signature
2 changed files with 20 additions and 22 deletions

View file

@ -21,6 +21,7 @@ import Annex.Link
import Annex.Hook import Annex.Hook
import qualified Git.Command import qualified Git.Command
import qualified Git.LsFiles as LsFiles import qualified Git.LsFiles as LsFiles
import qualified Git.UpdateIndex as UpdateIndex
import qualified Git.Merge import qualified Git.Merge
import qualified Git.Branch import qualified Git.Branch
import qualified Git.Ref import qualified Git.Ref
@ -314,11 +315,11 @@ mergeFrom branch = do
, go , go
) )
where where
go = inRepo (Git.Merge.mergeNonInteractive branch) <||> resolveMerge go = inRepo (Git.Merge.mergeNonInteractive branch) <||> resolveMerge branch
godirect currbranch = do godirect currbranch = do
old <- inRepo $ Git.Ref.sha currbranch old <- inRepo $ Git.Ref.sha currbranch
d <- fromRepo gitAnnexMergeDir d <- fromRepo gitAnnexMergeDir
r <- inRepo (mergeDirect d branch) <||> resolveMerge r <- inRepo (mergeDirect d branch) <||> resolveMerge branch
new <- inRepo $ Git.Ref.sha currbranch new <- inRepo $ Git.Ref.sha currbranch
case (old, new) of case (old, new) of
(Just oldsha, Just newsha) -> (Just oldsha, Just newsha) ->
@ -352,11 +353,11 @@ mergeFrom branch = do
- staged to the index, and written to the gitAnnexMergeDir, and later - staged to the index, and written to the gitAnnexMergeDir, and later
- mergeDirectCleanup handles updating the work tree. - mergeDirectCleanup handles updating the work tree.
-} -}
resolveMerge :: Annex Bool resolveMerge :: Git.Ref -> Annex Bool
resolveMerge = do resolveMerge branch = do
top <- fromRepo Git.repoPath top <- fromRepo Git.repoPath
(fs, cleanup) <- inRepo (LsFiles.unmerged [top]) (fs, cleanup) <- inRepo (LsFiles.unmerged [top])
mergedfs <- catMaybes <$> mapM resolveMerge' fs mergedfs <- catMaybes <$> mapM (resolveMerge' branch) fs
let merged = not (null mergedfs) let merged = not (null mergedfs)
void $ liftIO cleanup void $ liftIO cleanup
@ -378,8 +379,8 @@ resolveMerge = do
showLongNote "Merge conflict was automatically resolved; you may want to examine the result." showLongNote "Merge conflict was automatically resolved; you may want to examine the result."
return merged return merged
resolveMerge' :: LsFiles.Unmerged -> Annex (Maybe FilePath) resolveMerge' :: Git.Ref -> LsFiles.Unmerged -> Annex (Maybe FilePath)
resolveMerge' u resolveMerge' branch u
| mergeable LsFiles.valUs && mergeable LsFiles.valThem = do | mergeable LsFiles.valUs && mergeable LsFiles.valThem = do
kus <- getKey LsFiles.valUs kus <- getKey LsFiles.valUs
kthem <- getKey LsFiles.valThem kthem <- getKey LsFiles.valThem
@ -429,21 +430,10 @@ resolveMerge' u
-- removing the conflicted file from cache clears the conflict -- removing the conflicted file from cache clears the conflict
unstageoldfile = Annex.Queue.addCommand "rm" [Params "--quiet -f --cached --"] [file] unstageoldfile = Annex.Queue.addCommand "rm" [Params "--quiet -f --cached --"] [file]
{- stage an item from the direct mode merge directory -} {- stage an item from the direct mode merge directory, which may
stagefromdirectmergedir item = do - be a directory with arbitrary contents -}
d <- fromRepo gitAnnexMergeDir stagefromdirectmergedir item = Annex.Queue.addUpdateIndex
l <- liftIO $ dirContentsRecursive (d </> item) =<< fromRepo (UpdateIndex.lsSubTree branch item)
if null l
then go d (d </> item)
else mapM_ (go d) l
where
go d f = do
v <- getAnnexLinkTarget f
let worktreef = makeRelative d f
case v of
Just target -> stageSymlink worktreef
=<< hashSymlink target
Nothing -> noop
{- git-merge moves conflicting files away to files {- git-merge moves conflicting files away to files
- named something like f~HEAD or f~branch, but the - named something like f~HEAD or f~branch, but the

View file

@ -15,6 +15,7 @@ module Git.UpdateIndex (
startUpdateIndex, startUpdateIndex,
stopUpdateIndex, stopUpdateIndex,
lsTree, lsTree,
lsSubTree,
updateIndexLine, updateIndexLine,
stageFile, stageFile,
unstageFile, unstageFile,
@ -74,6 +75,13 @@ lsTree (Ref x) repo streamer = do
void $ cleanup void $ cleanup
where where
params = map Param ["ls-tree", "-z", "-r", "--full-tree", x] params = map Param ["ls-tree", "-z", "-r", "--full-tree", x]
lsSubTree :: Ref -> FilePath -> Repo -> Streamer
lsSubTree (Ref x) p repo streamer = do
(s, cleanup) <- pipeNullSplit params repo
mapM_ streamer s
void $ cleanup
where
params = map Param ["ls-tree", "-z", "-r", "--full-tree", x, p]
{- Generates a line suitable to be fed into update-index, to add {- Generates a line suitable to be fed into update-index, to add
- a given file with a given sha. -} - a given file with a given sha. -}