Browse code

Change misnamed TarFilter to TarWithOptions

Docker-DCO-1.1-Signed-off-by: Travis Cline <travis.cline@gmail.com> (github: tmc)

Travis Cline authored on 2014/02/14 09:05:36
Showing 4 changed files
... ...
@@ -27,6 +27,7 @@ type (
27 27
 	Compression   int
28 28
 	TarOptions    struct {
29 29
 		Includes    []string
30
+		Excludes    []string
30 31
 		Compression Compression
31 32
 		NoLchown    bool
32 33
 	}
... ...
@@ -286,7 +287,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
286 286
 // Tar creates an archive from the directory at `path`, and returns it as a
287 287
 // stream of bytes.
288 288
 func Tar(path string, compression Compression) (io.ReadCloser, error) {
289
-	return TarFilter(path, &TarOptions{Compression: compression})
289
+	return TarWithOptions(path, &TarOptions{Compression: compression})
290 290
 }
291 291
 
292 292
 func escapeName(name string) string {
... ...
@@ -305,12 +306,9 @@ func escapeName(name string) string {
305 305
 	return string(escaped)
306 306
 }
307 307
 
308
-// TarFilter creates an archive from the directory at `srcPath` with `options`, and returns it as a
309
-// stream of bytes.
310
-//
311
-// Files are included according to `options.Includes`, default to including all files.
312
-// Stream is compressed according to `options.Compression', default to Uncompressed.
313
-func TarFilter(srcPath string, options *TarOptions) (io.ReadCloser, error) {
308
+// TarWithOptions creates an archive from the directory at `path`, only including files whose relative
309
+// paths are included in `options.Includes` (if non-nil) or not in `options.Excludes`.
310
+func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) {
314 311
 	pipeReader, pipeWriter := io.Pipe()
315 312
 
316 313
 	compressWriter, err := CompressStream(pipeWriter, options.Compression)
... ...
@@ -342,6 +340,21 @@ func TarFilter(srcPath string, options *TarOptions) (io.ReadCloser, error) {
342 342
 					return nil
343 343
 				}
344 344
 
345
+				for _, exclude := range options.Excludes {
346
+					matched, err := filepath.Match(exclude, relFilePath)
347
+					if err != nil {
348
+						utils.Errorf("Error matching: %s (pattern: %s)\n", relFilePath, exclude)
349
+						return err
350
+					}
351
+					if matched {
352
+						utils.Debugf("Skipping excluded path: %s\n", relFilePath)
353
+						if f.IsDir() {
354
+							return filepath.SkipDir
355
+						}
356
+						return nil
357
+					}
358
+				}
359
+
345 360
 				if err := addTarFile(filePath, relFilePath, tw); err != nil {
346 361
 					utils.Debugf("Can't add file %s to tar: %s\n", srcPath, err)
347 362
 				}
... ...
@@ -482,7 +495,7 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
482 482
 // TarUntar aborts and returns the error.
483 483
 func TarUntar(src string, dst string) error {
484 484
 	utils.Debugf("TarUntar(%s %s)", src, dst)
485
-	archive, err := TarFilter(src, &TarOptions{Compression: Uncompressed})
485
+	archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed})
486 486
 	if err != nil {
487 487
 		return err
488 488
 	}
... ...
@@ -63,8 +63,8 @@ func TestCmdStreamGood(t *testing.T) {
63 63
 	}
64 64
 }
65 65
 
66
-func tarUntar(t *testing.T, origin string, compression Compression) error {
67
-	archive, err := Tar(origin, compression)
66
+func tarUntar(t *testing.T, origin string, options *TarOptions) ([]Change, error) {
67
+	archive, err := TarWithOptions(origin, options)
68 68
 	if err != nil {
69 69
 		t.Fatal(err)
70 70
 	}
... ...
@@ -72,37 +72,29 @@ func tarUntar(t *testing.T, origin string, compression Compression) error {
72 72
 
73 73
 	buf := make([]byte, 10)
74 74
 	if _, err := archive.Read(buf); err != nil {
75
-		return err
75
+		return nil, err
76 76
 	}
77 77
 	wrap := io.MultiReader(bytes.NewReader(buf), archive)
78 78
 
79 79
 	detectedCompression := DetectCompression(buf)
80
+	compression := options.Compression
80 81
 	if detectedCompression.Extension() != compression.Extension() {
81
-		return fmt.Errorf("Wrong compression detected. Actual compression: %s, found %s", compression.Extension(), detectedCompression.Extension())
82
+		return nil, fmt.Errorf("Wrong compression detected. Actual compression: %s, found %s", compression.Extension(), detectedCompression.Extension())
82 83
 	}
83 84
 
84 85
 	tmp, err := ioutil.TempDir("", "docker-test-untar")
85 86
 	if err != nil {
86
-		return err
87
+		return nil, err
87 88
 	}
88 89
 	defer os.RemoveAll(tmp)
89 90
 	if err := Untar(wrap, tmp, nil); err != nil {
90
-		return err
91
+		return nil, err
91 92
 	}
92 93
 	if _, err := os.Stat(tmp); err != nil {
93
-		return err
94
+		return nil, err
94 95
 	}
95 96
 
96
-	changes, err := ChangesDirs(origin, tmp)
97
-	if err != nil {
98
-		return err
99
-	}
100
-
101
-	if len(changes) != 0 {
102
-		t.Fatalf("Unexpected differences after tarUntar: %v", changes)
103
-	}
104
-
105
-	return nil
97
+	return ChangesDirs(origin, tmp)
106 98
 }
107 99
 
108 100
 func TestTarUntar(t *testing.T) {
... ...
@@ -122,9 +114,49 @@ func TestTarUntar(t *testing.T) {
122 122
 		Uncompressed,
123 123
 		Gzip,
124 124
 	} {
125
-		if err := tarUntar(t, origin, c); err != nil {
125
+		changes, err := tarUntar(t, origin, &TarOptions{
126
+			Compression: c,
127
+		})
128
+
129
+		if err != nil {
126 130
 			t.Fatalf("Error tar/untar for compression %s: %s", c.Extension(), err)
127 131
 		}
132
+
133
+		if len(changes) != 0 {
134
+			t.Fatalf("Unexpected differences after tarUntar: %v", changes)
135
+		}
136
+	}
137
+}
138
+
139
+func TestTarWithOptions(t *testing.T) {
140
+	origin, err := ioutil.TempDir("", "docker-test-untar-origin")
141
+	if err != nil {
142
+		t.Fatal(err)
143
+	}
144
+	defer os.RemoveAll(origin)
145
+	if err := ioutil.WriteFile(path.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
146
+		t.Fatal(err)
147
+	}
148
+	if err := ioutil.WriteFile(path.Join(origin, "2"), []byte("welcome!"), 0700); err != nil {
149
+		t.Fatal(err)
150
+	}
151
+
152
+	cases := []struct {
153
+		opts       *TarOptions
154
+		numChanges int
155
+	}{
156
+		{&TarOptions{Includes: []string{"1"}}, 1},
157
+		{&TarOptions{Excludes: []string{"2"}}, 1},
158
+	}
159
+	for _, testCase := range cases {
160
+		changes, err := tarUntar(t, origin, testCase.opts)
161
+		if err != nil {
162
+			t.Fatalf("Error tar/untar when testing inclusion/exclusion: %s", err)
163
+		}
164
+		if len(changes) != testCase.numChanges {
165
+			t.Errorf("Expected %d changes, got %d for %+v:",
166
+				testCase.numChanges, len(changes), testCase.opts)
167
+		}
128 168
 	}
129 169
 }
130 170
 
... ...
@@ -813,7 +813,7 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) {
813 813
 		basePath = path.Dir(basePath)
814 814
 	}
815 815
 
816
-	archive, err := archive.TarFilter(basePath, &archive.TarOptions{
816
+	archive, err := archive.TarWithOptions(basePath, &archive.TarOptions{
817 817
 		Compression: archive.Uncompressed,
818 818
 		Includes:    filter,
819 819
 	})
... ...
@@ -295,7 +295,7 @@ func (a *Driver) Put(id string) {
295 295
 
296 296
 // Returns an archive of the contents for the id
297 297
 func (a *Driver) Diff(id string) (archive.Archive, error) {
298
-	return archive.TarFilter(path.Join(a.rootPath(), "diff", id), &archive.TarOptions{
298
+	return archive.TarWithOptions(path.Join(a.rootPath(), "diff", id), &archive.TarOptions{
299 299
 		Compression: archive.Uncompressed,
300 300
 	})
301 301
 }