fix indirect mode conflict merge when only one side is annexed file

git-merge's creation of file~HEAD type files did not make this especially
nice to do.
This commit is contained in:
Joey Hess 2013-10-16 15:37:06 -04:00
parent 78acbfeb6a
commit f6560ffcb7

View file

@ -31,6 +31,7 @@ import Config
import Annex.ReplaceFile import Annex.ReplaceFile
import Git.FileMode import Git.FileMode
import qualified Data.Set as S
import Data.Hash.MD5 import Data.Hash.MD5
def :: [Command] def :: [Command]
@ -272,7 +273,8 @@ resolveMerge :: Annex Bool
resolveMerge = do resolveMerge = do
top <- fromRepo Git.repoPath top <- fromRepo Git.repoPath
(fs, cleanup) <- inRepo (LsFiles.unmerged [top]) (fs, cleanup) <- inRepo (LsFiles.unmerged [top])
merged <- and <$> mapM resolveMerge' fs mergedfs <- catMaybes <$> mapM resolveMerge' fs
let merged = not (null mergedfs)
void $ liftIO cleanup void $ liftIO cleanup
(deleted, cleanup2) <- inRepo (LsFiles.deleted [top]) (deleted, cleanup2) <- inRepo (LsFiles.deleted [top])
@ -281,6 +283,8 @@ resolveMerge = do
void $ liftIO cleanup2 void $ liftIO cleanup2
when merged $ do when merged $ do
unlessM isDirect $
cleanConflictCruft mergedfs top
Annex.Queue.flush Annex.Queue.flush
void $ inRepo $ Git.Command.runBool void $ inRepo $ Git.Command.runBool
[ Param "commit" [ Param "commit"
@ -289,7 +293,7 @@ resolveMerge = do
] ]
return merged return merged
resolveMerge' :: LsFiles.Unmerged -> Annex Bool resolveMerge' :: LsFiles.Unmerged -> Annex (Maybe FilePath)
resolveMerge' u resolveMerge' u
| issymlink LsFiles.valUs && issymlink LsFiles.valThem = do | issymlink LsFiles.valUs && issymlink LsFiles.valThem = do
kus <- getKey LsFiles.valUs kus <- getKey LsFiles.valUs
@ -303,24 +307,31 @@ resolveMerge' u
else do else do
makelink keyUs makelink keyUs
makelink keyThem makelink keyThem
return True return $ Just file
-- Our side is annexed, other side is not. -- Our side is annexed, other side is not.
(Just keyUs, Nothing) -> do (Just keyUs, Nothing) -> do
removeoldfile keyUs ifM isDirect
makelink keyUs -- Move newly added non-annexed object
-- Move newly added non-annexed object -- out of direct mode merge directory.
-- out of merge directory. ( do
whenM isDirect $ do removeoldfile keyUs
d <- fromRepo gitAnnexMergeDir makelink keyUs
liftIO $ rename (d </> file) file d <- fromRepo gitAnnexMergeDir
return True liftIO $ rename (d </> file) file
-- cleaup tree after git merge
, do
unstageoldfile
makelink keyUs
)
return $ Just file
-- Our side is not annexed, other side is. -- Our side is not annexed, other side is.
(Nothing, Just keyThem) -> do (Nothing, Just keyThem) -> do
makelink keyThem makelink keyThem
return True unstageoldfile
return $ Just file
-- Neither side is annexed; cannot resolve. -- Neither side is annexed; cannot resolve.
(Nothing, Nothing) -> return False (Nothing, Nothing) -> return Nothing
| otherwise = return False | otherwise = return Nothing
where where
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]
@ -337,10 +348,32 @@ resolveMerge' u
, liftIO $ nukeFile file , liftIO $ nukeFile file
) )
Annex.Queue.addCommand "rm" [Params "--quiet -f --"] [file] Annex.Queue.addCommand "rm" [Params "--quiet -f --"] [file]
unstageoldfile = Annex.Queue.addCommand "rm" [Params "--quiet -f --cached --"] [file]
getKey select = case select (LsFiles.unmergedSha u) of getKey select = case select (LsFiles.unmergedSha u) of
Nothing -> return Nothing Nothing -> return Nothing
Just sha -> catKey sha symLinkMode Just sha -> catKey sha symLinkMode
{- git-merge moves conflicting files away to files
- named something like f~HEAD or f~branch, but the
- exact name chosen can vary. Once the conflict is resolved,
- this cruft can be deleted. To avoid deleting legitimate
- files that look like this, only delete files that are
- A) not staged in git and B) look like git-annex symlinks.
-}
cleanConflictCruft :: [FilePath] -> FilePath -> Annex ()
cleanConflictCruft resolvedfs top = do
(fs, cleanup) <- inRepo $ LsFiles.notInRepo False [top]
mapM_ clean fs
void $ liftIO cleanup
where
clean f
| matchesresolved f = whenM (isJust <$> isAnnexLink f) $
liftIO $ nukeFile f
| otherwise = noop
s = S.fromList resolvedfs
matchesresolved f = S.member (base f) s
base f = reverse $ drop 1 $ dropWhile (/= '~') $ reverse f
{- 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.
- -