Skip to content

Commit

Permalink
supports unzip symlinks
Browse files Browse the repository at this point in the history
  • Loading branch information
fujiwara committed Feb 10, 2025
1 parent 4a75d7e commit 415e171
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 5 deletions.
23 changes: 22 additions & 1 deletion archive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"slices"
"sort"
Expand Down Expand Up @@ -142,8 +143,28 @@ func TestUnzip(t *testing.T) {
t.Error("failed to walk", err)
}
sort.Strings(unzipEntries)
expected := []string{"dir/sub.txt", "hello.txt", "world"}
expected := []string{"dir.symlink", "dir/sub.txt", "hello.symlink", "hello.txt", "world"}
if diff := cmp.Diff(unzipEntries, expected); diff != "" {
t.Errorf("unexpected unzip entries %s", diff)
}

// debug
o, _ := exec.Command("ls", "-lR", dest).Output()
t.Log(string(o))

// check symlink
fi, err := os.Lstat(filepath.Join(dest, "hello.symlink"))
if err != nil {
t.Error("failed to stat hello.symlink", err)
}
if fi.Mode()&os.ModeSymlink == 0 {
t.Error("hello.symlink must be symlink", fi.Mode())
}
linkTarget, err := os.Readlink(filepath.Join(dest, "hello.symlink"))
if err != nil {
t.Error("failed to readlink hello.symlink", err)
}
if diff := cmp.Diff(linkTarget, "hello.txt"); diff != "" {
t.Errorf("unexpected symlink target %s", diff)
}
}
39 changes: 36 additions & 3 deletions init.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
"io/fs"
"log"
"net/http"
"os"
Expand Down Expand Up @@ -173,7 +174,8 @@ func unzip(ctx context.Context, src, dest string, force bool) error {

for _, f := range r.File {
fpath := filepath.Join(dest, f.Name)
if f.FileInfo().IsDir() {
fi := f.FileInfo()
if fi.IsDir() {
log.Printf("[debug] creating directory %s", fpath)
if err := os.MkdirAll(fpath, f.Mode()); err != nil {
return err
Expand All @@ -185,14 +187,45 @@ func unzip(ctx context.Context, src, dest string, force bool) error {
if err := os.MkdirAll(filepath.Dir(fpath), 0755); err != nil {
return err
}

fc, err := f.Open()
if err != nil {
return err
}
if err := saveFileIO(ctx, fpath, fc, f.Mode(), force); err != nil {
return err
if fi.Mode()&os.ModeSymlink != 0 {
// supports for symbolic link
if err := saveSymlinkIO(ctx, fpath, fc, f.Mode()); err != nil {
return err
}
} else {
// normal file
if err := saveFileIO(ctx, fpath, fc, f.Mode(), force); err != nil {
return err
}
}
}

return nil
}

func saveSymlinkIO(_ context.Context, fpath string, r io.ReadCloser, mode fs.FileMode) error {
defer r.Close()
l, err := io.ReadAll(r)
if err != nil {
return err
}
linkTo := string(l)
log.Printf("[debug] writing symlink %s -> %s mode %s", fpath, linkTo, mode)

cwd, err := os.Getwd()
if err != nil {
return err
}
defer os.Chdir(cwd)
if err := os.Chdir(filepath.Dir(fpath)); err != nil {
return err
}
name := filepath.Base(fpath)
log.Printf("[debug] creating symlink %s -> %s", name, linkTo)
return os.Symlink(linkTo, name)
}
Binary file modified test/src.zip
Binary file not shown.
5 changes: 4 additions & 1 deletion utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
)

func (app *App) saveFile(ctx context.Context, path string, b []byte, mode os.FileMode, force bool) error {
log.Printf("[debug] writing file to %s mode %s", path, mode)
if _, err := os.Stat(path); err == nil {
ok := force || prompter.YN(fmt.Sprintf("Overwrite existing file %s?", path), false)
if !ok {
Expand All @@ -28,7 +29,9 @@ func (app *App) saveFile(ctx context.Context, path string, b []byte, mode os.Fil
return os.WriteFile(path, b, mode)
}

func saveFileIO(ctx context.Context, path string, r io.Reader, mode os.FileMode, force bool) error {
func saveFileIO(ctx context.Context, path string, r io.ReadCloser, mode os.FileMode, force bool) error {
log.Printf("[debug] writing file to %s mode %s", path, mode)
defer r.Close()
if _, err := os.Stat(path); err == nil {
ok := force || prompter.YN(fmt.Sprintf("Overwrite existing file %s?", path), false)
if !ok {
Expand Down

0 comments on commit 415e171

Please sign in to comment.