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 }