diff options
author | Joey Hess <joey@kitenet.net> | 2012-06-19 09:56:03 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-06-19 09:56:03 -0400 |
commit | 2a61df23e72ed4880f8927e6094acd9b256bb13b (patch) | |
tree | dd33d00dcb2f3650685ba043732e1b2d01b2e125 /Utility | |
parent | 627504744c80c8a7b3f4b43e3646a5ad5c35d92f (diff) |
kqueue recursive directory adding
Diffstat (limited to 'Utility')
-rw-r--r-- | Utility/Kqueue.hs | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/Utility/Kqueue.hs b/Utility/Kqueue.hs index 1f65b2dba..a0edcb5a9 100644 --- a/Utility/Kqueue.hs +++ b/Utility/Kqueue.hs @@ -48,7 +48,11 @@ changedFile :: Change -> FilePath changedFile (Added f) = f changedFile (Deleted f) = f -data Kqueue = Kqueue Fd DirMap Pruner +data Kqueue = Kqueue + { kqueueFd :: Fd + , kqueueMap :: DirMap + , kqueuePruner :: Pruner + } type Pruner = FilePath -> Bool @@ -115,6 +119,13 @@ removeSubDir dirmap dir = do where (toremove, rest) = M.partition (dirContains dir . dirName) dirmap +findDirContents :: DirMap -> FilePath -> [FilePath] +findDirContents dirmap dir = concatMap absolutecontents $ search + where + absolutecontents i = map (dirName i </>) (S.toList $ dirCache i) + search = map snd $ M.toList $ + M.filter (\i -> dirName i == dir) dirmap + foreign import ccall unsafe "libkqueue.h init_kqueue" c_init_kqueue :: IO Fd foreign import ccall unsafe "libkqueue.h addfds_kqueue" c_addfds_kqueue @@ -140,7 +151,7 @@ updateKqueue (Kqueue h dirmap _) = {- Stops a Kqueue. Note: Does not directly close the Fds in the dirmap, - so it can be reused. -} stopKqueue :: Kqueue -> IO () -stopKqueue (Kqueue h _ _) = closeFd h +stopKqueue = closeFd . kqueueFd {- Waits for a change on a Kqueue. - May update the Kqueue. @@ -206,22 +217,30 @@ runHooks kq hooks = do (kq', changes) <- waitChange kq forM_ changes $ \c -> do print c - dispatch kq' c + dispatch (kqueueMap kq') c runHooks kq' hooks where -- Kqueue returns changes for both whole directories -- being added and deleted, and individual files being -- added and deleted. - dispatch q change - | isAdd change = withstatus change $ dispatchadd q + dispatch dirmap change + | isAdd change = withstatus change $ dispatchadd dirmap | otherwise = callhook delDirHook Nothing change - dispatchadd q change s - | Files.isSymbolicLink s = callhook addSymlinkHook (Just s) change - | Files.isDirectory s = print $ "TODO: recursive directory add: " ++ show change - | Files.isRegularFile s = callhook addHook (Just s) change - | otherwise = print "not a file??" + dispatchadd dirmap change s + | Files.isSymbolicLink s = + callhook addSymlinkHook (Just s) change + | Files.isDirectory s = do + -- Recursively add directory contents. + let contents = findDirContents dirmap $ + changedFile change + forM_ contents $ \f -> + withstatus (Added f) $ + dispatchadd dirmap + | Files.isRegularFile s = + callhook addHook (Just s) change + | otherwise = noop callhook h s change = case h hooks of - Nothing -> print "missing hook??" + Nothing -> noop Just a -> a (changedFile change) s withstatus change a = maybe noop (a change) =<< (catchMaybeIO (getSymbolicLinkStatus (changedFile change))) |