diff --git a/go.mod b/go.mod index 54b9d99..b5e9706 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,10 @@ require ( github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995 // indirect github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e // indirect github.com/motemen/go-colorine v0.0.0-20180816141035-45d19169413a - github.com/saracen/walker v0.0.0-20191020095038-4d832ad28155 + github.com/saracen/walker v0.0.0-20191030103630-c86836c89b0d github.com/urfave/cli v1.20.0 golang.org/x/net v0.0.0-20190620200207-3b0461eec859 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e + golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c // indirect golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 ) diff --git a/go.sum b/go.sum index 64aa30b..d4cfc7c 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/motemen/go-colorine v0.0.0-20180816141035-45d19169413a h1:CONqI/36EjY github.com/motemen/go-colorine v0.0.0-20180816141035-45d19169413a/go.mod h1:PU2urRC7j30rrabSyp1MGGhyoiWSninPD8ckjzBSgkU= github.com/saracen/walker v0.0.0-20191020095038-4d832ad28155 h1:6cXEis177J1IafLIpOHbPmn8di/6nBECKDUc+Ulfo/Q= github.com/saracen/walker v0.0.0-20191020095038-4d832ad28155/go.mod h1:VYm6MDHqbAnTSqTpGgLKPoDhJrUXtknAIO6qQAiFwN4= +github.com/saracen/walker v0.0.0-20191030103630-c86836c89b0d h1:k+brI8haJpvUV/MynREwYQV0n7jq1FkEayozuu4fgYM= +github.com/saracen/walker v0.0.0-20191030103630-c86836c89b0d/go.mod h1:VYm6MDHqbAnTSqTpGgLKPoDhJrUXtknAIO6qQAiFwN4= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -26,6 +28,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE= +golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191011211836-4c025a95b26e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= diff --git a/local_repository.go b/local_repository.go index 56235dd..163b3b5 100644 --- a/local_repository.go +++ b/local_repository.go @@ -10,6 +10,7 @@ import ( "github.com/Songmu/gitconfig" "github.com/saracen/walker" + "golang.org/x/xerrors" ) type LocalRepository struct { @@ -57,7 +58,7 @@ func LocalRepositoryFromFullPath(fullPath string, backend *VCSBackend) (*LocalRe return &LocalRepository{ FullPath: fullPath, - RelPath: relPath, + RelPath: filepath.ToSlash(relPath), RootPath: root, PathParts: pathParts, vcsBackend: backend, @@ -202,44 +203,54 @@ func walkLocalRepositories(callback func(*LocalRepository)) error { if err != nil { return err } + + walkFn := func(fpath string, fi os.FileInfo) error { + isSymlink := false + if fi.Mode()&os.ModeSymlink == os.ModeSymlink { + isSymlink = true + realpath, err := filepath.EvalSymlinks(fpath) + if err != nil { + return nil + } + fi, err = os.Stat(realpath) + if err != nil { + return nil + } + } + if !fi.IsDir() { + return nil + } + vcsBackend := findVCSBackend(fpath) + if vcsBackend == nil { + return nil + } + + repo, err := LocalRepositoryFromFullPath(fpath, vcsBackend) + if err != nil || repo == nil { + return nil + } + callback(repo) + + if isSymlink { + return nil + } + return filepath.SkipDir + } + + errCb := walker.WithErrorCallback(func(pathname string, err error) error { + if os.IsPermission(xerrors.Unwrap(err)) { + return nil + } + return err + }) + for _, root := range roots { if _, err := os.Stat(root); err != nil { - if os.IsNotExist(err) { + if os.IsNotExist(err) || os.IsPermission(err) { continue } } - if err := walker.Walk(root, func(fpath string, fi os.FileInfo) error { - isSymlink := false - if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - isSymlink = true - realpath, err := filepath.EvalSymlinks(fpath) - if err != nil { - return nil - } - fi, err = os.Stat(realpath) - if err != nil { - return nil - } - } - if !fi.IsDir() { - return nil - } - vcsBackend := findVCSBackend(fpath) - if vcsBackend == nil { - return nil - } - - repo, err := LocalRepositoryFromFullPath(fpath, vcsBackend) - if err != nil || repo == nil { - return nil - } - callback(repo) - - if isSymlink { - return nil - } - return filepath.SkipDir - }); err != nil { + if err := walker.Walk(root, walkFn, errCb); err != nil { return err } }