2025-06-28 17:14:54 -06:00
package main
import (
2025-06-29 10:33:58 -06:00
"crypto/sha256"
2025-06-28 17:14:54 -06:00
"fmt"
2025-06-29 10:33:58 -06:00
"io"
2025-06-28 17:14:54 -06:00
"io/fs"
"log"
"os"
"path/filepath"
flags "github.com/jessevdk/go-flags"
)
const VERSION string = "v0.1.0"
var opts struct {
Version bool ` short:"v" long:"version" description:"Displays version info and exits" `
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" `
2025-06-29 10:33:58 -06:00
Checksum bool ` short:"c" long:"checksum" description:"Use checksum to determine when file(s) are changed instead of writes/modification time" `
2025-06-28 17:14:54 -06:00
Interval string ` short:"i" long:"interval" description:"Use this time interval (ex. 5m30s, 1s) between filesystem checks instead of using kernel events" `
}
func validateFiles ( files [ ] string ) error {
if len ( files ) <= 0 {
fmt . Println ( "listen: at least one file (-f) is required" )
return flags . ErrCommandRequired
}
for _ , file := range files {
info , err := os . Stat ( file )
if err != nil {
fmt . Printf ( "listen: %s\n" , err )
return err
}
if info . IsDir ( ) {
fmt . Printf ( "listen: %s: not a file\n" , file )
return fs . ErrInvalid
}
_ , err = os . Open ( file )
if err != nil {
fmt . Printf ( "listen: %s\n" , err )
return err
}
}
return nil
}
func main ( ) {
parser := flags . NewParser ( & opts , flags . Default )
parser . Usage = "[OPTIONS] -- [COMMAND]"
remaining , err := parser . Parse ( )
if err == nil {
if opts . Version {
fmt . Printf ( "listen %s\n" , VERSION )
} else if err := validateFiles ( opts . Files ) ; err == nil {
var filesMap map [ string ] bool = make ( map [ string ] bool )
2025-06-29 10:33:58 -06:00
var cksumMap map [ string ] [ ] byte = make ( map [ string ] [ ] byte )
2025-06-28 17:14:54 -06:00
success := true
for _ , file := range opts . Files {
2025-06-29 10:33:58 -06:00
hasher := sha256 . New ( )
f , err := os . Open ( file )
if err != nil {
success = false
break
}
if _ , err := io . Copy ( hasher , f ) ; err != nil {
log . Fatal ( err )
}
2025-06-28 17:14:54 -06:00
abs , err := filepath . Abs ( file )
if err == nil {
filesMap [ abs ] = false
2025-06-29 10:33:58 -06:00
cksumMap [ abs ] = hasher . Sum ( nil )
2025-06-28 17:14:54 -06:00
} else {
success = false
2025-06-29 10:33:58 -06:00
break
2025-06-28 17:14:54 -06:00
}
}
if success {
2025-06-29 10:33:58 -06:00
l := Listen { filesMap , cksumMap , opts . Condition , opts . Checksum , opts . Interval , remaining }
l . Run ( )
2025-06-28 17:14:54 -06:00
}
}
}
}