package Archive import ( "PackageManager/Variables" "archive/tar" "compress/gzip" "io" "os" "strings" ) func CreateArchive(files []string, target string) error { var ( outFile *os.File gzipWriter *gzip.Writer tarWriter *tar.Writer file string err error ) // Create output file outFile, err = os.Create(target) if err != nil { return err } defer outFile.Close() gzipWriter = gzip.NewWriter(outFile) defer gzipWriter.Close() tarWriter = tar.NewWriter(gzipWriter) defer tarWriter.Close() // Iterate over files and add them to the tar archive for _, file = range files { err = addToArchive(tarWriter, file) if err != nil { return err } } return nil } func addToArchive(tarWriter *tar.Writer, filename string) error { var ( file *os.File info os.FileInfo header *tar.Header err error ) // Get FileInfo about our file providing file size, mode, etc. info, err = os.Lstat(filename) if err != nil { return err } // Create a tar Header from the FileInfo data header, err = tar.FileInfoHeader(info, info.Name()) if err != nil { return err } isSymlink := info.Mode()&os.ModeSymlink != 0 if isSymlink { header.Typeflag = tar.TypeSymlink } // Use full path as name (FileInfoHeader only takes the basename) // If we don't do this the directory strucuture would // not be preserved // https://golang.org/src/archive/tar/common.go?#L626 header.Name = strings.TrimPrefix( strings.TrimPrefix( filename, Variables.RootDir, ), "/", ) // Write file header to the tar archive err = tarWriter.WriteHeader(header) if err != nil { return err } // Do not write file if it is a symlink if isSymlink { return nil } // Open the file which will be written into the archive file, err = os.Open(filename) if err != nil { return err } defer file.Close() // Copy file content to tar archive _, err = io.Copy(tarWriter, file) if err != nil { return err } return nil }