packages feed

spy 0.4 → 0.5

raw patch · 5 files changed

+62/−71 lines, 5 filesdep +fsnotifydep +system-filepathdep +timedep −hfsevents

Dependencies added: fsnotify, system-filepath, time

Dependencies removed: hfsevents

Files

README.md view
@@ -1,7 +1,7 @@ Spy === -Spy is a compact file system watcher for Mac OS X using the [File System Events API](https://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/FSEvents_ProgGuide/Introduction/Introduction.html) via [hfsevents](https://github.com/luite/hfsevents).+Spy is a compact file system watcher for Mac OS X and Linux (Note: Should work on Windows but is currently untested).   Usage@@ -28,8 +28,11 @@ The default format is the full path to the modified file followed by a newline. To make it easier to parse the output, the `--format=json` changes the output to be printed formatted as a JSON object (again followed by a newline).      $> spy watch --format=json .-    {"path": "path/to/modified/file", "flags": ["ItemModified"], "id": 123143234}+    {"path":"/path/to/modified.file","flag":"Added","time":"2012-12-20 11:26:56.859456 UTC"} +Flag is one of "Added", "Modified", "Removed".++ For directories the following options apply:  An optional second argument can be used to filter the files in the given directory using a glob pattern:@@ -54,17 +57,15 @@ Installation ============ -Spy only works on Mac OS X >= 10.7 (Lion and above)!- Binary distribution ------------------- -The binary distribution contains a 64bit binary compiled for Mac OS X > 10.7.+The binary distribution contains a 64bit binary compiled for Mac OS X or Linux. -Download the tarball and run "make install" to copy the binary and the man page into the correct target directories:+Download the tarball from https://bitbucket.org/ssaasen/spy/downloads and run "make install" to copy the binary and the man page into the correct target directories: -    $> curl -OL https://bitbucket.org/ssaasen/spy/downloads/spy-osx-x86_64-v0.4.tar.gz-    $> tar xfz spy-osx-x86_64-v0.4.tar.gz+    $> curl -OL https://bitbucket.org/ssaasen/spy/downloads/spy-PLATFORM-ARCH-VERSION.tar.gz+    $> tar xfz spy-PLATFORM-ARCH-VERSION.tar.gz     $> cd spy     $> make install @@ -74,8 +75,18 @@ Source distribution ------------------- -To install spy from source you need the Haskell platform installed and cabal-install available on your $PATH:+You need the Haskell platform installed and cabal-install available on your $PATH. +To install spy from hackage simply run:++    $> cabal install spy++Done!++To install spy from git you need the Haskell platform installed and cabal-install available on your $PATH:++    $> git@bitbucket.org:ssaasen/spy.git+    $> cd spy     $> cabal install --only-dependencies     $> cabal configure     $> cabal build
spy.cabal view
@@ -1,11 +1,11 @@ name:               spy-version:            0.4+version:            0.5 license:            BSD3 license-file:       LICENSE author:             Stefan Saasen maintainer:         stefan@saasen.me-synopsis:           A compact file system watcher for Mac OS X-category:           Apple, Development+synopsis:           A compact file system watcher for Mac OS X, Linux and Windows+category:           Development description:        Spy can be used to watch for file changes and to either report the modified files or run a command if files change. It can be used to trigger compilation, to run tests or start a deployment. homepage:           https://bitbucket.org/ssaasen/spy bug-reports:        https://bitbucket.org/ssaasen/spy/issues@@ -30,26 +30,30 @@                             test-framework-hunit,                             HUnit,                             QuickCheck >= 2.4.0.1,-                            hfsevents >= 0.1.3,+                            fsnotify >= 0.0.4,                             cmdargs >= 0.10,                             filepath >= 1.3,                             filemanip >= 0.3.6.2,                             process >= 1.1,                             json >= 0.7,-                            directory >= 1.1+                            directory >= 1.1,+                            system-filepath >= 0.4.7,+                            time >= 1.4  executable  spy   main-is:          Main.hs   other-modules:    Spy.Watcher   build-depends:                     base < 5 && >= 3,-                    hfsevents >= 0.1.3,+                    fsnotify >= 0.0.4,                     cmdargs >= 0.10,                     filepath >= 1.3,                     filemanip >= 0.3.6.2,                     process >= 1.1,                     json >= 0.7,-                    directory >= 1.1+                    directory >= 1.1,+                    system-filepath >= 0.4.7,+                    time >= 1.4    ghc-options:                     -Wall
src/Main.hs view
@@ -6,7 +6,7 @@ import Spy.Watcher  version :: String-version = "spy v0.4, (C) Stefan Saasen"+version = "spy v0.5, (C) Stefan Saasen"  hiddenOpts x = x &= help "Set to true if hidden files/directories should be included" &= name "i" &= typ  "BOOL" 
src/Spy/Watcher.hs view
@@ -11,18 +11,16 @@ ,containsHiddenPathElement ) where -import System.OSX.FSEvents+import System.FSNotify import System.Console.CmdArgs import System.Cmd import System.Exit import System.IO (stderr, hPrint) import System.FilePath.GlobPattern import System.FilePath (splitDirectories, takeFileName)-import Control.Monad (unless)-import Control.Exception (bracket)+import Filesystem.Path.CurrentOS (encodeString, decodeString)+import Data.Time.Clock(UTCTime) import Data.Maybe (fromMaybe, maybeToList)-import Data.Bits-import Data.Word import Text.JSON  -- | The output format when Spy prints out changes to STDOUT@@ -48,15 +46,15 @@  -- | Register for FS events using the given Spy config. spy :: Spy -> IO String-spy config = bracket-  (eventStreamCreate [dir config] 1.0 True True True $ handleEvent config)-  eventStreamDestroy-  (\_ -> getLine)+spy config = withManager $ \wm ->+  watchTree wm (decodeString $ dir config)+              (not . skipEvent config . eventPath)+              (handleEvent config) >>+  getLine  -- | Handle the FS event based on the current Spy run configuration handleEvent :: Spy -> Event -> IO ()-handleEvent config@Run{..} event =-        unless (skipEvent config event) $+handleEvent Run{..} event =         runCommand command pathAsArg >>=             \exit -> case exit of                 ExitSuccess     -> return ()@@ -65,8 +63,7 @@                             Nothing                             else Just (eventPath event) -handleEvent config@Watch{..} event =-        unless (skipEvent config event) $+handleEvent Watch{..} event =         putStrLn $ (outputHandler $ fromMaybe Plain format) event  -- =================================================================================@@ -86,20 +83,33 @@ outputHandler :: Format -> Printer outputHandler Json  = \event -> encode $ makeObj [     ("path", showJSON $ eventPath event),-    ("id", showJSON $ eventId event),-    ("flags", showJSONs $ showEventFlags $ eventFlags event)]+    ("flag", showJSON $ eventType event),+    ("time", showJSON . show $ eventTime event)] outputHandler Plain = eventPath   -- | Skip events based on the configuration given-skipEvent :: Spy -> Event -> Bool-skipEvent config event = skipHidden || skipNonMatchingGlob+skipEvent :: Spy -> FilePath -> Bool+skipEvent config path = skipHidden || skipNonMatchingGlob     where skipHidden            = let includeHiddenfiles = hidden config                                   in not includeHiddenfiles && containsHiddenPathElement path           skipNonMatchingGlob   = maybe False (not . matchesFile path) $ glob config-          path                  = eventPath event +eventTime :: Event -> UTCTime+eventTime (Added _ t) = t+eventTime (Modified _ t) = t+eventTime (Removed _ t) = t +eventPath :: Event -> FilePath+eventPath (Added fp _) = encodeString fp+eventPath (Modified fp _) = encodeString fp+eventPath (Removed fp _) = encodeString fp++eventType :: Event -> FilePath+eventType (Added _ _) = "Added"+eventType (Modified _ _) = "Modified"+eventType (Removed _ _) = "Removed"+ matchesFile :: FilePath -> GlobPattern -> Bool matchesFile path glob' = takeFileName path ~~ glob' @@ -109,34 +119,3 @@                       isHidden name' = case name' of                                             (x:_)   -> x == '.'                                             _       -> False---- =================================================================================--- The following code is taken from:--- https://github.com/luite/hfsevents/blob/master/test/trace.hs--- Copyright (c) 2012, Luite Stegeman-showEventFlags :: Word64 -> [String]-showEventFlags fl = map fst . filter hasFlag $ flagList-  where hasFlag (_,f) = fl .&. f /= 0---flagList :: [(String, Word64)]-flagList = [ ("MustScanSubDirs"   , 0x00000001)-           , ("UserDropped"       , 0x00000002)-           , ("KernelDropped"     , 0x00000004)-           , ("EventIdsWrapped"   , 0x00000008)-           , ("HistoryDone"       , 0x00000010)-           , ("RootChanged"       , 0x00000020)-           , ("Mount"             , 0x00000040)-           , ("Unmount"           , 0x00000080)-           , ("ItemCreated"       , 0x00000100)-           , ("ItemRemoved"       , 0x00000200)-           , ("ItemInodeMetaMod"  , 0x00000400)-           , ("ItemRenamed"       , 0x00000800)-           , ("ItemModified"      , 0x00001000)-           , ("ItemFinderInfoMod" , 0x00002000)-           , ("ItemChangeOwner"   , 0x00004000)-           , ("ItemXattrMod"      , 0x00008000)-           , ("ItemIsFile"        , 0x00010000)-           , ("ItemIsDir"         , 0x00020000)-           , ("ItemIsSymlink"     , 0x00040000)-           ]
tests/Tests.hs view
@@ -4,7 +4,6 @@  import qualified Test.HUnit as H import Data.Maybe-import System.OSX.FSEvents import Spy.Watcher import Test.QuickCheck hiding ((.&.)) import Test.Framework (Test, defaultMain, testGroup)@@ -22,7 +21,7 @@  test_skipEventHidden = H.assertBool   "Skip path if hidden directory and showing hidden files is not enabled"-  (skipEvent (mockWatch {hidden = False}) (mockEvent "/a/b/.git/refs"))+  (skipEvent (mockWatch {hidden = False}) "/a/b/.git/refs")  test_containsHiddenPathElement = H.assertBool   "Should identify hidden directory"@@ -32,9 +31,7 @@ mockWatch :: Spy mockWatch = Watch { dir = ".", glob = Nothing, format = Nothing, hidden = False } -mockEvent :: FilePath -> Event-mockEvent path = Event path 0x00000001 0x00000001-------------------------------------------------------------------------+-- =========================================================== -- Test harness  main :: IO ()