Skip to content

Instantly share code, notes, and snippets.

@egonelbre
Last active October 17, 2021 17:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egonelbre/b5afcef2eab7c6072111f5e9ffe46cd3 to your computer and use it in GitHub Desktop.
Save egonelbre/b5afcef2eab7c6072111f5e9ffe46cd3 to your computer and use it in GitHub Desktop.
Tool for rewriting import paths safely.
module rename-imports
go 1.13
require golang.org/x/tools v0.0.0-20191224055732-dd894d0a8a40
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191224055732-dd894d0a8a40 h1:UyP2XDSgSc8ldYCxAK735zQxeH3Gd81sK7Iy7AoaVxk=
golang.org/x/tools v0.0.0-20191224055732-dd894d0a8a40/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
package main
import (
"bytes"
"flag"
"fmt"
"go/parser"
"go/printer"
"go/token"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"golang.org/x/tools/go/ast/astutil"
)
type Rules []Rule
type Rule struct{ From, To string }
func ParseRule(s string) (Rule, error) {
tk := strings.SplitN(s, "=>", 2)
if len(tk) != 2 {
return Rule{}, fmt.Errorf("invalid rule %q", s)
}
return Rule{
From: strings.TrimSpace(tk[0]),
To: strings.TrimSpace(tk[1]),
}, nil
}
func (r Rule) String() string { return r.From + "=>" + r.To }
func (rs *Rules) String() string {
var b strings.Builder
for i, r := range *rs {
if i > 0 {
b.WriteByte(';')
}
b.WriteString(r.String())
}
return b.String()
}
func (rs *Rules) Set(xs string) error {
for _, x := range strings.Split(xs, ";") {
r, err := ParseRule(x)
if err != nil {
return err
}
*rs = append(*rs, r)
}
return nil
}
func main() {
var rules Rules
flag.Var(&rules, "r", "rewrite rule")
flag.Parse()
if len(rules) == 0 {
log.Fatal("rules not specified")
}
err := filepath.Walk(flag.Arg(0), func(path string, info os.FileInfo, err error) error {
if filepath.Base(path) == ".git" {
return filepath.SkipDir
}
if err != nil || info.IsDir() {
return nil
}
if filepath.Ext(path) != ".go" {
return nil
}
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
if err != nil {
return err
}
rewrote := false
for _, rule := range rules {
if astutil.RewriteImport(fset, f, rule.From, rule.To) {
rewrote = true
}
}
if rewrote {
var buf bytes.Buffer
if err := printer.Fprint(&buf, fset, f); err != nil {
return err
}
tokfile := fset.File(f.Pos())
if err := ioutil.WriteFile(tokfile.Name(), buf.Bytes(), 0755); err != nil {
return err
}
log.Println("renamed", tokfile.Name())
}
return nil
})
if err != nil {
log.Fatal(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment