Skip to content

Commit b8450b9

Browse files
authored
Fix: black only respects the root gitignore. (psf#2225)
Commit history before merge: Black now respects .gitignore files in all levels, not only root/.gitignore file (apply .gitignore rules like git does). * Fix: typo * Fix: respect .gitignore files in all levels. * Add: CHANGELOG note. * Fix: TypeError: unsupported operand type(s) for +: 'NoneType' and 'PathSpec' * Update docs. * Fix: no parent .gitignore * Add a comment since the if expression is a bit hard to understand * Update tests - conver no parent .gitignore case. * Use main's Pipfile.lock instead The original changes in Pipfile.lock are whitespace only. The changes turned the JSON's file indentation from 4 to 2. Effectively this happened: `json.dumps(json.loads(old_pipfile_lock), indent=2) + "\n"`. Just using main's Pipfile.lock instead of undoing the changes because 1) I don't know how to do that easily and quickly, and 2) there's a merge conflict. Co-authored-by: Richard Si <[email protected]> * Merge remote-tracking branch 'upstream/main' into i1730 … conflicts for days ay?
1 parent 60f8bd2 commit b8450b9

File tree

14 files changed

+45
-4
lines changed

14 files changed

+45
-4
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### _Black_
66

7+
- Respect `.gitignore` files in all levels, not only `root/.gitignore` file (apply
8+
`.gitignore` rules like `git` does) (#2225)
79
- Restored compatibility with Click 8.0 on Python 3.6 when LANG=C used (#2227)
810

911
### _Blackd_

docs/usage_and_configuration/file_collection_and_discovery.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ then write the above files to `.cache/black/<version>/`.
3030
## .gitignore
3131

3232
If `--exclude` is not set, _Black_ will automatically ignore files and directories in
33-
`.gitignore` file, if present. The `.gitignore` file must be in the project root to be
34-
used and nested `.gitignore` aren't supported.
33+
`.gitignore` file(s), if present.
3534

3635
If you want _Black_ to continue using `.gitignore` while also configuring the exclusion
3736
rules, please use `--extend-exclude`.

src/black/files.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ def gen_python_files(
204204
continue
205205

206206
if child.is_dir():
207+
# If gitignore is None, gitignore usage is disabled, while a Falsey
208+
# gitignore is when the directory doesn't have a .gitignore file.
207209
yield from gen_python_files(
208210
child.iterdir(),
209211
root,
@@ -212,7 +214,7 @@ def gen_python_files(
212214
extend_exclude,
213215
force_exclude,
214216
report,
215-
gitignore,
217+
gitignore + get_gitignore(child) if gitignore is not None else None,
216218
)
217219

218220
elif child.is_file():
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[build-system]
2+
requires = ["setuptools>=41.0", "setuptools-scm", "wheel"]
3+
build-backend = "setuptools.build_meta"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# should be excluded (root/.gitignore)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# should be included
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# should be included
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
b.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# should be excluded (root/.gitignore)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# should be excluded (child/.gitignore)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# should be included

tests/data/nested_gitignore_tests/x.py

Whitespace-only changes.

tests/test_black.py

+28-1
Original file line numberDiff line numberDiff line change
@@ -1406,7 +1406,7 @@ def test_include_exclude(self) -> None:
14061406
)
14071407
self.assertEqual(sorted(expected), sorted(sources))
14081408

1409-
def test_gitingore_used_as_default(self) -> None:
1409+
def test_gitignore_used_as_default(self) -> None:
14101410
path = Path(THIS_DIR / "data" / "include_exclude_tests")
14111411
include = re.compile(r"\.pyi?$")
14121412
extend_exclude = re.compile(r"/exclude/")
@@ -1703,6 +1703,33 @@ def test_gitignore_exclude(self) -> None:
17031703
)
17041704
self.assertEqual(sorted(expected), sorted(sources))
17051705

1706+
def test_nested_gitignore(self) -> None:
1707+
path = Path(THIS_DIR / "data" / "nested_gitignore_tests")
1708+
include = re.compile(r"\.pyi?$")
1709+
exclude = re.compile(r"")
1710+
root_gitignore = black.files.get_gitignore(path)
1711+
report = black.Report()
1712+
expected: List[Path] = [
1713+
Path(path / "x.py"),
1714+
Path(path / "root/b.py"),
1715+
Path(path / "root/c.py"),
1716+
Path(path / "root/child/c.py"),
1717+
]
1718+
this_abs = THIS_DIR.resolve()
1719+
sources = list(
1720+
black.gen_python_files(
1721+
path.iterdir(),
1722+
this_abs,
1723+
include,
1724+
exclude,
1725+
None,
1726+
None,
1727+
report,
1728+
root_gitignore,
1729+
)
1730+
)
1731+
self.assertEqual(sorted(expected), sorted(sources))
1732+
17061733
def test_empty_include(self) -> None:
17071734
path = THIS_DIR / "data" / "include_exclude_tests"
17081735
report = black.Report()

0 commit comments

Comments
 (0)