From 3ed885d8f086ccc050f47f1e9d425ef06c946b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Thu, 21 Sep 2023 00:05:37 +0200 Subject: [PATCH 1/5] chore: adds --include-files flag. --- cmd/porto/main.go | 20 ++++++++++++++------ import.go | 14 ++++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/cmd/porto/main.go b/cmd/porto/main.go index 0d5e829..6fa9ae5 100644 --- a/cmd/porto/main.go +++ b/cmd/porto/main.go @@ -18,6 +18,7 @@ func main() { flagSkipDirs := flag.String("skip-dirs", "", "Regexps of directories to skip") flagSkipDefaultDirs := flag.Bool("skip-dirs-use-default", true, "use default skip directory list") flagIncludeInternal := flag.Bool("include-internal", false, "include internal folders") + flagIncludeFiles := flag.String("include-files", "", "Regexps of files to include") flag.Parse() baseDir := flag.Arg(0) @@ -32,6 +33,7 @@ Options: --skip-dirs Regexps of directories to skip --skip-dirs-use-default Use default skip directory list (default: true) --include-internal Include internal folders +--include-files Regexps of files to include. It takes precedence over --skip-files Examples: @@ -53,7 +55,12 @@ Add import path to a folder skipFilesRegex, err := porto.GetRegexpList(*flagSkipFiles) if err != nil { - log.Fatalf("failed to build files regexes: %v", err) + log.Fatalf("failed to build files regexes to exclude: %v", err) + } + + includeFilesRegex, err := porto.GetRegexpList(*flagIncludeFiles) + if err != nil { + log.Fatalf("failed to build files regexes to include: %v", err) } var skipDirsRegex []*regexp.Regexp @@ -67,11 +74,12 @@ Add import path to a folder skipDirsRegex = append(skipDirsRegex, userSkipDirsRegex...) diffCount, err := porto.FindAndAddVanityImportForDir(workingDir, baseAbsDir, porto.Options{ - WriteResultToFile: *flagWriteOutputToFile, - ListDiffFiles: *flagListDiff, - SkipFilesRegexes: skipFilesRegex, - SkipDirsRegexes: skipDirsRegex, - IncludeInternal: *flagIncludeInternal, + WriteResultToFile: *flagWriteOutputToFile, + ListDiffFiles: *flagListDiff, + SkipFilesRegexes: skipFilesRegex, + SkipDirsRegexes: skipDirsRegex, + IncludeInternal: *flagIncludeInternal, + IncludeFilesRegexes: includeFilesRegex, }) if err != nil { log.Fatal(err) diff --git a/import.go b/import.go index 7cae7c5..7caa622 100644 --- a/import.go +++ b/import.go @@ -7,7 +7,7 @@ import ( "go/ast" "go/parser" "go/token" - "io/ioutil" + "os" "path/filepath" "regexp" "strings" @@ -56,7 +56,7 @@ func addImportPath(absFilepath string, module string) (bool, []byte, error) { return false, nil, errGenerated } - content, err := ioutil.ReadFile(absFilepath) + content, err := os.ReadFile(absFilepath) if err != nil { return false, nil, fmt.Errorf("failed to parse the file %q: %v", absFilepath, err) } @@ -99,7 +99,7 @@ func findAndAddVanityImportForModuleDir(workingDir, absDir string, moduleName st return 0, nil } - files, err := ioutil.ReadDir(absDir) + files, err := os.ReadDir(absDir) if err != nil { return 0, fmt.Errorf("failed to read the content of %q: %v", absDir, err) } @@ -127,7 +127,7 @@ func findAndAddVanityImportForModuleDir(workingDir, absDir string, moduleName st } gc += c - } else if fileName := f.Name(); isGoFile(fileName) && !isGoTestFile(fileName) && !matchesAny(opts.SkipFilesRegexes, fileName) { + } else if fileName := f.Name(); isGoFile(fileName) && !isGoTestFile(fileName) && matchesAny(opts.IncludeFilesRegexes, fileName) && !matchesAny(opts.SkipFilesRegexes, fileName) { absFilepath := absDir + pathSeparator + fileName hasChanged, newContent, err := addImportPath(absDir+pathSeparator+fileName, moduleName) @@ -181,7 +181,7 @@ func matchesAny(regexes []*regexp.Regexp, str string) bool { } func findAndAddVanityImportForNonModuleDir(workingDir, absDir string, opts Options) (int, error) { - files, err := ioutil.ReadDir(absDir) + files, err := os.ReadDir(absDir) if err != nil { return 0, fmt.Errorf("failed to read %q: %v", absDir, err) } @@ -231,6 +231,8 @@ type Options struct { SkipDirsRegexes []*regexp.Regexp // Include internal packages IncludeInternal bool + // Set of regex for matching files to be included + IncludeFilesRegexes []*regexp.Regexp } // FindAndAddVanityImportForDir scans all files in a folder and based on go.mod files @@ -240,7 +242,7 @@ func FindAndAddVanityImportForDir(workingDir, absDir string, opts Options) (int, return findAndAddVanityImportForModuleDir(workingDir, absDir, moduleName, opts) } - files, err := ioutil.ReadDir(absDir) + files, err := os.ReadDir(absDir) if err != nil { return 0, fmt.Errorf("failed to read the content of %q: %v", absDir, err) } From 46dc46e1c6eb4ddd263f96d464280e5c420d582f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Thu, 21 Sep 2023 00:20:02 +0200 Subject: [PATCH 2/5] chore: drops older go versions. --- .github/workflows/merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index ddd9f35..7fb21e7 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - go: ["1.13", "1.14", "1.15", "1.16", "1.17", "1.18", "1.19", "1.20", "1.21"] + go: ["1.19", "1.20", "1.21"] steps: # Set fetch-depth: 0 to fetch commit history and tags for use in version calculation - name: Check out code From 4ac7c254a69a877d413000b5e4b8148bfef10440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Thu, 21 Sep 2023 22:40:47 +0200 Subject: [PATCH 3/5] fix: include/skip logic. --- cmd/porto/main.go | 22 ++++++++++++++-------- import.go | 13 ++++++++++++- import_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/cmd/porto/main.go b/cmd/porto/main.go index 6fa9ae5..648bf36 100644 --- a/cmd/porto/main.go +++ b/cmd/porto/main.go @@ -73,14 +73,20 @@ Add import path to a folder } skipDirsRegex = append(skipDirsRegex, userSkipDirsRegex...) - diffCount, err := porto.FindAndAddVanityImportForDir(workingDir, baseAbsDir, porto.Options{ - WriteResultToFile: *flagWriteOutputToFile, - ListDiffFiles: *flagListDiff, - SkipFilesRegexes: skipFilesRegex, - SkipDirsRegexes: skipDirsRegex, - IncludeInternal: *flagIncludeInternal, - IncludeFilesRegexes: includeFilesRegex, - }) + opts := porto.Options{ + WriteResultToFile: *flagWriteOutputToFile, + ListDiffFiles: *flagListDiff, + IncludeInternal: *flagIncludeInternal, + } + + if len(includeFilesRegex) > 0 { + opts.IncludeFilesRegexes = includeFilesRegex + } else { + opts.SkipFilesRegexes = skipFilesRegex + opts.SkipDirsRegexes = skipDirsRegex + } + + diffCount, err := porto.FindAndAddVanityImportForDir(workingDir, baseAbsDir, opts) if err != nil { log.Fatal(err) } diff --git a/import.go b/import.go index 7caa622..7156762 100644 --- a/import.go +++ b/import.go @@ -127,7 +127,18 @@ func findAndAddVanityImportForModuleDir(workingDir, absDir string, moduleName st } gc += c - } else if fileName := f.Name(); isGoFile(fileName) && !isGoTestFile(fileName) && matchesAny(opts.IncludeFilesRegexes, fileName) && !matchesAny(opts.SkipFilesRegexes, fileName) { + } else if fileName := f.Name(); isGoFile(fileName) && !isGoTestFile(fileName) { + shouldEvaluate := true + if len(opts.IncludeFilesRegexes) > 0 { + shouldEvaluate = matchesAny(opts.IncludeFilesRegexes, fileName) + } else if len(opts.SkipFilesRegexes) > 0 { + shouldEvaluate = !matchesAny(opts.SkipFilesRegexes, fileName) + } + + if !shouldEvaluate { + continue + } + absFilepath := absDir + pathSeparator + fileName hasChanged, newContent, err := addImportPath(absDir+pathSeparator+fileName, moduleName) diff --git a/import_test.go b/import_test.go index 4d99c3b..d47815b 100644 --- a/import_test.go +++ b/import_test.go @@ -72,6 +72,52 @@ func TestFindFilesWithVanityImport(t *testing.T) { assert.Equal(t, 0, c) }) + t.Run("skip file", func(t *testing.T) { + c, err := findAndAddVanityImportForModuleDir( + cwd, + cwd+"/testdata/leftpad", + "github.com/jcchavezs/porto-integration-leftpad", + Options{ + ListDiffFiles: true, + SkipFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`leftpad\.go`)}, + }, + ) + + require.NoError(t, err) + assert.Equal(t, 1, c) + }) + + t.Run("include file", func(t *testing.T) { + c, err := findAndAddVanityImportForModuleDir( + cwd, + cwd+"/testdata/leftpad", + "github.com/jcchavezs/porto-integration-leftpad", + Options{ + ListDiffFiles: true, + IncludeFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`other\.go`)}, + }, + ) + + require.NoError(t, err) + assert.Equal(t, 1, c) + }) + + t.Run("skip and include file", func(t *testing.T) { + c, err := findAndAddVanityImportForModuleDir( + cwd, + cwd+"/testdata/leftpad", + "github.com/jcchavezs/porto-integration-leftpad", + Options{ + ListDiffFiles: true, + IncludeFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`other\.go`)}, + SkipFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`leftpad\.go`)}, + }, + ) + + require.NoError(t, err) + assert.Equal(t, 1, c) + }) + } func TestMatchesAny(t *testing.T) { From 6a5fe7f348d20e55d2965c99a19ab07c82b1f8c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Sat, 30 Sep 2023 23:49:47 +0200 Subject: [PATCH 4/5] chore: changes the flag from include to restrict to express the intention. --- cmd/porto/main.go | 29 ++++++++++------------------- import.go | 6 +++--- import_test.go | 10 +++++----- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/cmd/porto/main.go b/cmd/porto/main.go index 648bf36..e2a4a81 100644 --- a/cmd/porto/main.go +++ b/cmd/porto/main.go @@ -12,29 +12,20 @@ import ( ) func main() { - flagWriteOutputToFile := flag.Bool("w", false, "write result to (source) file instead of stdout") - flagListDiff := flag.Bool("l", false, "list files whose vanity import differs from porto's") + flagWriteOutputToFile := flag.Bool("w", false, "Write result to (source) file instead of stdout") + flagListDiff := flag.Bool("l", false, "List files whose vanity import differs from porto's") flagSkipFiles := flag.String("skip-files", "", "Regexps of files to skip") flagSkipDirs := flag.String("skip-dirs", "", "Regexps of directories to skip") - flagSkipDefaultDirs := flag.Bool("skip-dirs-use-default", true, "use default skip directory list") - flagIncludeInternal := flag.Bool("include-internal", false, "include internal folders") - flagIncludeFiles := flag.String("include-files", "", "Regexps of files to include") + flagSkipDefaultDirs := flag.Bool("skip-dirs-use-default", true, "Use default skip directory list") + flagIncludeInternal := flag.Bool("include-internal", false, "Include internal folders") + restrictToFiles := flag.String("restrict-to-files", "", "Regexps of files to restrict the inspection on. It takes precedence over -skip-files and -skip-dirs") flag.Parse() baseDir := flag.Arg(0) + if len(flag.Args()) == 0 { + flag.Usage() fmt.Println(` -usage: porto [options] - -Options: --w Write result to (source) file instead of stdout (default: false) --l List files whose vanity import differs from porto's (default: false) ---skip-files Regexps of files to skip ---skip-dirs Regexps of directories to skip ---skip-dirs-use-default Use default skip directory list (default: true) ---include-internal Include internal folders ---include-files Regexps of files to include. It takes precedence over --skip-files - Examples: Add import path to a folder @@ -58,7 +49,7 @@ Add import path to a folder log.Fatalf("failed to build files regexes to exclude: %v", err) } - includeFilesRegex, err := porto.GetRegexpList(*flagIncludeFiles) + restrictToFilesRegex, err := porto.GetRegexpList(*restrictToFiles) if err != nil { log.Fatalf("failed to build files regexes to include: %v", err) } @@ -79,8 +70,8 @@ Add import path to a folder IncludeInternal: *flagIncludeInternal, } - if len(includeFilesRegex) > 0 { - opts.IncludeFilesRegexes = includeFilesRegex + if len(restrictToFilesRegex) > 0 { + opts.RestrictToFilesRegexes = restrictToFilesRegex } else { opts.SkipFilesRegexes = skipFilesRegex opts.SkipDirsRegexes = skipDirsRegex diff --git a/import.go b/import.go index 7156762..385dc8c 100644 --- a/import.go +++ b/import.go @@ -129,8 +129,8 @@ func findAndAddVanityImportForModuleDir(workingDir, absDir string, moduleName st gc += c } else if fileName := f.Name(); isGoFile(fileName) && !isGoTestFile(fileName) { shouldEvaluate := true - if len(opts.IncludeFilesRegexes) > 0 { - shouldEvaluate = matchesAny(opts.IncludeFilesRegexes, fileName) + if len(opts.RestrictToFilesRegexes) > 0 { + shouldEvaluate = matchesAny(opts.RestrictToFilesRegexes, fileName) } else if len(opts.SkipFilesRegexes) > 0 { shouldEvaluate = !matchesAny(opts.SkipFilesRegexes, fileName) } @@ -243,7 +243,7 @@ type Options struct { // Include internal packages IncludeInternal bool // Set of regex for matching files to be included - IncludeFilesRegexes []*regexp.Regexp + RestrictToFilesRegexes []*regexp.Regexp } // FindAndAddVanityImportForDir scans all files in a folder and based on go.mod files diff --git a/import_test.go b/import_test.go index d47815b..d41f2aa 100644 --- a/import_test.go +++ b/import_test.go @@ -93,8 +93,8 @@ func TestFindFilesWithVanityImport(t *testing.T) { cwd+"/testdata/leftpad", "github.com/jcchavezs/porto-integration-leftpad", Options{ - ListDiffFiles: true, - IncludeFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`other\.go`)}, + ListDiffFiles: true, + RestrictToFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`other\.go`)}, }, ) @@ -108,9 +108,9 @@ func TestFindFilesWithVanityImport(t *testing.T) { cwd+"/testdata/leftpad", "github.com/jcchavezs/porto-integration-leftpad", Options{ - ListDiffFiles: true, - IncludeFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`other\.go`)}, - SkipFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`leftpad\.go`)}, + ListDiffFiles: true, + RestrictToFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`other\.go`)}, + SkipFilesRegexes: []*regexp.Regexp{regexp.MustCompile(`leftpad\.go`)}, }, ) From 01e89196a5080c41a6c4a684b56bb9ae0619aa88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Sat, 30 Sep 2023 23:55:17 +0200 Subject: [PATCH 5/5] docs: adds example for restrict to files. --- README.md | 10 ++++++++++ cmd/porto/main.go | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 104779b..2629b8b 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ If you just want to list the files that porto would change vanity import, run: ```bash porto -l path/to/library ``` + ## Inclusion/exclusion rules `porto` skips autogenerated, internal, third party and vendored files by default. You can customize what files get included using some flags: @@ -38,13 +39,22 @@ porto -l path/to/library ```bash porto --skip-files ".*\\.pb\\.go$" path/to/library ``` + - If you want to ignore directories (e.g. tooling directories), pass the `--skip-dirs` flag: ```bash porto --skip-dirs "^tools$" path/to/library ``` + - If you want to include `internal` folders and directories skipped by default: ```bash porto --include-internal --skip-dirs-use-default=false path/to/library ``` + +- If you want to restrict to certain files e.g. `doc.go` you +can use: + +```bash +porto --restrict-to-files "doc.go$" path/to/library +``` diff --git a/cmd/porto/main.go b/cmd/porto/main.go index e2a4a81..25a961e 100644 --- a/cmd/porto/main.go +++ b/cmd/porto/main.go @@ -18,7 +18,7 @@ func main() { flagSkipDirs := flag.String("skip-dirs", "", "Regexps of directories to skip") flagSkipDefaultDirs := flag.Bool("skip-dirs-use-default", true, "Use default skip directory list") flagIncludeInternal := flag.Bool("include-internal", false, "Include internal folders") - restrictToFiles := flag.String("restrict-to-files", "", "Regexps of files to restrict the inspection on. It takes precedence over -skip-files and -skip-dirs") + flagRestrictToFiles := flag.String("restrict-to-files", "", "Regexps of files to restrict the inspection on. It takes precedence over -skip-files and -skip-dirs") flag.Parse() baseDir := flag.Arg(0) @@ -49,7 +49,7 @@ Add import path to a folder log.Fatalf("failed to build files regexes to exclude: %v", err) } - restrictToFilesRegex, err := porto.GetRegexpList(*restrictToFiles) + restrictToFilesRegex, err := porto.GetRegexpList(*flagRestrictToFiles) if err != nil { log.Fatalf("failed to build files regexes to include: %v", err) }