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  }