Command line + readme

This commit is contained in:
simon 2019-07-16 14:50:24 -04:00
parent 00d92a6084
commit 230a2cba59
3 changed files with 107 additions and 18 deletions

View File

@ -3,4 +3,44 @@
[![Build Status](https://ci.simon987.net/buildStatus/icon?job=beemer_builds)](https://ci.simon987.net/job/beemer_builds/)
[![CodeFactor](https://www.codefactor.io/repository/github/simon987/beemer/badge)](https://www.codefactor.io/repository/github/simon987/beemer)
wip
**beemer** executes a custom command on files written in the watched directory and deletes it.
### Usage
```
NAME:
beemer - Execute a command on a file after a delay of inactivity
GLOBAL OPTIONS:
--command value, -c value Will be executed on file write. You can use %file and %dir. Example: "rclone move %file remote:/beem/%dir"
--wait DELAY, -w DELAY Files will be beemed after DELAY of inactivity (default: 10s)
--directory DIRECTORY, -d DIRECTORY DIRECTORY to watch. If non-empty, its current files & subdirectories will be ignored
--help, -h show help
--version, -v print the version
```
### Examples
Upload file to an rclone remote when it has been inactive for at least 30s,
keeps the directory structure
```bash
./beemer -w 30s -d ./test -c "rclone move %file remote:/beem/%dir"
```
Send file via SSH, ignoring the local directory structure
```bash
./beemer -d ./test -c "scp %file worker@StagingServer:flatdir/"
```
Upload file to transfer.sh, store URLs in `urls.txt`
```bash
./beemer -w 1s -d ./test -c "bash -c \"curl -s -w '\\n' --upload-file %file https://transfer.sh/%name &>> urls.txt\""
```
### Beem command template
| Special sequence | Description | Example |
| :--- | :--- | :--- |
| `%file` | Full path of the modified file | `/tmp/beemer/test/a/myFile.txt` |
| `%name` | Name of the modified file | `myFile.txt` |
| `%dir` | Directory of the modified file, relative to the watched dir. | `test/a` |

76
main.go
View File

@ -2,7 +2,9 @@ package main
import (
"github.com/fsnotify/fsnotify"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"os"
"os/exec"
"path/filepath"
@ -21,8 +23,7 @@ type File struct {
BeemLock bool
}
var CmdString = "rclone move %file remote:/beem/%dir"
var InactiveDelay = time.Second * 5
var InactiveDelay time.Duration
var ctx = Ctx{
FileMap: make(map[string]*File, 0),
@ -31,26 +32,71 @@ var ctx = Ctx{
func main() {
logrus.SetLevel(logrus.TraceLevel)
initTempDir()
ctx.BeemCommand = parseCommand(CmdString)
app := cli.NewApp()
app.Name = "beemer"
app.Usage = "Execute a command on a file after a delay of inactivity"
app.Email = "me@simon987.net"
app.Author = "simon987"
app.Version = "1.0"
watcher, err := fsnotify.NewWatcher()
if err != nil {
logrus.Fatal(err)
var cmdString string
var watchDir string
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "command, c",
Usage: "Will be executed on file write. You can use %file, %name and %dir. " +
"Example: \"rclone move %file remote:/beem/%dir\"",
Destination: &cmdString,
},
cli.DurationFlag{
Name: "wait, w",
Usage: "Files will be beemed after `DELAY` of inactivity",
Destination: &InactiveDelay,
Value: time.Second * 10,
},
cli.StringFlag{
Name: "directory, d",
Usage: "`DIRECTORY` to watch. If non-empty, its current files & subdirectories will be ignored",
Destination: &watchDir,
},
}
defer watcher.Close()
app.Action = func(c *cli.Context) error {
go handleFileChange(watcher)
if !c.IsSet("directory") {
return errors.New("Directory must be specified")
}
err = watcher.Add("./test")
if err != nil {
logrus.Fatal(err)
initTempDir()
ctx.BeemCommand = parseCommand(cmdString)
watcher, err := fsnotify.NewWatcher()
if err != nil {
logrus.Fatal(err)
}
defer watcher.Close()
go handleFileChange(watcher)
logrus.WithField("dir", watchDir).Info("Watching directory for changes")
err = watcher.Add(watchDir)
if err != nil {
logrus.Fatal(err)
}
//TODO gracefully handle SIGINT
done := make(chan bool)
<-done
return nil
}
//TODO gracefully handle SIGINT
done := make(chan bool)
<-done
err := app.Run(os.Args)
if err != nil {
logrus.Fatal(app.OnUsageError)
}
}
func getAndResetTimer(name string) *time.Timer {

View File

@ -84,13 +84,16 @@ func copyFile(src string, dst string) error {
func parseCommand(command string) func(string, string) (string, []string) {
args, _ := argv.Argv([]rune(command), argv.ParseEnv(os.Environ()), argv.Run)
logrus.WithField("cmd", args[0]).Info("Parsed beem command")
return func(name string, dir string) (string, []string) {
newTokens := make([]string, len(args[0]))
copy(newTokens, args[0])
for i := range newTokens {
newTokens[i] = strings.Replace(newTokens[i], "%file", name,-1)
newTokens[i] = strings.Replace(newTokens[i], "%dir", dir,-1)
newTokens[i] = strings.Replace(newTokens[i], "%file", name, -1)
newTokens[i] = strings.Replace(newTokens[i], "%dir", dir, -1)
newTokens[i] = strings.Replace(newTokens[i], "%name", filepath.Base(name), -1)
}
return args[0][0], newTokens[1:]
}