package Archive import ( "archive/tar" "bufio" "bytes" "compress/gzip" "io" "io/fs" "os" "path/filepath" ) func ExtractArchive(source, target string) error { var ( inFile *os.File gzipReader *gzip.Reader tarReader *tar.Reader err error ) inFile, err = os.Open(source) if err != nil { return err } defer inFile.Close() gzipReader, err = gzip.NewReader(inFile) if err != nil { return err } defer gzipReader.Close() tarReader = tar.NewReader(gzipReader) return extractFromArchive(tarReader, target) } func extractFromArchive(tarReader *tar.Reader, target string) error { var ( header *tar.Header info fs.FileInfo file *os.File path, basePath string err error ) for { header, err = tarReader.Next() if err == io.EOF { break } if err != nil { return err } path = filepath.Join(target, header.Name) info = header.FileInfo() if filepath.Base(info.Name()) == "manifest.yml" { continue } if info.IsDir() { err = os.MkdirAll(path, info.Mode()) if err != nil { return err } continue } basePath, err = filepath.Abs(filepath.Dir(path)) if err != nil { return err } _, err = os.Stat(basePath) if os.IsNotExist(err) { err = os.MkdirAll(basePath, info.Mode()) if err != nil { return err } } file, err = os.OpenFile(path, os.O_CREATE|os.O_RDWR, info.Mode()) if err != nil { return err } _, err = io.Copy(file, tarReader) if err != nil { return err } file.Close() } return nil } func ExtractManifestFile(source string) (string, error) { var ( inFile *os.File gzipReader *gzip.Reader tarReader *tar.Reader err error ) inFile, err = os.Open(source) if err != nil { return "", err } defer inFile.Close() gzipReader, err = gzip.NewReader(inFile) if err != nil { return "", err } defer gzipReader.Close() tarReader = tar.NewReader(gzipReader) return extractManifestFromArchive(tarReader) } func extractManifestFromArchive(tarReader *tar.Reader) (string, error) { var ( header *tar.Header info fs.FileInfo manifestWriter *bufio.Writer manifestBytes bytes.Buffer err error ) for { header, err = tarReader.Next() if err == io.EOF { break } if err != nil { return manifestBytes.String(), err } info = header.FileInfo() if filepath.Base(info.Name()) != "manifest.yml" { continue } manifestWriter = bufio.NewWriter(&manifestBytes) _, err = io.Copy(manifestWriter, tarReader) if err != nil { return manifestBytes.String(), err } } return manifestBytes.String(), nil } func GetPackageFilePaths(source string) ([]string, error) { var ( inFile *os.File gzipReader *gzip.Reader tarReader *tar.Reader info os.FileInfo header *tar.Header pkgFiles []string err error ) inFile, err = os.Open(source) if err != nil { return pkgFiles, err } defer inFile.Close() gzipReader, err = gzip.NewReader(inFile) if err != nil { return pkgFiles, err } defer gzipReader.Close() tarReader = tar.NewReader(gzipReader) for { header, err = tarReader.Next() if err == io.EOF { break } if err != nil { return pkgFiles, err } info = header.FileInfo() if filepath.Base(info.Name()) == "manifest.yml" { continue } pkgFiles = append(pkgFiles, header.Name) } return pkgFiles, nil }