graphTree now works properly in all cases

(That I could think of.)
This commit is contained in:
Joey Hess 2019-02-21 22:25:42 -04:00
parent 8fdea8f444
commit 1580ff3866
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38

View file

@ -231,7 +231,8 @@ adjustTree adjusttreeitem addtreeitems removefiles r repo =
removed (TreeBlob f _ _) = S.member (normalise (gitPath f)) removeset removed (TreeBlob f _ _) = S.member (normalise (gitPath f)) removeset
removed _ = False removed _ = False
{- Grafts subtree into the basetree at the specified location. {- Grafts subtree into the basetree at the specified location, replacing
- anything that the basetree already had at that location.
- -
- This is generally much more efficient than using getTree and recordTree, - This is generally much more efficient than using getTree and recordTree,
- or adjustTree, since it only needs to traverse from the top of the tree - or adjustTree, since it only needs to traverse from the top of the tree
@ -247,15 +248,11 @@ graftTree subtree graftloc basetree repo =
withMkTreeHandle repo $ withMkTreeHandle repo $
go basetree graftdirs go basetree graftdirs
where where
go :: Ref -> [TopFilePath] -> MkTreeHandle -> IO Sha go tsha (topmostgraphdir:restgraphdirs) h = do
go tsha [] h = do
graft <- graftin h []
mkTree h [graft]
go tsha graftdirs@(topmostgraphdir:_) h = do
Tree t <- getTree LsTree.LsTreeNonRecursive tsha repo Tree t <- getTree LsTree.LsTreeNonRecursive tsha repo
t' <- case partition isabovegraft t of t' <- case partition isabovegraft t of
([], _) -> do ([], _) -> do
graft <- graftin h graftdirs graft <- graftin h (topmostgraphdir:restgraphdirs)
return (graft:t) return (graft:t)
-- normally there can only be one matching item -- normally there can only be one matching item
-- in the tree, but it's theoretically possible -- in the tree, but it's theoretically possible
@ -263,18 +260,24 @@ graftTree subtree graftloc basetree repo =
-- same name, so process them all -- same name, so process them all
(matching, rest) -> do (matching, rest) -> do
newshas <- forM matching $ \case newshas <- forM matching $ \case
RecordedSubTree tloc tsha' _ -> do RecordedSubTree tloc tsha' _
tsha'' <- go tsha' (drop 1 graftdirs) h | null restgraphdirs -> return $
return $ RecordedSubTree tloc tsha'' [] RecordedSubTree tloc subtree []
_ -> graftin h $ drop 1 graftdirs | otherwise -> do
tsha'' <- go tsha' restgraphdirs h
return $ RecordedSubTree tloc tsha'' []
_ -> graftin h (topmostgraphdir:restgraphdirs)
return (newshas ++ rest) return (newshas ++ rest)
mkTree h t' mkTree h t'
go tsha [] h = return subtree
isabovegraft i = beneathSubTree i graftloc || gitPath i == gitPath graftloc isabovegraft i = beneathSubTree i graftloc || gitPath i == gitPath graftloc
graftin h t = recordSubTree h $ graftin' t graftin h t = recordSubTree h $ graftin' t
graftin' [] = RecordedSubTree graftloc subtree [] graftin' [] = RecordedSubTree graftloc subtree []
graftin' (d:rest) = NewSubTree d [graftin' rest] graftin' (d:rest)
| d == graftloc = graftin' []
| otherwise = NewSubTree d [graftin' rest]
-- For a graftloc of "foo/bar/baz", this generates -- For a graftloc of "foo/bar/baz", this generates
-- ["foo", "foo/bar", "foo/bar/baz"] -- ["foo", "foo/bar", "foo/bar/baz"]