Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Commit

Permalink
Fix nested directory listing for archives without explicit directory …
Browse files Browse the repository at this point in the history
…names.
  • Loading branch information
jeremyje committed Jun 15, 2022
1 parent 3869ede commit b9eb37f
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
_gitignore
__debug_bin
6 changes: 6 additions & 0 deletions archiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ func nameOnDiskToNameInArchive(nameOnDisk, rootOnDisk, rootInArchive string) str
//
// For example, "a/b/c" => "b/c".
func trimTopDir(dir string) string {
if len(dir) > 0 && dir[0] == '/' {
dir = dir[1:]
}
if pos := strings.Index(dir, "/"); pos >= 0 {
return dir[pos+1:]
}
Expand All @@ -159,6 +162,9 @@ func trimTopDir(dir string) string {
//
// For example, "a/b/c" => "a".
func topDir(dir string) string {
if len(dir) > 0 && dir[0] == '/' {
dir = dir[1:]
}
if pos := strings.Index(dir, "/"); pos >= 0 {
return dir[:pos]
}
Expand Down
40 changes: 40 additions & 0 deletions archiver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,46 @@ import (
"testing"
)

func TestTrimTopDir(t *testing.T) {
for _, tc := range []struct {
input string
want string
}{
{input: "a/b/c", want: "b/c"},
{input: "a", want: "a"},
{input: "abc/def", want: "def"},
{input: "/abc/def", want: "def"},
} {
tc := tc
t.Run(tc.input, func(t *testing.T) {
got := trimTopDir(tc.input)
if got != tc.want {
t.Errorf("want: '%s', got: '%s')", tc.want, got)
}
})
}
}

func TestTopDir(t *testing.T) {
for _, tc := range []struct {
input string
want string
}{
{input: "a/b/c", want: "a"},
{input: "a", want: "a"},
{input: "abc/def", want: "abc"},
{input: "/abc/def", want: "abc"},
} {
tc := tc
t.Run(tc.input, func(t *testing.T) {
got := topDir(tc.input)
if got != tc.want {
t.Errorf("want: '%s', got: '%s')", tc.want, got)
}
})
}
}

func TestFileIsIncluded(t *testing.T) {
for i, tc := range []struct {
included []string
Expand Down
8 changes: 6 additions & 2 deletions fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,13 +458,17 @@ func (f ArchiveFS) ReadDir(name string) ([]fs.DirEntry, error) {
// leaving them to be inferred from the names of files instead (issue #330)
// so as we traverse deeper, we need to implicitly find subfolders within
// this current directory and add fake entries to the output
remainingPath := strings.TrimPrefix(file.NameInArchive, name)
remainingPath := file.NameInArchive

if name != "." {
remainingPath = strings.TrimPrefix(file.NameInArchive, name)
}
nextDir := topDir(remainingPath) // if name in archive is "a/b/c" and root is "a", this becomes "b" (the implied folder to add)
implicitDir := path.Join(name, nextDir) // the full path of the implied directory

// create fake entry only if no entry currently exists (don't overwrite a real entry)
if _, ok := entries[implicitDir]; !ok {
entries[implicitDir] = implicitDirEntry{implicitDir}
entries[implicitDir] = implicitDirEntry{nextDir}
}

return fs.SkipDir
Expand Down
51 changes: 49 additions & 2 deletions fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
"log"
"net/http"
"path"
"sort"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestPathWithoutTopDir(t *testing.T) {
Expand Down Expand Up @@ -40,9 +43,14 @@ func TestPathWithoutTopDir(t *testing.T) {
}

//go:generate zip testdata/test.zip go.mod
//go:generate zip -qr9 testdata/nodir.zip archiver.go go.mod cmd/arc/main.go .github/ISSUE_TEMPLATE/bug_report.md .github/FUNDING.yml README.md .github/workflows/ubuntu-latest.yml

//go:embed testdata/test.zip
var testZIP []byte
var (
//go:embed testdata/test.zip
testZIP []byte
//go:embed testdata/nodir.zip
nodirZIP []byte
)

func ExampleArchiveFS_Stream() {
fsys := ArchiveFS{
Expand Down Expand Up @@ -70,3 +78,42 @@ func ExampleArchiveFS_Stream() {
// go.mod
// true
}

func TestArchiveFS_Stream_Nodir(t *testing.T) {
fsys := ArchiveFS{
Stream: io.NewSectionReader(bytes.NewReader(nodirZIP), 0, int64(len(nodirZIP))),
Format: Zip{},
}

if err := verifyDirList(fsys, ".", []string{".github", "README.md", "archiver.go", "cmd", "go.mod"}); err != nil {
t.Error(err)
}

if err := verifyDirList(fsys, ".github", []string{"FUNDING.yml", "ISSUE_TEMPLATE", "workflows"}); err != nil {
t.Error(err)
}

if err := verifyDirList(fsys, "cmd", []string{"arc"}); err != nil {
t.Error(err)
}
}

func verifyDirList(fsys ArchiveFS, dir string, want []string) error {
dis, err := fsys.ReadDir(dir)
if err != nil {
return err
}

dirs := []string{}
for _, di := range dis {
dirs = append(dirs, di.Name())
}

// Stabilize the sort order
sort.Strings(dirs)

if diff := cmp.Diff(want, dirs); diff != "" {
return fmt.Errorf("ReadDir() mismatch (-want +got):\n%s", diff)
}
return nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (

require (
github.com/golang/snappy v0.0.4
github.com/google/go-cmp v0.5.8
github.com/pierrec/lz4/v4 v4.1.14
golang.org/x/text v0.3.7
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5Jflh
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.15.5 h1:qyCLMz2JCrKADihKOh9FxnW3houKeNsp2h5OEz0QSEA=
github.com/klauspost/compress v1.15.5/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
Expand Down
Binary file added testdata/nodir.zip
Binary file not shown.
Binary file modified testdata/test.zip
Binary file not shown.

0 comments on commit b9eb37f

Please sign in to comment.