Browse code

Add ability to exclude files from tar

Michael Crosby authored on 2013/11/12 07:30:38
Showing 4 changed files
... ...
@@ -15,7 +15,15 @@ import (
15 15
 
16 16
 type Archive io.Reader
17 17
 
18
-type Compression uint32
18
+type Compression int
19
+
20
+type TarOptions struct {
21
+	Includes    []string
22
+	Excludes    []string
23
+	Recursive   bool
24
+	Compression Compression
25
+	CreateFiles []string
26
+}
19 27
 
20 28
 const (
21 29
 	Uncompressed Compression = iota
... ...
@@ -80,7 +88,7 @@ func (compression *Compression) Extension() string {
80 80
 // Tar creates an archive from the directory at `path`, and returns it as a
81 81
 // stream of bytes.
82 82
 func Tar(path string, compression Compression) (io.Reader, error) {
83
-	return TarFilter(path, compression, nil, true, nil)
83
+	return TarFilter(path, &TarOptions{Recursive: true, Compression: compression})
84 84
 }
85 85
 
86 86
 func escapeName(name string) string {
... ...
@@ -101,25 +109,29 @@ func escapeName(name string) string {
101 101
 
102 102
 // Tar creates an archive from the directory at `path`, only including files whose relative
103 103
 // paths are included in `filter`. If `filter` is nil, then all files are included.
104
-func TarFilter(path string, compression Compression, filter []string, recursive bool, createFiles []string) (io.Reader, error) {
104
+func TarFilter(path string, options *TarOptions) (io.Reader, error) {
105 105
 	args := []string{"tar", "--numeric-owner", "-f", "-", "-C", path, "-T", "-"}
106
-	if filter == nil {
107
-		filter = []string{"."}
106
+	if options.Includes == nil {
107
+		options.Includes = []string{"."}
108
+	}
109
+	args = append(args, "-c"+options.Compression.Flag())
110
+
111
+	for _, exclude := range options.Excludes {
112
+		args = append(args, fmt.Sprintf("--exclude=%s", exclude))
108 113
 	}
109
-	args = append(args, "-c"+compression.Flag())
110 114
 
111
-	if !recursive {
115
+	if !options.Recursive {
112 116
 		args = append(args, "--no-recursion")
113 117
 	}
114 118
 
115 119
 	files := ""
116
-	for _, f := range filter {
120
+	for _, f := range options.Includes {
117 121
 		files = files + escapeName(f) + "\n"
118 122
 	}
119 123
 
120 124
 	tmpDir := ""
121 125
 
122
-	if createFiles != nil {
126
+	if options.CreateFiles != nil {
123 127
 		var err error // Can't use := here or we override the outer tmpDir
124 128
 		tmpDir, err = ioutil.TempDir("", "docker-tar")
125 129
 		if err != nil {
... ...
@@ -127,7 +139,7 @@ func TarFilter(path string, compression Compression, filter []string, recursive
127 127
 		}
128 128
 
129 129
 		files = files + "-C" + tmpDir + "\n"
130
-		for _, f := range createFiles {
130
+		for _, f := range options.CreateFiles {
131 131
 			path := filepath.Join(tmpDir, f)
132 132
 			err := os.MkdirAll(filepath.Dir(path), 0600)
133 133
 			if err != nil {
... ...
@@ -194,7 +206,7 @@ func Untar(archive io.Reader, path string) error {
194 194
 // TarUntar aborts and returns the error.
195 195
 func TarUntar(src string, filter []string, dst string) error {
196 196
 	utils.Debugf("TarUntar(%s %s %s)", src, filter, dst)
197
-	archive, err := TarFilter(src, Uncompressed, filter, true, nil)
197
+	archive, err := TarFilter(src, &TarOptions{Compression: Uncompressed, Includes: filter, Recursive: true})
198 198
 	if err != nil {
199 199
 		return err
200 200
 	}
... ...
@@ -207,24 +207,22 @@ func ChangesDirs(newDir, oldDir string) ([]Change, error) {
207 207
 	return changes, nil
208 208
 }
209 209
 
210
-
211 210
 func ExportChanges(root, rw string) (Archive, error) {
212
-        changes, err := ChangesDirs(root, rw)
213
-        if err != nil {
214
-                return nil, err
215
-        }
216
-        files := make([]string, 0)
217
-        deletions := make([]string, 0)
218
-        for _, change := range changes {
219
-                if change.Kind == ChangeModify || change.Kind == ChangeAdd {
220
-                        files = append(files, change.Path)
221
-                }
222
-                if change.Kind == ChangeDelete {
223
-                        base := filepath.Base(change.Path)
224
-                        dir := filepath.Dir(change.Path)
225
-                        deletions = append(deletions, filepath.Join(dir, ".wh."+base))
226
-                }
227
-        }
228
-        return TarFilter(root, Uncompressed, files, false, deletions)
211
+	changes, err := ChangesDirs(root, rw)
212
+	if err != nil {
213
+		return nil, err
214
+	}
215
+	files := make([]string, 0)
216
+	deletions := make([]string, 0)
217
+	for _, change := range changes {
218
+		if change.Kind == ChangeModify || change.Kind == ChangeAdd {
219
+			files = append(files, change.Path)
220
+		}
221
+		if change.Kind == ChangeDelete {
222
+			base := filepath.Base(change.Path)
223
+			dir := filepath.Dir(change.Path)
224
+			deletions = append(deletions, filepath.Join(dir, ".wh."+base))
225
+		}
226
+	}
227
+	return TarFilter(root, &TarOptions{Compression: Uncompressed, Recursive: false, Includes: files, CreateFiles: deletions})
229 228
 }
230
-
... ...
@@ -137,8 +137,7 @@ func (a *AufsDriver) createDirsFor(id string) error {
137 137
 	}
138 138
 
139 139
 	for _, p := range paths {
140
-		dir := path.Join(a.rootPath(), p, id)
141
-		if err := os.MkdirAll(dir, 0755); err != nil {
140
+		if err := os.MkdirAll(path.Join(a.rootPath(), p, id), 0755); err != nil {
142 141
 			return err
143 142
 		}
144 143
 	}
... ...
@@ -201,11 +200,14 @@ func (a *AufsDriver) Get(id string) (string, error) {
201 201
 
202 202
 // Returns an archive of the contents for the id
203 203
 func (a *AufsDriver) Diff(id string) (archive.Archive, error) {
204
-	p, err := a.Get(id)
205
-	if err != nil {
206
-		return nil, err
207
-	}
208
-	return archive.Tar(p, archive.Uncompressed)
204
+	// Exclude top level aufs metadata from the diff
205
+	return archive.TarFilter(
206
+		path.Join(a.rootPath(), "diff", id),
207
+		&archive.TarOptions{
208
+			Excludes:    []string{".wh*"},
209
+			Recursive:   true,
210
+			Compression: archive.Uncompressed,
211
+		})
209 212
 }
210 213
 
211 214
 // Returns the size of the contents for the id
... ...
@@ -1527,7 +1527,11 @@ func (container *Container) Copy(resource string) (archive.Archive, error) {
1527 1527
 		filter = []string{path.Base(basePath)}
1528 1528
 		basePath = path.Dir(basePath)
1529 1529
 	}
1530
-	return archive.TarFilter(basePath, archive.Uncompressed, filter, true, nil)
1530
+	return archive.TarFilter(basePath, &archive.TarOptions{
1531
+		Compression: archive.Uncompressed,
1532
+		Includes:    filter,
1533
+		Recursive:   true,
1534
+	})
1531 1535
 }
1532 1536
 
1533 1537
 // Returns true if the container exposes a certain port