Skip to content

Commit 7fe43c8

Browse files
authored
fix(core): vcs root resolution (#9514)
1 parent 1302740 commit 7fe43c8

8 files changed

Lines changed: 159 additions & 11 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Fixed [#6964](https://github.com/biomejs/biome/issues/6964): Biome now correctly resolves the `.gitignore` file relative to `vcs.root` when configured. Previously, the `vcs.root` setting was ignored and Biome always looked for the ignore file in the workspace directory.

crates/biome_cli/tests/cases/vcs_ignored_files.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,52 @@ fn should_fail_when_ignore_file_is_absent() {
264264
));
265265
}
266266

267+
#[test]
268+
fn should_resolve_gitignore_using_vcs_root() {
269+
let mut fs = TemporaryFs::new("should_resolve_gitignore_using_vcs_root");
270+
let mut console = BufferConsole::default();
271+
272+
// .gitignore is at the repo root (one level up from the workspace)
273+
fs.create_file(".gitignore", "**/file2.js\n");
274+
275+
// biome.json is in a subdirectory (workspace), with vcs.root pointing to parent
276+
fs.create_file(
277+
"workspace/biome.json",
278+
r#"{
279+
"vcs": {
280+
"enabled": true,
281+
"clientKind": "git",
282+
"useIgnoreFile": true,
283+
"root": ".."
284+
}
285+
}"#,
286+
);
287+
288+
// This file should be formatted (not ignored)
289+
fs.create_file("workspace/file1.js", UNFORMATTED);
290+
// This file should be ignored by .gitignore at the root
291+
fs.create_file("workspace/file2.js", UNFORMATTED);
292+
293+
// Run CLI from the workspace subdirectory
294+
fs.append_to_working_directory("workspace");
295+
296+
let result = run_cli_with_dyn_fs(
297+
Box::new(fs.create_os()),
298+
&mut console,
299+
Args::from(["format", fs.cli_path()].as_slice()),
300+
);
301+
302+
assert!(result.is_err(), "run_cli returned {result:?}");
303+
304+
assert_cli_snapshot(SnapshotPayload::new(
305+
module_path!(),
306+
"should_resolve_gitignore_using_vcs_root",
307+
fs.create_mem(),
308+
console,
309+
result,
310+
));
311+
}
312+
267313
#[test]
268314
fn should_ignore_absolute_paths_in_ignore_file_with_glob() {
269315
let mut fs = TemporaryFs::new("should_ignore_absolute_paths_in_ignore_file_with_glob");

crates/biome_cli/tests/snapshots/main_cases_vcs_ignored_files/ignore_vcs_os_independent_parse.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ file3.js
2626

2727
```js
2828
blah.call();
29+
2930
```
3031

3132
## `file2.js`

crates/biome_cli/tests/snapshots/main_cases_vcs_ignored_files/include_vcs_ignore_cascade.snap

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ file4.js
2929
## `file1.js`
3030

3131
```js
32-
statement( )
32+
statement();
33+
3334
```
3435

3536
## `file2.js`
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
source: crates/biome_cli/tests/snap_test.rs
3+
expression: redactor(content)
4+
---
5+
## `workspace/biome.json`
6+
7+
```json
8+
{
9+
"vcs": {
10+
"enabled": true,
11+
"clientKind": "git",
12+
"useIgnoreFile": true,
13+
"root": ".."
14+
}
15+
}
16+
```
17+
18+
## `.gitignore`
19+
20+
```gitignore
21+
**/file2.js
22+
23+
```
24+
25+
## `workspace/file1.js`
26+
27+
```js
28+
statement( )
29+
```
30+
31+
## `workspace/file2.js`
32+
33+
```js
34+
statement( )
35+
```
36+
37+
# Termination Message
38+
39+
```block
40+
format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
41+
42+
× Some errors were emitted while running checks.
43+
44+
45+
46+
```
47+
48+
# Emitted Messages
49+
50+
```block
51+
biome.json format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
52+
53+
× Formatter would have printed the following content:
54+
55+
1 1 │ {
56+
2- ············"vcs":·{
57+
3 │ - ················"enabled"true,
58+
4 │ - ················"clientKind""git",
59+
5 │ - ················"useIgnoreFile"true,
60+
6 │ - ················"root"".."
61+
7- ············}
62+
8- ········}
63+
2 │ + → "vcs":·{
64+
3+ → → "enabled"true,
65+
4+ → → "clientKind""git",
66+
5+ → → "useIgnoreFile"true,
67+
6+ → → "root"".."
68+
7+}
69+
8 │ + }
70+
9 │ +
71+
72+
73+
```
74+
75+
```block
76+
file1.js format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
77+
78+
× Formatter would have printed the following content:
79+
80+
1 │ - ··statement(··)··
81+
1 │ + statement();
82+
2 │ +
83+
84+
85+
```
86+
87+
```block
88+
Checked 2 files in <TIME>. No fixes applied.
89+
Found 2 errors.
90+
```

crates/biome_cli/tests/snapshots/main_commands_migrate/should_migrate_jsonc_with_config_path.snap

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ expression: redactor(content)
55
## `base.biome.jsonc`
66

77
```jsonc
8-
9-
// this is another comment
10-
{
11-
// this is a comment
12-
"organizeImports": {
13-
"enabled": true
14-
}
8+
// this is another comment
9+
{
10+
// this is a comment
11+
"root": false,
12+
// this is a comment
13+
"assist": { "actions": { "source": { "organizeImports": "on" } } }
1514
}
15+
1616
```
1717

1818
# Emitted Messages

crates/biome_fs/src/fs/os.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,8 @@ impl TemporaryFs {
490490
/// will be stripped of the working directory path, making snapshots predictable.
491491
pub fn create_mem(&self) -> MemoryFileSystem {
492492
let fs = MemoryFileSystem::default();
493-
for (path, content) in self.files.iter() {
493+
for (path, _) in self.files.iter() {
494+
let content = fs::read_to_string(path.as_std_path()).expect("File to exist");
494495
fs.insert(
495496
path.clone()
496497
.strip_prefix(self.project_directory.as_str())

crates/biome_service/src/workspace/server.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use biome_diagnostics::{
4646
Diagnostic, DiagnosticExt, Severity, serde::Diagnostic as SerdeDiagnostic,
4747
};
4848
use biome_formatter::Printed;
49-
use biome_fs::{BiomePath, ConfigName, PathKind};
49+
use biome_fs::{BiomePath, ConfigName, PathKind, normalize_path};
5050
use biome_grit_patterns::{CompilePatternOptions, GritQuery, compile_pattern_with_options};
5151
use biome_html_syntax::HtmlRoot;
5252
use biome_js_syntax::{AnyJsRoot, LanguageVariant, ModuleKind};
@@ -1240,7 +1240,11 @@ impl Workspace for WorkspaceServer {
12401240
} else {
12411241
// If the configuration is a root one, we also load the ignore files
12421242
if settings.is_vcs_enabled() && settings.vcs_settings.should_use_ignore_file() {
1243-
let directory = workspace_directory.unwrap_or_default();
1243+
let directory = settings
1244+
.vcs_settings
1245+
.to_base_path(workspace_directory.as_deref())
1246+
.map(|p| normalize_path(&p))
1247+
.unwrap_or_default();
12441248
match settings.vcs_settings.client_kind {
12451249
None => {}
12461250
Some(VcsClientKind::Git) => {

0 commit comments

Comments
 (0)