From 19ab124f1bec275ccc08452ada8deb7f1bf0c612 Mon Sep 17 00:00:00 2001 From: Ori Rawlings Date: Tue, 29 Nov 2022 19:05:18 -0600 Subject: [PATCH] fix: retain symlinks added to zip archives (#3585) fixes #3584 When following the reproduction steps in #3584 I now get the following contents for the zip archive: ``` $ goreleaser --snapshot --skip-publish ... $ (mkdir thezip && cd thezip && unzip ../dist/test_0.0.0-SNAPSHOT-none_darwin_amd64.zip) && ls -lR thezip Archive: ../dist/test_0.0.0-SNAPSHOT-none_darwin_amd64.zip inflating: a/x -> ../x inflating: a/x2 -> x inflating: x inflating: test finishing deferred symbolic links: a/x -> ../x a/x2 -> x total 1640 drwxr-xr-x 4 orawlings staff 128 Nov 22 16:19 a -rwxr-xr-x 1 orawlings staff 833104 Nov 22 16:19 test -rw-r--r-- 1 orawlings staff 2 Nov 22 15:32 x thezip/a: total 0 lrwxr-xr-x 1 orawlings staff 4 Nov 22 16:19 x -> ../x lrwxr-xr-x 1 orawlings staff 1 Nov 22 16:19 x2 -> x ``` I'm using goreleaser for a project that packages multiple binaries in zip archives. We also include symlinks within the zip archives to give some of the binaries an alternate (usually shorter) spelling so they are easier to invoke on the command line. This brings the zip archive behavior regarding symlinks in line with tar.gz and tar archives. --- pkg/archive/zip/zip.go | 12 +++++++++++- pkg/archive/zip/zip_test.go | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pkg/archive/zip/zip.go b/pkg/archive/zip/zip.go index 507c843077f..7005465d14a 100644 --- a/pkg/archive/zip/zip.go +++ b/pkg/archive/zip/zip.go @@ -5,8 +5,10 @@ package zip import ( "archive/zip" "compress/flate" + "fmt" "io" "os" + "path/filepath" "github.com/goreleaser/goreleaser/pkg/config" ) @@ -57,9 +59,17 @@ func (a Archive) Add(f config.File) error { if err != nil { return err } - if info.IsDir() || info.Mode()&os.ModeSymlink != 0 { + if info.IsDir() { return nil } + if info.Mode()&os.ModeSymlink != 0 { + link, err := os.Readlink(f.Source) // #nosec + if err != nil { + return fmt.Errorf("%s: %w", f.Source, err) + } + _, err = io.WriteString(w, filepath.ToSlash(link)) + return err + } file, err := os.Open(f.Source) // #nosec if err != nil { return err diff --git a/pkg/archive/zip/zip_test.go b/pkg/archive/zip/zip_test.go index 1d5d3840804..231027bbd2a 100644 --- a/pkg/archive/zip/zip_test.go +++ b/pkg/archive/zip/zip_test.go @@ -2,6 +2,7 @@ package zip import ( "archive/zip" + "bytes" "io" "io/fs" "os" @@ -85,6 +86,13 @@ func TestZipFile(t *testing.T) { } if zf.Name == "link.txt" { require.True(t, zf.FileInfo().Mode()&os.ModeSymlink != 0) + rc, err := zf.Open() + require.NoError(t, err) + var link bytes.Buffer + _, err = io.Copy(&link, rc) + require.NoError(t, err) + rc.Close() + require.Equal(t, link.String(), "regular.txt") } } require.Equal(t, []string{