Skip to content

Commit c84efd9

Browse files
authored
Fix: Buildifier cannot find .buildifier-tables.json when run from a subdirectory (#1312)
* Fix: Resolve Relative Path Issues for .buildifier-tables.json in AddTables Configuration This commit addresses an issue where Buildifier fails to locate the .buildifier-tables.json file when specifying a relative path in the AddTables configuration and running Buildifier from subdirectories within the workspace. * Fix TestFindTablePath: wrong tmp path, removing, result comparing * Refactoring: minor fix test style * Small code improvements * Fix macOs test failuer: On MacOS '/tmp' is a symlink to '/private/tmp'
1 parent cf7952d commit c84efd9

File tree

2 files changed

+127
-4
lines changed

2 files changed

+127
-4
lines changed

buildifier/config/config.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,28 @@ func FindConfigPath(rootDir string) string {
6767
return filepath.Join(dirname, buildifierJSONFilename)
6868
}
6969

70+
// findTablesPath locates the specified table file starting from the process's
71+
// current working directory. It searches upward through the directory tree
72+
// until the file is found or the root of the workspace is reached.
73+
func findTablesPath(file string) (string, error) {
74+
if wspace.IsRegularFile(file) {
75+
return file, nil
76+
}
77+
rootDir, _ := os.Getwd()
78+
dirname, err := wspace.Find(
79+
rootDir,
80+
map[string]func(os.FileInfo) bool{
81+
file: func(fi os.FileInfo) bool {
82+
return fi.Mode()&os.ModeType == 0
83+
},
84+
},
85+
)
86+
if err != nil {
87+
return file, err
88+
}
89+
return filepath.Join(dirname, file), nil
90+
}
91+
7092
// Config is used to configure buildifier
7193
type Config struct {
7294
// InputType determines the input file type: build (for BUILD files), bzl
@@ -190,14 +212,22 @@ func (c *Config) Validate(args []string) error {
190212
}
191213

192214
if c.TablesPath != "" {
193-
if err := tables.ParseAndUpdateJSONDefinitions(c.TablesPath, false); err != nil {
194-
return fmt.Errorf("failed to parse %s for -tables: %w", c.TablesPath, err)
215+
foundTablesPath, err := findTablesPath(c.TablesPath)
216+
if err != nil {
217+
return fmt.Errorf("failed to find %s for -tables: %w", c.TablesPath, err)
218+
}
219+
if err := tables.ParseAndUpdateJSONDefinitions(foundTablesPath, false); err != nil {
220+
return fmt.Errorf("failed to parse %s for -tables: %w", foundTablesPath, err)
195221
}
196222
}
197223

198224
if c.AddTablesPath != "" {
199-
if err := tables.ParseAndUpdateJSONDefinitions(c.AddTablesPath, true); err != nil {
200-
return fmt.Errorf("failed to parse %s for -add_tables: %w", c.AddTablesPath, err)
225+
foundTablesPath, err := findTablesPath(c.AddTablesPath)
226+
if err != nil {
227+
return fmt.Errorf("failed to find %s for -add_tables: %w", c.AddTablesPath, err)
228+
}
229+
if err := tables.ParseAndUpdateJSONDefinitions(foundTablesPath, true); err != nil {
230+
return fmt.Errorf("failed to parse %s for -add_tables: %w", foundTablesPath, err)
201231
}
202232
}
203233

buildifier/config/config_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,3 +581,96 @@ func TestFindConfigPath(t *testing.T) {
581581
})
582582
}
583583
}
584+
585+
func TestFindTablePath(t *testing.T) {
586+
tests := []struct {
587+
name string
588+
file string
589+
files []string
590+
wd string
591+
want string
592+
wantErr error
593+
}{
594+
{
595+
name: "default",
596+
file: ".buildifier-tables.json",
597+
files: []string{".buildifier-tables.json"},
598+
wd: "",
599+
want: ".buildifier-tables.json",
600+
wantErr: nil,
601+
},
602+
{
603+
name: "working-dir-is-subdir",
604+
file: ".buildifier-tables.json",
605+
files: []string{".buildifier-tables.json", "foo/BUILD.bazel"},
606+
wd: "foo",
607+
want: ".buildifier-tables.json",
608+
wantErr: nil,
609+
},
610+
{
611+
name: "relative-subdir",
612+
file: "bar/.buildifier-tables.json",
613+
files: []string{"bar/.buildifier-tables.json", "foo/BUILD.bazel"},
614+
wd: "foo",
615+
want: "bar/.buildifier-tables.json",
616+
wantErr: nil,
617+
},
618+
{
619+
name: "file-not-found",
620+
file: "nonexistentFile.json",
621+
files: []string{".buildifier-tables.json"},
622+
wd: "",
623+
want: "nonexistentFile.json",
624+
wantErr: os.ErrNotExist,
625+
},
626+
}
627+
628+
for _, tc := range tests {
629+
t.Run(tc.name, func(t *testing.T) {
630+
tmp := t.TempDir()
631+
632+
// On MacOS "/tmp" is a symlink to "/private/tmp". Resolve it to make the testing easier
633+
tmp, err := filepath.EvalSymlinks(tmp)
634+
if err != nil {
635+
t.Fatalf("failed to resolve symlink for temporary directory: %v", err)
636+
}
637+
t.Log("tmp:", tmp)
638+
639+
if tc.wd != "" {
640+
if err := os.MkdirAll(filepath.Join(tmp, tc.wd), os.ModePerm); err != nil {
641+
t.Fatalf("failed to create working directory: %v", err)
642+
}
643+
if err := os.Chdir(filepath.Join(tmp, tc.wd)); err != nil {
644+
t.Fatalf("failed to change working directory: %v", err)
645+
}
646+
} else {
647+
if err := os.Chdir(tmp); err != nil {
648+
t.Fatalf("failed to change working directory: %v", err)
649+
}
650+
}
651+
652+
for _, file := range tc.files {
653+
filePath := filepath.Join(tmp, file)
654+
dir := filepath.Dir(filePath)
655+
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
656+
t.Fatalf("failed to create directory %v: %v", dir, err)
657+
}
658+
if err := os.WriteFile(filePath, []byte("{}"), 0644); err != nil {
659+
t.Fatalf("failed to create file %v: %v", filePath, err)
660+
}
661+
}
662+
663+
got, err := findTablesPath(tc.file)
664+
got = strings.TrimPrefix(got, tmp)
665+
got = strings.TrimPrefix(got, "/")
666+
667+
if (err != nil) != (tc.wantErr != nil) || (err != nil && tc.wantErr.Error() != err.Error()) {
668+
t.Errorf("FindTablePath wantErr = %q, error = %q", tc.wantErr, err)
669+
}
670+
671+
if tc.want != got {
672+
t.Errorf("FindTablePath want = %q, got = %q", tc.want, got)
673+
}
674+
})
675+
}
676+
}

0 commit comments

Comments
 (0)