kazel.go 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package main
  14. import (
  15. "bytes"
  16. "flag"
  17. "fmt"
  18. "go/build"
  19. "io/ioutil"
  20. "os"
  21. "path/filepath"
  22. "reflect"
  23. "regexp"
  24. "runtime"
  25. "sort"
  26. "strings"
  27. bzl "github.com/bazelbuild/buildtools/build"
  28. "github.com/golang/glog"
  29. )
  30. const (
  31. vendorPath = "vendor/"
  32. automanagedTag = "automanaged"
  33. manualTag = "manual"
  34. )
  35. var (
  36. root = flag.String("root", ".", "root of go source")
  37. dryRun = flag.Bool("dry-run", false, "run in dry mode")
  38. printDiff = flag.Bool("print-diff", false, "print diff to stdout")
  39. validate = flag.Bool("validate", false, "run in dry mode and exit nonzero if any BUILD files need to be updated")
  40. cfgPath = flag.String("cfg-path", ".kazelcfg.json", "path to kazel config (relative paths interpreted relative to -repo.")
  41. iswrote = false
  42. )
  43. func main() {
  44. flag.Parse()
  45. flag.Set("alsologtostderr", "true")
  46. if *root == "" {
  47. glog.Fatalf("-root argument is required")
  48. }
  49. if *validate {
  50. *dryRun = true
  51. }
  52. v, err := newVendorer(*root, *cfgPath, *dryRun)
  53. if err != nil {
  54. glog.Fatalf("unable to build vendorer: %v", err)
  55. }
  56. if err = os.Chdir(v.root); err != nil {
  57. glog.Fatalf("cannot chdir into root %q: %v", v.root, err)
  58. }
  59. if v.cfg.ManageGoRules {
  60. if err = v.walkVendor(); err != nil {
  61. glog.Fatalf("err walking vendor: %v", err)
  62. }
  63. if err = v.walkRepo(); err != nil {
  64. glog.Fatalf("err walking repo: %v", err)
  65. }
  66. }
  67. if err = v.walkGenerated(); err != nil {
  68. glog.Fatalf("err walking generated: %v", err)
  69. }
  70. if _, err = v.walkSource("."); err != nil {
  71. glog.Fatalf("err walking source: %v", err)
  72. }
  73. written := 0
  74. if written, err = v.reconcileAllRules(); err != nil {
  75. glog.Fatalf("err reconciling rules: %v", err)
  76. }
  77. if *validate && written > 0 {
  78. fmt.Fprintf(os.Stderr, "\n%d BUILD files not up-to-date.\n", written)
  79. os.Exit(1)
  80. }
  81. if iswrote {
  82. fmt.Fprintf(os.Stderr, "\nPlease re-run git-add\n")
  83. os.Exit(1)
  84. }
  85. }
  86. // Vendorer collects context, configuration, and cache while walking the tree.
  87. type Vendorer struct {
  88. ctx *build.Context
  89. icache map[icacheKey]icacheVal
  90. skippedPaths []*regexp.Regexp
  91. dryRun bool
  92. root string
  93. cfg *Cfg
  94. newRules map[string][]*bzl.Rule // package path -> list of rules to add or update
  95. managedAttrs []string
  96. }
  97. func newVendorer(root, cfgPath string, dryRun bool) (*Vendorer, error) {
  98. absRoot, err := filepath.Abs(root)
  99. if err != nil {
  100. return nil, fmt.Errorf("could not get absolute path: %v", err)
  101. }
  102. if !filepath.IsAbs(cfgPath) {
  103. cfgPath = filepath.Join(absRoot, cfgPath)
  104. }
  105. cfg, err := ReadCfg(cfgPath)
  106. if err != nil {
  107. return nil, err
  108. }
  109. v := Vendorer{
  110. ctx: context(),
  111. dryRun: dryRun,
  112. root: absRoot,
  113. icache: map[icacheKey]icacheVal{},
  114. cfg: cfg,
  115. newRules: make(map[string][]*bzl.Rule),
  116. managedAttrs: []string{"srcs", "deps", "importpath", "compilers"},
  117. }
  118. for _, sp := range cfg.SkippedPaths {
  119. r, err := regexp.Compile(sp)
  120. if err != nil {
  121. return nil, err
  122. }
  123. v.skippedPaths = append(v.skippedPaths, r)
  124. }
  125. for _, builtinSkip := range []string{
  126. "^\\.git",
  127. "^bazel-*",
  128. } {
  129. v.skippedPaths = append(v.skippedPaths, regexp.MustCompile(builtinSkip))
  130. }
  131. return &v, nil
  132. }
  133. type icacheKey struct {
  134. path, srcDir string
  135. }
  136. type icacheVal struct {
  137. pkg *build.Package
  138. err error
  139. }
  140. func (v *Vendorer) importPkg(path string, srcDir string) (*build.Package, error) {
  141. k := icacheKey{path: path, srcDir: srcDir}
  142. if val, ok := v.icache[k]; ok {
  143. return val.pkg, val.err
  144. }
  145. // cache miss
  146. pkg, err := v.ctx.Import(path, srcDir, build.ImportComment)
  147. v.icache[k] = icacheVal{pkg: pkg, err: err}
  148. return pkg, err
  149. }
  150. func writeHeaders(file *bzl.File) {
  151. pkgRule := bzl.Rule{
  152. Call: &bzl.CallExpr{
  153. X: &bzl.LiteralExpr{Token: "package"},
  154. },
  155. }
  156. pkgRule.SetAttr("default_visibility", asExpr([]string{"//visibility:public"}))
  157. file.Stmt = append(file.Stmt,
  158. []bzl.Expr{
  159. pkgRule.Call,
  160. &bzl.CallExpr{
  161. X: &bzl.LiteralExpr{Token: "load"},
  162. List: asExpr([]string{
  163. "@io_bazel_rules_go//go:def.bzl",
  164. }).(*bzl.ListExpr).List,
  165. },
  166. }...,
  167. )
  168. }
  169. func writeRules(file *bzl.File, rules []*bzl.Rule) {
  170. for _, rule := range rules {
  171. file.Stmt = append(file.Stmt, rule.Call)
  172. }
  173. }
  174. func (v *Vendorer) resolve(ipath string) Label {
  175. if ipath == v.cfg.GoPrefix {
  176. return Label{
  177. tag: "go_default_library",
  178. }
  179. } else if strings.HasPrefix(ipath, v.cfg.GoPrefix) {
  180. return Label{
  181. pkg: strings.TrimPrefix(ipath, v.cfg.GoPrefix+"/"),
  182. tag: "go_default_library",
  183. }
  184. }
  185. if v.cfg.VendorMultipleBuildFiles {
  186. return Label{
  187. pkg: "vendor/" + ipath,
  188. tag: "go_default_library",
  189. }
  190. }
  191. return Label{
  192. pkg: "vendor",
  193. tag: ipath,
  194. }
  195. }
  196. func (v *Vendorer) walk(root string, f func(path, ipath string, pkg *build.Package, conffile, proto []string) error) error {
  197. skipVendor := true
  198. if root == vendorPath {
  199. skipVendor = false
  200. }
  201. return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
  202. if err != nil {
  203. return err
  204. }
  205. if !info.IsDir() {
  206. return nil
  207. }
  208. if skipVendor && strings.HasPrefix(path, vendorPath) {
  209. return filepath.SkipDir
  210. }
  211. for _, r := range v.skippedPaths {
  212. if r.MatchString(path) {
  213. return filepath.SkipDir
  214. }
  215. }
  216. if _, err = os.Stat(filepath.Join(path, ".skip_kazel")); !os.IsNotExist(err) {
  217. return filepath.SkipDir
  218. }
  219. ipath, err := filepath.Rel(root, path)
  220. if err != nil {
  221. return err
  222. }
  223. protofiles := v.getAllProto(path)
  224. conffiles := v.getAllConf(path)
  225. pkg, err := v.importPkg(".", filepath.Join(v.root, path))
  226. if err != nil {
  227. if _, ok := err.(*build.NoGoError); err != nil && ok {
  228. return nil
  229. }
  230. return err
  231. }
  232. return f(path, ipath, pkg, conffiles, protofiles)
  233. })
  234. }
  235. func (v *Vendorer) walkRepo() error {
  236. for _, root := range v.cfg.SrcDirs {
  237. if err := v.walk(root, v.updatePkg); err != nil {
  238. return err
  239. }
  240. }
  241. return nil
  242. }
  243. func (v *Vendorer) getAllProto(path string) []string {
  244. var protofiles []string
  245. files, err := ioutil.ReadDir(path)
  246. if err != nil {
  247. glog.Fatalf("getallproto fail to readdir")
  248. }
  249. for _, f := range files {
  250. if strings.Contains(f.Name(), ".proto") {
  251. if f.Mode() != os.ModeDir {
  252. protofiles = append(protofiles, f.Name())
  253. }
  254. }
  255. }
  256. return protofiles
  257. }
  258. func (v *Vendorer) getAllConf(path string) []string {
  259. var conffiles []string
  260. files, err := ioutil.ReadDir(path)
  261. if err != nil {
  262. glog.Fatalf("getallconf fail to readdir")
  263. }
  264. for _, f := range files {
  265. if strings.Contains(f.Name(), ".toml") || strings.Contains(f.Name(), ".yaml") {
  266. if f.Mode() != os.ModeDir {
  267. conffiles = append(conffiles, f.Name())
  268. }
  269. }
  270. }
  271. return conffiles
  272. }
  273. func (v *Vendorer) updateSinglePkg(path string) error {
  274. pkg, err := v.importPkg(".", "./"+path)
  275. if err != nil {
  276. if _, ok := err.(*build.NoGoError); err != nil && ok {
  277. return nil
  278. }
  279. return err
  280. }
  281. protofiles := v.getAllProto(path)
  282. conffiles := v.getAllConf(path)
  283. return v.updatePkg(path, "", pkg, conffiles, protofiles)
  284. }
  285. type ruleType int
  286. // The RuleType* constants enumerate the bazel rules supported by this tool.
  287. const (
  288. RuleTypeGoBinary ruleType = iota
  289. RuleTypeGoLibrary
  290. RuleTypeGoTest
  291. RuleTypeGoXTest
  292. RuleTypeCGoGenrule
  293. RuleTypeFileGroup
  294. RuleTypeOpenAPILibrary
  295. RuleTypeProtoLibrary
  296. RuleTypeGoProtoLibrary
  297. )
  298. // RuleKind converts a value of the RuleType* enum into the BUILD string.
  299. func (rt ruleType) RuleKind() string {
  300. switch rt {
  301. case RuleTypeGoBinary:
  302. return "go_binary"
  303. case RuleTypeGoLibrary:
  304. return "go_library"
  305. case RuleTypeGoTest:
  306. return "go_test"
  307. case RuleTypeGoXTest:
  308. return "go_test"
  309. case RuleTypeCGoGenrule:
  310. return "cgo_genrule"
  311. case RuleTypeFileGroup:
  312. return "filegroup"
  313. case RuleTypeOpenAPILibrary:
  314. return "openapi_library"
  315. case RuleTypeProtoLibrary:
  316. return "proto_library"
  317. case RuleTypeGoProtoLibrary:
  318. return "go_proto_library"
  319. }
  320. panic("unreachable")
  321. }
  322. // NamerFunc is a function that returns the appropriate name for the rule for the provided RuleType.
  323. type NamerFunc func(ruleType) string
  324. func (v *Vendorer) updatePkg(path, _ string, pkg *build.Package, conffile, protofile []string) error {
  325. srcNameMap := func(srcs ...[]string) *bzl.ListExpr {
  326. return asExpr(merge(srcs...)).(*bzl.ListExpr)
  327. }
  328. goFileNotProto := []string{}
  329. for _, v := range pkg.GoFiles {
  330. if !strings.Contains(v, ".pb.go") {
  331. goFileNotProto = append(goFileNotProto, v)
  332. }
  333. }
  334. srcs := srcNameMap(goFileNotProto, pkg.SFiles)
  335. cgoSrcs := srcNameMap(pkg.CgoFiles, pkg.CFiles, pkg.CXXFiles, pkg.HFiles)
  336. testSrcs := srcNameMap(pkg.TestGoFiles)
  337. xtestSrcs := srcNameMap(pkg.XTestGoFiles)
  338. pf := protoFileInfo(v.cfg.GoPrefix, path, protofile)
  339. v.addRules(path, v.emit(path, srcs, cgoSrcs, testSrcs, xtestSrcs, pf, pkg, conffile, func(rt ruleType) string {
  340. switch rt {
  341. case RuleTypeGoBinary:
  342. return filepath.Base(pkg.Dir)
  343. case RuleTypeGoLibrary:
  344. return "go_default_library"
  345. case RuleTypeGoTest:
  346. return "go_default_test"
  347. case RuleTypeGoXTest:
  348. return "go_default_xtest"
  349. case RuleTypeCGoGenrule:
  350. return "cgo_codegen"
  351. case RuleTypeProtoLibrary:
  352. return pf.packageName + "_proto"
  353. case RuleTypeGoProtoLibrary:
  354. return pf.packageName + "_go_proto"
  355. }
  356. panic("unreachable")
  357. }))
  358. return nil
  359. }
  360. func (v *Vendorer) emit(path string, srcs, cgoSrcs, testSrcs, xtestSrcs *bzl.ListExpr, protoSrcs ProtoInfo, pkg *build.Package, conffile []string, namer NamerFunc) []*bzl.Rule {
  361. var goLibAttrs = make(Attrs)
  362. var rules []*bzl.Rule
  363. embedlist := []string{}
  364. if len(protoSrcs.src) > 0 {
  365. protoRuleAttrs := make(Attrs)
  366. protoRuleAttrs.SetList("srcs", asExpr(protoSrcs.src).(*bzl.ListExpr))
  367. protoRuleAttrs.SetList("deps", asExpr(protoMap(path, protoSrcs.imports)).(*bzl.ListExpr))
  368. rules = append(rules, newRule(RuleTypeProtoLibrary, namer, protoRuleAttrs))
  369. goProtoRuleAttrs := make(Attrs)
  370. if protoSrcs.isGogo {
  371. if protoSrcs.hasServices {
  372. goProtoRuleAttrs.SetList("compilers", asExpr([]string{"@io_bazel_rules_go//proto:gogofast_grpc"}).(*bzl.ListExpr))
  373. } else {
  374. goProtoRuleAttrs.SetList("compilers", asExpr([]string{"@io_bazel_rules_go//proto:gogofast_proto"}).(*bzl.ListExpr))
  375. }
  376. } else {
  377. if protoSrcs.hasServices {
  378. goProtoRuleAttrs.SetList("compilers", asExpr([]string{"@io_bazel_rules_go//proto:go_grpc"}).(*bzl.ListExpr))
  379. } else {
  380. goProtoRuleAttrs.SetList("compilers", asExpr([]string{"@io_bazel_rules_go//proto:go_proto"}).(*bzl.ListExpr))
  381. }
  382. }
  383. protovalue := ":" + protoSrcs.packageName + "_proto"
  384. goProtoRuleAttrs.Set("proto", asExpr(protovalue))
  385. goProtoRuleAttrs.Set("importpath", asExpr(protoSrcs.importPath))
  386. goProtoRuleAttrs.SetList("deps", asExpr(goProtoMap(path, protoSrcs.imports)).(*bzl.ListExpr))
  387. rules = append(rules, newRule(RuleTypeGoProtoLibrary, namer, goProtoRuleAttrs))
  388. embedlist = append(embedlist, protoSrcs.packageName+"_go_proto")
  389. }
  390. deps := v.extractDeps(depMapping(pkg.Imports))
  391. if len(srcs.List) >= 0 {
  392. if len(cgoSrcs.List) != 0 {
  393. goLibAttrs.SetList("srcs", &bzl.ListExpr{List: addExpr(srcs.List, cgoSrcs.List)})
  394. goLibAttrs.SetList("clinkopts", asExpr([]string{"-lz", "-lm", "-lpthread", "-ldl"}).(*bzl.ListExpr))
  395. goLibAttrs.Set("cgo", &bzl.LiteralExpr{Token: "True"})
  396. } else {
  397. goLibAttrs.Set("srcs", srcs)
  398. }
  399. if strings.Contains(path, "vendor") {
  400. goLibAttrs.Set("importpath", asExpr(strings.Replace(path, "vendor/", "", -1)))
  401. } else {
  402. goLibAttrs.Set("importpath", asExpr(filepath.Join(v.cfg.GoPrefix, path)))
  403. }
  404. goLibAttrs.SetList("visibility", asExpr([]string{"//visibility:public"}).(*bzl.ListExpr))
  405. } else if len(cgoSrcs.List) == 0 {
  406. return nil
  407. }
  408. if len(conffile) > 0 {
  409. goLibAttrs.SetList("data", asExpr(conffile).(*bzl.ListExpr))
  410. }
  411. if len(deps.List) > 0 {
  412. goLibAttrs.SetList("deps", deps)
  413. }
  414. if pkg.IsCommand() {
  415. rules = append(rules, newRule(RuleTypeGoBinary, namer, map[string]bzl.Expr{
  416. "embed": asExpr([]string{":" + namer(RuleTypeGoLibrary)}),
  417. }))
  418. }
  419. addGoDefaultLibrary := len(cgoSrcs.List) > 0 || len(srcs.List) > 0 || len(protoSrcs.src) == 1 || len(conffile) > 0
  420. if len(testSrcs.List) != 0 {
  421. testRuleAttrs := make(Attrs)
  422. testRuleAttrs.SetList("srcs", testSrcs)
  423. testRuleAttrs.SetList("deps", v.extractDeps(depMapping(pkg.TestImports)))
  424. //testRuleAttrs.Set("rundir", asExpr("."))
  425. //testRuleAttrs.Set("importmap", asExpr(filepath.Join(v.cfg.GoPrefix, path)))
  426. //testRuleAttrs.Set("importpath", asExpr(filepath.Join(v.cfg.GoPrefix, path)))
  427. if addGoDefaultLibrary {
  428. testRuleAttrs.SetList("embed", asExpr([]string{":" + namer(RuleTypeGoLibrary)}).(*bzl.ListExpr))
  429. }
  430. rules = append(rules, newRule(RuleTypeGoTest, namer, testRuleAttrs))
  431. }
  432. if len(embedlist) > 0 {
  433. goLibAttrs.SetList("embed", asExpr(embedlist).(*bzl.ListExpr))
  434. }
  435. if addGoDefaultLibrary || len(embedlist) > 0 {
  436. rules = append(rules, newRule(RuleTypeGoLibrary, namer, goLibAttrs))
  437. }
  438. if len(xtestSrcs.List) != 0 {
  439. xtestRuleAttrs := make(Attrs)
  440. xtestRuleAttrs.SetList("srcs", xtestSrcs)
  441. xtestRuleAttrs.SetList("deps", v.extractDeps(pkg.XTestImports))
  442. rules = append(rules, newRule(RuleTypeGoXTest, namer, xtestRuleAttrs))
  443. }
  444. return rules
  445. }
  446. func (v *Vendorer) addRules(pkgPath string, rules []*bzl.Rule) {
  447. cleanPath := filepath.Clean(pkgPath)
  448. v.newRules[cleanPath] = append(v.newRules[cleanPath], rules...)
  449. }
  450. func (v *Vendorer) walkVendor() error {
  451. var rules []*bzl.Rule
  452. updateFunc := func(path, ipath string, pkg *build.Package, conffile, proto []string) error {
  453. srcNameMap := func(srcs ...[]string) *bzl.ListExpr {
  454. return asExpr(
  455. apply(
  456. merge(srcs...),
  457. mapper(func(s string) string {
  458. return strings.TrimPrefix(filepath.Join(path, s), "vendor/")
  459. }),
  460. ),
  461. ).(*bzl.ListExpr)
  462. }
  463. srcs := srcNameMap(pkg.GoFiles, pkg.SFiles)
  464. cgoSrcs := srcNameMap(pkg.CgoFiles, pkg.CFiles, pkg.CXXFiles, pkg.HFiles)
  465. testSrcs := srcNameMap(pkg.TestGoFiles)
  466. xtestSrcs := srcNameMap(pkg.XTestGoFiles)
  467. pf := protoFileInfo(v.cfg.GoPrefix, path, proto)
  468. tagBase := v.resolve(ipath).tag
  469. rules = append(rules, v.emit(path, srcs, cgoSrcs, testSrcs, xtestSrcs, pf, pkg, []string{}, func(rt ruleType) string {
  470. switch rt {
  471. case RuleTypeGoBinary:
  472. return tagBase + "_bin"
  473. case RuleTypeGoLibrary:
  474. return tagBase
  475. case RuleTypeGoTest:
  476. return tagBase + "_test"
  477. case RuleTypeGoXTest:
  478. return tagBase + "_xtest"
  479. case RuleTypeCGoGenrule:
  480. return tagBase + "_cgo"
  481. case RuleTypeProtoLibrary:
  482. return pf.packageName + "_proto"
  483. case RuleTypeGoProtoLibrary:
  484. return pf.packageName + "_go_proto"
  485. }
  486. panic("unreachable")
  487. })...)
  488. return nil
  489. }
  490. if v.cfg.VendorMultipleBuildFiles {
  491. updateFunc = v.updatePkg
  492. }
  493. if err := v.walk(vendorPath, updateFunc); err != nil {
  494. return err
  495. }
  496. v.addRules(vendorPath, rules)
  497. return nil
  498. }
  499. func (v *Vendorer) extractDeps(deps []string) *bzl.ListExpr {
  500. return asExpr(
  501. depMapping(apply(
  502. merge(deps),
  503. filterer(func(s string) bool {
  504. pkg, err := v.importPkg(s, v.root)
  505. if err != nil {
  506. if strings.Contains(err.Error(), `cannot find package "C"`) ||
  507. // added in go1.7
  508. strings.Contains(err.Error(), `cannot find package "context"`) ||
  509. strings.Contains(err.Error(), `cannot find package "net/http/httptrace"`) {
  510. return false
  511. }
  512. fmt.Fprintf(os.Stderr, "extract err: %v\n", err)
  513. return false
  514. }
  515. if pkg.Goroot {
  516. return false
  517. }
  518. return true
  519. }),
  520. mapper(func(s string) string {
  521. return v.resolve(s).String()
  522. }),
  523. )),
  524. ).(*bzl.ListExpr)
  525. }
  526. func (v *Vendorer) reconcileAllRules() (int, error) {
  527. var paths []string
  528. for path := range v.newRules {
  529. paths = append(paths, path)
  530. }
  531. sort.Strings(paths)
  532. written := 0
  533. for _, path := range paths {
  534. w, err := ReconcileRules(path, v.newRules[path], v.managedAttrs, v.dryRun, v.cfg.ManageGoRules)
  535. if w {
  536. written++
  537. }
  538. if err != nil {
  539. return written, err
  540. }
  541. }
  542. return written, nil
  543. }
  544. // Attrs collects the attributes for a rule.
  545. type Attrs map[string]bzl.Expr
  546. // Set sets the named attribute to the provided bazel expression.
  547. func (a Attrs) Set(name string, expr bzl.Expr) {
  548. a[name] = expr
  549. }
  550. // SetList sets the named attribute to the provided bazel expression list.
  551. func (a Attrs) SetList(name string, expr *bzl.ListExpr) {
  552. if len(expr.List) == 0 {
  553. return
  554. }
  555. a[name] = expr
  556. }
  557. // Label defines a bazel label.
  558. type Label struct {
  559. pkg, tag string
  560. }
  561. func (l Label) String() string {
  562. return fmt.Sprintf("//%v:%v", l.pkg, l.tag)
  563. }
  564. func asExpr(e interface{}) bzl.Expr {
  565. rv := reflect.ValueOf(e)
  566. switch rv.Kind() {
  567. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  568. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  569. return &bzl.LiteralExpr{Token: fmt.Sprintf("%d", e)}
  570. case reflect.Float32, reflect.Float64:
  571. return &bzl.LiteralExpr{Token: fmt.Sprintf("%f", e)}
  572. case reflect.String:
  573. return &bzl.StringExpr{Value: e.(string)}
  574. case reflect.Slice, reflect.Array:
  575. var list []bzl.Expr
  576. for i := 0; i < rv.Len(); i++ {
  577. list = append(list, asExpr(rv.Index(i).Interface()))
  578. }
  579. return &bzl.ListExpr{List: list}
  580. default:
  581. glog.Fatalf("Uh oh")
  582. return nil
  583. }
  584. }
  585. type sed func(s []string) []string
  586. func mapString(in []string, f func(string) string) []string {
  587. var out []string
  588. for _, s := range in {
  589. out = append(out, f(s))
  590. }
  591. return out
  592. }
  593. func mapper(f func(string) string) sed {
  594. return func(in []string) []string {
  595. return mapString(in, f)
  596. }
  597. }
  598. func filterString(in []string, f func(string) bool) []string {
  599. var out []string
  600. for _, s := range in {
  601. if f(s) {
  602. out = append(out, s)
  603. }
  604. }
  605. return out
  606. }
  607. func filterer(f func(string) bool) sed {
  608. return func(in []string) []string {
  609. return filterString(in, f)
  610. }
  611. }
  612. func apply(stream []string, seds ...sed) []string {
  613. for _, sed := range seds {
  614. stream = sed(stream)
  615. }
  616. return stream
  617. }
  618. func merge(streams ...[]string) []string {
  619. var out []string
  620. for _, stream := range streams {
  621. out = append(out, stream...)
  622. }
  623. return out
  624. }
  625. func newRule(rt ruleType, namer NamerFunc, attrs map[string]bzl.Expr) *bzl.Rule {
  626. rule := &bzl.Rule{
  627. Call: &bzl.CallExpr{
  628. X: &bzl.LiteralExpr{Token: rt.RuleKind()},
  629. },
  630. }
  631. rule.SetAttr("name", asExpr(namer(rt)))
  632. for k, v := range attrs {
  633. rule.SetAttr(k, v)
  634. }
  635. rule.SetAttr("tags", asExpr([]string{automanagedTag}))
  636. return rule
  637. }
  638. // findBuildFile determines the name of a preexisting BUILD file, returning
  639. // a default if no such file exists.
  640. func findBuildFile(pkgPath string) (bool, string) {
  641. options := []string{"BUILD.bazel", "BUILD"}
  642. for _, b := range options {
  643. path := filepath.Join(pkgPath, b)
  644. info, err := os.Stat(path)
  645. if err == nil && !info.IsDir() {
  646. return true, path
  647. }
  648. }
  649. return false, filepath.Join(pkgPath, "BUILD")
  650. }
  651. // ReconcileRules reconciles, simplifies, and writes the rules for the specified package, adding
  652. // additional dependency rules as needed.
  653. func ReconcileRules(pkgPath string, rules []*bzl.Rule, managedAttrs []string, dryRun bool, manageGoRules bool) (bool, error) {
  654. goProtoLibrary := []string{}
  655. _, path := findBuildFile(pkgPath)
  656. info, err := os.Stat(path)
  657. if err != nil && os.IsNotExist(err) {
  658. f := &bzl.File{}
  659. writeHeaders(f)
  660. if manageGoRules {
  661. reconcileLoad(path, f, rules)
  662. }
  663. writeRules(f, rules)
  664. return writeFile(path, f, false, dryRun)
  665. } else if err != nil {
  666. return false, err
  667. }
  668. if info.IsDir() {
  669. return false, fmt.Errorf("%q cannot be a directory", path)
  670. }
  671. b, err := ioutil.ReadFile(path)
  672. if err != nil {
  673. return false, err
  674. }
  675. f, err := bzl.Parse(path, b)
  676. if err != nil {
  677. return false, err
  678. }
  679. oldRules := make(map[string]*bzl.Rule)
  680. for _, r := range f.Rules("") {
  681. if r.Kind() == "proto_library" {
  682. if r.Attr("tags") == nil {
  683. r.SetAttr("tags", asExpr([]string{automanagedTag}))
  684. }
  685. }
  686. if r.Kind() == "go_proto_library" {
  687. if r.Attr("tags") == nil {
  688. r.SetAttr("tags", asExpr([]string{automanagedTag}))
  689. }
  690. goProtoLibrary = append(goProtoLibrary, ":"+r.Name())
  691. }
  692. if (r.Kind() == "go_library" || r.Kind() == "go_test") && (len(rules) == 3 || len(rules) == 4) && !strings.Contains(pkgPath, "vendor") {
  693. if r.Attr("tags") == nil {
  694. r.SetAttr("tags", asExpr([]string{automanagedTag}))
  695. }
  696. }
  697. if r.Kind() == "go_library" || r.Kind() == "go_test" {
  698. if listExpr, ok := r.Attr("deps").(*bzl.ListExpr); ok {
  699. olddeps := []string{}
  700. for _, v := range listExpr.List {
  701. olddeps = append(olddeps, v.(*bzl.StringExpr).Value)
  702. }
  703. newdeps := depMapping(olddeps)
  704. r.SetAttr("deps", asExpr(newdeps))
  705. }
  706. }
  707. oldRules[r.Name()] = r
  708. }
  709. if len(goProtoLibrary) > 0 && goProtoLibrary != nil {
  710. r, ok := oldRules["go_default_library"]
  711. if ok {
  712. r.SetAttr("embed", asExpr(goProtoLibrary))
  713. oldRules["go_default_library"] = r
  714. }
  715. }
  716. for _, r := range rules {
  717. o, ok := oldRules[r.Name()]
  718. if !ok {
  719. f.Stmt = append(f.Stmt, r.Call)
  720. continue
  721. }
  722. if !RuleIsManaged(o, manageGoRules) {
  723. continue
  724. }
  725. reconcileAttr := func(o, n *bzl.Rule, name string) {
  726. if e := n.Attr(name); e != nil {
  727. o.SetAttr(name, e)
  728. } else {
  729. o.DelAttr(name)
  730. }
  731. }
  732. for _, attr := range managedAttrs {
  733. reconcileAttr(o, r, attr)
  734. }
  735. delete(oldRules, r.Name())
  736. }
  737. for _, r := range oldRules {
  738. if !RuleIsManaged(r, manageGoRules) {
  739. continue
  740. }
  741. f.DelRules(r.Kind(), r.Name())
  742. }
  743. if manageGoRules {
  744. reconcileLoad(path, f, f.Rules(""))
  745. }
  746. return writeFile(path, f, true, dryRun)
  747. }
  748. func reconcileLoad(path string, f *bzl.File, rules []*bzl.Rule) {
  749. contains := func(s []string, e string) bool {
  750. for _, a := range s {
  751. if a == e {
  752. return true
  753. }
  754. }
  755. return false
  756. }
  757. usedRuleKindsMap := map[string][]string{}
  758. for _, r := range rules {
  759. // Select only the Go rules we need to import, excluding builtins like filegroup.
  760. // TODO: make less fragile
  761. switch r.Kind() {
  762. case "go_prefix", "go_library", "go_binary", "go_test", "cgo_genrule", "cgo_library":
  763. if !contains(usedRuleKindsMap["@io_bazel_rules_go//go:def.bzl"], r.Kind()) {
  764. usedRuleKindsMap["@io_bazel_rules_go//go:def.bzl"] = append(usedRuleKindsMap["@io_bazel_rules_go//go:def.bzl"], r.Kind())
  765. }
  766. case "gazelle":
  767. if !contains(usedRuleKindsMap["@bazel_gazelle//:def.bzl"], r.Kind()) {
  768. usedRuleKindsMap["@bazel_gazelle//:def.bzl"] = append(usedRuleKindsMap["@bazel_gazelle//:def.bzl"], r.Kind())
  769. }
  770. case "go_proto_library":
  771. if !contains(usedRuleKindsMap["@io_bazel_rules_go//proto:def.bzl"], r.Kind()) {
  772. usedRuleKindsMap["@io_bazel_rules_go//proto:def.bzl"] = append(usedRuleKindsMap["@io_bazel_rules_go//proto:def.bzl"], r.Kind())
  773. }
  774. }
  775. }
  776. usedRuleKindsList := []string{}
  777. for k := range usedRuleKindsMap {
  778. usedRuleKindsList = append(usedRuleKindsList, k)
  779. }
  780. sort.Strings(usedRuleKindsList)
  781. for _, r := range f.Rules("load") {
  782. args := bzl.Strings(&bzl.ListExpr{List: r.Call.List})
  783. if len(args) == 0 {
  784. continue
  785. }
  786. if !contains(usedRuleKindsList, args[0]) {
  787. continue
  788. }
  789. if len(usedRuleKindsMap[args[0]]) == 0 {
  790. if r.Name() != "" {
  791. f.DelRules(r.Kind(), r.Name())
  792. }
  793. continue
  794. }
  795. r.Call.List = asExpr(append(
  796. []string{args[0]}, usedRuleKindsMap[args[0]]...,
  797. )).(*bzl.ListExpr).List
  798. delete(usedRuleKindsMap, args[0])
  799. }
  800. for k, v := range usedRuleKindsMap {
  801. rule :=
  802. &bzl.CallExpr{
  803. X: &bzl.LiteralExpr{Token: "load"},
  804. }
  805. rule.List = asExpr(append(
  806. []string{k}, v...,
  807. )).(*bzl.ListExpr).List
  808. f.Stmt = append([]bzl.Expr{rule}, f.Stmt...)
  809. }
  810. }
  811. // RuleIsManaged returns whether the provided rule is managed by this tool,
  812. // based on the tags set on the rule.
  813. func RuleIsManaged(r *bzl.Rule, manageGoRules bool) bool {
  814. var automanaged bool
  815. if !manageGoRules && (strings.HasPrefix(r.Kind(), "go_") || strings.HasPrefix(r.Kind(), "cgo_")) {
  816. return false
  817. }
  818. for _, tag := range r.AttrStrings("tags") {
  819. if tag == automanagedTag {
  820. automanaged = true
  821. break
  822. }
  823. }
  824. return automanaged
  825. }
  826. func writeFile(path string, f *bzl.File, exists, dryRun bool) (bool, error) {
  827. var info bzl.RewriteInfo
  828. bzl.Rewrite(f, &info)
  829. out := bzl.Format(f)
  830. //if strings.Contains(path, "vendor") {
  831. // return false, nil
  832. //}
  833. if exists {
  834. orig, err := ioutil.ReadFile(path)
  835. if err != nil {
  836. return false, err
  837. }
  838. if bytes.Compare(orig, out) == 0 {
  839. return false, nil
  840. }
  841. if *printDiff {
  842. Diff(orig, out)
  843. }
  844. }
  845. if dryRun {
  846. fmt.Fprintf(os.Stderr, "DRY-RUN: wrote %q\n", path)
  847. return true, nil
  848. }
  849. werr := ioutil.WriteFile(path, out, 0644)
  850. if werr == nil {
  851. fmt.Fprintf(os.Stderr, "wrote %q\n", path)
  852. iswrote = true
  853. }
  854. return werr == nil, werr
  855. }
  856. func context() *build.Context {
  857. return &build.Context{
  858. GOARCH: "amd64",
  859. GOOS: "linux",
  860. GOROOT: build.Default.GOROOT,
  861. GOPATH: build.Default.GOPATH,
  862. ReleaseTags: []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8", "go1.9", "go1.10"},
  863. Compiler: runtime.Compiler,
  864. CgoEnabled: true,
  865. }
  866. }
  867. func walk(root string, walkFn filepath.WalkFunc) error {
  868. return nil
  869. }
  870. func depMapping(dep []string) []string {
  871. result := []string{}
  872. mapping := map[string]string{
  873. "//vendor/github.com/golang/protobuf/proto:go_default_library": "@com_github_golang_protobuf//proto:go_default_library",
  874. "//vendor/github.com/golang/protobuf/ptypes/any:go_default_library": "@io_bazel_rules_go//proto/wkt:any_go_proto",
  875. "//vendor/github.com/golang/protobuf/jsonpb:go_default_library": "@com_github_golang_protobuf//jsonpb:go_default_library",
  876. "//vendor/github.com/golang/protobuf/protoc-gen-go/plugin:go_default_library": "@com_github_golang_protobuf//protoc-gen-go/plugin:go_default_library",
  877. "//vendor/github.com/golang/protobuf/protoc-gen-go/descriptor:go_default_library": "@com_github_golang_protobuf//protoc-gen-go/descriptor:go_default_library",
  878. "//vendor/github.com/golang/protobuf/ptypes:go_default_library": "@com_github_golang_protobuf//ptypes:go_default_library_gen",
  879. "//vendor/github.com/golang/protobuf/ptypes/empty:go_default_library": "@io_bazel_rules_go//proto/wkt:empty_go_proto",
  880. "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library": "@com_github_gogo_protobuf//gogoproto:go_default_library",
  881. "//vendor/github.com/gogo/protobuf/proto:go_default_library": "@com_github_gogo_protobuf//proto:go_default_library",
  882. "//vendor/github.com/gogo/protobuf/protoc-gen-gogo:go_default_library": "@com_github_gogo_protobuf//protoc-gen-gogo:go_default_library",
  883. "//vendor/github.com/gogo/protobuf/sortkeys:go_default_library": "@com_github_gogo_protobuf//sortkeys:go_default_library",
  884. "//vendor/github.com/gogo/protobuf/types:go_default_library": "@com_github_gogo_protobuf//types:go_default_library",
  885. "//vendor/github.com/gogo/protobuf/jsonpb:go_default_library": "@com_github_gogo_protobuf//jsonpb:go_default_library",
  886. "//vendor/google.golang.org/grpc/codes:go_default_library": "@org_golang_google_grpc//codes:go_default_library",
  887. "//vendor/google.golang.org/grpc/credentials:go_default_library": "@org_golang_google_grpc//credentials:go_default_library",
  888. "//vendor/google.golang.org/grpc/metadata:go_default_library": "@org_golang_google_grpc//metadata:go_default_library",
  889. "//vendor/google.golang.org/grpc/peer:go_default_library": "@org_golang_google_grpc//peer:go_default_library",
  890. "//vendor/google.golang.org/grpc/status:go_default_library": "@org_golang_google_grpc//status:go_default_library",
  891. "//vendor/google.golang.org/grpc/resolver:go_default_library": "@org_golang_google_grpc//resolver:go_default_library",
  892. "//vendor/google.golang.org/grpc/balancer:go_default_library": "@org_golang_google_grpc//balancer:go_default_library",
  893. "//vendor/google.golang.org/grpc/balancer/base:go_default_library": "@org_golang_google_grpc//balancer/base:go_default_library",
  894. "//vendor/google.golang.org/grpc/connectivity:go_default_library": "@org_golang_google_grpc//connectivity:go_default_library",
  895. "//vendor/google.golang.org/grpc:go_default_library": "@org_golang_google_grpc//:go_default_library",
  896. "//vendor/google.golang.org/grpc/grpclog:go_default_library": "@org_golang_google_grpc//grpclog:go_default_library",
  897. "//vendor/google.golang.org/grpc/interop:go_default_library": "@org_golang_google_grpc//interop:go_default_library",
  898. "//vendor/google.golang.org/grpc/interop/grpc_testing:go_default_library": "@org_golang_google_grpc//interop/grpc_testing:go_default_library",
  899. "//vendor/google.golang.org/grpc/stress/grpc_testing:go_default_library": "@org_golang_google_grpc//stress/grpc_testing:go_default_library",
  900. "//vendor/google.golang.org/grpc/reflection:go_default_library": "@org_golang_google_grpc//reflection:go_default_library",
  901. "//vendor/google.golang.org/grpc/testdata:go_default_library": "@org_golang_google_grpc//testdata:go_default_library",
  902. "//vendor/google.golang.org/grpc/interop/server:go_default_library": "@org_golang_google_grpc//interop/server:go_default_library",
  903. "//vendor/google.golang.org/grpc/interop/client:go_default_library": "@org_golang_google_grpc//interop/client:go_default_library",
  904. "//vendor/google.golang.org/grpc/interop/http2:go_default_library": "@org_golang_google_grpc//interop/http2:go_default_library",
  905. "//vendor/google.golang.org/grpc/stress/client:go_default_library": "@org_golang_google_grpc//stress/client:go_default_library",
  906. "//vendor/google.golang.org/grpc/keepalive:go_default_library": "@org_golang_google_grpc//keepalive:go_default_library",
  907. "//vendor/google.golang.org/grpc/encoding/gzip:go_default_library": "@org_golang_google_grpc//encoding/gzip:go_default_library",
  908. "//vendor/google.golang.org/grpc/stats:go_default_library": "@org_golang_google_grpc//stats:go_default_library",
  909. "//vendor/google.golang.org/grpc/tap:go_default_library": "@org_golang_google_grpc//tap:go_default_library",
  910. "//vendor/google.golang.org/grpc/encoding:go_default_library": "@org_golang_google_grpc//encoding:go_default_library",
  911. "//vendor/google.golang.org/genproto/googleapis/rpc/status:go_default_library": "@org_golang_google_genproto//googleapis/rpc/status:go_default_library",
  912. "//vendor/golang.org/x/net/context:go_default_library": "@org_golang_x_net//context:go_default_library",
  913. "//vendor/golang.org/x/net/http2:go_default_library": "@org_golang_x_net//http2:go_default_library",
  914. "//vendor/golang.org/x/net/proxy:go_default_library": "@org_golang_x_net//proxy:go_default_library",
  915. "//vendor/golang.org/x/net/html:go_default_library": "@org_golang_x_net//html:go_default_library",
  916. "//vendor/golang.org/x/net/html/atom:go_default_library": "@org_golang_x_net//html/atom:go_default_library",
  917. "//vendor/golang.org/x/net/http2/hpack:go_default_library": "@org_golang_x_net//http2/hpack:go_default_library",
  918. "//vendor/golang.org/x/net/context/ctxhttp:go_default_library": "@org_golang_x_net//context/ctxhttp:go_default_library",
  919. "//vendor/golang.org/x/net/ipv4:go_default_library": "@org_golang_x_net//ipv4:go_default_library",
  920. "//vendor/golang.org/x/net/ipv6:go_default_library": "@org_golang_x_net//ipv6:go_default_library",
  921. "//vendor/golang.org/x/net/trace:go_default_library": "@org_golang_x_net//trace:go_default_library",
  922. "//vendor/golang.org/x/net/websocket:go_default_library": "@org_golang_x_net//websocket:go_default_library",
  923. }
  924. for _, v := range dep {
  925. mapdep, ok := mapping[v]
  926. if ok {
  927. result = append(result, mapdep)
  928. } else {
  929. result = append(result, v)
  930. }
  931. }
  932. return result
  933. }
  934. func protoMap(path string, dep []string) []string {
  935. result := []string{}
  936. removeMap := map[string]struct{}{
  937. "//library/time:go_default_library": struct{}{},
  938. }
  939. mapping := map[string]string{
  940. "github.com/gogo/protobuf/gogoproto/gogo.proto": "@gogo_special_proto//github.com/gogo/protobuf/gogoproto",
  941. "google/protobuf/any.proto": "@com_google_protobuf//:any_proto",
  942. "google/api/annotations.proto": "@go_googleapis//google/api:annotations_proto",
  943. "google/protobuf/descriptor.proto": "@com_google_protobuf//:descriptor_proto",
  944. "google/protobuf/empty.proto": "@com_google_protobuf//:empty_proto",
  945. }
  946. for _, v := range dep {
  947. if _, ok := removeMap[v]; ok {
  948. continue
  949. }
  950. mapdep, ok := mapping[v]
  951. if ok {
  952. result = append(result, mapdep)
  953. } else {
  954. if custom := customgoproto(path, v); custom != "" {
  955. result = append(result, custom)
  956. }
  957. }
  958. }
  959. return result
  960. }
  961. func goProtoMap(path string, dep []string) []string {
  962. result := []string{}
  963. mapping := map[string]string{
  964. // gogo
  965. "github.com/gogo/protobuf/gogoproto/gogo.proto": "@com_github_gogo_protobuf//gogoproto:go_default_library",
  966. // googleapis
  967. "google/api/annotations.proto": "@go_googleapis//google/api:annotations_go_proto",
  968. "google/rpc/errdetails.proto": "@go_googleapis//google/rpc:errdetails_go_proto",
  969. "google/rpc/code.proto": "@go_googleapis//google/rpc:code_go_proto",
  970. "google/rpc/status.proto": "@go_googleapis//google/rpc:status_go_proto",
  971. // golang protobuf
  972. "@com_github_golang_protobuf//ptypes/any:go_default_library": "@io_bazel_rules_go//proto/wkt:any_go_proto",
  973. // google protobuf
  974. "google/protobuf/wrappers.proto": "@io_bazel_rules_go//proto/wkt:wrappers_go_proto",
  975. "google/protobuf/timestamp.proto": "@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
  976. "google/protobuf/struct.proto": "@io_bazel_rules_go//proto/wkt:struct_go_proto",
  977. "google/protobuf/field.proto": "@io_bazel_rules_go//proto/wkt:field_mask_go_proto",
  978. "google/protobuf/empty.proto": "@io_bazel_rules_go//proto/wkt:empty_go_proto",
  979. "google/protobuf/duration.proto": "@io_bazel_rules_go//proto/wkt:duration_go_proto",
  980. "google/protobuf/compiler.proto": "@io_bazel_rules_go//proto/wkt:compiler_plugin_go_proto",
  981. "google/protobuf/descriptor.proto": "@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
  982. "google/protobuf/api.proto": "@io_bazel_rules_go//proto/wkt:api_go_proto",
  983. "google/protobuf/type.proto": "@io_bazel_rules_go//proto/wkt:type_go_proto",
  984. "google/protobuf/source.proto": "@io_bazel_rules_go//proto/wkt:source_context_go_proto",
  985. "google/protobuf/any.proto": "@io_bazel_rules_go//proto/wkt:any_go_proto",
  986. }
  987. for _, v := range dep {
  988. mapdep, ok := mapping[v]
  989. if ok {
  990. result = append(result, mapdep)
  991. } else {
  992. if custom := customgoprotolibrary(path, v); custom != "" {
  993. result = append(result, custom)
  994. }
  995. }
  996. }
  997. return result
  998. }
  999. func addExpr(x []bzl.Expr, y []bzl.Expr) []bzl.Expr {
  1000. return append(x, y...)
  1001. }
  1002. func customgoprotolibrary(path, dep string) string {
  1003. if strings.HasPrefix(dep, "library") || strings.HasPrefix(dep, "app") && strings.HasSuffix(dep, ".proto") {
  1004. deplist := strings.Split(dep, "/")
  1005. last := deplist[:len(deplist)-1]
  1006. if strings.Join(last, "/") == path {
  1007. return ""
  1008. }
  1009. last[len(last)-1] = last[len(last)-1] + ":" + last[len(last)-1] + "_go_proto"
  1010. dep = strings.Join(last, "/")
  1011. return "//" + dep
  1012. }
  1013. return dep
  1014. }
  1015. func customgoproto(path, dep string) string {
  1016. if strings.HasPrefix(dep, "library") || strings.HasPrefix(dep, "app") && strings.HasSuffix(dep, ".proto") {
  1017. deplist := strings.Split(dep, "/")
  1018. last := deplist[:len(deplist)-1]
  1019. if strings.Join(last, "/") == path {
  1020. return ""
  1021. }
  1022. last[len(last)-1] = last[len(last)-1] + ":" + last[len(last)-1] + "_proto"
  1023. dep = strings.Join(last, "/")
  1024. return "//" + dep
  1025. }
  1026. return dep
  1027. }