github.com/goreleaser/goreleaser@v1.25.1/internal/testlib/archive.go (about) 1 package testlib 2 3 import ( 4 "archive/tar" 5 "archive/zip" 6 "compress/gzip" 7 "io" 8 "os" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 "github.com/ulikunitz/xz" 13 ) 14 15 // GetFileFromArchive returns the contents of filename inside the given archive 16 // path. 17 func GetFileFromArchive(tb testing.TB, path, format, filename string) []byte { 18 tb.Helper() 19 f := openFile(tb, path) 20 switch format { 21 case "tar.gz", "tgz": 22 return catTarFile(tb, openGzip(tb, f), filename) 23 case "tar.xz", "txz": 24 return catTarFile(tb, openXz(tb, f), filename) 25 case "tar": 26 return catTarFile(tb, f, filename) 27 case "zip": 28 return catZipFile(tb, f, filename) 29 case "gz": 30 out, err := io.ReadAll(openGzip(tb, f)) 31 require.NoError(tb, err) 32 return out 33 default: 34 tb.Errorf("invalid format: %s", format) 35 return nil 36 } 37 } 38 39 // LsArchive return the file list of a given archive in a given formatkj 40 func LsArchive(tb testing.TB, path, format string) []string { 41 tb.Helper() 42 f := openFile(tb, path) 43 switch format { 44 case "tar.gz", "tgz": 45 return doLsTar(openGzip(tb, f)) 46 case "tar.xz", "txz": 47 return doLsTar(openXz(tb, f)) 48 case "tar": 49 return doLsTar(f) 50 case "zip": 51 return lsZip(tb, f) 52 case "gz": 53 return []string{openGzip(tb, f).Header.Name} 54 default: 55 tb.Errorf("invalid format: %s", format) 56 return nil 57 } 58 } 59 60 func openGzip(tb testing.TB, r io.Reader) *gzip.Reader { 61 tb.Helper() 62 gz, err := gzip.NewReader(r) 63 require.NoError(tb, err) 64 return gz 65 } 66 67 func openXz(tb testing.TB, r io.Reader) *xz.Reader { 68 tb.Helper() 69 xz, err := xz.NewReader(r) 70 require.NoError(tb, err) 71 return xz 72 } 73 74 func catZipFile(tb testing.TB, f *os.File, path string) []byte { 75 tb.Helper() 76 77 stat, err := f.Stat() 78 require.NoError(tb, err) 79 z, err := zip.NewReader(f, stat.Size()) 80 require.NoError(tb, err) 81 82 for _, zf := range z.File { 83 if path == zf.Name { 84 zz, err := zf.Open() 85 require.NoError(tb, err) 86 tb.Cleanup(func() { require.NoError(tb, zz.Close()) }) 87 bts, err := io.ReadAll(zz) 88 require.NoError(tb, err) 89 return bts 90 } 91 } 92 return nil 93 } 94 95 func lsZip(tb testing.TB, f *os.File) []string { 96 tb.Helper() 97 98 stat, err := f.Stat() 99 require.NoError(tb, err) 100 z, err := zip.NewReader(f, stat.Size()) 101 require.NoError(tb, err) 102 103 var paths []string 104 for _, zf := range z.File { 105 paths = append(paths, zf.Name) 106 } 107 return paths 108 } 109 110 func catTarFile(tb testing.TB, f io.Reader, path string) []byte { 111 tb.Helper() 112 113 z := tar.NewReader(f) 114 for { 115 h, err := z.Next() 116 if h == nil || err == io.EOF { 117 break 118 } 119 if h.Format == tar.FormatPAX { 120 continue 121 } 122 if h.Name == path { 123 out, err := io.ReadAll(z) 124 require.NoError(tb, err) 125 return out 126 } 127 } 128 return nil 129 } 130 131 func doLsTar(f io.Reader) []string { 132 z := tar.NewReader(f) 133 var paths []string 134 for { 135 h, err := z.Next() 136 if h == nil || err == io.EOF { 137 break 138 } 139 if h.Name == "pax_global_header" { 140 continue 141 } 142 paths = append(paths, h.Name) 143 } 144 return paths 145 } 146 147 func openFile(tb testing.TB, path string) *os.File { 148 tb.Helper() 149 f, err := os.Open(path) 150 require.NoError(tb, err) 151 return f 152 }