diff options
author | Joey Hess <joey@kitenet.net> | 2012-06-04 17:32:46 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-06-04 18:09:18 -0400 |
commit | 5b4e5ce7e5141eac7f0bc81033d7d7676ff0008f (patch) | |
tree | 85ee183972451657f4a8b10cf9692da101dc8c9a /Command | |
parent | 659e6b13249ec9d8f3c01607b0eb819b8a5690fe (diff) |
deletion
When a new file is annexed, a deletion event occurs when it's moved away
to be replaced by a symlink. Most of the time, there is no problimatic
race, because the same thread runs the add event as the deletion event.
So, once the symlink is in place, the deletion code won't run at all,
due to existing checks that a deleted file is really gone.
But there is a race at startup, as then the inotify thread is running
at the same time as the main thread, which does the initial tree walking
and annexing. It would be possible for the deletion inotify to run
in a perfect race with the addition, and remove the newly added symlink
from the git cache.
To solve this race, added event serialization via a MVar. We putMVar
before running each event, which blocks if an event is already running.
And when an event finishes (or crashes!), we takeMVar to free the lock.
Also, make rm -rf not spew warnings by passing --ignore-unmatch when
deleting directories.
Diffstat (limited to 'Command')
-rw-r--r-- | Command/Watch.hs | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/Command/Watch.hs b/Command/Watch.hs index b38c04d2c..046777685 100644 --- a/Command/Watch.hs +++ b/Command/Watch.hs @@ -44,8 +44,11 @@ start = notBareRepo $ do gitdir dir = takeFileName dir /= ".git" {- Inotify events are run in separate threads, and so each is a - - self-contained Annex monad. Exceptions by the handlers are ignored, - - otherwise a whole watcher thread could be crashed. -} + - self-contained Annex monad. + - + - Exceptions by the handlers are ignored, + - otherwise a whole watcher thread could be crashed. + -} run :: Annex.AnnexState -> (FilePath -> Annex a) -> FilePath -> IO () run startstate a f = do r <- E.try go :: IO (Either E.SomeException ()) @@ -89,10 +92,11 @@ onAddSymlink file = go =<< Backend.lookupFile file [Params "--force --", File file] onDel :: FilePath -> Annex () -onDel file = liftIO $ print $ "del " ++ file +onDel file = inRepo $ Git.Command.run "rm" + [Params "--quiet --cached --", File file] -{- A directory has been deleted, so tell git to remove anything that - was inside it from its cache. -} +{- A directory has been deleted, or moved, so tell git to remove anything + - that was inside it from its cache. -} onDelDir :: FilePath -> Annex () onDelDir dir = inRepo $ Git.Command.run "rm" - [Params "--quiet -r --cached --", File dir] + [Params "--quiet -r --cached --ignore-unmatch --", File dir] |