make checksum default behavior, pass ^C to running command
This commit is contained in:
parent
0c58a1e8bd
commit
c8b8149be0
3 changed files with 81 additions and 34 deletions
80
listen.go
80
listen.go
|
@ -17,12 +17,14 @@ import (
|
|||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
var triggered bool = false
|
||||
|
||||
type Listen struct {
|
||||
FileMap map[string]bool
|
||||
CksumMap map[string][]byte
|
||||
IntervalMap map[string]time.Time
|
||||
Condition string
|
||||
Cksum bool
|
||||
NoCksum bool
|
||||
Interval time.Duration
|
||||
Command []string
|
||||
Quiet bool
|
||||
|
@ -74,6 +76,7 @@ func allCheck(l Listen) bool {
|
|||
}
|
||||
|
||||
func runTrigger(l Listen, f string, r bool, quit chan bool) bool {
|
||||
triggered = true
|
||||
if !l.Quiet && !r {
|
||||
if l.Condition == "any" {
|
||||
printStatus(fmt.Sprintf("& File %s modified. ", f))
|
||||
|
@ -94,12 +97,32 @@ func runTrigger(l Listen, f string, r bool, quit chan bool) bool {
|
|||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
if rc, ok := err.(*exec.ExitError); ok {
|
||||
if !l.Quiet {
|
||||
color.New(color.FgYellow).Fprintf(os.Stderr, "& WARNING: Command exited with code %d.\n", rc.ExitCode())
|
||||
exit := make(chan bool)
|
||||
s := make(chan os.Signal, 1)
|
||||
signal.Notify(s, os.Interrupt)
|
||||
|
||||
go func() {
|
||||
if err := cmd.Wait(); err != nil {
|
||||
if rc, ok := err.(*exec.ExitError); ok {
|
||||
if !l.Quiet {
|
||||
switch rc.ExitCode() {
|
||||
case -1:
|
||||
color.New(color.FgYellow).Fprintf(os.Stderr, "\n& WARNING: Command interrupted with ^C.\n")
|
||||
default:
|
||||
color.New(color.FgYellow).Fprintf(os.Stderr, "& WARNING: Command exited with code %d.\n", rc.ExitCode())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit <- true
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-s:
|
||||
cmd.Process.Signal(os.Interrupt)
|
||||
<-exit
|
||||
case <-exit:
|
||||
}
|
||||
|
||||
if !l.Quiet {
|
||||
|
@ -111,9 +134,11 @@ func runTrigger(l Listen, f string, r bool, quit chan bool) bool {
|
|||
}
|
||||
|
||||
quit <- true
|
||||
triggered = false
|
||||
return true
|
||||
}
|
||||
|
||||
triggered = false
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -140,13 +165,7 @@ func loopFsnotify(l Listen, quit chan bool) {
|
|||
|
||||
for key := range l.FileMap {
|
||||
if event.Name == key {
|
||||
if l.Cksum {
|
||||
// return value indicates a break is needed
|
||||
if cksumCheck(l, key, &trigger) {
|
||||
fileMod = key
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if l.NoCksum {
|
||||
if event.Has(fsnotify.Write) {
|
||||
if l.Condition == "any" {
|
||||
fileMod = key
|
||||
|
@ -169,6 +188,12 @@ func loopFsnotify(l Listen, quit chan bool) {
|
|||
|
||||
l.FileMap[key] = true
|
||||
}
|
||||
} else {
|
||||
// return value indicates a break is needed
|
||||
if cksumCheck(l, key, &trigger) {
|
||||
fileMod = key
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end for
|
||||
|
@ -206,13 +231,7 @@ func loopInterval(l Listen, quit chan bool) {
|
|||
trigger := false
|
||||
|
||||
for key := range l.FileMap {
|
||||
if l.Cksum {
|
||||
// return value indicates a break is needed
|
||||
if cksumCheck(l, key, &trigger) {
|
||||
fileMod = key
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if l.NoCksum {
|
||||
s, err := os.Stat(key)
|
||||
if err != nil {
|
||||
log.Fatal()
|
||||
|
@ -228,7 +247,12 @@ func loopInterval(l Listen, quit chan bool) {
|
|||
|
||||
l.FileMap[key] = true
|
||||
}
|
||||
|
||||
} else {
|
||||
// return value indicates a break is needed
|
||||
if cksumCheck(l, key, &trigger) {
|
||||
fileMod = key
|
||||
break
|
||||
}
|
||||
}
|
||||
} // end for key
|
||||
|
||||
|
@ -262,7 +286,7 @@ func startMessage(l Listen) {
|
|||
printStatus("& listen will exit when ")
|
||||
}
|
||||
|
||||
if l.Cksum {
|
||||
if !l.NoCksum {
|
||||
printStatus("the checksum of ")
|
||||
}
|
||||
|
||||
|
@ -278,10 +302,10 @@ func startMessage(l Listen) {
|
|||
printStatus("this file has ")
|
||||
}
|
||||
|
||||
if l.Cksum {
|
||||
printStatus("changed:\n")
|
||||
} else {
|
||||
if l.NoCksum {
|
||||
printStatus("been modified:\n")
|
||||
} else {
|
||||
printStatus("changed:\n")
|
||||
}
|
||||
|
||||
for key := range l.FileMap {
|
||||
|
@ -317,7 +341,13 @@ func (l Listen) Run() {
|
|||
|
||||
select {
|
||||
case <-c:
|
||||
fmt.Println()
|
||||
for {
|
||||
if !triggered {
|
||||
fmt.Println()
|
||||
break
|
||||
}
|
||||
<-c
|
||||
}
|
||||
case <-quit:
|
||||
}
|
||||
|
||||
|
|
26
main.go
26
main.go
|
@ -13,16 +13,16 @@ import (
|
|||
flags "github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
const VERSION string = "v0.3.1"
|
||||
const VERSION string = "v0.4.0"
|
||||
|
||||
type Options struct {
|
||||
Version bool `short:"v" long:"version" description:"Displays version info and exits"`
|
||||
Quiet bool `short:"q" long:"quiet" description:"Suppresses status messages (stderr lines beginning with '&')"`
|
||||
Files []string `short:"f" long:"file" description:"File(s) to listen to (watch)" value-name:"FILE"`
|
||||
Condition string `short:"w" long:"when" description:"If multiple files are specified, choose if any file or all files specified are needed to trigger COMMAND" default:"any" choice:"any" choice:"all"`
|
||||
Checksum bool `short:"c" long:"checksum" description:"Use checksum to determine when file(s) are changed instead of writes/modification time"`
|
||||
Interval string `short:"i" long:"interval" description:"Use this time interval (ex. 5m30s, 1s) between filesystem checks instead of watching kernel events. If the interval is effectively 0 (the default), kernel events are used" default:"0s"`
|
||||
RunFirst bool `short:"r" long:"run" description:"Runs COMMAND (if specified) before starting listen"`
|
||||
Version bool `short:"v" long:"version" description:"Displays version info and exits"`
|
||||
Quiet bool `short:"q" long:"quiet" description:"Suppresses status messages (stderr lines beginning with '&')"`
|
||||
Files []string `short:"f" long:"file" description:"File(s) to listen to (watch)" value-name:"FILE"`
|
||||
Condition string `short:"w" long:"when" description:"If multiple files are specified, choose if any file or all files specified are needed to trigger COMMAND" default:"any" choice:"any" choice:"all"`
|
||||
NoChecksum bool `short:"x" long:"no-checksum" description:"Do not calculate checksum as an additional check for file changes (see MODES section in man page for more info)"`
|
||||
Interval string `short:"i" long:"interval" description:"Use this time interval (ex. 5m30s, 1s) between filesystem checks instead of watching kernel events. If the interval is effectively 0 (the default), kernel events are used" default:"0s"`
|
||||
RunFirst bool `short:"r" long:"run" description:"Runs COMMAND (if specified) before starting listen"`
|
||||
}
|
||||
|
||||
func validateArgs(opts Options, commandLen int) error {
|
||||
|
@ -103,7 +103,7 @@ func setup(opts Options, command []string) {
|
|||
}
|
||||
|
||||
if success {
|
||||
l := Listen{filesMap, cksumMap, intervalMap, opts.Condition, opts.Checksum, intervalDuration, command, opts.Quiet, opts.RunFirst}
|
||||
l := Listen{filesMap, cksumMap, intervalMap, opts.Condition, opts.NoChecksum, intervalDuration, command, opts.Quiet, opts.RunFirst}
|
||||
l.Run()
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,13 @@ func main() {
|
|||
parser.Usage = "[OPTIONS] -- [COMMAND]"
|
||||
remaining, err := parser.Parse()
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
if err == nil {
|
||||
if opts.Version {
|
||||
fmt.Printf("listen %s\n", VERSION)
|
||||
|
@ -121,4 +128,5 @@ func main() {
|
|||
setup(opts, remaining)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
9
man/listen.1.md
Normal file
9
man/listen.1.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
% listen | General Commands Manual
|
||||
|
||||
# NAME
|
||||
|
||||
listen - A simple watcher program that runs commands when specified files are modified
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
listen [OPTIONS] -- [COMMAND]
|
Loading…
Add table
Reference in a new issue