Skip to content

Commit 485c0eb

Browse files
jhrotkoglours
authored andcommitted
initial sync for root directory
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
1 parent 69384a9 commit 485c0eb

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

pkg/compose/watch.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"errors"
2020
"fmt"
2121
"io"
22+
"io/fs"
2223
"os"
2324
"path"
2425
"path/filepath"
@@ -157,6 +158,13 @@ func (s *composeService) watch(ctx context.Context, syncChannel chan bool, proje
157158
if checkIfPathAlreadyBindMounted(trigger.Path, service.Volumes) {
158159
logrus.Warnf("path '%s' also declared by a bind mount volume, this path won't be monitored!\n", trigger.Path)
159160
continue
161+
} else {
162+
var initialSync bool
163+
success, err := trigger.Extensions.Get("x-initialSync", &initialSync)
164+
if err == nil && success && initialSync && (trigger.Action == types.WatchActionSync || trigger.Action == types.WatchActionSyncRestart) {
165+
// Need to check initial files are in container that are meant to be synched from watch action
166+
s.initialSync(ctx, service, trigger, ignore, syncer)
167+
}
160168
}
161169
paths = append(paths, trigger.Path)
162170
pathLogs = append(pathLogs, fmt.Sprintf("Action %s for path %q", trigger.Action, trigger.Path))
@@ -574,3 +582,67 @@ func (s *composeService) pruneDanglingImagesOnRebuild(ctx context.Context, proje
574582
}
575583
}
576584
}
585+
586+
func (s *composeService) initialSync(ctx context.Context, service types.ServiceConfig, trigger types.Trigger, ignore watch.PathMatcher, syncer sync.Syncer) error {
587+
dockerFileIgnore, _ := watch.NewDockerPatternMatcher("/", []string{"Dockerfile", "*compose*.y*ml"})
588+
triggerIgnore, _ := watch.NewDockerPatternMatcher("/", trigger.Ignore)
589+
ignoreInitialSync := watch.NewCompositeMatcher(ignore, dockerFileIgnore, triggerIgnore)
590+
591+
pathsToCopy, err := initialSyncFiles(service, trigger, ignoreInitialSync)
592+
if err != nil {
593+
return err
594+
}
595+
596+
return syncer.Sync(ctx, service, pathsToCopy)
597+
}
598+
599+
func initialSyncFiles(service types.ServiceConfig, trigger types.Trigger, ignore watch.PathMatcher) ([]sync.PathMapping, error) {
600+
fi, err := os.Stat(trigger.Path)
601+
if err != nil {
602+
return nil, err
603+
}
604+
605+
var pathsToCopy []sync.PathMapping
606+
switch mode := fi.Mode(); {
607+
case mode.IsDir():
608+
// do directory stuff
609+
err = filepath.WalkDir(trigger.Path, func(path string, d fs.DirEntry, err error) error {
610+
if err != nil {
611+
// handle possible path err, just in case...
612+
return err
613+
}
614+
if trigger.Path == path {
615+
// walk starts at the root directory
616+
return nil
617+
}
618+
rel, _ := filepath.Rel(trigger.Path, path)
619+
if shouldIgnoreOrSkip(filepath.Base(path), ignore) || checkIfPathAlreadyBindMounted(path, service.Volumes) {
620+
// By definition sync ignores bind mounted paths
621+
if d.IsDir() {
622+
return fs.SkipDir // ignore or skip folder
623+
}
624+
return nil // ignore or skip file
625+
}
626+
pathsToCopy = append(pathsToCopy, sync.PathMapping{
627+
HostPath: path,
628+
ContainerPath: filepath.Join(trigger.Target, rel),
629+
})
630+
return nil
631+
})
632+
case mode.IsRegular():
633+
// do file stuff
634+
if !shouldIgnoreOrSkip(filepath.Base(trigger.Path), ignore) && !checkIfPathAlreadyBindMounted(trigger.Path, service.Volumes) {
635+
pathsToCopy = append(pathsToCopy, sync.PathMapping{
636+
HostPath: trigger.Path,
637+
ContainerPath: trigger.Target,
638+
})
639+
}
640+
}
641+
return pathsToCopy, nil
642+
}
643+
644+
func shouldIgnoreOrSkip(rel string, ignore watch.PathMatcher) bool {
645+
shouldIgnore, _ := ignore.Matches(rel)
646+
// ignore files that match any ignore pattern
647+
return shouldIgnore
648+
}

0 commit comments

Comments
 (0)