Skip to content

Instantly share code, notes, and snippets.

@jkuri
Created June 13, 2021 18:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkuri/454a8d323f8955c3eceec41c12ea87ef to your computer and use it in GitHub Desktop.
Save jkuri/454a8d323f8955c3eceec41c12ea87ef to your computer and use it in GitHub Desktop.
create tar.gz archives using golang preserving symlinks
func createArchive(folders []string, outPath string) error {
out, err := os.Create(outPath)
if err != nil {
return err
}
defer out.Close()
gw := gzip.NewWriter(out)
defer gw.Close()
tw := tar.NewWriter(gw)
defer tw.Close()
for _, folder := range folders {
folder = filepath.Join(filepath.Dir(outPath), folder)
if err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
if err != nil {
return err
}
link := ""
if info.Mode()&os.ModeSymlink != 0 {
link, err = os.Readlink(path)
if err != nil {
return err
}
}
header, err := tar.FileInfoHeader(info, link)
if err != nil {
return err
}
header.Name = strings.TrimPrefix(path, fmt.Sprintf("%s/", filepath.Dir(outPath)))
if err := tw.WriteHeader(header); err != nil {
return err
}
switch header.Typeflag {
case tar.TypeLink, tar.TypeSymlink, tar.TypeChar, tar.TypeBlock, tar.TypeDir, tar.TypeFifo:
default:
file, err := os.Open(path)
if err != nil {
return err
}
if _, err := io.Copy(tw, file); err != nil {
return err
}
}
return nil
}); err != nil {
return err
}
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment