summaryrefslogtreecommitdiff
path: root/Git/UnionMerge.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2013-01-16 21:31:06 -0400
committerGravatar Joey Hess <joey@kitenet.net>2013-01-16 21:31:06 -0400
commitfb442da95e9f60a7fd5ee9e6c46792d256d2dca0 (patch)
tree13fcaa67a7988fe379e1ebe274a351e85747041a /Git/UnionMerge.hs
parent2fd0c120e18c2af234fd9a1a403d6ba3af850f83 (diff)
union merge bugfix
Union merges involving two or more repositories could sometimes result in data from one repository getting lost. This could result in the location log data becoming wrong, and fsck being needed to fix it. NB: I audited for any other occurrences of this problem. There are other places than union merge where multiple changes are fed into update-index in a stream, but they all involve working copy files being staged, or their deletion being staged, and in this case it's fine for the later changes to override the earlier ones.
Diffstat (limited to 'Git/UnionMerge.hs')
-rw-r--r--Git/UnionMerge.hs12
1 files changed, 9 insertions, 3 deletions
diff --git a/Git/UnionMerge.hs b/Git/UnionMerge.hs
index 05d512df3..464200af4 100644
--- a/Git/UnionMerge.hs
+++ b/Git/UnionMerge.hs
@@ -38,10 +38,16 @@ merge x y repo = do
catFileStop h
{- Merges a list of branches into the index. Previously staged changes in
- - the index are preserved (and participate in the merge). -}
+ - the index are preserved (and participate in the merge).
+ -
+ - update-index is run once per ref in turn, so that each ref is merged on
+ - top of the merge for the previous ref. It would be more efficient, but
+ - harder to calculate a single union merge involving all the refs, as well
+ - as the index.
+ -}
mergeIndex :: CatFileHandle -> Repo -> [Ref] -> IO ()
-mergeIndex h repo bs =
- streamUpdateIndex repo $ map (\b -> mergeTreeIndex b h repo) bs
+mergeIndex h repo bs = forM_ bs $ \b ->
+ streamUpdateIndex repo [mergeTreeIndex b h repo]
{- For merging two trees. -}
mergeTrees :: Ref -> Ref -> CatFileHandle -> Repo -> Streamer