add a new run command along with a new flag
This commit is contained in:
parent
8fdb78a858
commit
43338d4b2f
|
|
@ -174,6 +174,7 @@ func addKanikoOptionsFlags() {
|
||||||
RootCmd.PersistentFlags().BoolVarP(&opts.IgnoreVarRun, "whitelist-var-run", "", true, "Ignore /var/run directory when taking image snapshot. Set it to false to preserve /var/run/ in destination image. (Default true).")
|
RootCmd.PersistentFlags().BoolVarP(&opts.IgnoreVarRun, "whitelist-var-run", "", true, "Ignore /var/run directory when taking image snapshot. Set it to false to preserve /var/run/ in destination image. (Default true).")
|
||||||
RootCmd.PersistentFlags().VarP(&opts.Labels, "label", "", "Set metadata for an image. Set it repeatedly for multiple labels.")
|
RootCmd.PersistentFlags().VarP(&opts.Labels, "label", "", "Set metadata for an image. Set it repeatedly for multiple labels.")
|
||||||
RootCmd.PersistentFlags().BoolVarP(&opts.SkipUnusedStages, "skip-unused-stages", "", false, "Build only used stages if defined to true. Otherwise it builds by default all stages, even the unnecessaries ones until it reaches the target stage / end of Dockerfile")
|
RootCmd.PersistentFlags().BoolVarP(&opts.SkipUnusedStages, "skip-unused-stages", "", false, "Build only used stages if defined to true. Otherwise it builds by default all stages, even the unnecessaries ones until it reaches the target stage / end of Dockerfile")
|
||||||
|
RootCmd.PersistentFlags().BoolVarP(&opts.RunV2, "use-new-run", "", false, "Experimental run command to detect file system changes. This new run command does no rely on snapshotting to detect changes.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// addHiddenFlags marks certain flags as hidden from the executor help text
|
// addHiddenFlags marks certain flags as hidden from the executor help text
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Copyright 2018 Google, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
FROM debian:9.11
|
||||||
|
RUN echo "hey" > /etc/foo
|
||||||
|
RUN echo "baz" > /etc/baz
|
||||||
|
RUN cp /etc/baz /etc/bar
|
||||||
|
RUN rm /etc/baz
|
||||||
|
|
||||||
|
# Test with ARG
|
||||||
|
ARG file
|
||||||
|
RUN echo "run" > $file
|
||||||
|
|
||||||
|
RUN echo "test home" > $HOME/file
|
||||||
|
COPY context/foo $HOME/foo
|
||||||
|
|
@ -48,6 +48,7 @@ const (
|
||||||
// Arguments to build Dockerfiles with, used for both docker and kaniko builds
|
// Arguments to build Dockerfiles with, used for both docker and kaniko builds
|
||||||
var argsMap = map[string][]string{
|
var argsMap = map[string][]string{
|
||||||
"Dockerfile_test_run": {"file=/file"},
|
"Dockerfile_test_run": {"file=/file"},
|
||||||
|
"Dockerfile_test_run_new": {"file=/file"},
|
||||||
"Dockerfile_test_workdir": {"workdir=/arg/workdir"},
|
"Dockerfile_test_workdir": {"workdir=/arg/workdir"},
|
||||||
"Dockerfile_test_add": {"file=context/foo"},
|
"Dockerfile_test_add": {"file=context/foo"},
|
||||||
"Dockerfile_test_arg_secret": {"SSH_PRIVATE_KEY", "SSH_PUBLIC_KEY=Pµbl1cK€Y"},
|
"Dockerfile_test_arg_secret": {"SSH_PRIVATE_KEY", "SSH_PUBLIC_KEY=Pµbl1cK€Y"},
|
||||||
|
|
@ -74,6 +75,7 @@ var additionalDockerFlagsMap = map[string][]string{
|
||||||
// Arguments to build Dockerfiles with when building with kaniko
|
// Arguments to build Dockerfiles with when building with kaniko
|
||||||
var additionalKanikoFlagsMap = map[string][]string{
|
var additionalKanikoFlagsMap = map[string][]string{
|
||||||
"Dockerfile_test_add": {"--single-snapshot"},
|
"Dockerfile_test_add": {"--single-snapshot"},
|
||||||
|
"Dockerfile_test_run_new": {"--use-new-run=true"},
|
||||||
"Dockerfile_test_scratch": {"--single-snapshot"},
|
"Dockerfile_test_scratch": {"--single-snapshot"},
|
||||||
"Dockerfile_test_maintainer": {"--single-snapshot"},
|
"Dockerfile_test_maintainer": {"--single-snapshot"},
|
||||||
"Dockerfile_test_target": {"--target=second"},
|
"Dockerfile_test_target": {"--target=second"},
|
||||||
|
|
|
||||||
|
|
@ -51,3 +51,7 @@ func (b *BaseCommand) RequiresUnpackedFS() bool {
|
||||||
func (b *BaseCommand) ShouldCacheOutput() bool {
|
func (b *BaseCommand) ShouldCacheOutput() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *BaseCommand) ShouldDetectDeletedFiles() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,17 @@ type DockerCommand interface {
|
||||||
RequiresUnpackedFS() bool
|
RequiresUnpackedFS() bool
|
||||||
|
|
||||||
ShouldCacheOutput() bool
|
ShouldCacheOutput() bool
|
||||||
|
|
||||||
|
// ShouldDetectDeletedFiles turns true if the command could delete files.
|
||||||
|
ShouldDetectDeletedFiles() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCommand(cmd instructions.Command, buildcontext string) (DockerCommand, error) {
|
func GetCommand(cmd instructions.Command, buildcontext string, useNewRun bool) (DockerCommand, error) {
|
||||||
switch c := cmd.(type) {
|
switch c := cmd.(type) {
|
||||||
case *instructions.RunCommand:
|
case *instructions.RunCommand:
|
||||||
|
if useNewRun {
|
||||||
|
return &RunMarkerCommand{cmd: c}, nil
|
||||||
|
}
|
||||||
return &RunCommand{cmd: c}, nil
|
return &RunCommand{cmd: c}, nil
|
||||||
case *instructions.CopyCommand:
|
case *instructions.CopyCommand:
|
||||||
return &CopyCommand{cmd: c, buildcontext: buildcontext}, nil
|
return &CopyCommand{cmd: c, buildcontext: buildcontext}, nil
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,12 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
|
return runCommandInExec(config, buildArgs, r.cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCommandInExec(config *v1.Config, buildArgs *dockerfile.BuildArgs, cmdRun *instructions.RunCommand) error {
|
||||||
var newCommand []string
|
var newCommand []string
|
||||||
if r.cmd.PrependShell {
|
if cmdRun.PrependShell {
|
||||||
// This is the default shell on Linux
|
// This is the default shell on Linux
|
||||||
var shell []string
|
var shell []string
|
||||||
if len(config.Shell) > 0 {
|
if len(config.Shell) > 0 {
|
||||||
|
|
@ -56,9 +60,9 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
|
||||||
shell = append(shell, "/bin/sh", "-c")
|
shell = append(shell, "/bin/sh", "-c")
|
||||||
}
|
}
|
||||||
|
|
||||||
newCommand = append(shell, strings.Join(r.cmd.CmdLine, " "))
|
newCommand = append(shell, strings.Join(cmdRun.CmdLine, " "))
|
||||||
} else {
|
} else {
|
||||||
newCommand = r.cmd.CmdLine
|
newCommand = cmdRun.CmdLine
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Infof("cmd: %s", newCommand[0])
|
logrus.Infof("cmd: %s", newCommand[0])
|
||||||
|
|
@ -111,7 +115,6 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
|
||||||
if err := syscall.Kill(-pgid, syscall.SIGKILL); err != nil && err.Error() != "no such process" {
|
if err := syscall.Kill(-pgid, syscall.SIGKILL); err != nil && err.Error() != "no such process" {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Google LLC
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
|
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RunMarkerCommand struct {
|
||||||
|
BaseCommand
|
||||||
|
cmd *instructions.RunCommand
|
||||||
|
Files []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunMarkerCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
|
// run command `touch filemarker`
|
||||||
|
markerFile, err := ioutil.TempFile("", "marker")
|
||||||
|
defer func() {
|
||||||
|
os.Remove(markerFile.Name())
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := runCommandInExec(config, buildArgs, r.cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// run command find to find all new files generated
|
||||||
|
find := exec.Command("find", "/", "-newer", markerFile.Name())
|
||||||
|
out, err := find.Output()
|
||||||
|
if err != nil {
|
||||||
|
r.Files = []string{}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Files = []string{}
|
||||||
|
s := strings.Split(string(out), "\n")
|
||||||
|
for _, path := range s {
|
||||||
|
path = filepath.Clean(path)
|
||||||
|
if util.IsDestDir(path) || util.CheckIgnoreList(path) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r.Files = append(r.Files, path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns some information about the command for the image config
|
||||||
|
func (r *RunMarkerCommand) String() string {
|
||||||
|
return r.cmd.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunMarkerCommand) FilesToSnapshot() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunMarkerCommand) ProvidesFilesToSnapshot() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheCommand returns true since this command should be cached
|
||||||
|
func (r *RunMarkerCommand) CacheCommand(img v1.Image) DockerCommand {
|
||||||
|
|
||||||
|
return &CachingRunCommand{
|
||||||
|
img: img,
|
||||||
|
cmd: r.cmd,
|
||||||
|
extractFn: util.ExtractFile,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunMarkerCommand) MetadataOnly() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunMarkerCommand) RequiresUnpackedFS() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunMarkerCommand) ShouldCacheOutput() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseCommand) ShouldDetectDelete() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
@ -57,6 +57,7 @@ type KanikoOptions struct {
|
||||||
Cleanup bool
|
Cleanup bool
|
||||||
IgnoreVarRun bool
|
IgnoreVarRun bool
|
||||||
SkipUnusedStages bool
|
SkipUnusedStages bool
|
||||||
|
RunV2 bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// WarmerOptions are options that are set by command line arguments to the cache warmer.
|
// WarmerOptions are options that are set by command line arguments to the cache warmer.
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ type cachePusher func(*config.KanikoOptions, string, string, string) error
|
||||||
type snapShotter interface {
|
type snapShotter interface {
|
||||||
Init() error
|
Init() error
|
||||||
TakeSnapshotFS() (string, error)
|
TakeSnapshotFS() (string, error)
|
||||||
TakeSnapshot([]string) (string, error)
|
TakeSnapshot([]string, bool) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stageBuilder contains all fields necessary to build one stage of a Dockerfile
|
// stageBuilder contains all fields necessary to build one stage of a Dockerfile
|
||||||
|
|
@ -127,7 +127,7 @@ func newStageBuilder(opts *config.KanikoOptions, stage config.KanikoStage, cross
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cmd := range s.stage.Commands {
|
for _, cmd := range s.stage.Commands {
|
||||||
command, err := commands.GetCommand(cmd, opts.SrcContext)
|
command, err := commands.GetCommand(cmd, opts.SrcContext, opts.RunV2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -382,7 +382,7 @@ func (s *stageBuilder) build() error {
|
||||||
return errors.Wrap(err, "failed to save layer")
|
return errors.Wrap(err, "failed to save layer")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tarPath, err := s.takeSnapshot(files)
|
tarPath, err := s.takeSnapshot(files, command.ShouldDetectDeletedFiles())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to take snapshot")
|
return errors.Wrap(err, "failed to take snapshot")
|
||||||
}
|
}
|
||||||
|
|
@ -416,7 +416,7 @@ func (s *stageBuilder) build() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stageBuilder) takeSnapshot(files []string) (string, error) {
|
func (s *stageBuilder) takeSnapshot(files []string, shdDelete bool) (string, error) {
|
||||||
var snapshot string
|
var snapshot string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
@ -426,7 +426,7 @@ func (s *stageBuilder) takeSnapshot(files []string) (string, error) {
|
||||||
} else {
|
} else {
|
||||||
// Volumes are very weird. They get snapshotted in the next command.
|
// Volumes are very weird. They get snapshotted in the next command.
|
||||||
files = append(files, util.Volumes()...)
|
files = append(files, util.Volumes()...)
|
||||||
snapshot, err = s.snapshotter.TakeSnapshot(files)
|
snapshot, err = s.snapshotter.TakeSnapshot(files, shdDelete)
|
||||||
}
|
}
|
||||||
timing.DefaultRun.Stop(t)
|
timing.DefaultRun.Stop(t)
|
||||||
return snapshot, err
|
return snapshot, err
|
||||||
|
|
|
||||||
|
|
@ -1246,6 +1246,7 @@ func getCommands(dir string, cmds []instructions.Command) []commands.DockerComma
|
||||||
cmd, err := commands.GetCommand(
|
cmd, err := commands.GetCommand(
|
||||||
c,
|
c,
|
||||||
dir,
|
dir,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ func (m MockDockerCommand) RequiresUnpackedFS() bool {
|
||||||
func (m MockDockerCommand) ShouldCacheOutput() bool {
|
func (m MockDockerCommand) ShouldCacheOutput() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
func (m MockDockerCommand) ShouldDetectDeletedFiles() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type MockCachedDockerCommand struct {
|
type MockCachedDockerCommand struct {
|
||||||
contextFiles []string
|
contextFiles []string
|
||||||
|
|
@ -93,6 +96,9 @@ func (m MockCachedDockerCommand) ProvidesFilesToSnapshot() bool {
|
||||||
func (m MockCachedDockerCommand) CacheCommand(image v1.Image) commands.DockerCommand {
|
func (m MockCachedDockerCommand) CacheCommand(image v1.Image) commands.DockerCommand {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (m MockCachedDockerCommand) ShouldDetectDeletedFiles() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
func (m MockCachedDockerCommand) FilesUsedFromContext(c *v1.Config, args *dockerfile.BuildArgs) ([]string, error) {
|
func (m MockCachedDockerCommand) FilesUsedFromContext(c *v1.Config, args *dockerfile.BuildArgs) ([]string, error) {
|
||||||
return m.contextFiles, nil
|
return m.contextFiles, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ func (s *Snapshotter) Key() (string, error) {
|
||||||
|
|
||||||
// TakeSnapshot takes a snapshot of the specified files, avoiding directories in the ignorelist, and creates
|
// TakeSnapshot takes a snapshot of the specified files, avoiding directories in the ignorelist, and creates
|
||||||
// a tarball of the changed files. Return contents of the tarball, and whether or not any files were changed
|
// a tarball of the changed files. Return contents of the tarball, and whether or not any files were changed
|
||||||
func (s *Snapshotter) TakeSnapshot(files []string) (string, error) {
|
func (s *Snapshotter) TakeSnapshot(files []string, shdCheckDelete bool) (string, error) {
|
||||||
f, err := ioutil.TempFile(config.KanikoDir, "")
|
f, err := ioutil.TempFile(config.KanikoDir, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
@ -92,9 +92,30 @@ func (s *Snapshotter) TakeSnapshot(files []string) (string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get whiteout paths
|
||||||
|
filesToWhiteout := []string{}
|
||||||
|
if shdCheckDelete {
|
||||||
|
existingPaths := s.l.getFlattenedPathsForWhiteOut()
|
||||||
|
foundFiles := walkFS(s.directory)
|
||||||
|
for _, file := range foundFiles {
|
||||||
|
delete(existingPaths, file)
|
||||||
|
}
|
||||||
|
// The paths left here are the ones that have been deleted in this layer.
|
||||||
|
filesToWhiteOut := []string{}
|
||||||
|
for path := range existingPaths {
|
||||||
|
// Only add the whiteout if the directory for the file still exists.
|
||||||
|
dir := filepath.Dir(path)
|
||||||
|
if _, ok := existingPaths[dir]; !ok {
|
||||||
|
if s.l.MaybeAddWhiteout(path) {
|
||||||
|
logrus.Debugf("Adding whiteout for %s", path)
|
||||||
|
filesToWhiteOut = append(filesToWhiteOut, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
t := util.NewTar(f)
|
t := util.NewTar(f)
|
||||||
defer t.Close()
|
defer t.Close()
|
||||||
if err := writeToTar(t, filesToAdd, nil); err != nil {
|
if err := writeToTar(t, filesToAdd, filesToWhiteout); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return f.Name(), nil
|
return f.Name(), nil
|
||||||
|
|
@ -133,31 +154,8 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) {
|
||||||
|
|
||||||
s.l.Snapshot()
|
s.l.Snapshot()
|
||||||
|
|
||||||
timer := timing.Start("Walking filesystem")
|
foundPaths := walkFS(s.directory)
|
||||||
|
timer := timing.Start("Resolving Paths")
|
||||||
foundPaths := make([]string, 0)
|
|
||||||
|
|
||||||
godirwalk.Walk(s.directory, &godirwalk.Options{
|
|
||||||
Callback: func(path string, ent *godirwalk.Dirent) error {
|
|
||||||
if util.IsInIgnoreList(path) {
|
|
||||||
if util.IsDestDir(path) {
|
|
||||||
logrus.Tracef("Skipping paths under %s, as it is a ignored directory", path)
|
|
||||||
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
foundPaths = append(foundPaths, path)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Unsorted: true,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
timing.DefaultRun.Stop(timer)
|
|
||||||
timer = timing.Start("Resolving Paths")
|
|
||||||
// First handle whiteouts
|
// First handle whiteouts
|
||||||
// Get a list of all the files that existed before this layer
|
// Get a list of all the files that existed before this layer
|
||||||
existingPaths := s.l.getFlattenedPathsForWhiteOut()
|
existingPaths := s.l.getFlattenedPathsForWhiteOut()
|
||||||
|
|
@ -267,3 +265,29 @@ func filesWithLinks(path string) ([]string, error) {
|
||||||
}
|
}
|
||||||
return []string{path, link}, nil
|
return []string{path, link}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func walkFS(dir string) []string {
|
||||||
|
foundPaths := make([]string, 0)
|
||||||
|
timer := timing.Start("Walking filesystem")
|
||||||
|
godirwalk.Walk(dir, &godirwalk.Options{
|
||||||
|
Callback: func(path string, ent *godirwalk.Dirent) error {
|
||||||
|
if util.IsInIgnoreList(path) {
|
||||||
|
if util.IsDestDir(path) {
|
||||||
|
logrus.Tracef("Skipping paths under %s, as it is a ignored directory", path)
|
||||||
|
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
foundPaths = append(foundPaths, path)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Unsorted: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
timing.DefaultRun.Stop(timer)
|
||||||
|
return foundPaths
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ func TestSnapshotFiles(t *testing.T) {
|
||||||
filesToSnapshot := []string{
|
filesToSnapshot := []string{
|
||||||
filepath.Join(testDir, "foo"),
|
filepath.Join(testDir, "foo"),
|
||||||
}
|
}
|
||||||
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot)
|
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -359,7 +359,7 @@ func TestSnasphotPreservesFileOrder(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take a snapshot
|
// Take a snapshot
|
||||||
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot)
|
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error taking snapshot of fs: %s", err)
|
t.Fatalf("Error taking snapshot of fs: %s", err)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue