tools/version-tracker/pkg/util/tar/tar.go (43 lines of code) (raw):
package tar
import (
"archive/tar"
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// ExtractFileFromTarball extracts the specified file from the given tarball.
func ExtractFileFromTarball(tarballDownloadPath string, gzipStream io.Reader, targetFile string) error {
uncompressedStream, err := gzip.NewReader(gzipStream)
if err != nil {
return err
}
tarReader := tar.NewReader(uncompressedStream)
var header *tar.Header
for header, err = tarReader.Next(); err == nil; header, err = tarReader.Next() {
if header.Name == targetFile {
if strings.Contains(header.Name, "/") {
err = os.MkdirAll(filepath.Join(tarballDownloadPath, filepath.Dir(header.Name)), 0o755)
if err != nil {
return fmt.Errorf("creating parent directory for archive contents: %v", err)
}
}
outFile, err := os.Create(filepath.Join(tarballDownloadPath, header.Name))
if err != nil {
return fmt.Errorf("creating file from archive: %v", err)
}
if _, err := io.Copy(outFile, tarReader); err != nil {
outFile.Close()
return fmt.Errorf("copying file to output destination: %v", err)
}
if err := outFile.Close(); err != nil {
return fmt.Errorf("closing output destination file descriptor: %v", err)
}
}
}
if err != io.EOF {
return fmt.Errorf("advancing to next entry in archive: %v", err)
}
return nil
}