Have .dockerignore support Dockerfile/.dockerignore
If .dockerignore mentions either then the client will send them to the daemon but the daemon will erase them after the Dockerfile has been parsed to simulate them never being sent in the first place. an events test kept failing for me so I tried to fix that too Closes #8330 Signed-off-by: Doug Davis <dug@us.ibm.com>
This commit is contained in:
parent
c466b9baa5
commit
f8ec68ef67
5 changed files with 59 additions and 23 deletions
|
@ -30,11 +30,11 @@ type (
|
|||
ArchiveReader io.Reader
|
||||
Compression int
|
||||
TarOptions struct {
|
||||
Includes []string
|
||||
Excludes []string
|
||||
Compression Compression
|
||||
NoLchown bool
|
||||
Name string
|
||||
IncludeFiles []string
|
||||
ExcludePatterns []string
|
||||
Compression Compression
|
||||
NoLchown bool
|
||||
Name string
|
||||
}
|
||||
|
||||
// Archiver allows the reuse of most utility functions of this package
|
||||
|
@ -378,7 +378,7 @@ func escapeName(name string) string {
|
|||
}
|
||||
|
||||
// TarWithOptions creates an archive from the directory at `path`, only including files whose relative
|
||||
// paths are included in `options.Includes` (if non-nil) or not in `options.Excludes`.
|
||||
// paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`.
|
||||
func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) {
|
||||
pipeReader, pipeWriter := io.Pipe()
|
||||
|
||||
|
@ -401,12 +401,14 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
|||
// mutating the filesystem and we can see transient errors
|
||||
// from this
|
||||
|
||||
if options.Includes == nil {
|
||||
options.Includes = []string{"."}
|
||||
if options.IncludeFiles == nil {
|
||||
options.IncludeFiles = []string{"."}
|
||||
}
|
||||
|
||||
seen := make(map[string]bool)
|
||||
|
||||
var renamedRelFilePath string // For when tar.Options.Name is set
|
||||
for _, include := range options.Includes {
|
||||
for _, include := range options.IncludeFiles {
|
||||
filepath.Walk(filepath.Join(srcPath, include), func(filePath string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
log.Debugf("Tar: Can't stat file %s to tar: %s", srcPath, err)
|
||||
|
@ -420,10 +422,19 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
|||
return nil
|
||||
}
|
||||
|
||||
skip, err := fileutils.Matches(relFilePath, options.Excludes)
|
||||
if err != nil {
|
||||
log.Debugf("Error matching %s", relFilePath, err)
|
||||
return err
|
||||
skip := false
|
||||
|
||||
// If "include" is an exact match for the current file
|
||||
// then even if there's an "excludePatterns" pattern that
|
||||
// matches it, don't skip it. IOW, assume an explicit 'include'
|
||||
// is asking for that file no matter what - which is true
|
||||
// for some files, like .dockerignore and Dockerfile (sometimes)
|
||||
if include != relFilePath {
|
||||
skip, err = fileutils.Matches(relFilePath, options.ExcludePatterns)
|
||||
if err != nil {
|
||||
log.Debugf("Error matching %s", relFilePath, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if skip {
|
||||
|
@ -433,6 +444,11 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
|||
return nil
|
||||
}
|
||||
|
||||
if seen[relFilePath] {
|
||||
return nil
|
||||
}
|
||||
seen[relFilePath] = true
|
||||
|
||||
// Rename the base resource
|
||||
if options.Name != "" && filePath == srcPath+"/"+filepath.Base(relFilePath) {
|
||||
renamedRelFilePath = relFilePath
|
||||
|
@ -487,7 +503,7 @@ loop:
|
|||
// This keeps "../" as-is, but normalizes "/../" to "/"
|
||||
hdr.Name = filepath.Clean(hdr.Name)
|
||||
|
||||
for _, exclude := range options.Excludes {
|
||||
for _, exclude := range options.ExcludePatterns {
|
||||
if strings.HasPrefix(hdr.Name, exclude) {
|
||||
continue loop
|
||||
}
|
||||
|
@ -563,8 +579,8 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
|
|||
if options == nil {
|
||||
options = &TarOptions{}
|
||||
}
|
||||
if options.Excludes == nil {
|
||||
options.Excludes = []string{}
|
||||
if options.ExcludePatterns == nil {
|
||||
options.ExcludePatterns = []string{}
|
||||
}
|
||||
decompressedArchive, err := DecompressStream(archive)
|
||||
if err != nil {
|
||||
|
|
|
@ -165,8 +165,8 @@ func TestTarUntar(t *testing.T) {
|
|||
Gzip,
|
||||
} {
|
||||
changes, err := tarUntar(t, origin, &TarOptions{
|
||||
Compression: c,
|
||||
Excludes: []string{"3"},
|
||||
Compression: c,
|
||||
ExcludePatterns: []string{"3"},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
@ -196,8 +196,8 @@ func TestTarWithOptions(t *testing.T) {
|
|||
opts *TarOptions
|
||||
numChanges int
|
||||
}{
|
||||
{&TarOptions{Includes: []string{"1"}}, 1},
|
||||
{&TarOptions{Excludes: []string{"2"}}, 1},
|
||||
{&TarOptions{IncludeFiles: []string{"1"}}, 1},
|
||||
{&TarOptions{ExcludePatterns: []string{"2"}}, 1},
|
||||
}
|
||||
for _, testCase := range cases {
|
||||
changes, err := tarUntar(t, origin, testCase.opts)
|
||||
|
|
|
@ -50,8 +50,8 @@ func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error
|
|||
if options == nil {
|
||||
options = &archive.TarOptions{}
|
||||
}
|
||||
if options.Excludes == nil {
|
||||
options.Excludes = []string{}
|
||||
if options.ExcludePatterns == nil {
|
||||
options.ExcludePatterns = []string{}
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -40,7 +40,7 @@ func TestChrootTarUntar(t *testing.T) {
|
|||
if err := os.MkdirAll(dest, 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := Untar(stream, dest, &archive.TarOptions{Excludes: []string{"lolo"}}); err != nil {
|
||||
if err := Untar(stream, dest, &archive.TarOptions{ExcludePatterns: []string{"lolo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
20
tarsum/builder_context.go
Normal file
20
tarsum/builder_context.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package tarsum
|
||||
|
||||
// This interface extends TarSum by adding the Remove method. In general
|
||||
// there was concern about adding this method to TarSum itself so instead
|
||||
// it is being added just to "BuilderContext" which will then only be used
|
||||
// during the .dockerignore file processing - see builder/evaluator.go
|
||||
type BuilderContext interface {
|
||||
TarSum
|
||||
Remove(string)
|
||||
}
|
||||
|
||||
func (bc *tarSum) Remove(filename string) {
|
||||
for i, fis := range bc.sums {
|
||||
if fis.Name() == filename {
|
||||
bc.sums = append(bc.sums[:i], bc.sums[i+1:]...)
|
||||
// Note, we don't just return because there could be
|
||||
// more than one with this name
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue