mirror of
https://github.com/simon987/beemer.git
synced 2025-04-19 08:06:42 +00:00
Command line + readme
This commit is contained in:
parent
00d92a6084
commit
230a2cba59
42
README.md
42
README.md
@ -3,4 +3,44 @@
|
|||||||
[](https://ci.simon987.net/job/beemer_builds/)
|
[](https://ci.simon987.net/job/beemer_builds/)
|
||||||
[](https://www.codefactor.io/repository/github/simon987/beemer)
|
[](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
76
main.go
@ -2,7 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/urfave/cli"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -21,8 +23,7 @@ type File struct {
|
|||||||
BeemLock bool
|
BeemLock bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var CmdString = "rclone move %file remote:/beem/%dir"
|
var InactiveDelay time.Duration
|
||||||
var InactiveDelay = time.Second * 5
|
|
||||||
|
|
||||||
var ctx = Ctx{
|
var ctx = Ctx{
|
||||||
FileMap: make(map[string]*File, 0),
|
FileMap: make(map[string]*File, 0),
|
||||||
@ -31,26 +32,71 @@ var ctx = Ctx{
|
|||||||
func main() {
|
func main() {
|
||||||
logrus.SetLevel(logrus.TraceLevel)
|
logrus.SetLevel(logrus.TraceLevel)
|
||||||
|
|
||||||
initTempDir()
|
app := cli.NewApp()
|
||||||
ctx.BeemCommand = parseCommand(CmdString)
|
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()
|
var cmdString string
|
||||||
if err != nil {
|
var watchDir string
|
||||||
logrus.Fatal(err)
|
|
||||||
|
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")
|
initTempDir()
|
||||||
if err != nil {
|
ctx.BeemCommand = parseCommand(cmdString)
|
||||||
logrus.Fatal(err)
|
|
||||||
|
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
|
err := app.Run(os.Args)
|
||||||
done := make(chan bool)
|
if err != nil {
|
||||||
<-done
|
logrus.Fatal(app.OnUsageError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAndResetTimer(name string) *time.Timer {
|
func getAndResetTimer(name string) *time.Timer {
|
||||||
|
7
util.go
7
util.go
@ -84,13 +84,16 @@ func copyFile(src string, dst string) error {
|
|||||||
func parseCommand(command string) func(string, string) (string, []string) {
|
func parseCommand(command string) func(string, string) (string, []string) {
|
||||||
args, _ := argv.Argv([]rune(command), argv.ParseEnv(os.Environ()), argv.Run)
|
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) {
|
return func(name string, dir string) (string, []string) {
|
||||||
newTokens := make([]string, len(args[0]))
|
newTokens := make([]string, len(args[0]))
|
||||||
copy(newTokens, args[0])
|
copy(newTokens, args[0])
|
||||||
|
|
||||||
for i := range newTokens {
|
for i := range newTokens {
|
||||||
newTokens[i] = strings.Replace(newTokens[i], "%file", name,-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], "%dir", dir, -1)
|
||||||
|
newTokens[i] = strings.Replace(newTokens[i], "%name", filepath.Base(name), -1)
|
||||||
}
|
}
|
||||||
return args[0][0], newTokens[1:]
|
return args[0][0], newTokens[1:]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user