...
1
15
16
17
18
19
20
21
22
23
24
25 package main
26
27 import (
28 "bytes"
29 "flag"
30 "fmt"
31 "log"
32 "os"
33 "path/filepath"
34 "sort"
35 "strings"
36
37 "github.com/bazelbuild/bazel-gazelle/repo"
38 "github.com/bazelbuild/bazel-gazelle/rule"
39 )
40
41 const (
42 goRepoRuleKind = "go_repository"
43 httpArchiveRuleKind = "http_archive"
44 )
45
46 var (
47 configSource = flag.String("config_source", "", "a file that is read to learn about external repositories")
48 configDest = flag.String("config_dest", "", "destination file for the generated repo config")
49 )
50
51 type byName []*rule.Rule
52
53 func (s byName) Len() int { return len(s) }
54 func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
55 func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
56
57 func main() {
58 log.SetFlags(0)
59 log.SetPrefix("generate_repo_config: ")
60
61 flag.Parse()
62 if *configDest == "" {
63 log.Fatal("-config_dest must be set")
64 }
65 if *configSource == "" {
66 log.Fatal("-config_source must be set")
67 }
68 if flag.NArg() != 0 {
69 log.Fatal("generate_repo_config does not accept positional arguments")
70 }
71 files, err := generateRepoConfig(*configDest, *configSource)
72 if err != nil {
73 log.Fatal(err)
74 }
75 for _, f := range files {
76 fmt.Fprintln(os.Stdout, f)
77 }
78 }
79
80 func generateRepoConfig(configDest, configSource string) ([]string, error) {
81 var buf bytes.Buffer
82 buf.WriteString("# Code generated by generate_repo_config.go; DO NOT EDIT.\n")
83
84 sourceFile, err := rule.LoadWorkspaceFile(configSource, "")
85 if err != nil {
86 return nil, err
87 }
88 repos, repoFileMap, err := repo.ListRepositories(sourceFile)
89 if err != nil {
90 return nil, err
91 }
92 sort.Stable(byName(repos))
93
94 seenFile := make(map[*rule.File]bool)
95 var sortedFiles []*rule.File
96 for _, f := range repoFileMap {
97 if !seenFile[f] {
98 seenFile[f] = true
99 sortedFiles = append(sortedFiles, f)
100 }
101 }
102 sort.SliceStable(sortedFiles, func(i, j int) bool {
103 if cmp := strings.Compare(sortedFiles[i].Path, sortedFiles[j].Path); cmp != 0 {
104 return cmp < 0
105 }
106 return sortedFiles[i].DefName < sortedFiles[j].DefName
107 })
108
109 destFile := rule.EmptyFile(configDest, "")
110 for _, rsrc := range repos {
111 var rdst *rule.Rule
112 if rsrc.Kind() == goRepoRuleKind {
113 rdst = rule.NewRule(goRepoRuleKind, rsrc.Name())
114 rdst.SetAttr("importpath", rsrc.AttrString("importpath"))
115 if namingConvention := rsrc.AttrString("build_naming_convention"); namingConvention != "" {
116 rdst.SetAttr("build_naming_convention", namingConvention)
117 }
118 } else if rsrc.Kind() == httpArchiveRuleKind && rsrc.Name() == "io_bazel_rules_go" {
119 rdst = rule.NewRule(httpArchiveRuleKind, "io_bazel_rules_go")
120 rdst.SetAttr("urls", rsrc.AttrStrings("urls"))
121 }
122 if rdst != nil {
123 rdst.Insert(destFile)
124 }
125 }
126
127 buf.WriteString("\n")
128 buf.Write(destFile.Format())
129 if err := os.WriteFile(configDest, buf.Bytes(), 0o666); err != nil {
130 return nil, err
131 }
132
133 files := make([]string, 0, len(sortedFiles))
134 for _, m := range sortedFiles {
135
136
137
138
139
140 f, err := filepath.Rel(filepath.Dir(configSource), m.Path)
141 if err != nil {
142 return nil, err
143 }
144 files = append(files, f)
145 }
146
147 return files, nil
148 }
149
View as plain text