2013-09-04 22:02:17 -04:00
/ *
Copyright ( C ) 2013 Aaron Lindsay < aaron @ aclindsay . com >
* /
2013-02-11 23:16:19 -05:00
package main
import (
2013-02-20 23:43:01 -05:00
"asink"
2013-02-11 23:16:19 -05:00
"github.com/howeyc/fsnotify"
2013-02-12 09:11:38 -05:00
"os"
"path/filepath"
2013-02-13 07:31:10 -05:00
"time"
2013-02-11 23:16:19 -05:00
)
2013-02-20 23:43:01 -05:00
func StartWatching ( watchDir string , fileUpdates chan * asink . Event ) {
2013-02-11 23:16:19 -05:00
watcher , err := fsnotify . NewWatcher ( )
if err != nil {
panic ( "Failed to create fsnotify watcher" )
}
2013-02-12 09:11:38 -05:00
//function called by filepath.Walk to start watching a directory and all subdirectories
watchDirFn := func ( path string , info os . FileInfo , err error ) error {
if info . IsDir ( ) {
err = watcher . Watch ( path )
if err != nil {
panic ( "Failed to watch " + path )
2013-02-11 23:16:19 -05:00
}
2013-08-23 00:09:03 -04:00
} else if info . Mode ( ) . IsRegular ( ) {
event := new ( asink . Event )
event . Path = path
event . Type = asink . UPDATE
event . Timestamp = info . ModTime ( ) . UnixNano ( )
fileUpdates <- event
2013-02-12 09:11:38 -05:00
}
return nil
}
2013-02-11 23:16:19 -05:00
2013-02-12 09:11:38 -05:00
//processes all the fsnotify events into asink events
go func ( ) {
for {
select {
case ev := <- watcher . Event :
//if a directory was created, begin recursively watching all its subdirectories
if fi , err := os . Stat ( ev . Name ) ; err == nil && fi . IsDir ( ) {
if ev . IsCreate ( ) {
2013-09-05 19:58:32 -04:00
//Note: even though filepath.Walk will visit root, we must watch root first so we catch files/directories created after the walk begins but before this directory begins being watched
err = watcher . Watch ( ev . Name )
if err != nil {
panic ( "Failed to watch " + ev . Name )
}
2013-02-12 09:11:38 -05:00
filepath . Walk ( ev . Name , watchDirFn )
2013-08-14 22:58:34 -04:00
//TODO do a scan of this directory so we ensure any file events we missed before starting to watch this directory are caught
2013-02-12 09:11:38 -05:00
}
2013-02-11 23:17:12 -05:00
continue
}
2013-02-11 23:16:19 -05:00
2013-02-20 23:43:01 -05:00
event := new ( asink . Event )
2013-02-12 09:11:38 -05:00
if ev . IsCreate ( ) || ev . IsModify ( ) {
2013-02-20 23:43:01 -05:00
event . Type = asink . UPDATE
2013-02-12 09:11:38 -05:00
} else if ev . IsDelete ( ) || ev . IsRename ( ) {
2013-02-20 23:43:01 -05:00
event . Type = asink . DELETE
2013-02-12 09:11:38 -05:00
} else {
panic ( "Unknown fsnotify event type" )
}
event . Path = ev . Name
2013-02-20 23:43:01 -05:00
event . Timestamp = time . Now ( ) . UnixNano ( )
2013-02-13 07:31:10 -05:00
2013-02-12 09:11:38 -05:00
fileUpdates <- event
2013-02-11 23:16:19 -05:00
2013-02-12 09:11:38 -05:00
case err := <- watcher . Error :
panic ( err )
}
2013-02-11 23:16:19 -05:00
}
2013-02-12 09:11:38 -05:00
} ( )
//start watching the directory passed in
filepath . Walk ( watchDir , watchDirFn )
2013-02-11 23:16:19 -05:00
}