@@ -13,7 +13,10 @@ import (
1313// CreateTarGzWithStructure creates a tar.gz archive preserving directory structure
1414func CreateTarGzWithStructure (paths []string ) ([]byte , error ) {
1515 var buf bytes.Buffer
16- gzWriter := gzip .NewWriter (& buf )
16+ gzWriter , err := gzip .NewWriterLevel (& buf , gzip .BestCompression )
17+ if err != nil {
18+ return nil , fmt .Errorf ("failed to create gzip writer: %v" , err )
19+ }
1720 tarWriter := tar .NewWriter (gzWriter )
1821
1922 for _ , path := range paths {
@@ -34,9 +37,20 @@ func CreateTarGzWithStructure(paths []string) ([]byte, error) {
3437 if err != nil {
3538 relPath = filePath
3639 }
40+ relPath = filepath .ToSlash (relPath )
3741
3842 if info .IsDir () {
39- // Add directory entry
43+ // Add directory headers only for empty directories.
44+ // Non-empty directories are implicitly created during extraction
45+ // from file paths and omitting them keeps the archive smaller.
46+ isEmpty , err := isDirEmpty (filePath )
47+ if err != nil {
48+ return err
49+ }
50+ if ! isEmpty {
51+ return nil
52+ }
53+
4054 header := & tar.Header {
4155 Name : relPath + "/" ,
4256 Mode : int64 (info .Mode ()),
@@ -97,6 +111,8 @@ func addFileToTarWithName(tarWriter *tar.Writer, filePath, tarName string) error
97111 }
98112 defer file .Close ()
99113
114+ tarName = filepath .ToSlash (tarName )
115+
100116 stat , err := file .Stat ()
101117 if err != nil {
102118 return err
@@ -117,6 +133,14 @@ func addFileToTarWithName(tarWriter *tar.Writer, filePath, tarName string) error
117133 return err
118134}
119135
136+ func isDirEmpty (path string ) (bool , error ) {
137+ entries , err := os .ReadDir (path )
138+ if err != nil {
139+ return false , err
140+ }
141+ return len (entries ) == 0 , nil
142+ }
143+
120144// ExtractTarGz extracts a tar.gz archive to a directory
121145func ExtractTarGz (data []byte , destDir string ) error {
122146 gzReader , err := gzip .NewReader (bytes .NewReader (data ))
0 commit comments