1127 lines
36 KiB
Go
1127 lines
36 KiB
Go
/*
|
|
Copyright 2017 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"fmt"
|
|
"go/build"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"regexp"
|
|
"runtime"
|
|
"sort"
|
|
"strings"
|
|
|
|
bzl "github.com/bazelbuild/buildtools/build"
|
|
"github.com/golang/glog"
|
|
)
|
|
|
|
const (
|
|
vendorPath = "vendor/"
|
|
automanagedTag = "automanaged"
|
|
manualTag = "manual"
|
|
)
|
|
|
|
var (
|
|
root = flag.String("root", ".", "root of go source")
|
|
dryRun = flag.Bool("dry-run", false, "run in dry mode")
|
|
printDiff = flag.Bool("print-diff", false, "print diff to stdout")
|
|
validate = flag.Bool("validate", false, "run in dry mode and exit nonzero if any BUILD files need to be updated")
|
|
cfgPath = flag.String("cfg-path", ".kazelcfg.json", "path to kazel config (relative paths interpreted relative to -repo.")
|
|
iswrote = false
|
|
)
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
flag.Set("alsologtostderr", "true")
|
|
if *root == "" {
|
|
glog.Fatalf("-root argument is required")
|
|
}
|
|
if *validate {
|
|
*dryRun = true
|
|
}
|
|
v, err := newVendorer(*root, *cfgPath, *dryRun)
|
|
if err != nil {
|
|
glog.Fatalf("unable to build vendorer: %v", err)
|
|
}
|
|
if err = os.Chdir(v.root); err != nil {
|
|
glog.Fatalf("cannot chdir into root %q: %v", v.root, err)
|
|
}
|
|
|
|
if v.cfg.ManageGoRules {
|
|
if err = v.walkVendor(); err != nil {
|
|
glog.Fatalf("err walking vendor: %v", err)
|
|
}
|
|
if err = v.walkRepo(); err != nil {
|
|
glog.Fatalf("err walking repo: %v", err)
|
|
}
|
|
}
|
|
if err = v.walkGenerated(); err != nil {
|
|
glog.Fatalf("err walking generated: %v", err)
|
|
}
|
|
if _, err = v.walkSource("."); err != nil {
|
|
glog.Fatalf("err walking source: %v", err)
|
|
}
|
|
written := 0
|
|
if written, err = v.reconcileAllRules(); err != nil {
|
|
glog.Fatalf("err reconciling rules: %v", err)
|
|
}
|
|
if *validate && written > 0 {
|
|
fmt.Fprintf(os.Stderr, "\n%d BUILD files not up-to-date.\n", written)
|
|
os.Exit(1)
|
|
}
|
|
if iswrote {
|
|
fmt.Fprintf(os.Stderr, "\nPlease re-run git-add\n")
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// Vendorer collects context, configuration, and cache while walking the tree.
|
|
type Vendorer struct {
|
|
ctx *build.Context
|
|
icache map[icacheKey]icacheVal
|
|
skippedPaths []*regexp.Regexp
|
|
dryRun bool
|
|
root string
|
|
cfg *Cfg
|
|
newRules map[string][]*bzl.Rule // package path -> list of rules to add or update
|
|
managedAttrs []string
|
|
}
|
|
|
|
func newVendorer(root, cfgPath string, dryRun bool) (*Vendorer, error) {
|
|
absRoot, err := filepath.Abs(root)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get absolute path: %v", err)
|
|
}
|
|
if !filepath.IsAbs(cfgPath) {
|
|
cfgPath = filepath.Join(absRoot, cfgPath)
|
|
}
|
|
cfg, err := ReadCfg(cfgPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
v := Vendorer{
|
|
ctx: context(),
|
|
dryRun: dryRun,
|
|
root: absRoot,
|
|
icache: map[icacheKey]icacheVal{},
|
|
cfg: cfg,
|
|
newRules: make(map[string][]*bzl.Rule),
|
|
managedAttrs: []string{"srcs", "deps", "importpath", "compilers"},
|
|
}
|
|
|
|
for _, sp := range cfg.SkippedPaths {
|
|
r, err := regexp.Compile(sp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
v.skippedPaths = append(v.skippedPaths, r)
|
|
}
|
|
for _, builtinSkip := range []string{
|
|
"^\\.git",
|
|
"^bazel-*",
|
|
} {
|
|
v.skippedPaths = append(v.skippedPaths, regexp.MustCompile(builtinSkip))
|
|
}
|
|
|
|
return &v, nil
|
|
|
|
}
|
|
|
|
type icacheKey struct {
|
|
path, srcDir string
|
|
}
|
|
|
|
type icacheVal struct {
|
|
pkg *build.Package
|
|
err error
|
|
}
|
|
|
|
func (v *Vendorer) importPkg(path string, srcDir string) (*build.Package, error) {
|
|
k := icacheKey{path: path, srcDir: srcDir}
|
|
if val, ok := v.icache[k]; ok {
|
|
return val.pkg, val.err
|
|
}
|
|
|
|
// cache miss
|
|
pkg, err := v.ctx.Import(path, srcDir, build.ImportComment)
|
|
v.icache[k] = icacheVal{pkg: pkg, err: err}
|
|
return pkg, err
|
|
}
|
|
|
|
func writeHeaders(file *bzl.File) {
|
|
pkgRule := bzl.Rule{
|
|
Call: &bzl.CallExpr{
|
|
X: &bzl.LiteralExpr{Token: "package"},
|
|
},
|
|
}
|
|
pkgRule.SetAttr("default_visibility", asExpr([]string{"//visibility:public"}))
|
|
|
|
file.Stmt = append(file.Stmt,
|
|
[]bzl.Expr{
|
|
pkgRule.Call,
|
|
&bzl.CallExpr{
|
|
X: &bzl.LiteralExpr{Token: "load"},
|
|
List: asExpr([]string{
|
|
"@io_bazel_rules_go//go:def.bzl",
|
|
}).(*bzl.ListExpr).List,
|
|
},
|
|
}...,
|
|
)
|
|
}
|
|
|
|
func writeRules(file *bzl.File, rules []*bzl.Rule) {
|
|
for _, rule := range rules {
|
|
file.Stmt = append(file.Stmt, rule.Call)
|
|
}
|
|
}
|
|
|
|
func (v *Vendorer) resolve(ipath string) Label {
|
|
if ipath == v.cfg.GoPrefix {
|
|
return Label{
|
|
tag: "go_default_library",
|
|
}
|
|
} else if strings.HasPrefix(ipath, v.cfg.GoPrefix) {
|
|
return Label{
|
|
pkg: strings.TrimPrefix(ipath, v.cfg.GoPrefix+"/"),
|
|
tag: "go_default_library",
|
|
}
|
|
}
|
|
if v.cfg.VendorMultipleBuildFiles {
|
|
return Label{
|
|
pkg: "vendor/" + ipath,
|
|
tag: "go_default_library",
|
|
}
|
|
}
|
|
return Label{
|
|
pkg: "vendor",
|
|
tag: ipath,
|
|
}
|
|
}
|
|
|
|
func (v *Vendorer) walk(root string, f func(path, ipath string, pkg *build.Package, conffile, proto []string) error) error {
|
|
skipVendor := true
|
|
if root == vendorPath {
|
|
skipVendor = false
|
|
}
|
|
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.IsDir() {
|
|
return nil
|
|
}
|
|
if skipVendor && strings.HasPrefix(path, vendorPath) {
|
|
return filepath.SkipDir
|
|
}
|
|
for _, r := range v.skippedPaths {
|
|
if r.MatchString(path) {
|
|
return filepath.SkipDir
|
|
}
|
|
}
|
|
if _, err = os.Stat(filepath.Join(path, ".skip_kazel")); !os.IsNotExist(err) {
|
|
return filepath.SkipDir
|
|
}
|
|
ipath, err := filepath.Rel(root, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
protofiles := v.getAllProto(path)
|
|
conffiles := v.getAllConf(path)
|
|
pkg, err := v.importPkg(".", filepath.Join(v.root, path))
|
|
if err != nil {
|
|
if _, ok := err.(*build.NoGoError); err != nil && ok {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
return f(path, ipath, pkg, conffiles, protofiles)
|
|
})
|
|
}
|
|
|
|
func (v *Vendorer) walkRepo() error {
|
|
for _, root := range v.cfg.SrcDirs {
|
|
if err := v.walk(root, v.updatePkg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *Vendorer) getAllProto(path string) []string {
|
|
var protofiles []string
|
|
files, err := ioutil.ReadDir(path)
|
|
if err != nil {
|
|
glog.Fatalf("getallproto fail to readdir")
|
|
}
|
|
for _, f := range files {
|
|
if strings.Contains(f.Name(), ".proto") {
|
|
if f.Mode() != os.ModeDir {
|
|
protofiles = append(protofiles, f.Name())
|
|
}
|
|
}
|
|
}
|
|
return protofiles
|
|
}
|
|
|
|
func (v *Vendorer) getAllConf(path string) []string {
|
|
var conffiles []string
|
|
files, err := ioutil.ReadDir(path)
|
|
if err != nil {
|
|
glog.Fatalf("getallconf fail to readdir")
|
|
}
|
|
for _, f := range files {
|
|
if strings.Contains(f.Name(), ".toml") || strings.Contains(f.Name(), ".yaml") {
|
|
if f.Mode() != os.ModeDir {
|
|
conffiles = append(conffiles, f.Name())
|
|
}
|
|
}
|
|
}
|
|
return conffiles
|
|
}
|
|
|
|
func (v *Vendorer) updateSinglePkg(path string) error {
|
|
pkg, err := v.importPkg(".", "./"+path)
|
|
if err != nil {
|
|
if _, ok := err.(*build.NoGoError); err != nil && ok {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
protofiles := v.getAllProto(path)
|
|
conffiles := v.getAllConf(path)
|
|
return v.updatePkg(path, "", pkg, conffiles, protofiles)
|
|
}
|
|
|
|
type ruleType int
|
|
|
|
// The RuleType* constants enumerate the bazel rules supported by this tool.
|
|
const (
|
|
RuleTypeGoBinary ruleType = iota
|
|
RuleTypeGoLibrary
|
|
RuleTypeGoTest
|
|
RuleTypeGoXTest
|
|
RuleTypeCGoGenrule
|
|
RuleTypeFileGroup
|
|
RuleTypeOpenAPILibrary
|
|
RuleTypeProtoLibrary
|
|
RuleTypeGoProtoLibrary
|
|
)
|
|
|
|
// RuleKind converts a value of the RuleType* enum into the BUILD string.
|
|
func (rt ruleType) RuleKind() string {
|
|
switch rt {
|
|
case RuleTypeGoBinary:
|
|
return "go_binary"
|
|
case RuleTypeGoLibrary:
|
|
return "go_library"
|
|
case RuleTypeGoTest:
|
|
return "go_test"
|
|
case RuleTypeGoXTest:
|
|
return "go_test"
|
|
case RuleTypeCGoGenrule:
|
|
return "cgo_genrule"
|
|
case RuleTypeFileGroup:
|
|
return "filegroup"
|
|
case RuleTypeOpenAPILibrary:
|
|
return "openapi_library"
|
|
case RuleTypeProtoLibrary:
|
|
return "proto_library"
|
|
case RuleTypeGoProtoLibrary:
|
|
return "go_proto_library"
|
|
}
|
|
panic("unreachable")
|
|
}
|
|
|
|
// NamerFunc is a function that returns the appropriate name for the rule for the provided RuleType.
|
|
type NamerFunc func(ruleType) string
|
|
|
|
func (v *Vendorer) updatePkg(path, _ string, pkg *build.Package, conffile, protofile []string) error {
|
|
|
|
srcNameMap := func(srcs ...[]string) *bzl.ListExpr {
|
|
return asExpr(merge(srcs...)).(*bzl.ListExpr)
|
|
}
|
|
goFileNotProto := []string{}
|
|
for _, v := range pkg.GoFiles {
|
|
if !strings.Contains(v, ".pb.go") {
|
|
goFileNotProto = append(goFileNotProto, v)
|
|
}
|
|
}
|
|
srcs := srcNameMap(goFileNotProto, pkg.SFiles)
|
|
cgoSrcs := srcNameMap(pkg.CgoFiles, pkg.CFiles, pkg.CXXFiles, pkg.HFiles)
|
|
testSrcs := srcNameMap(pkg.TestGoFiles)
|
|
xtestSrcs := srcNameMap(pkg.XTestGoFiles)
|
|
pf := protoFileInfo(v.cfg.GoPrefix, path, protofile)
|
|
|
|
v.addRules(path, v.emit(path, srcs, cgoSrcs, testSrcs, xtestSrcs, pf, pkg, conffile, func(rt ruleType) string {
|
|
switch rt {
|
|
case RuleTypeGoBinary:
|
|
return filepath.Base(pkg.Dir)
|
|
case RuleTypeGoLibrary:
|
|
return "go_default_library"
|
|
case RuleTypeGoTest:
|
|
return "go_default_test"
|
|
case RuleTypeGoXTest:
|
|
return "go_default_xtest"
|
|
case RuleTypeCGoGenrule:
|
|
return "cgo_codegen"
|
|
case RuleTypeProtoLibrary:
|
|
return pf.packageName + "_proto"
|
|
case RuleTypeGoProtoLibrary:
|
|
return pf.packageName + "_go_proto"
|
|
}
|
|
panic("unreachable")
|
|
}))
|
|
|
|
return nil
|
|
}
|
|
|
|
func (v *Vendorer) emit(path string, srcs, cgoSrcs, testSrcs, xtestSrcs *bzl.ListExpr, protoSrcs ProtoInfo, pkg *build.Package, conffile []string, namer NamerFunc) []*bzl.Rule {
|
|
var goLibAttrs = make(Attrs)
|
|
var rules []*bzl.Rule
|
|
embedlist := []string{}
|
|
if len(protoSrcs.src) > 0 {
|
|
protoRuleAttrs := make(Attrs)
|
|
|
|
protoRuleAttrs.SetList("srcs", asExpr(protoSrcs.src).(*bzl.ListExpr))
|
|
protoRuleAttrs.SetList("deps", asExpr(protoMap(path, protoSrcs.imports)).(*bzl.ListExpr))
|
|
|
|
rules = append(rules, newRule(RuleTypeProtoLibrary, namer, protoRuleAttrs))
|
|
goProtoRuleAttrs := make(Attrs)
|
|
if protoSrcs.isGogo {
|
|
if protoSrcs.hasServices {
|
|
goProtoRuleAttrs.SetList("compilers", asExpr([]string{"@io_bazel_rules_go//proto:gogofast_grpc"}).(*bzl.ListExpr))
|
|
} else {
|
|
goProtoRuleAttrs.SetList("compilers", asExpr([]string{"@io_bazel_rules_go//proto:gogofast_proto"}).(*bzl.ListExpr))
|
|
}
|
|
} else {
|
|
if protoSrcs.hasServices {
|
|
goProtoRuleAttrs.SetList("compilers", asExpr([]string{"@io_bazel_rules_go//proto:go_grpc"}).(*bzl.ListExpr))
|
|
} else {
|
|
goProtoRuleAttrs.SetList("compilers", asExpr([]string{"@io_bazel_rules_go//proto:go_proto"}).(*bzl.ListExpr))
|
|
}
|
|
}
|
|
|
|
protovalue := ":" + protoSrcs.packageName + "_proto"
|
|
goProtoRuleAttrs.Set("proto", asExpr(protovalue))
|
|
goProtoRuleAttrs.Set("importpath", asExpr(protoSrcs.importPath))
|
|
goProtoRuleAttrs.SetList("deps", asExpr(goProtoMap(path, protoSrcs.imports)).(*bzl.ListExpr))
|
|
rules = append(rules, newRule(RuleTypeGoProtoLibrary, namer, goProtoRuleAttrs))
|
|
|
|
embedlist = append(embedlist, protoSrcs.packageName+"_go_proto")
|
|
}
|
|
|
|
deps := v.extractDeps(depMapping(pkg.Imports))
|
|
if len(srcs.List) >= 0 {
|
|
if len(cgoSrcs.List) != 0 {
|
|
goLibAttrs.SetList("srcs", &bzl.ListExpr{List: addExpr(srcs.List, cgoSrcs.List)})
|
|
goLibAttrs.SetList("clinkopts", asExpr([]string{"-lz", "-lm", "-lpthread", "-ldl"}).(*bzl.ListExpr))
|
|
goLibAttrs.Set("cgo", &bzl.LiteralExpr{Token: "True"})
|
|
} else {
|
|
goLibAttrs.Set("srcs", srcs)
|
|
}
|
|
if strings.Contains(path, "vendor") {
|
|
goLibAttrs.Set("importpath", asExpr(strings.Replace(path, "vendor/", "", -1)))
|
|
} else {
|
|
goLibAttrs.Set("importpath", asExpr(filepath.Join(v.cfg.GoPrefix, path)))
|
|
}
|
|
goLibAttrs.SetList("visibility", asExpr([]string{"//visibility:public"}).(*bzl.ListExpr))
|
|
|
|
} else if len(cgoSrcs.List) == 0 {
|
|
return nil
|
|
}
|
|
if len(conffile) > 0 {
|
|
goLibAttrs.SetList("data", asExpr(conffile).(*bzl.ListExpr))
|
|
}
|
|
if len(deps.List) > 0 {
|
|
goLibAttrs.SetList("deps", deps)
|
|
}
|
|
|
|
if pkg.IsCommand() {
|
|
rules = append(rules, newRule(RuleTypeGoBinary, namer, map[string]bzl.Expr{
|
|
"embed": asExpr([]string{":" + namer(RuleTypeGoLibrary)}),
|
|
}))
|
|
}
|
|
|
|
addGoDefaultLibrary := len(cgoSrcs.List) > 0 || len(srcs.List) > 0 || len(protoSrcs.src) == 1 || len(conffile) > 0
|
|
|
|
if len(testSrcs.List) != 0 {
|
|
testRuleAttrs := make(Attrs)
|
|
|
|
testRuleAttrs.SetList("srcs", testSrcs)
|
|
testRuleAttrs.SetList("deps", v.extractDeps(depMapping(pkg.TestImports)))
|
|
//testRuleAttrs.Set("rundir", asExpr("."))
|
|
//testRuleAttrs.Set("importmap", asExpr(filepath.Join(v.cfg.GoPrefix, path)))
|
|
//testRuleAttrs.Set("importpath", asExpr(filepath.Join(v.cfg.GoPrefix, path)))
|
|
if addGoDefaultLibrary {
|
|
testRuleAttrs.SetList("embed", asExpr([]string{":" + namer(RuleTypeGoLibrary)}).(*bzl.ListExpr))
|
|
|
|
}
|
|
rules = append(rules, newRule(RuleTypeGoTest, namer, testRuleAttrs))
|
|
}
|
|
if len(embedlist) > 0 {
|
|
goLibAttrs.SetList("embed", asExpr(embedlist).(*bzl.ListExpr))
|
|
}
|
|
if addGoDefaultLibrary || len(embedlist) > 0 {
|
|
rules = append(rules, newRule(RuleTypeGoLibrary, namer, goLibAttrs))
|
|
}
|
|
|
|
if len(xtestSrcs.List) != 0 {
|
|
xtestRuleAttrs := make(Attrs)
|
|
|
|
xtestRuleAttrs.SetList("srcs", xtestSrcs)
|
|
xtestRuleAttrs.SetList("deps", v.extractDeps(pkg.XTestImports))
|
|
|
|
rules = append(rules, newRule(RuleTypeGoXTest, namer, xtestRuleAttrs))
|
|
}
|
|
|
|
return rules
|
|
}
|
|
|
|
func (v *Vendorer) addRules(pkgPath string, rules []*bzl.Rule) {
|
|
cleanPath := filepath.Clean(pkgPath)
|
|
v.newRules[cleanPath] = append(v.newRules[cleanPath], rules...)
|
|
}
|
|
|
|
func (v *Vendorer) walkVendor() error {
|
|
var rules []*bzl.Rule
|
|
updateFunc := func(path, ipath string, pkg *build.Package, conffile, proto []string) error {
|
|
srcNameMap := func(srcs ...[]string) *bzl.ListExpr {
|
|
return asExpr(
|
|
apply(
|
|
merge(srcs...),
|
|
mapper(func(s string) string {
|
|
return strings.TrimPrefix(filepath.Join(path, s), "vendor/")
|
|
}),
|
|
),
|
|
).(*bzl.ListExpr)
|
|
}
|
|
|
|
srcs := srcNameMap(pkg.GoFiles, pkg.SFiles)
|
|
cgoSrcs := srcNameMap(pkg.CgoFiles, pkg.CFiles, pkg.CXXFiles, pkg.HFiles)
|
|
testSrcs := srcNameMap(pkg.TestGoFiles)
|
|
xtestSrcs := srcNameMap(pkg.XTestGoFiles)
|
|
pf := protoFileInfo(v.cfg.GoPrefix, path, proto)
|
|
tagBase := v.resolve(ipath).tag
|
|
|
|
rules = append(rules, v.emit(path, srcs, cgoSrcs, testSrcs, xtestSrcs, pf, pkg, []string{}, func(rt ruleType) string {
|
|
switch rt {
|
|
case RuleTypeGoBinary:
|
|
return tagBase + "_bin"
|
|
case RuleTypeGoLibrary:
|
|
return tagBase
|
|
case RuleTypeGoTest:
|
|
return tagBase + "_test"
|
|
case RuleTypeGoXTest:
|
|
return tagBase + "_xtest"
|
|
case RuleTypeCGoGenrule:
|
|
return tagBase + "_cgo"
|
|
case RuleTypeProtoLibrary:
|
|
return pf.packageName + "_proto"
|
|
case RuleTypeGoProtoLibrary:
|
|
return pf.packageName + "_go_proto"
|
|
}
|
|
panic("unreachable")
|
|
})...)
|
|
|
|
return nil
|
|
}
|
|
if v.cfg.VendorMultipleBuildFiles {
|
|
updateFunc = v.updatePkg
|
|
}
|
|
if err := v.walk(vendorPath, updateFunc); err != nil {
|
|
return err
|
|
}
|
|
v.addRules(vendorPath, rules)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (v *Vendorer) extractDeps(deps []string) *bzl.ListExpr {
|
|
return asExpr(
|
|
depMapping(apply(
|
|
merge(deps),
|
|
filterer(func(s string) bool {
|
|
pkg, err := v.importPkg(s, v.root)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), `cannot find package "C"`) ||
|
|
// added in go1.7
|
|
strings.Contains(err.Error(), `cannot find package "context"`) ||
|
|
strings.Contains(err.Error(), `cannot find package "net/http/httptrace"`) {
|
|
return false
|
|
}
|
|
fmt.Fprintf(os.Stderr, "extract err: %v\n", err)
|
|
return false
|
|
}
|
|
if pkg.Goroot {
|
|
return false
|
|
}
|
|
return true
|
|
}),
|
|
mapper(func(s string) string {
|
|
return v.resolve(s).String()
|
|
}),
|
|
)),
|
|
).(*bzl.ListExpr)
|
|
}
|
|
|
|
func (v *Vendorer) reconcileAllRules() (int, error) {
|
|
var paths []string
|
|
for path := range v.newRules {
|
|
paths = append(paths, path)
|
|
}
|
|
sort.Strings(paths)
|
|
written := 0
|
|
for _, path := range paths {
|
|
w, err := ReconcileRules(path, v.newRules[path], v.managedAttrs, v.dryRun, v.cfg.ManageGoRules)
|
|
if w {
|
|
written++
|
|
}
|
|
if err != nil {
|
|
return written, err
|
|
}
|
|
}
|
|
return written, nil
|
|
}
|
|
|
|
// Attrs collects the attributes for a rule.
|
|
type Attrs map[string]bzl.Expr
|
|
|
|
// Set sets the named attribute to the provided bazel expression.
|
|
func (a Attrs) Set(name string, expr bzl.Expr) {
|
|
a[name] = expr
|
|
}
|
|
|
|
// SetList sets the named attribute to the provided bazel expression list.
|
|
func (a Attrs) SetList(name string, expr *bzl.ListExpr) {
|
|
if len(expr.List) == 0 {
|
|
return
|
|
}
|
|
a[name] = expr
|
|
}
|
|
|
|
// Label defines a bazel label.
|
|
type Label struct {
|
|
pkg, tag string
|
|
}
|
|
|
|
func (l Label) String() string {
|
|
return fmt.Sprintf("//%v:%v", l.pkg, l.tag)
|
|
}
|
|
|
|
func asExpr(e interface{}) bzl.Expr {
|
|
rv := reflect.ValueOf(e)
|
|
switch rv.Kind() {
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
|
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
return &bzl.LiteralExpr{Token: fmt.Sprintf("%d", e)}
|
|
case reflect.Float32, reflect.Float64:
|
|
return &bzl.LiteralExpr{Token: fmt.Sprintf("%f", e)}
|
|
case reflect.String:
|
|
return &bzl.StringExpr{Value: e.(string)}
|
|
case reflect.Slice, reflect.Array:
|
|
var list []bzl.Expr
|
|
for i := 0; i < rv.Len(); i++ {
|
|
list = append(list, asExpr(rv.Index(i).Interface()))
|
|
}
|
|
return &bzl.ListExpr{List: list}
|
|
default:
|
|
glog.Fatalf("Uh oh")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
type sed func(s []string) []string
|
|
|
|
func mapString(in []string, f func(string) string) []string {
|
|
var out []string
|
|
for _, s := range in {
|
|
out = append(out, f(s))
|
|
}
|
|
return out
|
|
}
|
|
|
|
func mapper(f func(string) string) sed {
|
|
return func(in []string) []string {
|
|
return mapString(in, f)
|
|
}
|
|
}
|
|
|
|
func filterString(in []string, f func(string) bool) []string {
|
|
var out []string
|
|
for _, s := range in {
|
|
if f(s) {
|
|
out = append(out, s)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func filterer(f func(string) bool) sed {
|
|
return func(in []string) []string {
|
|
return filterString(in, f)
|
|
}
|
|
}
|
|
|
|
func apply(stream []string, seds ...sed) []string {
|
|
for _, sed := range seds {
|
|
stream = sed(stream)
|
|
}
|
|
return stream
|
|
}
|
|
|
|
func merge(streams ...[]string) []string {
|
|
var out []string
|
|
for _, stream := range streams {
|
|
out = append(out, stream...)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func newRule(rt ruleType, namer NamerFunc, attrs map[string]bzl.Expr) *bzl.Rule {
|
|
rule := &bzl.Rule{
|
|
Call: &bzl.CallExpr{
|
|
X: &bzl.LiteralExpr{Token: rt.RuleKind()},
|
|
},
|
|
}
|
|
rule.SetAttr("name", asExpr(namer(rt)))
|
|
for k, v := range attrs {
|
|
rule.SetAttr(k, v)
|
|
}
|
|
rule.SetAttr("tags", asExpr([]string{automanagedTag}))
|
|
return rule
|
|
}
|
|
|
|
// findBuildFile determines the name of a preexisting BUILD file, returning
|
|
// a default if no such file exists.
|
|
func findBuildFile(pkgPath string) (bool, string) {
|
|
options := []string{"BUILD.bazel", "BUILD"}
|
|
for _, b := range options {
|
|
path := filepath.Join(pkgPath, b)
|
|
info, err := os.Stat(path)
|
|
if err == nil && !info.IsDir() {
|
|
return true, path
|
|
}
|
|
}
|
|
return false, filepath.Join(pkgPath, "BUILD")
|
|
}
|
|
|
|
// ReconcileRules reconciles, simplifies, and writes the rules for the specified package, adding
|
|
// additional dependency rules as needed.
|
|
func ReconcileRules(pkgPath string, rules []*bzl.Rule, managedAttrs []string, dryRun bool, manageGoRules bool) (bool, error) {
|
|
goProtoLibrary := []string{}
|
|
_, path := findBuildFile(pkgPath)
|
|
info, err := os.Stat(path)
|
|
if err != nil && os.IsNotExist(err) {
|
|
f := &bzl.File{}
|
|
writeHeaders(f)
|
|
if manageGoRules {
|
|
reconcileLoad(path, f, rules)
|
|
}
|
|
writeRules(f, rules)
|
|
return writeFile(path, f, false, dryRun)
|
|
} else if err != nil {
|
|
return false, err
|
|
}
|
|
if info.IsDir() {
|
|
return false, fmt.Errorf("%q cannot be a directory", path)
|
|
}
|
|
b, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
f, err := bzl.Parse(path, b)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
oldRules := make(map[string]*bzl.Rule)
|
|
for _, r := range f.Rules("") {
|
|
if r.Kind() == "proto_library" {
|
|
if r.Attr("tags") == nil {
|
|
r.SetAttr("tags", asExpr([]string{automanagedTag}))
|
|
}
|
|
}
|
|
if r.Kind() == "go_proto_library" {
|
|
if r.Attr("tags") == nil {
|
|
r.SetAttr("tags", asExpr([]string{automanagedTag}))
|
|
}
|
|
goProtoLibrary = append(goProtoLibrary, ":"+r.Name())
|
|
}
|
|
if (r.Kind() == "go_library" || r.Kind() == "go_test") && (len(rules) == 3 || len(rules) == 4) && !strings.Contains(pkgPath, "vendor") {
|
|
if r.Attr("tags") == nil {
|
|
r.SetAttr("tags", asExpr([]string{automanagedTag}))
|
|
}
|
|
}
|
|
if r.Kind() == "go_library" || r.Kind() == "go_test" {
|
|
if listExpr, ok := r.Attr("deps").(*bzl.ListExpr); ok {
|
|
olddeps := []string{}
|
|
for _, v := range listExpr.List {
|
|
olddeps = append(olddeps, v.(*bzl.StringExpr).Value)
|
|
}
|
|
newdeps := depMapping(olddeps)
|
|
r.SetAttr("deps", asExpr(newdeps))
|
|
}
|
|
}
|
|
oldRules[r.Name()] = r
|
|
}
|
|
if len(goProtoLibrary) > 0 && goProtoLibrary != nil {
|
|
r, ok := oldRules["go_default_library"]
|
|
if ok {
|
|
r.SetAttr("embed", asExpr(goProtoLibrary))
|
|
oldRules["go_default_library"] = r
|
|
}
|
|
}
|
|
|
|
for _, r := range rules {
|
|
o, ok := oldRules[r.Name()]
|
|
if !ok {
|
|
f.Stmt = append(f.Stmt, r.Call)
|
|
continue
|
|
}
|
|
if !RuleIsManaged(o, manageGoRules) {
|
|
continue
|
|
}
|
|
reconcileAttr := func(o, n *bzl.Rule, name string) {
|
|
if e := n.Attr(name); e != nil {
|
|
o.SetAttr(name, e)
|
|
} else {
|
|
o.DelAttr(name)
|
|
}
|
|
}
|
|
for _, attr := range managedAttrs {
|
|
reconcileAttr(o, r, attr)
|
|
}
|
|
delete(oldRules, r.Name())
|
|
}
|
|
|
|
for _, r := range oldRules {
|
|
if !RuleIsManaged(r, manageGoRules) {
|
|
continue
|
|
}
|
|
f.DelRules(r.Kind(), r.Name())
|
|
}
|
|
if manageGoRules {
|
|
reconcileLoad(path, f, f.Rules(""))
|
|
}
|
|
|
|
return writeFile(path, f, true, dryRun)
|
|
}
|
|
|
|
func reconcileLoad(path string, f *bzl.File, rules []*bzl.Rule) {
|
|
|
|
contains := func(s []string, e string) bool {
|
|
for _, a := range s {
|
|
if a == e {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
usedRuleKindsMap := map[string][]string{}
|
|
for _, r := range rules {
|
|
// Select only the Go rules we need to import, excluding builtins like filegroup.
|
|
// TODO: make less fragile
|
|
switch r.Kind() {
|
|
case "go_prefix", "go_library", "go_binary", "go_test", "cgo_genrule", "cgo_library":
|
|
if !contains(usedRuleKindsMap["@io_bazel_rules_go//go:def.bzl"], r.Kind()) {
|
|
usedRuleKindsMap["@io_bazel_rules_go//go:def.bzl"] = append(usedRuleKindsMap["@io_bazel_rules_go//go:def.bzl"], r.Kind())
|
|
}
|
|
case "gazelle":
|
|
if !contains(usedRuleKindsMap["@bazel_gazelle//:def.bzl"], r.Kind()) {
|
|
usedRuleKindsMap["@bazel_gazelle//:def.bzl"] = append(usedRuleKindsMap["@bazel_gazelle//:def.bzl"], r.Kind())
|
|
}
|
|
case "go_proto_library":
|
|
if !contains(usedRuleKindsMap["@io_bazel_rules_go//proto:def.bzl"], r.Kind()) {
|
|
usedRuleKindsMap["@io_bazel_rules_go//proto:def.bzl"] = append(usedRuleKindsMap["@io_bazel_rules_go//proto:def.bzl"], r.Kind())
|
|
}
|
|
}
|
|
}
|
|
usedRuleKindsList := []string{}
|
|
for k := range usedRuleKindsMap {
|
|
usedRuleKindsList = append(usedRuleKindsList, k)
|
|
}
|
|
sort.Strings(usedRuleKindsList)
|
|
|
|
for _, r := range f.Rules("load") {
|
|
args := bzl.Strings(&bzl.ListExpr{List: r.Call.List})
|
|
if len(args) == 0 {
|
|
continue
|
|
}
|
|
if !contains(usedRuleKindsList, args[0]) {
|
|
continue
|
|
}
|
|
if len(usedRuleKindsMap[args[0]]) == 0 {
|
|
if r.Name() != "" {
|
|
f.DelRules(r.Kind(), r.Name())
|
|
}
|
|
continue
|
|
}
|
|
r.Call.List = asExpr(append(
|
|
[]string{args[0]}, usedRuleKindsMap[args[0]]...,
|
|
)).(*bzl.ListExpr).List
|
|
delete(usedRuleKindsMap, args[0])
|
|
}
|
|
for k, v := range usedRuleKindsMap {
|
|
rule :=
|
|
&bzl.CallExpr{
|
|
X: &bzl.LiteralExpr{Token: "load"},
|
|
}
|
|
rule.List = asExpr(append(
|
|
[]string{k}, v...,
|
|
)).(*bzl.ListExpr).List
|
|
f.Stmt = append([]bzl.Expr{rule}, f.Stmt...)
|
|
}
|
|
}
|
|
|
|
// RuleIsManaged returns whether the provided rule is managed by this tool,
|
|
// based on the tags set on the rule.
|
|
func RuleIsManaged(r *bzl.Rule, manageGoRules bool) bool {
|
|
var automanaged bool
|
|
if !manageGoRules && (strings.HasPrefix(r.Kind(), "go_") || strings.HasPrefix(r.Kind(), "cgo_")) {
|
|
return false
|
|
}
|
|
for _, tag := range r.AttrStrings("tags") {
|
|
if tag == automanagedTag {
|
|
automanaged = true
|
|
break
|
|
}
|
|
}
|
|
return automanaged
|
|
}
|
|
|
|
func writeFile(path string, f *bzl.File, exists, dryRun bool) (bool, error) {
|
|
var info bzl.RewriteInfo
|
|
bzl.Rewrite(f, &info)
|
|
out := bzl.Format(f)
|
|
//if strings.Contains(path, "vendor") {
|
|
// return false, nil
|
|
//}
|
|
if exists {
|
|
orig, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if bytes.Compare(orig, out) == 0 {
|
|
return false, nil
|
|
}
|
|
if *printDiff {
|
|
Diff(orig, out)
|
|
}
|
|
}
|
|
if dryRun {
|
|
fmt.Fprintf(os.Stderr, "DRY-RUN: wrote %q\n", path)
|
|
return true, nil
|
|
}
|
|
werr := ioutil.WriteFile(path, out, 0644)
|
|
if werr == nil {
|
|
fmt.Fprintf(os.Stderr, "wrote %q\n", path)
|
|
iswrote = true
|
|
}
|
|
return werr == nil, werr
|
|
}
|
|
|
|
func context() *build.Context {
|
|
return &build.Context{
|
|
GOARCH: "amd64",
|
|
GOOS: "linux",
|
|
GOROOT: build.Default.GOROOT,
|
|
GOPATH: build.Default.GOPATH,
|
|
ReleaseTags: []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8", "go1.9", "go1.10"},
|
|
Compiler: runtime.Compiler,
|
|
CgoEnabled: true,
|
|
}
|
|
}
|
|
|
|
func walk(root string, walkFn filepath.WalkFunc) error {
|
|
return nil
|
|
}
|
|
|
|
func depMapping(dep []string) []string {
|
|
result := []string{}
|
|
mapping := map[string]string{
|
|
"//vendor/github.com/golang/protobuf/proto:go_default_library": "@com_github_golang_protobuf//proto:go_default_library",
|
|
"//vendor/github.com/golang/protobuf/ptypes/any:go_default_library": "@io_bazel_rules_go//proto/wkt:any_go_proto",
|
|
"//vendor/github.com/golang/protobuf/jsonpb:go_default_library": "@com_github_golang_protobuf//jsonpb:go_default_library",
|
|
"//vendor/github.com/golang/protobuf/protoc-gen-go/plugin:go_default_library": "@com_github_golang_protobuf//protoc-gen-go/plugin:go_default_library",
|
|
"//vendor/github.com/golang/protobuf/protoc-gen-go/descriptor:go_default_library": "@com_github_golang_protobuf//protoc-gen-go/descriptor:go_default_library",
|
|
"//vendor/github.com/golang/protobuf/ptypes:go_default_library": "@com_github_golang_protobuf//ptypes:go_default_library_gen",
|
|
"//vendor/github.com/golang/protobuf/ptypes/empty:go_default_library": "@io_bazel_rules_go//proto/wkt:empty_go_proto",
|
|
|
|
"//vendor/github.com/gogo/protobuf/gogoproto:go_default_library": "@com_github_gogo_protobuf//gogoproto:go_default_library",
|
|
"//vendor/github.com/gogo/protobuf/proto:go_default_library": "@com_github_gogo_protobuf//proto:go_default_library",
|
|
"//vendor/github.com/gogo/protobuf/protoc-gen-gogo:go_default_library": "@com_github_gogo_protobuf//protoc-gen-gogo:go_default_library",
|
|
"//vendor/github.com/gogo/protobuf/sortkeys:go_default_library": "@com_github_gogo_protobuf//sortkeys:go_default_library",
|
|
"//vendor/github.com/gogo/protobuf/types:go_default_library": "@com_github_gogo_protobuf//types:go_default_library",
|
|
"//vendor/github.com/gogo/protobuf/jsonpb:go_default_library": "@com_github_gogo_protobuf//jsonpb:go_default_library",
|
|
|
|
"//vendor/google.golang.org/grpc/codes:go_default_library": "@org_golang_google_grpc//codes:go_default_library",
|
|
"//vendor/google.golang.org/grpc/credentials:go_default_library": "@org_golang_google_grpc//credentials:go_default_library",
|
|
"//vendor/google.golang.org/grpc/metadata:go_default_library": "@org_golang_google_grpc//metadata:go_default_library",
|
|
"//vendor/google.golang.org/grpc/peer:go_default_library": "@org_golang_google_grpc//peer:go_default_library",
|
|
"//vendor/google.golang.org/grpc/status:go_default_library": "@org_golang_google_grpc//status:go_default_library",
|
|
"//vendor/google.golang.org/grpc/resolver:go_default_library": "@org_golang_google_grpc//resolver:go_default_library",
|
|
"//vendor/google.golang.org/grpc/balancer:go_default_library": "@org_golang_google_grpc//balancer:go_default_library",
|
|
"//vendor/google.golang.org/grpc/balancer/base:go_default_library": "@org_golang_google_grpc//balancer/base:go_default_library",
|
|
"//vendor/google.golang.org/grpc/connectivity:go_default_library": "@org_golang_google_grpc//connectivity:go_default_library",
|
|
"//vendor/google.golang.org/grpc:go_default_library": "@org_golang_google_grpc//:go_default_library",
|
|
"//vendor/google.golang.org/grpc/grpclog:go_default_library": "@org_golang_google_grpc//grpclog:go_default_library",
|
|
"//vendor/google.golang.org/grpc/interop:go_default_library": "@org_golang_google_grpc//interop:go_default_library",
|
|
"//vendor/google.golang.org/grpc/interop/grpc_testing:go_default_library": "@org_golang_google_grpc//interop/grpc_testing:go_default_library",
|
|
"//vendor/google.golang.org/grpc/stress/grpc_testing:go_default_library": "@org_golang_google_grpc//stress/grpc_testing:go_default_library",
|
|
"//vendor/google.golang.org/grpc/reflection:go_default_library": "@org_golang_google_grpc//reflection:go_default_library",
|
|
"//vendor/google.golang.org/grpc/testdata:go_default_library": "@org_golang_google_grpc//testdata:go_default_library",
|
|
"//vendor/google.golang.org/grpc/interop/server:go_default_library": "@org_golang_google_grpc//interop/server:go_default_library",
|
|
"//vendor/google.golang.org/grpc/interop/client:go_default_library": "@org_golang_google_grpc//interop/client:go_default_library",
|
|
"//vendor/google.golang.org/grpc/interop/http2:go_default_library": "@org_golang_google_grpc//interop/http2:go_default_library",
|
|
"//vendor/google.golang.org/grpc/stress/client:go_default_library": "@org_golang_google_grpc//stress/client:go_default_library",
|
|
"//vendor/google.golang.org/grpc/keepalive:go_default_library": "@org_golang_google_grpc//keepalive:go_default_library",
|
|
"//vendor/google.golang.org/grpc/encoding/gzip:go_default_library": "@org_golang_google_grpc//encoding/gzip:go_default_library",
|
|
"//vendor/google.golang.org/grpc/stats:go_default_library": "@org_golang_google_grpc//stats:go_default_library",
|
|
"//vendor/google.golang.org/grpc/tap:go_default_library": "@org_golang_google_grpc//tap:go_default_library",
|
|
"//vendor/google.golang.org/grpc/encoding:go_default_library": "@org_golang_google_grpc//encoding:go_default_library",
|
|
|
|
"//vendor/google.golang.org/genproto/googleapis/rpc/status:go_default_library": "@org_golang_google_genproto//googleapis/rpc/status:go_default_library",
|
|
|
|
"//vendor/golang.org/x/net/context:go_default_library": "@org_golang_x_net//context:go_default_library",
|
|
"//vendor/golang.org/x/net/http2:go_default_library": "@org_golang_x_net//http2:go_default_library",
|
|
"//vendor/golang.org/x/net/proxy:go_default_library": "@org_golang_x_net//proxy:go_default_library",
|
|
"//vendor/golang.org/x/net/html:go_default_library": "@org_golang_x_net//html:go_default_library",
|
|
"//vendor/golang.org/x/net/html/atom:go_default_library": "@org_golang_x_net//html/atom:go_default_library",
|
|
"//vendor/golang.org/x/net/http2/hpack:go_default_library": "@org_golang_x_net//http2/hpack:go_default_library",
|
|
"//vendor/golang.org/x/net/context/ctxhttp:go_default_library": "@org_golang_x_net//context/ctxhttp:go_default_library",
|
|
"//vendor/golang.org/x/net/ipv4:go_default_library": "@org_golang_x_net//ipv4:go_default_library",
|
|
"//vendor/golang.org/x/net/ipv6:go_default_library": "@org_golang_x_net//ipv6:go_default_library",
|
|
"//vendor/golang.org/x/net/trace:go_default_library": "@org_golang_x_net//trace:go_default_library",
|
|
"//vendor/golang.org/x/net/websocket:go_default_library": "@org_golang_x_net//websocket:go_default_library",
|
|
}
|
|
for _, v := range dep {
|
|
mapdep, ok := mapping[v]
|
|
if ok {
|
|
result = append(result, mapdep)
|
|
} else {
|
|
result = append(result, v)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func protoMap(path string, dep []string) []string {
|
|
result := []string{}
|
|
|
|
removeMap := map[string]struct{}{
|
|
"//library/time:go_default_library": struct{}{},
|
|
}
|
|
mapping := map[string]string{
|
|
"github.com/gogo/protobuf/gogoproto/gogo.proto": "@gogo_special_proto//github.com/gogo/protobuf/gogoproto",
|
|
"google/protobuf/any.proto": "@com_google_protobuf//:any_proto",
|
|
"google/api/annotations.proto": "@go_googleapis//google/api:annotations_proto",
|
|
"google/protobuf/descriptor.proto": "@com_google_protobuf//:descriptor_proto",
|
|
"google/protobuf/empty.proto": "@com_google_protobuf//:empty_proto",
|
|
}
|
|
for _, v := range dep {
|
|
if _, ok := removeMap[v]; ok {
|
|
continue
|
|
}
|
|
mapdep, ok := mapping[v]
|
|
if ok {
|
|
result = append(result, mapdep)
|
|
} else {
|
|
if custom := customgoproto(path, v); custom != "" {
|
|
result = append(result, custom)
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func goProtoMap(path string, dep []string) []string {
|
|
result := []string{}
|
|
mapping := map[string]string{
|
|
// gogo
|
|
"github.com/gogo/protobuf/gogoproto/gogo.proto": "@com_github_gogo_protobuf//gogoproto:go_default_library",
|
|
// googleapis
|
|
"google/api/annotations.proto": "@go_googleapis//google/api:annotations_go_proto",
|
|
"google/rpc/errdetails.proto": "@go_googleapis//google/rpc:errdetails_go_proto",
|
|
"google/rpc/code.proto": "@go_googleapis//google/rpc:code_go_proto",
|
|
"google/rpc/status.proto": "@go_googleapis//google/rpc:status_go_proto",
|
|
// golang protobuf
|
|
"@com_github_golang_protobuf//ptypes/any:go_default_library": "@io_bazel_rules_go//proto/wkt:any_go_proto",
|
|
// google protobuf
|
|
"google/protobuf/wrappers.proto": "@io_bazel_rules_go//proto/wkt:wrappers_go_proto",
|
|
"google/protobuf/timestamp.proto": "@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
|
|
"google/protobuf/struct.proto": "@io_bazel_rules_go//proto/wkt:struct_go_proto",
|
|
"google/protobuf/field.proto": "@io_bazel_rules_go//proto/wkt:field_mask_go_proto",
|
|
"google/protobuf/empty.proto": "@io_bazel_rules_go//proto/wkt:empty_go_proto",
|
|
"google/protobuf/duration.proto": "@io_bazel_rules_go//proto/wkt:duration_go_proto",
|
|
"google/protobuf/compiler.proto": "@io_bazel_rules_go//proto/wkt:compiler_plugin_go_proto",
|
|
"google/protobuf/descriptor.proto": "@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
|
|
"google/protobuf/api.proto": "@io_bazel_rules_go//proto/wkt:api_go_proto",
|
|
"google/protobuf/type.proto": "@io_bazel_rules_go//proto/wkt:type_go_proto",
|
|
"google/protobuf/source.proto": "@io_bazel_rules_go//proto/wkt:source_context_go_proto",
|
|
"google/protobuf/any.proto": "@io_bazel_rules_go//proto/wkt:any_go_proto",
|
|
}
|
|
for _, v := range dep {
|
|
mapdep, ok := mapping[v]
|
|
if ok {
|
|
result = append(result, mapdep)
|
|
} else {
|
|
if custom := customgoprotolibrary(path, v); custom != "" {
|
|
result = append(result, custom)
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func addExpr(x []bzl.Expr, y []bzl.Expr) []bzl.Expr {
|
|
return append(x, y...)
|
|
}
|
|
|
|
func customgoprotolibrary(path, dep string) string {
|
|
if strings.HasPrefix(dep, "library") || strings.HasPrefix(dep, "app") && strings.HasSuffix(dep, ".proto") {
|
|
deplist := strings.Split(dep, "/")
|
|
last := deplist[:len(deplist)-1]
|
|
if strings.Join(last, "/") == path {
|
|
return ""
|
|
}
|
|
last[len(last)-1] = last[len(last)-1] + ":" + last[len(last)-1] + "_go_proto"
|
|
dep = strings.Join(last, "/")
|
|
return "//" + dep
|
|
}
|
|
return dep
|
|
}
|
|
|
|
func customgoproto(path, dep string) string {
|
|
if strings.HasPrefix(dep, "library") || strings.HasPrefix(dep, "app") && strings.HasSuffix(dep, ".proto") {
|
|
deplist := strings.Split(dep, "/")
|
|
last := deplist[:len(deplist)-1]
|
|
if strings.Join(last, "/") == path {
|
|
return ""
|
|
}
|
|
last[len(last)-1] = last[len(last)-1] + ":" + last[len(last)-1] + "_proto"
|
|
dep = strings.Join(last, "/")
|
|
return "//" + dep
|
|
}
|
|
return dep
|
|
}
|