Unused: bugfix

Detect staged files that are not in the working tree.
This commit is contained in:
guilhem 2013-08-26 19:01:48 +02:00 committed by Joey Hess
parent 88e2618e38
commit f754779c02
3 changed files with 64 additions and 17 deletions

View file

@ -27,6 +27,7 @@ import qualified Annex
import qualified Git import qualified Git
import qualified Git.Command import qualified Git.Command
import qualified Git.Ref import qualified Git.Ref
import qualified Git.Branch
import qualified Git.LsFiles as LsFiles import qualified Git.LsFiles as LsFiles
import qualified Git.DiffTree as DiffTree import qualified Git.DiffTree as DiffTree
import qualified Backend import qualified Backend
@ -253,35 +254,49 @@ withKeysReferenced' mdir initial a = do
go v' fs go v' fs
withKeysReferencedInGit :: (Key -> Annex ()) -> Annex () withKeysReferencedInGit :: (Key -> Annex ()) -> Annex ()
withKeysReferencedInGit a = withKeysReferencedInGit a = do
showref >>= mapM_ (withKeysReferencedInGitRef a) . relevantrefs current <- inRepo Git.Branch.currentUnsafe
shaHead <- maybe (return Nothing) (inRepo . Git.Ref.sha) current
showref >>= mapM_ (withKeysReferencedInGitRef a) .
relevantrefs (shaHead, current)
where where
showref = inRepo $ Git.Command.pipeReadStrict [Param "show-ref"] showref = inRepo $ Git.Command.pipeReadStrict [Param "show-ref"]
relevantrefs = map (Git.Ref . snd) . relevantrefs headRef = addHead headRef .
nubBy uniqref .
filter ourbranches . filter ourbranches .
map (separate (== ' ')) . map (separate (== ' ')) .
lines lines
uniqref (x, _) (y, _) = x == y nubRefs = map (Git.Ref . snd) . nubBy (\(x, _) (y, _) -> x == y)
ourbranchend = '/' : show Annex.Branch.name ourbranchend = '/' : show Annex.Branch.name
ourbranches (_, b) = not (ourbranchend `isSuffixOf` b) ourbranches (_, b) = not (ourbranchend `isSuffixOf` b)
&& not ("refs/synced/" `isPrefixOf` b) && not ("refs/synced/" `isPrefixOf` b)
addHead headRef refs = case headRef of
-- if HEAD diverges from all branches (except the branch it
-- points to), run the actions on staged keys (and keys
-- that are only present in the work tree if the repo is
-- non bare)
(Just (Git.Ref x), Just (Git.Ref b))
| all (\(x',b') -> x /= x' || b == b') refs ->
Git.Ref.headRef
: nubRefs (filter ((/= x) . fst) refs)
_ -> nubRefs refs
{- Runs an action on keys referenced in the given Git reference which {- Runs an action on keys referenced in the given Git reference which
- differ from those referenced in the index. -} - differ from those referenced in the index. -}
withKeysReferencedInGitRef :: (Key -> Annex ()) -> Git.Ref -> Annex () withKeysReferencedInGitRef :: (Key -> Annex ()) -> Git.Ref -> Annex ()
withKeysReferencedInGitRef a ref = do withKeysReferencedInGitRef a ref = do
showAction $ "checking " ++ Git.Ref.describe ref showAction $ "checking " ++ Git.Ref.describe ref
(ts, clean) <- inRepo $ DiffTree.diffIndex ref bare <- isBareRepo
forM_ ts $ \t -> (ts,clean) <- inRepo $ if bare
mapM_ (`process` t) [DiffTree.dstsha, DiffTree.srcsha] then DiffTree.diffIndex ref
else DiffTree.diffWorkTree ref
let lookAtWorkingTree = not bare && ref == Git.Ref.headRef
forM_ ts $ tKey lookAtWorkingTree >=> maybe noop a
liftIO $ void clean liftIO $ void clean
where where
-- the key will be Nothing for the nullSha tKey True = Backend.lookupFile . DiffTree.file >=*>
process getsha = catObject . getsha >=> fmap fst
encodeW8 . L.unpack *>=> tKey False = catFile ref . DiffTree.file >=*>
fileKey . takeFileName *>=> fileKey . takeFileName . encodeW8 . L.unpack
maybe noop a
{- Looks in the specified directory for bad/tmp keys, and returns a list {- Looks in the specified directory for bad/tmp keys, and returns a list
- of those that might still have value, or might be stale and removable. - of those that might still have value, or might be stale and removable.

View file

@ -10,6 +10,7 @@ module Git.DiffTree (
diffTree, diffTree,
diffTreeRecursive, diffTreeRecursive,
diffIndex, diffIndex,
diffWorkTree,
) where ) where
import Numeric import Numeric
@ -44,12 +45,23 @@ diffTreeRecursive src dst = getdiff (Param "diff-tree")
{- Diffs between a tree and the index. Does nothing if there is not yet a {- Diffs between a tree and the index. Does nothing if there is not yet a
- commit in the repository. -} - commit in the repository. -}
diffIndex :: Ref -> Repo -> IO ([DiffTreeItem], IO Bool) diffIndex :: Ref -> Repo -> IO ([DiffTreeItem], IO Bool)
diffIndex ref repo = do diffIndex ref = diffIndex' ref [Param "--cached"]
{- Diffs between a tree and the working tree. Does nothing if there is not
- yet a commit in the repository, of if the repository is bare. -}
diffWorkTree :: Ref -> Repo -> IO ([DiffTreeItem], IO Bool)
diffWorkTree ref repo =
ifM (Git.Ref.headExists repo)
( diffIndex' ref [] repo
, return ([], return True)
)
diffIndex' :: Ref -> [CommandParam] -> Repo -> IO ([DiffTreeItem], IO Bool)
diffIndex' ref params repo =
ifM (Git.Ref.headExists repo) ifM (Git.Ref.headExists repo)
( getdiff (Param "diff-index") ( getdiff (Param "diff-index")
[ Param "--cached" ( params ++ [Param $ show ref] )
, Param $ show ref repo
] repo
, return ([], return True) , return ([], return True)
) )

20
Test.hs
View file

@ -598,6 +598,26 @@ test_unused env = "git-annex unused/dropunused" ~: intmpclonerepoInDirect env $
removeFile "unusedunstagedfile" removeFile "unusedunstagedfile"
checkunused [unusedfilekey] "with unstaged link deleted" checkunused [unusedfilekey] "with unstaged link deleted"
-- unused used to miss symlinks that were deleted or modified
-- manually, but commited as such.
writeFile "unusedfile" "unusedcontent"
git_annex env "add" ["unusedfile"] @? "add of unusedfile failed"
boolSystem "git" [Param "add", File "unusedfile"] @? "git add failed"
unusedfilekey' <- annexeval $ findkey "unusedfile"
checkunused [] "with staged deleted link"
boolSystem "git" [Params "rm -qf", File "unusedfile"] @? "git rm failed"
checkunused [unusedfilekey'] "with staged link deleted"
-- unused used to miss symlinks that were deleted or modified
-- manually, but not staged as such.
writeFile "unusedfile" "unusedcontent"
git_annex env "add" ["unusedfile"] @? "add of unusedfile failed"
boolSystem "git" [Param "add", File "unusedfile"] @? "git add failed"
unusedfilekey'' <- annexeval $ findkey "unusedfile"
checkunused [] "with unstaged deleted link"
removeFile "unusedfile"
checkunused [unusedfilekey''] "with unstaged link deleted"
where where
checkunused expectedkeys desc = do checkunused expectedkeys desc = do
git_annex env "unused" [] @? "unused failed" git_annex env "unused" [] @? "unused failed"