Skip to content

Commit

Permalink
feat: new option to exclude files and dirs (#115)
Browse files Browse the repository at this point in the history
new option to exclude files and dirs
  • Loading branch information
tk103331 authored Aug 16, 2023
1 parent 3efe815 commit 1743775
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 9 deletions.
12 changes: 10 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
recursiveArg = "recursive"
useCacheArg = "use-cache"
applyToGeneratedFiles = "apply-to-generated-files"
excludesArg = "excludes"

// Deprecated options
localArg = "local"
Expand All @@ -55,7 +56,7 @@ var (
)

var (
projectName, companyPkgPrefixes, output, importsOrder string
projectName, companyPkgPrefixes, output, importsOrder, excludes string

// Deprecated
localPkgPrefixes, filePath string
Expand All @@ -69,6 +70,13 @@ func init() {
"Deprecated. Put file name as an argument(last item) of command line.",
)

flag.StringVar(
&excludes,
excludesArg,
"",
"Exclude files or dirs, example: '.git/,proto/*.go'.",
)

flag.StringVar(
&projectName,
projectNameArg,
Expand Down Expand Up @@ -259,7 +267,7 @@ func main() {
close(deprecatedMessagesCh)

if _, ok := reviser.IsDir(originPath); ok {
err := reviser.NewSourceDir(originProjectName, originPath, *isRecursive).Fix(options...)
err := reviser.NewSourceDir(originProjectName, originPath, *isRecursive, excludes).Fix(options...)
if err != nil {
log.Fatalf("Failed to fix directory: %+v\n", err)
}
Expand Down
58 changes: 51 additions & 7 deletions reviser/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"
"os"
"path/filepath"
"strings"

"golang.org/x/exp/slices"
)
Expand All @@ -26,16 +27,41 @@ var (

// SourceDir to validate and fix import
type SourceDir struct {
projectName string
dir string
isRecursive bool
projectName string
dir string
isRecursive bool
excludePatterns []string // see filepath.Match
}

func NewSourceDir(projectName string, path string, isRecursive bool) *SourceDir {
func NewSourceDir(projectName string, path string, isRecursive bool, excludes string) *SourceDir {
if path == recursivePath {
isRecursive = true
}
return &SourceDir{projectName: projectName, dir: path, isRecursive: isRecursive}
patterns := make([]string, 0)
// get the absolute path
absPath, err := filepath.Abs(path)
if err == nil {
segs := strings.Split(excludes, ",")
for _, seg := range segs {
p := strings.TrimSpace(seg)
if p != "" {
if !filepath.IsAbs(p) {
// resolve the absolute path
p = filepath.Join(absPath, p)
}
// Check pattern is well-formed.
if _, err = filepath.Match(p, ""); err == nil {
patterns = append(patterns, p)
}
}
}
}
return &SourceDir{
projectName: projectName,
dir: absPath,
isRecursive: isRecursive,
excludePatterns: patterns,
}
}

func (d *SourceDir) Fix(options ...SourceFileOption) error {
Expand All @@ -44,7 +70,6 @@ func (d *SourceDir) Fix(options ...SourceFileOption) error {
if !ok {
return ErrPathIsNotDir
}

err := filepath.WalkDir(d.dir, d.walk(options...))
if err != nil {
return fmt.Errorf("failed to walk dif: %w", err)
Expand All @@ -58,7 +83,10 @@ func (d *SourceDir) walk(options ...SourceFileOption) fs.WalkDirFunc {
if !d.isRecursive && dirEntry.IsDir() && filepath.Base(d.dir) != dirEntry.Name() {
return filepath.SkipDir
}
if isGoFile(path) && !dirEntry.IsDir() {
if dirEntry.IsDir() && d.isExcluded(path) {
return filepath.SkipDir
}
if isGoFile(path) && !dirEntry.IsDir() && !d.isExcluded(path) {
content, hasChange, err := NewSourceFile(d.projectName, path).Fix(options...)
if err != nil {
return fmt.Errorf("failed to fix: %w", err)
Expand All @@ -73,6 +101,22 @@ func (d *SourceDir) walk(options ...SourceFileOption) fs.WalkDirFunc {
}
}

func (d *SourceDir) isExcluded(path string) bool {
var absPath string
if filepath.IsAbs(path) {
absPath = path
} else {
absPath = filepath.Join(d.dir, path)
}
for _, pattern := range d.excludePatterns {
matched, err := filepath.Match(pattern, absPath)
if err == nil && matched {
return true
}
}
return false
}

func IsDir(path string) (string, bool) {
if path == recursivePath || slices.Contains(currentPaths, path) {
var err error
Expand Down
158 changes: 158 additions & 0 deletions reviser/dir_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package reviser

import (
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
"testing"
)

const sep = string(os.PathSeparator)

func TestSourceDir_Fix(t *testing.T) {
testFile := "testdata/dir/dir1/file1.go"

originContent := `package dir1
import (
"strings"
"fmt"
)
func main() {
fmt.Println(strings.ToLower("Hello World!"))
}
`
exec := func(tt *testing.T, fn func(*testing.T) error) {
// create test file
err := os.MkdirAll(filepath.Dir(testFile), os.ModePerm)
assert.NoError(tt, err)
err = os.WriteFile(testFile, []byte(originContent), os.ModePerm)
assert.NoError(tt, err)

// exec test func
err = fn(tt)
assert.NoError(tt, err)

// remove test file
err = os.Remove(testFile)
assert.NoError(tt, err)
}
var sortedContent string
exec(t, func(tt *testing.T) error {
// get sorted content via SourceFile.Fix
sortedData, changed, err := NewSourceFile("testdata", testFile).Fix()
assert.NoError(tt, err)
sortedContent = string(sortedData)
assert.Equal(tt, true, changed)
assert.NotEqual(tt, originContent, sortedContent)
return nil
})

type args struct {
project string
path string
excludes string
}
tests := []struct {
name string
args args
want string
}{
{
name: "exclude-file",
args: args{project: "testdata", path: "testdata/dir", excludes: "dir1" + sep + "file1.go"},
want: originContent,
}, {
name: "exclude-dir",
args: args{project: "testdata", path: "testdata/dir", excludes: "dir1" + sep},
want: originContent,
}, {
name: "exclude-file-*",
args: args{project: "testdata", path: "testdata/dir", excludes: "dir1" + sep + "f*1.go"},
want: originContent,
}, {
name: "exclude-file-?",
args: args{project: "testdata", path: "testdata/dir", excludes: "dir1" + sep + "file?.go"},
want: originContent,
}, {
name: "exclude-file-multi",
args: args{project: "testdata", path: "testdata/dir", excludes: "dir1" + sep + "file?.go,aaa,bbb"},
want: originContent,
}, {
name: "not-exclude",
args: args{project: "testdata", path: "testdata/dir", excludes: "dir1" + sep + "test.go"},
want: sortedContent,
},
}
for _, test := range tests {
t.Run(test.name, func(tt *testing.T) {

exec(tt, func(ttt *testing.T) error {
// executing SourceDir.Fix
err := NewSourceDir(test.args.project, test.args.path, true, test.args.excludes).Fix()
assert.NoError(tt, err)
// read new content
content, err := os.ReadFile(testFile)
assert.NoError(tt, err)
assert.Equal(tt, test.want, string(content))
return nil
})
})
}
}

func TestSourceDir_IsExcluded(t *testing.T) {
type args struct {
project string
path string
excludes string
testPath string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "normal",
args: args{project: "project", path: "project", excludes: "test.go", testPath: "test.go"},
want: true,
},
{
name: "dir",
args: args{project: "project", path: "project", excludes: "test/", testPath: "test"},
want: true,
},
{
name: "wildcard-1",
args: args{project: "project", path: "project", excludes: "tes?.go", testPath: "test.go"},
want: true,
},
{
name: "wildcard-2",
args: args{project: "project", path: "project", excludes: "t*.go", testPath: "test.go"},
want: true,
},
{
name: "not-excluded",
args: args{project: "project", path: "project", excludes: "t*.go", testPath: "abc.go"},
want: false,
},
{
name: "multi-excludes",
args: args{project: "project", path: "project", excludes: "t*.go,abc.go", testPath: "abc.go"},
want: true,
},
}

for _, test := range tests {
args := test.args
t.Run(test.name, func(tt *testing.T) {
excluded := NewSourceDir(args.project, args.path, true, args.excludes).isExcluded(args.testPath)
assert.Equal(tt, test.want, excluded)
})
}
}

func join(elem ...string) string {
return filepath.Join(elem...)
}

0 comments on commit 1743775

Please sign in to comment.