github.com/YousefHaggyHeroku/pack@v1.5.5/internal/archive/tar_builder.go (about)

     1  package archive
     2  
     3  import (
     4  	"archive/tar"
     5  	"io"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/pkg/errors"
    10  
    11  	"github.com/YousefHaggyHeroku/pack/internal/style"
    12  )
    13  
    14  type TarBuilder struct {
    15  	files []fileEntry
    16  }
    17  
    18  type fileEntry struct {
    19  	typeFlag byte
    20  	path     string
    21  	mode     int64
    22  	modTime  time.Time
    23  	contents []byte
    24  }
    25  
    26  func (t *TarBuilder) AddFile(path string, mode int64, modTime time.Time, contents []byte) {
    27  	t.files = append(t.files, fileEntry{
    28  		typeFlag: tar.TypeReg,
    29  		path:     path,
    30  		mode:     mode,
    31  		modTime:  modTime,
    32  		contents: contents,
    33  	})
    34  }
    35  
    36  func (t *TarBuilder) AddDir(path string, mode int64, modTime time.Time) {
    37  	t.files = append(t.files, fileEntry{
    38  		typeFlag: tar.TypeDir,
    39  		path:     path,
    40  		mode:     mode,
    41  		modTime:  modTime,
    42  	})
    43  }
    44  
    45  func (t *TarBuilder) Reader(twf TarWriterFactory) io.ReadCloser {
    46  	pr, pw := io.Pipe()
    47  	go func() {
    48  		var err error
    49  		defer func() {
    50  			pw.CloseWithError(err)
    51  		}()
    52  		_, err = t.WriteTo(pw, twf)
    53  	}()
    54  
    55  	return pr
    56  }
    57  
    58  func (t *TarBuilder) WriteToPath(path string, twf TarWriterFactory) error {
    59  	fh, err := os.Create(path)
    60  	if err != nil {
    61  		return errors.Wrapf(err, "create file for tar: %s", style.Symbol(path))
    62  	}
    63  	defer fh.Close()
    64  
    65  	_, err = t.WriteTo(fh, twf)
    66  	return err
    67  }
    68  
    69  func (t *TarBuilder) WriteTo(w io.Writer, twf TarWriterFactory) (int64, error) {
    70  	var written int64
    71  	tw := twf.NewWriter(w)
    72  	defer tw.Close()
    73  
    74  	for _, f := range t.files {
    75  		if err := tw.WriteHeader(&tar.Header{
    76  			Typeflag: f.typeFlag,
    77  			Name:     f.path,
    78  			Size:     int64(len(f.contents)),
    79  			Mode:     f.mode,
    80  			ModTime:  f.modTime,
    81  		}); err != nil {
    82  			return written, err
    83  		}
    84  
    85  		n, err := tw.Write(f.contents)
    86  		if err != nil {
    87  			return written, err
    88  		}
    89  
    90  		written += int64(n)
    91  	}
    92  
    93  	return written, nil
    94  }