summaryrefslogtreecommitdiff
path: root/archive/archive.go
diff options
context:
space:
mode:
Diffstat (limited to 'archive/archive.go')
-rw-r--r--archive/archive.go39
1 files changed, 31 insertions, 8 deletions
diff --git a/archive/archive.go b/archive/archive.go
index 1982218b46..2ba62f5363 100644
--- a/archive/archive.go
+++ b/archive/archive.go
@@ -27,6 +27,7 @@ type (
Compression int
TarOptions struct {
Includes []string
+ Excludes []string
Compression Compression
NoLchown bool
}
@@ -43,6 +44,16 @@ const (
Xz
)
+func IsArchive(header []byte) bool {
+ compression := DetectCompression(header)
+ if compression != Uncompressed {
+ return true
+ }
+ r := tar.NewReader(bytes.NewBuffer(header))
+ _, err := r.Next()
+ return err == nil
+}
+
func DetectCompression(source []byte) Compression {
for compression, m := range map[Compression][]byte{
Bzip2: {0x42, 0x5A, 0x68},
@@ -276,7 +287,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
// Tar creates an archive from the directory at `path`, and returns it as a
// stream of bytes.
func Tar(path string, compression Compression) (io.ReadCloser, error) {
- return TarFilter(path, &TarOptions{Compression: compression})
+ return TarWithOptions(path, &TarOptions{Compression: compression})
}
func escapeName(name string) string {
@@ -295,12 +306,9 @@ func escapeName(name string) string {
return string(escaped)
}
-// TarFilter creates an archive from the directory at `srcPath` with `options`, and returns it as a
-// stream of bytes.
-//
-// Files are included according to `options.Includes`, default to including all files.
-// Stream is compressed according to `options.Compression', default to Uncompressed.
-func TarFilter(srcPath string, options *TarOptions) (io.ReadCloser, error) {
+// 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`.
+func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) {
pipeReader, pipeWriter := io.Pipe()
compressWriter, err := CompressStream(pipeWriter, options.Compression)
@@ -332,6 +340,21 @@ func TarFilter(srcPath string, options *TarOptions) (io.ReadCloser, error) {
return nil
}
+ for _, exclude := range options.Excludes {
+ matched, err := filepath.Match(exclude, relFilePath)
+ if err != nil {
+ utils.Errorf("Error matching: %s (pattern: %s)", relFilePath, exclude)
+ return err
+ }
+ if matched {
+ utils.Debugf("Skipping excluded path: %s", relFilePath)
+ if f.IsDir() {
+ return filepath.SkipDir
+ }
+ return nil
+ }
+ }
+
if err := addTarFile(filePath, relFilePath, tw); err != nil {
utils.Debugf("Can't add file %s to tar: %s\n", srcPath, err)
}
@@ -443,7 +466,7 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
// TarUntar aborts and returns the error.
func TarUntar(src string, dst string) error {
utils.Debugf("TarUntar(%s %s)", src, dst)
- archive, err := TarFilter(src, &TarOptions{Compression: Uncompressed})
+ archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed})
if err != nil {
return err
}