Fix: black only respects the root gitignore. (#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 <63936253+ichard26@users.noreply.github.com>

* Merge remote-tracking branch 'upstream/main' into i1730 …
  
  conflicts for days ay?
This commit is contained in:
Hadi Alqattan 2021-05-16 20:51:27 +03:00 committed by GitHub
parent 60f8bd2c89
commit b8450b9fae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 45 additions and 4 deletions

View File

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

View File

@ -30,8 +30,7 @@ then write the above files to `.cache/black/<version>/`.
## .gitignore
If `--exclude` is not set, _Black_ will automatically ignore files and directories in
`.gitignore` file, if present. The `.gitignore` file must be in the project root to be
used and nested `.gitignore` aren't supported.
`.gitignore` file(s), if present.
If you want _Black_ to continue using `.gitignore` while also configuring the exclusion
rules, please use `--extend-exclude`.

View File

@ -204,6 +204,8 @@ def gen_python_files(
continue
if child.is_dir():
# If gitignore is None, gitignore usage is disabled, while a Falsey
# gitignore is when the directory doesn't have a .gitignore file.
yield from gen_python_files(
child.iterdir(),
root,
@ -212,7 +214,7 @@ def gen_python_files(
extend_exclude,
force_exclude,
report,
gitignore,
gitignore + get_gitignore(child) if gitignore is not None else None,
)
elif child.is_file():

View File

@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools>=41.0", "setuptools-scm", "wheel"]
build-backend = "setuptools.build_meta"

View File

@ -0,0 +1 @@
a.py

View File

@ -0,0 +1 @@
# should be excluded (root/.gitignore)

View File

@ -0,0 +1 @@
# should be included

View File

@ -0,0 +1 @@
# should be included

View File

@ -0,0 +1 @@
b.py

View File

@ -0,0 +1 @@
# should be excluded (root/.gitignore)

View File

@ -0,0 +1 @@
# should be excluded (child/.gitignore)

View File

@ -0,0 +1 @@
# should be included

View File

View File

@ -1406,7 +1406,7 @@ def test_include_exclude(self) -> None:
)
self.assertEqual(sorted(expected), sorted(sources))
def test_gitingore_used_as_default(self) -> None:
def test_gitignore_used_as_default(self) -> None:
path = Path(THIS_DIR / "data" / "include_exclude_tests")
include = re.compile(r"\.pyi?$")
extend_exclude = re.compile(r"/exclude/")
@ -1703,6 +1703,33 @@ def test_gitignore_exclude(self) -> None:
)
self.assertEqual(sorted(expected), sorted(sources))
def test_nested_gitignore(self) -> None:
path = Path(THIS_DIR / "data" / "nested_gitignore_tests")
include = re.compile(r"\.pyi?$")
exclude = re.compile(r"")
root_gitignore = black.files.get_gitignore(path)
report = black.Report()
expected: List[Path] = [
Path(path / "x.py"),
Path(path / "root/b.py"),
Path(path / "root/c.py"),
Path(path / "root/child/c.py"),
]
this_abs = THIS_DIR.resolve()
sources = list(
black.gen_python_files(
path.iterdir(),
this_abs,
include,
exclude,
None,
None,
report,
root_gitignore,
)
)
self.assertEqual(sorted(expected), sorted(sources))
def test_empty_include(self) -> None:
path = THIS_DIR / "data" / "include_exclude_tests"
report = black.Report()