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
|
ArchiveReader io.Reader
|
||||||
Compression int
|
Compression int
|
||||||
TarOptions struct {
|
TarOptions struct {
|
||||||
Includes []string
|
IncludeFiles []string
|
||||||
Excludes []string
|
ExcludePatterns []string
|
||||||
Compression Compression
|
Compression Compression
|
||||||
NoLchown bool
|
NoLchown bool
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Archiver allows the reuse of most utility functions of this package
|
// 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
|
// 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) {
|
func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) {
|
||||||
pipeReader, pipeWriter := io.Pipe()
|
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
|
// mutating the filesystem and we can see transient errors
|
||||||
// from this
|
// from this
|
||||||
|
|
||||||
if options.Includes == nil {
|
if options.IncludeFiles == nil {
|
||||||
options.Includes = []string{"."}
|
options.IncludeFiles = []string{"."}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seen := make(map[string]bool)
|
||||||
|
|
||||||
var renamedRelFilePath string // For when tar.Options.Name is set
|
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 {
|
filepath.Walk(filepath.Join(srcPath, include), func(filePath string, f os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("Tar: Can't stat file %s to tar: %s", srcPath, err)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
skip, err := fileutils.Matches(relFilePath, options.Excludes)
|
skip := false
|
||||||
if err != nil {
|
|
||||||
log.Debugf("Error matching %s", relFilePath, err)
|
// If "include" is an exact match for the current file
|
||||||
return err
|
// 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 {
|
if skip {
|
||||||
|
@ -433,6 +444,11 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if seen[relFilePath] {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
seen[relFilePath] = true
|
||||||
|
|
||||||
// Rename the base resource
|
// Rename the base resource
|
||||||
if options.Name != "" && filePath == srcPath+"/"+filepath.Base(relFilePath) {
|
if options.Name != "" && filePath == srcPath+"/"+filepath.Base(relFilePath) {
|
||||||
renamedRelFilePath = relFilePath
|
renamedRelFilePath = relFilePath
|
||||||
|
@ -487,7 +503,7 @@ loop:
|
||||||
// This keeps "../" as-is, but normalizes "/../" to "/"
|
// This keeps "../" as-is, but normalizes "/../" to "/"
|
||||||
hdr.Name = filepath.Clean(hdr.Name)
|
hdr.Name = filepath.Clean(hdr.Name)
|
||||||
|
|
||||||
for _, exclude := range options.Excludes {
|
for _, exclude := range options.ExcludePatterns {
|
||||||
if strings.HasPrefix(hdr.Name, exclude) {
|
if strings.HasPrefix(hdr.Name, exclude) {
|
||||||
continue loop
|
continue loop
|
||||||
}
|
}
|
||||||
|
@ -563,8 +579,8 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
|
||||||
if options == nil {
|
if options == nil {
|
||||||
options = &TarOptions{}
|
options = &TarOptions{}
|
||||||
}
|
}
|
||||||
if options.Excludes == nil {
|
if options.ExcludePatterns == nil {
|
||||||
options.Excludes = []string{}
|
options.ExcludePatterns = []string{}
|
||||||
}
|
}
|
||||||
decompressedArchive, err := DecompressStream(archive)
|
decompressedArchive, err := DecompressStream(archive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -165,8 +165,8 @@ func TestTarUntar(t *testing.T) {
|
||||||
Gzip,
|
Gzip,
|
||||||
} {
|
} {
|
||||||
changes, err := tarUntar(t, origin, &TarOptions{
|
changes, err := tarUntar(t, origin, &TarOptions{
|
||||||
Compression: c,
|
Compression: c,
|
||||||
Excludes: []string{"3"},
|
ExcludePatterns: []string{"3"},
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -196,8 +196,8 @@ func TestTarWithOptions(t *testing.T) {
|
||||||
opts *TarOptions
|
opts *TarOptions
|
||||||
numChanges int
|
numChanges int
|
||||||
}{
|
}{
|
||||||
{&TarOptions{Includes: []string{"1"}}, 1},
|
{&TarOptions{IncludeFiles: []string{"1"}}, 1},
|
||||||
{&TarOptions{Excludes: []string{"2"}}, 1},
|
{&TarOptions{ExcludePatterns: []string{"2"}}, 1},
|
||||||
}
|
}
|
||||||
for _, testCase := range cases {
|
for _, testCase := range cases {
|
||||||
changes, err := tarUntar(t, origin, testCase.opts)
|
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 {
|
if options == nil {
|
||||||
options = &archive.TarOptions{}
|
options = &archive.TarOptions{}
|
||||||
}
|
}
|
||||||
if options.Excludes == nil {
|
if options.ExcludePatterns == nil {
|
||||||
options.Excludes = []string{}
|
options.ExcludePatterns = []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -40,7 +40,7 @@ func TestChrootTarUntar(t *testing.T) {
|
||||||
if err := os.MkdirAll(dest, 0700); err != nil {
|
if err := os.MkdirAll(dest, 0700); err != nil {
|
||||||
t.Fatal(err)
|
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)
|
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