forked from wlan0/jennifer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ImportNames and gennames command
- Loading branch information
Showing
13 changed files
with
276 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# gennames | ||
For large projects, it may be useful to generate an index of package names for commonly used packages. | ||
The index of names can be added to each generated file using `File.ImportNames`. The `gennames` command | ||
is used internally to generate the list of standard library package names. | ||
|
||
### Usage | ||
|
||
``` | ||
Usage of gennames: | ||
-filter string | ||
Regex to filter paths (operates on full path including vendor directory) (default ".*") | ||
-name string | ||
Name of the variable to define (default "PackageNames") | ||
-novendor | ||
Exclude packages in vendor directories | ||
-output string | ||
Output filename to write (default "./package-names.go") | ||
-package string | ||
Package name in generated file (default "main") | ||
-path string | ||
Path to pass to go list command (default "all") | ||
-standard | ||
Use standard library packages | ||
``` | ||
|
||
### Path | ||
Supply a `path` to pass to the `go list` command. You may use the wildcard `/...` to recursively return | ||
packages, but it's worth remembering that vendored packages are not returned by this method unless the | ||
path itself is a vendored path. Use `all` to return all packages in your `GOPATH` (including vendored | ||
packages), however remember this may take some time for a large `GOPATH`. | ||
|
||
### Filter | ||
Supply a regex `filter` to limit the packages that are returned by the `go list` command. The filter | ||
operates on the full vendored package path (e.g. `github.com/foo/bar/vendor/github.com/baz/qux`), however | ||
the package path added to the index is unvendored (e.g. `github.com/baz/qux`). | ||
|
||
### Examples | ||
|
||
``` | ||
gennames -filter "foo|bar" | ||
``` | ||
|
||
Create a file named `package-names.go` with `package main` listing the names of all packages with paths | ||
containing `foo` or `bar`. | ||
|
||
``` | ||
gennames -output "foo/names.go" -package "foo" -path "github.com/foo/bar/vendor/..." | ||
``` | ||
|
||
Create a file named `foo/names.go` with `package foo` listing the names of all packages that are vendored | ||
inside `github.com/foo/bar`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"go/build" | ||
"io" | ||
"os/exec" | ||
"strings" | ||
|
||
"regexp" | ||
|
||
"path/filepath" | ||
|
||
. "github.com/dave/jennifer/jen" | ||
) | ||
|
||
func hints(w io.Writer, pkg, name, goListPath, filter string, standard, novendor bool) error { | ||
|
||
// notest | ||
|
||
file := NewFile(pkg) | ||
|
||
file.HeaderComment("This file is generated - do not edit.") | ||
file.Line() | ||
|
||
packages, err := getPackages(goListPath, filter, standard, novendor) | ||
if err != nil { | ||
return err | ||
} | ||
/* | ||
// <name> contains package name hints | ||
var <name> = map[string]string{ | ||
... | ||
} | ||
*/ | ||
file.Commentf("%s contains package name hints", name) | ||
file.Var().Id(name).Op("=").Map(String()).String().Values(DictFunc(func(d Dict) { | ||
for path, name := range packages { | ||
d[Lit(path)] = Lit(name) | ||
} | ||
})) | ||
|
||
return file.Render(w) | ||
} | ||
|
||
func getPackages(goListPath, filter string, standard, novendor bool) (map[string]string, error) { | ||
|
||
// notest | ||
|
||
r, err := regexp.Compile(filter) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
cmd := exec.Command("go", "list", "-e", "-f", "{{ .Standard }} {{ .ImportPath }} {{ .Name }}", goListPath) | ||
cmd.Env = []string{ | ||
fmt.Sprintf("GOPATH=%s", build.Default.GOPATH), | ||
fmt.Sprintf("GOROOT=%s", build.Default.GOROOT), | ||
} | ||
if standard { | ||
cmd.Dir = filepath.Join(build.Default.GOROOT, "src") | ||
} else { | ||
cmd.Dir = filepath.Join(build.Default.GOPATH, "src") | ||
} | ||
b, err := cmd.Output() | ||
if err != nil { | ||
if x, ok := err.(*exec.ExitError); ok { | ||
return nil, fmt.Errorf("go list command returned an error - %s: %s", err.Error(), string(x.Stderr)) | ||
} | ||
return nil, fmt.Errorf("go list command returned an error: %s", err.Error()) | ||
} | ||
all := strings.Split(strings.TrimSpace(string(b)), "\n") | ||
|
||
packages := map[string]string{} | ||
for _, j := range all { | ||
|
||
parts := strings.Split(j, " ") | ||
|
||
isStandard := parts[0] == "true" | ||
if isStandard != standard { | ||
continue | ||
} | ||
|
||
path := parts[1] | ||
name := parts[2] | ||
|
||
if novendor && hasVendor(path) { | ||
continue | ||
} | ||
|
||
if name == "main" { | ||
continue | ||
} | ||
|
||
if !r.MatchString(path) { | ||
continue | ||
} | ||
|
||
path = unvendorPath(path) | ||
|
||
if packages[path] != "" { | ||
continue | ||
} | ||
|
||
packages[path] = name | ||
} | ||
return packages, nil | ||
} | ||
|
||
func unvendorPath(path string) string { | ||
// notest | ||
i, ok := findVendor(path) | ||
if !ok { | ||
return path | ||
} | ||
return path[i+len("vendor/"):] | ||
} | ||
|
||
// FindVendor looks for the last non-terminating "vendor" path element in the given import path. | ||
// If there isn't one, FindVendor returns ok=false. | ||
// Otherwise, FindVendor returns ok=true and the index of the "vendor". | ||
// Copied from cmd/go/internal/load | ||
func findVendor(path string) (index int, ok bool) { | ||
// notest | ||
// Two cases, depending on internal at start of string or not. | ||
// The order matters: we must return the index of the final element, | ||
// because the final one is where the effective import path starts. | ||
switch { | ||
case strings.Contains(path, "/vendor/"): | ||
return strings.LastIndex(path, "/vendor/") + 1, true | ||
case strings.HasPrefix(path, "vendor/"): | ||
return 0, true | ||
} | ||
return 0, false | ||
} | ||
|
||
func hasVendor(path string) bool { | ||
// notest | ||
_, v := findVendor(path) | ||
return v | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"flag" | ||
"io/ioutil" | ||
"log" | ||
) | ||
|
||
func main() { | ||
// notest | ||
|
||
var out = flag.String("output", "./package-names.go", "Output filename to write") | ||
var pkg = flag.String("package", "main", "Package name in generated file") | ||
var name = flag.String("name", "PackageNames", "Name of the variable to define") | ||
var filter = flag.String("filter", ".*", "Regex to filter paths (operates on full path including vendor directory)") | ||
var standard = flag.Bool("standard", false, "Use standard library packages") | ||
var novendor = flag.Bool("novendor", false, "Exclude packages in vendor directories") | ||
var goListPath = flag.String("path", "all", "Path to pass to go list command") | ||
flag.Parse() | ||
|
||
buf := &bytes.Buffer{} | ||
if err := hints(buf, *pkg, *name, *goListPath, *filter, *standard, *novendor); err != nil { | ||
log.Fatal(err.Error()) | ||
} | ||
if err := ioutil.WriteFile(*out, buf.Bytes(), 0644); err != nil { | ||
log.Fatal(err.Error()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.