From b2f04c1ed094aec6f734103d50077c48f3aad2a9 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 11 Mar 2013 15:14:42 -0400 Subject: synthesize RmChange when a directory is deleted This gets directory renames closer to being fully detected. There's close to no extra overhead to doing it this way. --- Assistant/Threads/Committer.hs | 13 ++++++++----- Assistant/Threads/Watcher.hs | 24 +++++++++++++++++------- Assistant/Types/Changes.hs | 2 +- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Assistant/Threads/Committer.hs b/Assistant/Threads/Committer.hs index f1e26f9aa..0d9010cb7 100644 --- a/Assistant/Threads/Committer.hs +++ b/Assistant/Threads/Committer.hs @@ -80,7 +80,7 @@ waitChangeTime a = runEvery (Seconds 1) <~> do changes <- getChanges -- See if now's a good time to commit. now <- liftIO getCurrentTime - case (shouldCommit now changes, lonelychange changes) of + case (shouldCommit now changes, possiblyrename changes) of (True, False) -> a (changes, now) (True, True) -> do -- Wait for other, related changes to arrive. @@ -92,10 +92,13 @@ waitChangeTime a = runEvery (Seconds 1) <~> do _ -> refill changes where {- Did we perhaps only get one of the AddChange and RmChange pair - - that make up a rename? -} - lonelychange [(PendingAddChange _ _)] = True - lonelychange [c] | isRmChange c = True - lonelychange _ = False + - that make up a file rename? Or some of the pairs that make up + - a directory rename? + -} + possiblyrename cs = all renamepart cs + + renamepart (PendingAddChange _ _) = True + renamepart c = isRmChange c isRmChange :: Change -> Bool isRmChange (Change { changeInfo = i }) | i == RmChange = True diff --git a/Assistant/Threads/Watcher.hs b/Assistant/Threads/Watcher.hs index 0f76c6a4c..8d06e6659 100644 --- a/Assistant/Threads/Watcher.hs +++ b/Assistant/Threads/Watcher.hs @@ -43,6 +43,7 @@ import Data.Bits.Utils import Data.Typeable import qualified Data.ByteString.Lazy as L import qualified Control.Exception as E +import Data.Time.Clock checkCanWatch :: Annex () checkCanWatch @@ -251,17 +252,26 @@ onDel file _ = do {- A directory has been deleted, or moved, so tell git to remove anything - that was inside it from its cache. Since it could reappear at any time, - - use --cached to only delete it from the index. + - use --cached to only delete it from the index. - - - Note: This could use unstageFile, but would need to run another git - - command to get the recursive list of files in the directory, so rm is - - just as good. -} + - This queues up a lot of RmChanges, which assists the Committer in + - pairing up renamed files when the directory was renamed. -} onDelDir :: Handler onDelDir dir _ = do debug ["directory deleted", dir] - liftAnnex $ Annex.Queue.addCommand "rm" - [Params "--quiet -r --cached --ignore-unmatch --"] [dir] - madeChange dir RmDirChange + (fs, clean) <- liftAnnex $ inRepo $ LsFiles.deleted [dir] + + liftAnnex $ forM_ fs $ \f -> Annex.Queue.addUpdateIndex =<< + inRepo (Git.UpdateIndex.unstageFile f) + + -- Get the events queued up as fast as possible, so the + -- committer sees them all in one block. + now <- liftIO getCurrentTime + forM_ fs $ \f -> recordChange $ Change now f RmChange + + void $ liftIO $ clean + liftAnnex $ Annex.Queue.flushWhenFull + noChange {- Called when there's an error with inotify or kqueue. -} onErr :: Handler diff --git a/Assistant/Types/Changes.hs b/Assistant/Types/Changes.hs index 9f0aad7a7..651085947 100644 --- a/Assistant/Types/Changes.hs +++ b/Assistant/Types/Changes.hs @@ -14,7 +14,7 @@ import Utility.TSet import Data.Time.Clock import Control.Concurrent.STM -data ChangeInfo = AddChange Key | LinkChange (Maybe Key) | RmChange | RmDirChange +data ChangeInfo = AddChange Key | LinkChange (Maybe Key) | RmChange deriving (Show, Eq) changeInfoKey :: ChangeInfo -> Maybe Key -- cgit v1.2.3