pkg/archive: add interface for Untar
| ... | ... |
@@ -36,10 +36,17 @@ type ( |
| 36 | 36 |
NoLchown bool |
| 37 | 37 |
Name string |
| 38 | 38 |
} |
| 39 |
+ |
|
| 40 |
+ // Archiver allows the reuse of most utility functions of this package |
|
| 41 |
+ // with a pluggable Untar function. |
|
| 42 |
+ Archiver struct {
|
|
| 43 |
+ Untar func(io.Reader, string, *TarOptions) error |
|
| 44 |
+ } |
|
| 39 | 45 |
) |
| 40 | 46 |
|
| 41 | 47 |
var ( |
| 42 | 48 |
ErrNotImplemented = errors.New("Function not implemented")
|
| 49 |
+ defaultArchiver = &Archiver{Untar}
|
|
| 43 | 50 |
) |
| 44 | 51 |
|
| 45 | 52 |
const ( |
| ... | ... |
@@ -549,45 +556,47 @@ loop: |
| 549 | 549 |
return nil |
| 550 | 550 |
} |
| 551 | 551 |
|
| 552 |
-// TarUntar is a convenience function which calls Tar and Untar, with |
|
| 553 |
-// the output of one piped into the other. If either Tar or Untar fails, |
|
| 554 |
-// TarUntar aborts and returns the error. |
|
| 555 |
-func TarUntar(src string, dst string) error {
|
|
| 552 |
+func (archiver *Archiver) TarUntar(src, dst string) error {
|
|
| 556 | 553 |
log.Debugf("TarUntar(%s %s)", src, dst)
|
| 557 | 554 |
archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed})
|
| 558 | 555 |
if err != nil {
|
| 559 | 556 |
return err |
| 560 | 557 |
} |
| 561 | 558 |
defer archive.Close() |
| 562 |
- return Untar(archive, dst, nil) |
|
| 559 |
+ return archiver.Untar(archive, dst, nil) |
|
| 563 | 560 |
} |
| 564 | 561 |
|
| 565 |
-// UntarPath is a convenience function which looks for an archive |
|
| 566 |
-// at filesystem path `src`, and unpacks it at `dst`. |
|
| 567 |
-func UntarPath(src, dst string) error {
|
|
| 562 |
+// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other. |
|
| 563 |
+// If either Tar or Untar fails, TarUntar aborts and returns the error. |
|
| 564 |
+func TarUntar(src, dst string) error {
|
|
| 565 |
+ return defaultArchiver.TarUntar(src, dst) |
|
| 566 |
+} |
|
| 567 |
+ |
|
| 568 |
+func (archiver *Archiver) UntarPath(src, dst string) error {
|
|
| 568 | 569 |
archive, err := os.Open(src) |
| 569 | 570 |
if err != nil {
|
| 570 | 571 |
return err |
| 571 | 572 |
} |
| 572 | 573 |
defer archive.Close() |
| 573 |
- if err := Untar(archive, dst, nil); err != nil {
|
|
| 574 |
+ if err := archiver.Untar(archive, dst, nil); err != nil {
|
|
| 574 | 575 |
return err |
| 575 | 576 |
} |
| 576 | 577 |
return nil |
| 577 | 578 |
} |
| 578 | 579 |
|
| 579 |
-// CopyWithTar creates a tar archive of filesystem path `src`, and |
|
| 580 |
-// unpacks it at filesystem path `dst`. |
|
| 581 |
-// The archive is streamed directly with fixed buffering and no |
|
| 582 |
-// intermediary disk IO. |
|
| 583 |
-// |
|
| 584 |
-func CopyWithTar(src, dst string) error {
|
|
| 580 |
+// UntarPath is a convenience function which looks for an archive |
|
| 581 |
+// at filesystem path `src`, and unpacks it at `dst`. |
|
| 582 |
+func UntarPath(src, dst string) error {
|
|
| 583 |
+ return defaultArchiver.UntarPath(src, dst) |
|
| 584 |
+} |
|
| 585 |
+ |
|
| 586 |
+func (archiver *Archiver) CopyWithTar(src, dst string) error {
|
|
| 585 | 587 |
srcSt, err := os.Stat(src) |
| 586 | 588 |
if err != nil {
|
| 587 | 589 |
return err |
| 588 | 590 |
} |
| 589 | 591 |
if !srcSt.IsDir() {
|
| 590 |
- return CopyFileWithTar(src, dst) |
|
| 592 |
+ return archiver.CopyFileWithTar(src, dst) |
|
| 591 | 593 |
} |
| 592 | 594 |
// Create dst, copy src's content into it |
| 593 | 595 |
log.Debugf("Creating dest directory: %s", dst)
|
| ... | ... |
@@ -595,16 +604,18 @@ func CopyWithTar(src, dst string) error {
|
| 595 | 595 |
return err |
| 596 | 596 |
} |
| 597 | 597 |
log.Debugf("Calling TarUntar(%s, %s)", src, dst)
|
| 598 |
- return TarUntar(src, dst) |
|
| 598 |
+ return archiver.TarUntar(src, dst) |
|
| 599 | 599 |
} |
| 600 | 600 |
|
| 601 |
-// CopyFileWithTar emulates the behavior of the 'cp' command-line |
|
| 602 |
-// for a single file. It copies a regular file from path `src` to |
|
| 603 |
-// path `dst`, and preserves all its metadata. |
|
| 604 |
-// |
|
| 605 |
-// If `dst` ends with a trailing slash '/', the final destination path |
|
| 606 |
-// will be `dst/base(src)`. |
|
| 607 |
-func CopyFileWithTar(src, dst string) (err error) {
|
|
| 601 |
+// CopyWithTar creates a tar archive of filesystem path `src`, and |
|
| 602 |
+// unpacks it at filesystem path `dst`. |
|
| 603 |
+// The archive is streamed directly with fixed buffering and no |
|
| 604 |
+// intermediary disk IO. |
|
| 605 |
+func CopyWithTar(src, dst string) error {
|
|
| 606 |
+ return defaultArchiver.CopyWithTar(src, dst) |
|
| 607 |
+} |
|
| 608 |
+ |
|
| 609 |
+func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
|
|
| 608 | 610 |
log.Debugf("CopyFileWithTar(%s, %s)", src, dst)
|
| 609 | 611 |
srcSt, err := os.Stat(src) |
| 610 | 612 |
if err != nil {
|
| ... | ... |
@@ -652,7 +663,17 @@ func CopyFileWithTar(src, dst string) (err error) {
|
| 652 | 652 |
err = er |
| 653 | 653 |
} |
| 654 | 654 |
}() |
| 655 |
- return Untar(r, filepath.Dir(dst), nil) |
|
| 655 |
+ return archiver.Untar(r, filepath.Dir(dst), nil) |
|
| 656 |
+} |
|
| 657 |
+ |
|
| 658 |
+// CopyFileWithTar emulates the behavior of the 'cp' command-line |
|
| 659 |
+// for a single file. It copies a regular file from path `src` to |
|
| 660 |
+// path `dst`, and preserves all its metadata. |
|
| 661 |
+// |
|
| 662 |
+// If `dst` ends with a trailing slash '/', the final destination path |
|
| 663 |
+// will be `dst/base(src)`. |
|
| 664 |
+func CopyFileWithTar(src, dst string) (err error) {
|
|
| 665 |
+ return defaultArchiver.CopyFileWithTar(src, dst) |
|
| 656 | 666 |
} |
| 657 | 667 |
|
| 658 | 668 |
// CmdStream executes a command, and returns its stdout as a stream. |