package tar import ( "archive/tar" "bytes" "compress/gzip" "io" "os" "path/filepath" "strings" ) func Compress(source, dest string) error { // tar + gzip var buf bytes.Buffer _ = compress(source, &buf) // write the .tar.gzip fileToWrite, err := os.OpenFile(dest, os.O_CREATE|os.O_RDWR, 0666) if err != nil { return err } _, err = io.Copy(fileToWrite, &buf) return err } func compress(src string, buf io.Writer) error { // tar > gzip > buf zr := gzip.NewWriter(buf) tw := tar.NewWriter(zr) // walk through every file in the folder filepath.Walk(src, func(file string, fi os.FileInfo, err error) error { // generate tar header header, err := tar.FileInfoHeader(fi, file) if err != nil { return err } // must provide real name // (see https://golang.org/src/archive/tar/common.go?#L626) srcWithSlash := src if !strings.HasSuffix(src, string(filepath.Separator)) { srcWithSlash = src + string(filepath.Separator) } header.Name = strings.ReplaceAll(file, srcWithSlash, "") if header.Name == src || len(strings.TrimSpace(header.Name)) == 0 { return nil } // @todo This is a quick hack to speed up whole repo uploads // https://github.com/micro/micro/pull/956 if !fi.IsDir() && !strings.HasSuffix(header.Name, ".go") && !strings.HasSuffix(header.Name, ".mod") && !strings.HasSuffix(header.Name, ".sum") { return nil } // write header if err := tw.WriteHeader(header); err != nil { return err } if fi.IsDir() { return nil } // if not a dir, write file content data, err := os.Open(file) if err != nil { return err } if _, err := io.Copy(tw, data); err != nil { return err } return nil }) // produce tar if err := tw.Close(); err != nil { return err } // produce gzip if err := zr.Close(); err != nil { return err } // return nil }