Skip to content

Commit

Permalink
replace version alias mechanism with a more flexible rule set, add a …
Browse files Browse the repository at this point in the history
…bunch of tests
  • Loading branch information
xrstf committed May 9, 2021
1 parent b2649c6 commit a9f4aa6
Show file tree
Hide file tree
Showing 54 changed files with 1,175 additions and 1,026 deletions.
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ the `vendor` folder and generated files.
- Output is always formatted, `-format` has been removed.
- The notion of `local` packages with configurable prefixes has been removed,
configure a set instead. Usually the `project` set will be sufficient.
- Likewise, the notion of "version aliases" was replaced with a flexible rule system,
allowing to configure dynamic aliases for matching packages and rewriting the code
accordingly (see below for important notes on this).
- Configuration happens primarily via the config file `.gimps.yaml`.
- Many files and directories can be specified as one; the main focus of gimps is not to be
a goimports/gopls alternative, but to be an addition and useful in CI environments.
Expand Down Expand Up @@ -95,11 +98,47 @@ sets:
patterns:
- 'k8c.io/**'
- 'github.com/kubermatic/**'
- name: kubernetes
patterns:
- 'k8s.io/**'
- '*.k8s.io/**'
# gimps can enforce aliases for certain imports. For example, you can ensure
# that all imports of "k8s.io/api/core/v1" are aliased as "corev1".
# Rules are processed one at a time and the first matching is applied.
#
# There are a few important caveats to note:
#
# * gimps only tokenizes source code and doesn't have deep knowledge of
# the semantics. If a package named "foo" is important and a local
# function call to `foo.DoSomething()` happens, gimps cannot determine
# whether "foo" here is the package or a local variable.
# To prevent accidental rewrites, ensure to never name a variable after
# any imported package (i.e. don't shadow the package name).
# * Rewriting aliases requires to load package dependencies for each
# package that is processed. This requires quite a bit of CPU and can
# can slow down gimps noticibly. If no rules are configured, gimps
# automatically skips loading package dependencies.
aliasRules:
- # a unique name
name: k8s-api
# a Go regexp, ideally anchored (with ^ and $) to prevent mismatches,
# all packages that match will get an alias as configured below.
# The example below matches for example "k8s.io/api/core/v1"
expr: '^k8s.io/api/([a-z0-9-]+)/(v[a-z0-9-]+)$'
# the alias to use for the import; you will most likely always use
# references to groups in the expr ($1 gives the first matched group, etc.).
# Pay attention to not accidentically generate the same alias for
# multiple packages used in the same file (gimps will abort in this case).
# With the example package above, the configuration below yields "corev1".
alias: '$1$2'
- name: k8s-apimachinery
# contains an optional third subpackage, $4 will be empty if no subpackage was found
expr: '^k8s.io/apimachinery/pkg/apis/([a-z0-9-]+)/(v[a-z0-9-]+)(/([a-z0-9-]+))?$'
alias: '$1$2$4'
# paths that match any of the following glob expressions (relative to the
# go.mod) will be ignored; if nothing is configured, the following shows
# the default configuration.
Expand Down Expand Up @@ -146,6 +185,8 @@ only makes sense if you provide exactly one file, otherwise separating the outpu

If you just want to see which files would be fixed, run with `-dry-run`.

Give `-verbose` to show all files being processed instead of just fixed files.

```bash
$ cd ~/myproject
$ gimps .
Expand Down
13 changes: 7 additions & 6 deletions fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"errors"
"fmt"
"go/parser"
"go/token"
"io/fs"
Expand All @@ -11,7 +12,7 @@ import (
"regexp"
"strings"

doublestar "github.com/bmatcuk/doublestar/v4"
doublestarx "github.com/bmatcuk/doublestar/v4"
)

// listFiles takes a filename or directory as its start argument and returns
Expand All @@ -24,7 +25,7 @@ func listFiles(start string, moduleRoot string, skips []string) ([]string, error

info, err := os.Stat(start)
if err != nil {
return nil, err
return nil, fmt.Errorf("invalid file: %v", err)
}

if !info.IsDir() {
Expand All @@ -34,7 +35,7 @@ func listFiles(start string, moduleRoot string, skips []string) ([]string, error
err = filepath.WalkDir(start, func(path string, d fs.DirEntry, err error) error {
relPath, err := filepath.Rel(moduleRoot, path)
if err != nil {
return err
return fmt.Errorf("invalid file: %v", err)
}

if isSkipped(relPath, skips) {
Expand All @@ -60,7 +61,7 @@ func listFiles(start string, moduleRoot string, skips []string) ([]string, error

func isSkipped(relPath string, skips []string) bool {
for _, skip := range skips {
if match, _ := doublestar.Match(skip, relPath); match {
if match, _ := doublestarx.Match(skip, relPath); match {
return true
}
}
Expand Down Expand Up @@ -98,7 +99,7 @@ var (
func isGeneratedFile(filename string) (bool, error) {
content, err := ioutil.ReadFile(filename)
if err != nil {
return false, err
return false, fmt.Errorf("failed to read file: %v", err)
}

return isGeneratedCode(content)
Expand All @@ -109,7 +110,7 @@ func isGeneratedCode(sourceCode []byte) (bool, error) {

file, err := parser.ParseFile(fset, "", sourceCode, parser.ParseComments)
if err != nil {
return false, err
return false, fmt.Errorf("failed to parse code: %v", err)
}

// go through all comments until we reach the package declaration
Expand Down
27 changes: 21 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ func main() {
dryRun := false
showVersion := false
stdout := false
verbose := false

flag.StringVar(&configFile, "config", configFile, "Path to the config file (mandatory).")
flag.BoolVar(&stdout, "stdout", showVersion, "Print output to stdout instead of updating the source file(s).")
flag.BoolVar(&dryRun, "dry-run", dryRun, "Do not update files.")
flag.BoolVar(&verbose, "verbose", verbose, "List all instead of just changed files.")
flag.BoolVar(&showVersion, "version", stdout, "Show version and exit.")
flag.Parse()

Expand Down Expand Up @@ -82,6 +84,11 @@ func main() {
config.ProjectName = modName
}

aliaser, err := gimps.NewAliaser(config.ProjectName, config.AliasRules)
if err != nil {
log.Fatalf("Failed to initialize aliaser: %v", err)
}

for _, input := range inputs {
filenames, err := listFiles(input, modRoot, config.Exclude)
if err != nil {
Expand All @@ -100,21 +107,29 @@ func main() {
}
}

formattedOutput, hasChange, err := gimps.Execute(&config.Config, filename)
relPath, err := filepath.Rel(modRoot, filename)
if err != nil {
log.Fatalf("This should never happen, could not determine relative path: %v", err)
}

if verbose {
log.Printf("> %s", relPath)
}

formattedOutput, hasChange, err := gimps.Execute(&config.Config, filename, aliaser)
if err != nil {
log.Fatalf("Failed to process %q: %v", filename, err)
}

if stdout {
fmt.Print(string(formattedOutput))
} else if hasChange {
relPath, err := filepath.Rel(modRoot, filename)
if err != nil {
log.Fatalf("This should never happen, could not determine relative path: %v", err)
if verbose {
log.Printf("! %s", relPath)
} else {
log.Printf("Fixed %s", relPath)
}

log.Printf("Fixing %s", relPath)

if !dryRun {
if err := ioutil.WriteFile(filename, formattedOutput, 0644); err != nil {
log.Fatalf("Failed to write fixed result to file %q: %v", filename, err)
Expand Down
Loading

0 comments on commit a9f4aa6

Please sign in to comment.