From eee0befe423b7d41b7eae367fa9664e0c552dddf Mon Sep 17 00:00:00 2001 From: David Arnold Date: Sun, 4 Oct 2015 12:19:41 -0500 Subject: [PATCH 1/2] WIP (windows support): stub for supporting windows via fsnotify.v1 --- main.go | 2 + main_windows.go | 166 ++++++++++++++++++++++++++++++++++++++++++++++++ watch.go | 2 + 3 files changed, 170 insertions(+) create mode 100644 main_windows.go diff --git a/main.go b/main.go index 470a7bb..1795eaf 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,5 @@ +// +build darwin + package main import ( diff --git a/main_windows.go b/main_windows.go new file mode 100644 index 0000000..b4df758 --- /dev/null +++ b/main_windows.go @@ -0,0 +1,166 @@ +// +build windows + +package main + +import ( + "flag" + "fmt" + "gopkg.in/fsnotify.v1" + "log" + "os" + pathpkg "path" + "strings" +) + +func main() { + pwd, err := os.Getwd() + if err != nil { + fmt.Println("error: unable to get current directory:", err) + os.Exit(1) + } + + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "usage: %v [options] DOCKER-MACHINE-NAME\n", os.Args[0]) + fmt.Fprintf(os.Stderr, " or: %v [options] rsync://IP:PORT/MODULE\n", os.Args[0]) + fmt.Print("\nOptions:\n") + flag.PrintDefaults() + } + + var version = flag.Bool("version", false, "Print version") + var watch = flag.Bool("watch", true, "Watch source directory for changes") + var verbose = flag.Bool("verbose", false, "Verbose output") + var srcpath = flag.String("src", pwd, "Source directory") + var dstpath = flag.String("dst", pathpkg.Join("/rsync", pwd), "Destination directory") + + flag.Parse() + + if *version { + fmt.Println(Version) + os.Exit(0) + } + + if len(flag.Args()) != 1 { + flag.Usage() + os.Exit(1) + } + + via := flag.Args()[0] + + if *srcpath == "" { + fmt.Println("error: please specify -src argument") + os.Exit(1) + } + + if *dstpath == "" { + fmt.Println("error: please specify -dst argument") + os.Exit(1) + } + + rpath := *srcpath + rpathDir := pathpkg.Dir(*dstpath) + + // TODO: refactor the following part... + + if strings.HasPrefix(via, "rsync://") { + // use rsync protocol directly + rsyncEndpoint := via + + fmt.Printf("Syncing %s (local) to %s (%s)\n", *srcpath, *dstpath, rsyncEndpoint) + Sync(rsyncEndpoint, 0, rpath, rpathDir, *verbose) // initial sync + + if *watch { + fmt.Println("Watching for file changes ...") + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + done := make(chan bool) + go func() { + for { + select { + case event := <-watcher.Events: + log.Println("event:", event) + if event.Op&fsnotify.Create == fsnotify.Create { + Sync(rsyncEndpoint, 0, rpath, rpathDir, true) + } + if event.Op&fsnotify.Write == fsnotify.Write { + Sync(rsyncEndpoint, 0, rpath, rpathDir, true) + } + if event.Op&fsnotify.Remove == fsnotify.Remove { + Sync(rsyncEndpoint, 0, rpath, rpathDir, true) + } + if event.Op&fsnotify.Rename == fsnotify.Rename { + Sync(rsyncEndpoint, 0, rpath, rpathDir, true) + } + case err := <-watcher.Errors: + log.Println("error:", err) + } + } + }() + + err = watcher.Add("/tmp/foo") + if err != nil { + log.Fatal(err) + } + <-done + } + + } else { + // use rsync via ssh + machineName := via + + port, err := GetSSHPort(machineName) + if err != nil { + fmt.Printf("error: unable to get port for machine '%v': %v\n", machineName, err) + os.Exit(1) + } + + Provision(machineName, *verbose) + RunSSHCommand(machineName, "sudo mkdir -p "+rpathDir, *verbose) + fmt.Printf("Syncing %s (local) to %s (docker-machine %s)\n", *srcpath, *dstpath, machineName) + Sync(machineName, port, rpath, rpathDir, *verbose) // initial sync + + if *watch { + fmt.Println("Watching for file changes ...") + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + done := make(chan bool) + go func() { + for { + select { + case event := <-watcher.Events: + log.Println("event:", event) + if event.Op&fsnotify.Create == fsnotify.Create { + Sync(machineName, port, rpath, rpathDir, true) + } + if event.Op&fsnotify.Write == fsnotify.Write { + Sync(machineName, port, rpath, rpathDir, true) + } + if event.Op&fsnotify.Remove == fsnotify.Remove { + Sync(machineName, port, rpath, rpathDir, true) + } + if event.Op&fsnotify.Rename == fsnotify.Rename { + Sync(machineName, port, rpath, rpathDir, true) + } + case err := <-watcher.Errors: + log.Println("error:", err) + } + } + }() + + err = watcher.Add("/tmp/foo") + if err != nil { + log.Fatal(err) + } + <-done + } + + } + +} diff --git a/watch.go b/watch.go index 86e6fb4..e2b4788 100644 --- a/watch.go +++ b/watch.go @@ -1,3 +1,5 @@ +// +build darwin + package main import ( From 8b667b14478625ba5aecac1b26a7bd225887a38d Mon Sep 17 00:00:00 2001 From: David Arnold Date: Sun, 4 Oct 2015 14:35:04 -0500 Subject: [PATCH 2/2] WIP (windos_support): avoide /bin/sh not found on windows. --- dockermachine.go | 4 ++-- rsync.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dockermachine.go b/dockermachine.go index 4af88c4..e96f0c1 100644 --- a/dockermachine.go +++ b/dockermachine.go @@ -31,11 +31,11 @@ func RunSSHCommand(machineName, command string, verbose bool) (out []byte, err e if verbose { fmt.Println(`docker-machine ssh ` + machineName + ` '` + command + `'`) } - return exec.Command("/bin/sh", "-c", `docker-machine ssh `+machineName+` '`+command+`'`).CombinedOutput() + return exec.Command("sh", "-c", `docker-machine ssh `+machineName+` '`+command+`'`).CombinedOutput() } func GetSSHPort(machineName string) (port uint, err error) { - out, err := exec.Command("/bin/sh", "-c", `docker-machine inspect `+machineName).CombinedOutput() + out, err := exec.Command("sh", "-c", `docker-machine inspect `+machineName).CombinedOutput() if err != nil { return 0, err } diff --git a/rsync.go b/rsync.go index f20d072..1223fdc 100644 --- a/rsync.go +++ b/rsync.go @@ -43,8 +43,8 @@ func Sync(via string, port uint, src, dst string, verbose bool) { command := "rsync " + strings.Join(args, " ") - // fmt.Println("/bin/sh", "-c", command) - cmd := exec.Command("/bin/sh", "-c", command) + // fmt.Println("sh", "-c", command) + cmd := exec.Command("sh", "-c", command) if verbose { cmd.Stdout = os.Stdout