act/vendor/github.com/andreaskoch/go-fswatch/file.go
Jesse Newland 3198627879 --watch
2019-02-09 20:39:09 -06:00

192 lines
3.8 KiB
Go

// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package fswatch
import (
"fmt"
"os"
"time"
)
var numberOfFileWatchers int
func init() {
numberOfFolderWatchers = 0
}
func NumberOfFileWatchers() int {
return numberOfFileWatchers
}
type FileWatcher struct {
modified chan bool
moved chan bool
stopped chan bool
file string
running bool
wasStopped bool
checkInterval time.Duration
previousModTime time.Time
}
func NewFileWatcher(filePath string, checkIntervalInSeconds int) *FileWatcher {
if checkIntervalInSeconds < 1 {
panic(fmt.Sprintf("Cannot create a file watcher with a check interval of %v seconds.", checkIntervalInSeconds))
}
return &FileWatcher{
modified: make(chan bool),
moved: make(chan bool),
stopped: make(chan bool),
file: filePath,
checkInterval: time.Duration(checkIntervalInSeconds),
}
}
func (fileWatcher *FileWatcher) String() string {
return fmt.Sprintf("Filewatcher %q", fileWatcher.file)
}
func (fileWatcher *FileWatcher) SetFile(filePath string) {
fileWatcher.file = filePath
}
func (filewatcher *FileWatcher) Modified() chan bool {
return filewatcher.modified
}
func (filewatcher *FileWatcher) Moved() chan bool {
return filewatcher.moved
}
func (filewatcher *FileWatcher) Stopped() chan bool {
return filewatcher.stopped
}
func (fileWatcher *FileWatcher) Start() {
fileWatcher.running = true
sleepInterval := time.Second * fileWatcher.checkInterval
go func() {
// increment watcher count
numberOfFileWatchers++
var modTime time.Time
previousModTime := fileWatcher.getPreviousModTime()
if timeIsSet(previousModTime) {
modTime = previousModTime
} else {
currentModTime, err := getLastModTimeFromFile(fileWatcher.file)
if err != nil {
// send out the notification
log("File %q has been moved or is inaccessible.", fileWatcher.file)
go func() {
fileWatcher.moved <- true
}()
// stop this file watcher
fileWatcher.Stop()
} else {
modTime = currentModTime
}
}
for fileWatcher.wasStopped == false {
newModTime, err := getLastModTimeFromFile(fileWatcher.file)
if err != nil {
// send out the notification
log("File %q has been moved.", fileWatcher.file)
go func() {
fileWatcher.moved <- true
}()
// stop this file watcher
fileWatcher.Stop()
continue
}
// detect changes
if modTime.Before(newModTime) {
// send out the notification
log("File %q has been modified.", fileWatcher.file)
go func() {
fileWatcher.modified <- true
}()
} else {
log("File %q has not changed.", fileWatcher.file)
}
// assign the new modtime
modTime = newModTime
time.Sleep(sleepInterval)
}
fileWatcher.running = false
// capture the entry list for a restart
fileWatcher.captureModTime(modTime)
// inform channel-subscribers
go func() {
fileWatcher.stopped <- true
}()
// decrement the watch counter
numberOfFileWatchers--
// final log message
log("Stopped file watcher %q", fileWatcher.String())
}()
}
func (fileWatcher *FileWatcher) Stop() {
log("Stopping file watcher %q", fileWatcher.String())
fileWatcher.wasStopped = true
}
func (fileWatcher *FileWatcher) IsRunning() bool {
return fileWatcher.running
}
func (fileWatcher *FileWatcher) getPreviousModTime() time.Time {
return fileWatcher.previousModTime
}
// Remember the last mod time for a later restart
func (fileWatcher *FileWatcher) captureModTime(modTime time.Time) {
fileWatcher.previousModTime = modTime
}
func getLastModTimeFromFile(file string) (time.Time, error) {
fileInfo, err := os.Stat(file)
if err != nil {
return time.Time{}, err
}
return fileInfo.ModTime(), nil
}
func timeIsSet(t time.Time) bool {
return time.Time{} == t
}