Browse code

Merge pull request #9090 from unclejack/archive_interface

pkg/archive: add interface for Untar

unclejack authored on 2014/11/12 03:57:58
Showing 1 changed files
... ...
@@ -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.