
* Fix minor FD leak in journal code. Closes: #754608 * direct: Fix handling of case where a work tree subdirectory cannot be written to due to permissions. * migrate: Avoid re-checksumming when migrating from hashE to hash backend. * uninit: Avoid failing final removal in some direct mode repositories due to file modes. * S3: Deal with AWS ACL configurations that do not allow creating or checking the location of a bucket, but only reading and writing content to it. * resolvemerge: New plumbing command that runs the automatic merge conflict resolver. * Deal with change in git 2.0 that made indirect mode merge conflict resolution leave behind old files. * sync: Fix git sync with local git remotes even when they don't have an annex.uuid set. (The assistant already did so.) * Set gcrypt-publish-participants when setting up a gcrypt repository, to avoid unncessary passphrase prompts. This is a security/usability tradeoff. To avoid exposing the gpg key ids who can decrypt the repository, users can unset gcrypt-publish-participants. * Install nautilus hooks even when ~/.local/share/nautilus/ does not yet exist, since it is not automatically created for Gnome 3 users. * Windows: Move .vbs files out of git\bin, to avoid that being in the PATH, which caused some weird breakage. (Thanks, divB) * Windows: Fix locking issue that prevented the webapp starting (since 5.20140707). # imported from the archive
96 lines
3.1 KiB
Haskell
96 lines
3.1 KiB
Haskell
{- FSEvents interface
|
|
-
|
|
- Copyright 2012 Joey Hess <joey@kitenet.net>
|
|
-
|
|
- License: BSD-2-clause
|
|
-}
|
|
|
|
module Utility.DirWatcher.FSEvents where
|
|
|
|
import Common hiding (isDirectory)
|
|
import Utility.DirWatcher.Types
|
|
|
|
import System.OSX.FSEvents
|
|
import qualified System.Posix.Files as Files
|
|
import Data.Bits ((.&.))
|
|
|
|
watchDir :: FilePath -> (FilePath -> Bool) -> Bool -> WatchHooks -> IO EventStream
|
|
watchDir dir ignored scanevents hooks = do
|
|
unlessM fileLevelEventsSupported $
|
|
error "Need at least OSX 10.7.0 for file-level FSEvents"
|
|
scan dir
|
|
eventStreamCreate [dir] 1.0 True True True handle
|
|
where
|
|
handle evt
|
|
| ignoredPath ignored (eventPath evt) = noop
|
|
| otherwise = do
|
|
{- More than one flag may be set, if events occurred
|
|
- close together.
|
|
-
|
|
- Order is important..
|
|
- If a file is added and then deleted, we'll see it's
|
|
- not present, and addHook won't run.
|
|
- OTOH, if a file is deleted and then re-added,
|
|
- the delHook will run first, followed by the addHook.
|
|
-}
|
|
|
|
when (hasflag eventFlagItemRemoved) $
|
|
if hasflag eventFlagItemIsDir
|
|
then runhook delDirHook Nothing
|
|
else runhook delHook Nothing
|
|
when (hasflag eventFlagItemCreated) $
|
|
maybe noop handleadd =<< getstatus (eventPath evt)
|
|
{- When a file or dir is renamed, a rename event is
|
|
- received for both its old and its new name. -}
|
|
when (hasflag eventFlagItemRenamed) $
|
|
if hasflag eventFlagItemIsDir
|
|
then ifM (doesDirectoryExist $ eventPath evt)
|
|
( scan $ eventPath evt
|
|
, runhook delDirHook Nothing
|
|
)
|
|
else maybe (runhook delHook Nothing) handleadd
|
|
=<< getstatus (eventPath evt)
|
|
{- Add hooks are run when a file is modified for
|
|
- compatability with INotify, which calls the add
|
|
- hook when a file is closed, and so tends to call
|
|
- both add and modify for file modifications. -}
|
|
when (hasflag eventFlagItemModified && not (hasflag eventFlagItemIsDir)) $ do
|
|
ms <- getstatus $ eventPath evt
|
|
maybe noop handleadd ms
|
|
runhook modifyHook ms
|
|
where
|
|
hasflag f = eventFlags evt .&. f /= 0
|
|
runhook h s = maybe noop (\a -> a (eventPath evt) s) (h hooks)
|
|
handleadd s
|
|
| Files.isSymbolicLink s = runhook addSymlinkHook $ Just s
|
|
| Files.isRegularFile s = runhook addHook $ Just s
|
|
| otherwise = noop
|
|
|
|
scan d = unless (ignoredPath ignored d) $
|
|
-- Do not follow symlinks when scanning.
|
|
-- This mirrors the inotify startup scan behavior.
|
|
mapM_ go =<< dirContentsRecursiveSkipping (const False) False d
|
|
where
|
|
go f
|
|
| ignoredPath ignored f = noop
|
|
| otherwise = do
|
|
ms <- getstatus f
|
|
case ms of
|
|
Nothing -> noop
|
|
Just s
|
|
| Files.isSymbolicLink s ->
|
|
when scanevents $
|
|
runhook addSymlinkHook ms
|
|
| Files.isRegularFile s ->
|
|
when scanevents $
|
|
runhook addHook ms
|
|
| otherwise ->
|
|
noop
|
|
where
|
|
runhook h s = maybe noop (\a -> a f s) (h hooks)
|
|
|
|
getstatus = catchMaybeIO . getSymbolicLinkStatus
|
|
|
|
{- Check each component of the path to see if it's ignored. -}
|
|
ignoredPath :: (FilePath -> Bool) -> FilePath -> Bool
|
|
ignoredPath ignored = any ignored . map dropTrailingPathSeparator . splitPath
|