Skip to content

Commit 2c900b7

Browse files
committed
checkpoint: before remove starlark_library gen
1 parent c88be12 commit 2c900b7

File tree

6 files changed

+343
-24
lines changed

6 files changed

+343
-24
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/* Copyright 2020 The Bazel Authors. All rights reserved.
2+
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+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
package starlarkbundle
17+
18+
import (
19+
"os"
20+
"path/filepath"
21+
"testing"
22+
)
23+
24+
func TestRemoveAbsolutePathsFromBazelignore(t *testing.T) {
25+
tests := []struct {
26+
name string
27+
input string
28+
expected string
29+
removed bool
30+
}{
31+
{
32+
name: "removes absolute paths",
33+
input: `.build/
34+
/.github/
35+
.swiftpm/
36+
/.vscode/
37+
`,
38+
expected: `.build/
39+
.swiftpm/
40+
`,
41+
removed: true,
42+
},
43+
{
44+
name: "keeps relative paths",
45+
input: `.build/
46+
.github/
47+
.swiftpm/
48+
.vscode/
49+
`,
50+
expected: `.build/
51+
.github/
52+
.swiftpm/
53+
.vscode/
54+
`,
55+
removed: false,
56+
},
57+
{
58+
name: "handles empty lines",
59+
input: `.build/
60+
61+
/.github/
62+
63+
.swiftpm/
64+
`,
65+
expected: `.build/
66+
67+
68+
.swiftpm/
69+
`,
70+
removed: true,
71+
},
72+
{
73+
name: "handles comments and absolute paths",
74+
input: `# Comment
75+
.build/
76+
/absolute/path
77+
relative/path
78+
/another/absolute
79+
`,
80+
expected: `# Comment
81+
.build/
82+
relative/path
83+
`,
84+
removed: true,
85+
},
86+
{
87+
name: "empty file",
88+
input: "",
89+
expected: "",
90+
removed: false,
91+
},
92+
{
93+
name: "only absolute paths",
94+
input: `/path1
95+
/path2
96+
/path3
97+
`,
98+
expected: ``,
99+
removed: true,
100+
},
101+
}
102+
103+
for _, tt := range tests {
104+
t.Run(tt.name, func(t *testing.T) {
105+
// Create temp directory
106+
tmpDir := t.TempDir()
107+
bazelignorePath := filepath.Join(tmpDir, ".bazelignore")
108+
109+
// Write input content
110+
if err := os.WriteFile(bazelignorePath, []byte(tt.input), 0644); err != nil {
111+
t.Fatalf("failed to write test file: %v", err)
112+
}
113+
114+
// Create extension
115+
ext := NewLanguage().(*starlarkBundleLang)
116+
ext.logger = nil // Disable logging for tests
117+
118+
// Run the function
119+
err := ext.removeAbsolutePathsFromBazelignore(bazelignorePath)
120+
if err != nil {
121+
t.Fatalf("removeAbsolutePathsFromBazelignore failed: %v", err)
122+
}
123+
124+
// Read result
125+
result, err := os.ReadFile(bazelignorePath)
126+
if err != nil {
127+
t.Fatalf("failed to read result file: %v", err)
128+
}
129+
130+
if string(result) != tt.expected {
131+
t.Errorf("Content mismatch:\ngot:\n%q\n\nwant:\n%q", string(result), tt.expected)
132+
}
133+
})
134+
}
135+
}
136+
137+
func TestRemoveAbsolutePathsFromBazelignore_NonExistent(t *testing.T) {
138+
tmpDir := t.TempDir()
139+
bazelignorePath := filepath.Join(tmpDir, ".bazelignore")
140+
141+
ext := NewLanguage().(*starlarkBundleLang)
142+
ext.logger = nil
143+
144+
// Should not error on non-existent file
145+
err := ext.removeAbsolutePathsFromBazelignore(bazelignorePath)
146+
if err != nil {
147+
t.Errorf("expected no error for non-existent file, got: %v", err)
148+
}
149+
}

language/starlarkbundle/language.go

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ package starlarkbundle
2323

2424
import (
2525
"flag"
26+
"fmt"
2627
"io"
2728
"log"
2829
"maps"
2930
"os"
31+
"path/filepath"
3032
"strings"
3133

3234
"github.com/bazelbuild/bazel-gazelle/config"
@@ -39,17 +41,21 @@ import (
3941

4042
const (
4143
languageName = "starlark_bundle"
44+
starlarkBundleRepoNameDirectiveName = "starlark_bundle_repo_name"
4245
starlarkBundleRootDirectiveName = "starlark_bundle_root"
4346
starlarkBundleExcludeDirectiveName = "starlark_bundle_exclude"
4447
starlarkBundleLogFileDirectiveName = "starlark_bundle_log_file"
4548
starlarkModuleDependencyDirectiveName = "module_dependency"
49+
coarseDependencies = true
4650
)
4751

4852
type starlarkBundleLang struct {
4953
starlarkBundleRoot *string
54+
starlarkBundleRepoName string
5055
starlarkBundleExcludeDirs []string
5156
moduleDeps map[string]string
5257
starlarkLibraries map[label.Label]*rule.Rule
58+
bzlFiles map[string]bool
5359
logFile string
5460
logWriter *os.File
5561
logger *log.Logger
@@ -60,6 +66,7 @@ type starlarkBundleLang struct {
6066
func NewLanguage() language.Language {
6167
return &starlarkBundleLang{
6268
starlarkLibraries: map[label.Label]*rule.Rule{},
69+
bzlFiles: map[string]bool{},
6370
moduleDeps: map[string]string{},
6471
}
6572
}
@@ -80,7 +87,7 @@ func (ext *starlarkBundleLang) RegisterFlags(fs *flag.FlagSet, cmd string, c *co
8087

8188
func (ext *starlarkBundleLang) CheckFlags(fs *flag.FlagSet, c *config.Config) error {
8289
if ext.logFile != "" {
83-
ext.createLogger(c, ext.logFile)
90+
ext.createLogger(ext.logFile)
8491
ext.logf("CheckFlags: log file initialized from flag: %s", ext.logFile)
8592
}
8693
if ext.logger == nil {
@@ -108,6 +115,8 @@ func (ext *starlarkBundleLang) Configure(c *config.Config, rel string, f *rule.F
108115
log.Fatalf("gazelle:%s should only be set once (refusing to override %q with %q)", starlarkBundleRootDirectiveName, *ext.starlarkBundleRoot, d.Value)
109116
}
110117
ext.starlarkBundleRoot = &rel
118+
case starlarkBundleRepoNameDirectiveName:
119+
ext.starlarkBundleRepoName = d.Value
111120
case starlarkBundleExcludeDirectiveName:
112121
ext.starlarkBundleExcludeDirs = append(ext.starlarkBundleExcludeDirs, d.Value)
113122
case starlarkModuleDependencyDirectiveName:
@@ -118,13 +127,13 @@ func (ext *starlarkBundleLang) Configure(c *config.Config, rel string, f *rule.F
118127
ext.moduleDeps[nameVersion[0]] = nameVersion[1]
119128
ext.logf("Added module dependency: %q -> %q", nameVersion[0], nameVersion[1])
120129
case starlarkBundleLogFileDirectiveName:
121-
ext.createLogger(c, d.Value)
130+
ext.createLogger(d.Value)
122131
}
123132
}
124133
}
125134
}
126135

127-
func (ext *starlarkBundleLang) createLogger(c *config.Config, logFile string) {
136+
func (ext *starlarkBundleLang) createLogger(logFile string) {
128137
if logFile != "" {
129138
f, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
130139
if err == nil {
@@ -202,7 +211,12 @@ func (ext *starlarkBundleLang) Resolve(c *config.Config, ix *resolve.RuleIndex,
202211
case starlarkLibraryKind:
203212
starlarkLibraryResolve(c, ix, r, importsRaw, from, ext)
204213
case starlarkBundleKind:
205-
starlarkBundleResolve(r, ext.starlarkLibraries)
214+
if coarseDependencies {
215+
starlarkBundleResolveCoarse(r, ext.starlarkLibraries, ext.moduleDeps)
216+
} else {
217+
starlarkBundleResolve(r, ext.starlarkLibraries)
218+
219+
}
206220
}
207221
}
208222

@@ -230,6 +244,26 @@ func (ext *starlarkBundleLang) GenerateRules(args language.GenerateArgs) (result
230244

231245
ext.logf("GenerateRules: visiting %s", args.Rel)
232246

247+
if args.Rel == "" {
248+
// REPO.bazel causes visibility issues if the root BUILD file has been
249+
// deleted but still referencing non-existent rules. This should be
250+
// moved to the part where gazelle cleans up build files.
251+
repoFile := filepath.Join(args.Config.RepoRoot, "REPO.bazel")
252+
if _, err := os.Stat(repoFile); err == nil {
253+
ext.logf("Removing REPO.bazel from root package")
254+
if err := os.Remove(repoFile); err != nil {
255+
ext.logf("ERROR: failed to remove REPO.bazel: %v", err)
256+
}
257+
}
258+
259+
bazelIgnore := filepath.Join(args.Config.RepoRoot, "REPO.bazel")
260+
if _, err := os.Stat(bazelIgnore); err == nil {
261+
if err := ext.removeAbsolutePathsFromBazelignore(bazelIgnore); err != nil {
262+
ext.logf("ERROR: failed to cleanup .bazelignore file: %v", err)
263+
}
264+
}
265+
}
266+
233267
for _, r := range []language.GenerateResult{
234268
starlarkLibraryGenerate(args, ext.starlarkLibraries, ext),
235269
starlarkBundleGenerate(args, ext.starlarkBundleRoot),
@@ -264,3 +298,49 @@ func (ext *starlarkBundleLang) logf(format string, args ...any) {
264298
ext.logger.Printf(format, args...)
265299
}
266300
}
301+
302+
// removeAbsolutePathsFromBazelignore reads a .bazelignore file and removes
303+
// any lines that are absolute paths (starting with /).
304+
func (ext *starlarkBundleLang) removeAbsolutePathsFromBazelignore(bazelignorePath string) error {
305+
ext.logf("Checking .bazelignore file: %s", bazelignorePath)
306+
307+
// Read the file
308+
content, err := os.ReadFile(bazelignorePath)
309+
if err != nil {
310+
if os.IsNotExist(err) {
311+
return nil // File doesn't exist, nothing to do
312+
}
313+
return fmt.Errorf("failed to read .bazelignore: %w", err)
314+
}
315+
316+
// Split into lines
317+
lines := strings.Split(string(content), "\n")
318+
var filteredLines []string
319+
removedCount := 0
320+
321+
for _, line := range lines {
322+
trimmed := strings.TrimSpace(line)
323+
// Keep the line if it's not an absolute path
324+
if trimmed == "" || !strings.HasPrefix(trimmed, "/") {
325+
filteredLines = append(filteredLines, line)
326+
} else {
327+
ext.logf(" Removing absolute path from .bazelignore: %q", trimmed)
328+
removedCount++
329+
}
330+
}
331+
332+
// If nothing changed, don't rewrite the file
333+
if removedCount == 0 {
334+
ext.logf(" No absolute paths found in .bazelignore")
335+
return nil
336+
}
337+
338+
// Write back the filtered content
339+
newContent := strings.Join(filteredLines, "\n")
340+
if err := os.WriteFile(bazelignorePath, []byte(newContent), 0644); err != nil {
341+
return fmt.Errorf("failed to write .bazelignore: %w", err)
342+
}
343+
344+
ext.logf(" Removed %d absolute path(s) from .bazelignore", removedCount)
345+
return nil
346+
}

language/starlarkbundle/starlark_bundle.go

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ limitations under the License.
2222
package starlarkbundle
2323

2424
import (
25+
"log"
2526
"sort"
2627

2728
"github.com/bazelbuild/bazel-gazelle/config"
@@ -33,7 +34,7 @@ import (
3334

3435
const (
3536
starlarkBundleKind = "starlark_bundle"
36-
starlarkBundleName = "docs"
37+
starlarkBundleName = "bundle"
3738
)
3839

3940
var starlarkBundleKindInfo = map[string]rule.KindInfo{
@@ -60,6 +61,8 @@ func starlarkBundleImports(_ *config.Config, _ *rule.Rule, _ *rule.File) []resol
6061
return nil
6162
}
6263

64+
// starlarkBundleResolveResolve iterates the set of stalark_library rules and
65+
// adds them to it's deps list.
6366
func starlarkBundleResolve(r *rule.Rule, starlarkLibraries map[label.Label]*rule.Rule) {
6467
deps := make([]string, 0, len(starlarkLibraries))
6568
for dep := range starlarkLibraries {
@@ -72,6 +75,54 @@ func starlarkBundleResolve(r *rule.Rule, starlarkLibraries map[label.Label]*rule
7275
}
7376
}
7477

78+
// starlarkBundleResolveCoarse iterates the set of stalark_library rules and
79+
// adds them to it's deps list. It also takes out all external dependencies
80+
// from the library rules and collects them into itself, but only as the :bundle
81+
// target. This is because we cannot ensure that the fine-grained dependency
82+
// structure is correct. However, we can (hopefully) ensure that the
83+
// coarse-grained dependency graph of bundles is correct.
84+
func starlarkBundleResolveCoarse(r *rule.Rule, starlarkLibraries map[label.Label]*rule.Rule, moduleDeps map[string]string) {
85+
deps := make([]string, 0, len(starlarkLibraries))
86+
for dep, r := range starlarkLibraries {
87+
deps = append(deps, dep.String())
88+
89+
ruleDeps := r.AttrStrings("deps")
90+
p1, _ := partitionExternalDeps(ruleDeps)
91+
r.SetAttr("deps", p1)
92+
}
93+
94+
if false {
95+
for _, module := range moduleDeps {
96+
dep := label.New(module, "", "bundle")
97+
deps = append(deps, dep.String())
98+
}
99+
}
100+
101+
if len(deps) > 0 {
102+
sort.Strings(deps)
103+
r.SetAttr("deps", deps)
104+
}
105+
}
106+
107+
func partitionExternalDeps(deps []string) ([]string, []label.Label) {
108+
var p1 []string // first and third-party deps
109+
var p3 []label.Label // first and third-party deps
110+
111+
for _, dep := range deps {
112+
from, err := label.Parse(dep)
113+
if err != nil {
114+
log.Panicf("invalid dep label: %v", dep)
115+
}
116+
if from.Repo != "" {
117+
p3 = append(p3, from)
118+
} else {
119+
p1 = append(p1, dep)
120+
}
121+
}
122+
123+
return p1, p3
124+
}
125+
75126
func starlarkBundleGenerate(args language.GenerateArgs, root *string) (result language.GenerateResult) {
76127
if root == nil || *root != args.Rel {
77128
return result

0 commit comments

Comments
 (0)