Skip to content

Commit

Permalink
Merge pull request #8 from haya14busa/fastwalk
Browse files Browse the repository at this point in the history
breaking: Use fastwalk instead to improve performance and simplify code
  • Loading branch information
haya14busa authored Oct 5, 2019
2 parents e8eceac + a471376 commit 07dce9d
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 52 deletions.
3 changes: 1 addition & 2 deletions cmd/ghglob/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ var version = "master"
var (
showVersion = flag.Bool("version", false, "print version")
all = flag.Bool("all", false, "do not ignore entries starting with .")
sort = flag.Bool("sort", false, "sort results.")
followSym = flag.Bool("symlink", true, "follow symlink if true")
)

Expand Down Expand Up @@ -60,7 +59,7 @@ func glob() {
ps = append(ps, "!**/.*")
ps = append(ps, "!**/.*/**")
}
opt := ghglob.Option{Sort: *sort, FollowSymbolicLinks: *followSym}
opt := ghglob.Option{FollowSymbolicLinks: *followSym}
if shouldRoot(flag.Args()) {
opt.Root = "/"
}
Expand Down
78 changes: 35 additions & 43 deletions ghglob.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ package ghglob
import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/haya14busa/ghglob/ghmatcher"
"github.com/karrick/godirwalk"
"github.com/s12chung/fastwalk"
)

type Option struct {
// True for faster yet non-deterministic enumeration.
Sort bool
FollowSymbolicLinks bool
Root string
}
Expand All @@ -38,57 +37,50 @@ func Glob(files chan<- string, patterns []string, opt Option) error {
if err != nil {
return err
}
isRoot := len(opt.Root) > 0 && opt.Root[0] == '/'
subms, err := buildSubMatchers(patterns)
if err != nil {
return fmt.Errorf("fail to build submatchers: %v", err)
}
root := opt.Root
if root == "" {
rootPrefix := ""
switch root {
case "":
root = "."
rootPrefix = "./"
case "/":
rootPrefix = "/"
default:
rootPrefix = root + "/"
}
rootPrefix := strings.TrimPrefix(root, "./")
if err := godirwalk.Walk(root, &godirwalk.Options{
Callback: func(path string, de *godirwalk.Dirent) error {
p := path
if !isRoot {
p = strings.TrimPrefix(path, rootPrefix)
}
if p == "" {
return nil
}
if de.ModeType().IsDir() {
if p != strings.TrimSuffix(rootPrefix, "/") && p != "/" && shouldSkipDir(subms, p) {
return skipdir{}

return fastwalk.Walk(root, func(path string, typ os.FileMode) error {
p := strings.TrimPrefix(path, rootPrefix)
if p == "" {
return nil
}

if opt.FollowSymbolicLinks && typ == os.ModeSymlink {
followedPath, err := filepath.EvalSymlinks(path)
if err == nil {
fi, err := os.Lstat(followedPath)
if err == nil && fi.IsDir() {
return fastwalk.TraverseLink
}
return nil
}
if !matcher.Match(p) {
return nil
}

if typ.IsDir() {
if p != strings.TrimSuffix(rootPrefix, "/") && p != "/" && shouldSkipDir(subms, p) {
return filepath.SkipDir
}
files <- p
return nil
},
ErrorCallback: func(path string, err error) godirwalk.ErrorAction {
if _, ok := err.(skipdir); ok {
return godirwalk.SkipNode
}
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
return godirwalk.Halt
},

Unsorted: !opt.Sort,
FollowSymbolicLinks: opt.FollowSymbolicLinks,
}); err != nil {
return err
}
return nil
}

type skipdir struct{}

func (skipdir) Error() string {
return "skipdir"
}
if !matcher.Match(p) {
return nil
}
files <- p
return nil
})
}

func buildSubMatchers(patterns []string) ([]*ghmatcher.Matcher, error) {
Expand Down
11 changes: 7 additions & 4 deletions ghglob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ghglob

import (
"path/filepath"
"sort"
"strings"
"testing"

Expand Down Expand Up @@ -162,11 +163,12 @@ var tests = []struct {

func TestGlobList(t *testing.T) {
opt := Option{
Sort: true,
Root: "./_testdir/",
}
for _, tt := range tests {
got, err := GlobList(tt.ps, opt)
sort.Strings(got)
sort.Strings(tt.want)
if err != nil {
t.Errorf("GlobList(%v, ...) got error: %v", tt.ps, err)
continue
Expand All @@ -184,17 +186,18 @@ func TestGlobList_root(t *testing.T) {
}
testdir := filepath.Join(wd, "_testdir")
opt := Option{
Sort: true,
Root: testdir,
}
for _, tt := range tests {
ps := addPrefixDirToPattern(testdir, tt.ps)
ps := tt.ps
got, err := GlobList(ps, opt)
if err != nil {
t.Errorf("GlobList(%v, ...) got error: %v", ps, err)
continue
}
want := addPrefixDir(testdir, tt.want)
sort.Strings(got)
sort.Strings(tt.want)
want := tt.want
if diff := cmp.Diff(got, want); diff != "" {
t.Errorf("GlobList(%v, ...) got diff:\n%s\n\ngot:\n%s", ps, diff, strings.Join(got, "\n"))
}
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.13

require (
github.com/google/go-cmp v0.3.1
github.com/karrick/godirwalk v1.12.0
github.com/mattn/go-isatty v0.0.9
github.com/s12chung/fastwalk v1.0.0
golang.org/x/tools v0.0.0-20191005014404-c9f9432ec4b2 // indirect
)
12 changes: 10 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/karrick/godirwalk v1.12.0 h1:nkS4xxsjiZMvVlazd0mFyiwD4BR9f3m6LXGhM2TUx3Y=
github.com/karrick/godirwalk v1.12.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/s12chung/fastwalk v1.0.0 h1:FiJMtOgeIVBIYQEl1KjR0Gh6vkInwuO4neheT2NTj3c=
github.com/s12chung/fastwalk v1.0.0/go.mod h1:ePJo83sNwuxv3MBmfEcoTrNLne7nUMtqGWqJNSur/lo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191005014404-c9f9432ec4b2 h1:cizXZUfmWsxq3+I8k+qEgLy3QlTEC1UoAvkaPMpTAmA=
golang.org/x/tools v0.0.0-20191005014404-c9f9432ec4b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

0 comments on commit 07dce9d

Please sign in to comment.