From 12c9d4844e858d4dccb678b5be803ce4e10af3bf Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Thu, 9 Feb 2023 15:26:59 +0100 Subject: [PATCH] add support for `excludes` and `rebuild` Signed-off-by: Nicolas De Loof --- pkg/compose/watch.go | 70 +++++++++++++++++++++++++------------ pkg/watch/watcher_darwin.go | 13 ++----- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/pkg/compose/watch.go b/pkg/compose/watch.go index 4b32ad3fdd6..887cbab94ef 100644 --- a/pkg/compose/watch.go +++ b/pkg/compose/watch.go @@ -28,12 +28,23 @@ import ( "github.com/jonboulle/clockwork" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" ) type DevelopmentConfig struct { - Sync map[string]string `json:"sync,omitempty"` - Excludes []string `json:"excludes,omitempty"` + Watch []Trigger `json:"watch,omitempty"` +} + +const ( + WatchActionSync = "sync" + WatchActionRebuild = "rebuild" +) + +type Trigger struct { + Path string `json:"path,omitempty"` + Action string `json:"action,omitempty"` + Target string `json:"target,omitempty"` } const quietPeriod = 2 * time.Second @@ -85,26 +96,38 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv case <-ctx.Done(): return nil case event := <-watcher.Events(): - fmt.Fprintf(s.stderr(), "change detected on %s\n", event.Path()) - - for src, dest := range config.Sync { - path := filepath.Clean(event.Path()) - src = filepath.Clean(src) - if watch.IsChild(path, src) { - rel, err := filepath.Rel(src, path) - if err != nil { - return err - } - dest = filepath.Join(dest, rel) - needSync <- api.CopyOptions{ - Source: path, - Destination: fmt.Sprintf("%s:%s", service.Name, dest), + path := event.Path() + + for _, trigger := range config.Watch { + logrus.Debugf("change deteced on %s - comparing with %s", path, trigger.Path) + if watch.IsChild(trigger.Path, path) { + fmt.Fprintf(s.stderr(), "change detected on %s\n", path) + + switch trigger.Action { + case WatchActionSync: + logrus.Debugf("modified file %s triggered sync", path) + rel, err := filepath.Rel(trigger.Path, path) + if err != nil { + return err + } + dest := filepath.Join(trigger.Target, rel) + needSync <- api.CopyOptions{ + Source: path, + Destination: fmt.Sprintf("%s:%s", service.Name, dest), + } + case WatchActionRebuild: + logrus.Debugf("modified file %s require image to be rebuilt", path) + needRebuild <- service.Name + default: + return fmt.Errorf("watch action %q is not supported", trigger) } continue WATCH } } + // default needRebuild <- service.Name + case err := <-watcher.Errors(): return err } @@ -124,14 +147,17 @@ func loadDevelopmentConfig(service types.ServiceConfig, project *types.Project) if y, ok := service.Extensions["x-develop"]; ok { err := mapstructure.Decode(y, &config) if err != nil { - return DevelopmentConfig{}, err + return config, err } - for src, dest := range config.Sync { - if !filepath.IsAbs(src) { - delete(config.Sync, src) - src = filepath.Join(project.WorkingDir, src) - config.Sync[src] = dest + for i, trigger := range config.Watch { + if !filepath.IsAbs(trigger.Path) { + trigger.Path = filepath.Join(project.WorkingDir, trigger.Path) + } + trigger.Path = filepath.Clean(trigger.Path) + if trigger.Path == "" { + return config, errors.New("watch rules MUST define a path") } + config.Watch[i] = trigger } } return config, nil diff --git a/pkg/watch/watcher_darwin.go b/pkg/watch/watcher_darwin.go index 46d6dc06ea0..9329a294b78 100644 --- a/pkg/watch/watcher_darwin.go +++ b/pkg/watch/watcher_darwin.go @@ -20,6 +20,7 @@ package watch import ( + "fmt" "path/filepath" "time" @@ -52,19 +53,9 @@ func (d *fseventNotify) loop() { } for _, e := range events { + fmt.Println(e) e.Path = filepath.Join("/", e.Path) - if e.Flags&fsevents.HistoryDone == fsevents.HistoryDone { - d.sawAnyHistoryDone = true - continue - } - - // We wait until we've seen the HistoryDone event for this watcher before processing any events - // so that we skip all of the "spurious" events that precede it. - if !d.sawAnyHistoryDone { - continue - } - _, isPathWereWatching := d.pathsWereWatching[e.Path] if e.Flags&fsevents.ItemIsDir == fsevents.ItemIsDir && e.Flags&fsevents.ItemCreated == fsevents.ItemCreated && isPathWereWatching { // This is the first create for the path that we're watching. We always get exactly one of these