Skip to content

Commit

Permalink
Merge pull request #3 from jabgibson/master
Browse files Browse the repository at this point in the history
add support for symbolic links and preserve file mode.
  • Loading branch information
mholt committed Jun 6, 2016
2 parents 831cc3c + e1b068b commit bbda37c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 21 deletions.
25 changes: 14 additions & 11 deletions targz.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,18 @@ func tarGzFile(tarWriter *tar.Writer, source string) error {
return nil
}

file, err := os.Open(path)
if err != nil {
return fmt.Errorf("%s: open: %v", path, err)
if header.Typeflag == tar.TypeReg {
file, err := os.Open(path)
if err != nil {
return fmt.Errorf("%s: open: %v", path, err)
}
defer file.Close()

_, err = io.Copy(tarWriter, file)
if err != nil {
return fmt.Errorf("%s: copying contents: %v", path, err)
}
}
defer file.Close()

_, err = io.Copy(tarWriter, file)
if err != nil {
return fmt.Errorf("%s: copying contents: %v", path, err)
}

return nil
})
}
Expand Down Expand Up @@ -128,7 +129,9 @@ func untarGzFile(tr *tar.Reader, header *tar.Header, destination string) error {
case tar.TypeDir:
return mkdir(filepath.Join(destination, header.Name))
case tar.TypeReg:
return writeNewFile(filepath.Join(destination, header.Name), tr)
return writeNewFile(filepath.Join(destination, header.Name), tr, header.FileInfo().Mode())
case tar.TypeSymlink:
return writeNewSymbolicLink(filepath.Join(destination, header.Name), header.Linkname)
default:
return fmt.Errorf("%s: unknown type flag: %c", header.Name, header.Typeflag)
}
Expand Down
42 changes: 32 additions & 10 deletions zip.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path"
"path/filepath"
"runtime"
"strings"
)

Expand Down Expand Up @@ -84,15 +85,17 @@ func zipFile(w *zip.Writer, source string) error {
return nil
}

file, err := os.Open(fpath)
if err != nil {
return fmt.Errorf("%s: opening: %v", fpath, err)
}
defer file.Close()
if header.Mode().IsRegular() {
file, err := os.Open(fpath)
if err != nil {
return fmt.Errorf("%s: opening: %v", fpath, err)
}
defer file.Close()

_, err = io.Copy(writer, file)
if err != nil {
return fmt.Errorf("%s: copying contents: %v", fpath, err)
_, err = io.Copy(writer, file)
if err != nil {
return fmt.Errorf("%s: copying contents: %v", fpath, err)
}
}

return nil
Expand Down Expand Up @@ -127,10 +130,10 @@ func unzipFile(zf *zip.File, destination string) error {
}
defer rc.Close()

return writeNewFile(filepath.Join(destination, zf.Name), rc)
return writeNewFile(filepath.Join(destination, zf.Name), rc, zf.FileInfo().Mode())
}

func writeNewFile(fpath string, in io.Reader) error {
func writeNewFile(fpath string, in io.Reader, fm os.FileMode) error {
err := os.MkdirAll(path.Dir(fpath), 0755)
if err != nil {
return fmt.Errorf("%s: making directory for file: %v", fpath, err)
Expand All @@ -142,13 +145,32 @@ func writeNewFile(fpath string, in io.Reader) error {
}
defer out.Close()

err = out.Chmod(fm)
if err != nil && runtime.GOOS != "windows" {
return fmt.Errorf("%s: changing file mode: %v", fpath, err)
}

_, err = io.Copy(out, in)
if err != nil {
return fmt.Errorf("%s: writing file: %v", fpath, err)
}
return nil
}

func writeNewSymbolicLink(fpath string, target string) error {
err := os.MkdirAll(path.Dir(fpath), 0755)
if err != nil {
return fmt.Errorf("%s: making directory for file: %v", fpath, err)
}

err = os.Symlink(target, fpath)
if err != nil {
return fmt.Errorf("%s: making symbolic link for: %v", fpath, err)
}

return nil
}

func mkdir(dirPath string) error {
err := os.Mkdir(dirPath, 0755)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions zip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,29 @@ func symmetricTest(t *testing.T, ext string, cf CompressFunc, dcf DecompressFunc
return nil
}

expectedFileInfo, err := os.Stat(origPath)
if err != nil {
t.Fatalf("%s: Error obtaining original file info: %v", fpath, err)
}
expected, err := ioutil.ReadFile(origPath)
if err != nil {
t.Fatalf("%s: Couldn't open original file (%s) from disk: %v",
fpath, origPath, err)
}

actualFileInfo, err := os.Stat(fpath)
if err != nil {
t.Fatalf("%s: Error obtaining actual file info: %v", fpath, err)
}
actual, err := ioutil.ReadFile(fpath)
if err != nil {
t.Fatalf("%s: Couldn't open new file from disk: %v", fpath, err)
}

if actualFileInfo.Mode() != expectedFileInfo.Mode() {
t.Fatalf("%s: File mode differed between on disk and compressed",
expectedFileInfo.Mode().String()+" : "+actualFileInfo.Mode().String())
}
if !bytes.Equal(expected, actual) {
t.Fatalf("%s: File contents differed between on disk and compressed", origPath)
}
Expand Down

0 comments on commit bbda37c

Please sign in to comment.