Skip to content

Commit 26325c1

Browse files
authored
Merge pull request #195 from akaihola/relative-GIT_DIR
Improve Git robustness
2 parents 7fbcfa2 + 8786696 commit 26325c1

File tree

4 files changed

+24
-14
lines changed

4 files changed

+24
-14
lines changed

src/darker/__main__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ def main(argv: List[str] = None) -> int:
349349
" Either --diff or --check must be used.",
350350
)
351351

352-
missing = get_missing_at_revision(paths, revrange.rev2)
352+
missing = get_missing_at_revision(paths, revrange.rev2, root)
353353
if missing:
354354
missing_reprs = " ".join(repr(str(path)) for path in missing)
355355
rev2_repr = "the working tree" if revrange.rev2 == WORKTREE else revrange.rev2

src/darker/git.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ def git_get_content_at_revision(path: Path, revision: str, cwd: Path) -> TextDoc
7777
abspath = cwd / path
7878
return TextDocument.from_file(abspath)
7979
cmd = ["show", f"{revision}:./{path.as_posix()}"]
80-
logger.debug("[%s]$ %s", cwd, " ".join(cmd))
8180
try:
8281
return TextDocument.from_lines(
8382
_git_check_output_lines(cmd, cwd, exit_on_error=False),
@@ -177,7 +176,7 @@ def _git_check_output_lines(
177176
cmd: List[str], cwd: Path, exit_on_error: bool = True
178177
) -> List[str]:
179178
"""Log command line, run Git, split stdout to lines, exit with 123 on error"""
180-
logger.debug("[%s]$ %s", cwd, " ".join(cmd))
179+
logger.debug("[%s]$ git %s", cwd, " ".join(cmd))
181180
try:
182181
return check_output(
183182
["git"] + cmd,
@@ -200,36 +199,39 @@ def _git_check_output_lines(
200199
sys.exit(123)
201200

202201

203-
def _git_exists_in_revision(path: Path, rev2: str) -> bool:
202+
def _git_exists_in_revision(path: Path, rev2: str, cwd: Path) -> bool:
204203
"""Return ``True`` if the given path exists in the given Git revision
205204
206205
:param path: The path of the file or directory to check
207206
:param rev2: The Git revision to look at
207+
:param cwd: The Git repository root
208208
:return: ``True`` if the file or directory exists at the revision, or ``False`` if
209209
it doesn't.
210210
211211
"""
212212
# Surprise: On Windows, `git cat-file` doesn't work with backslash directory
213213
# separators in paths. We need to use Posix paths and forward slashes instead.
214214
cmd = ["git", "cat-file", "-e", f"{rev2}:{path.as_posix()}"]
215-
result = run(cmd, check=False, stderr=DEVNULL, env={"LC_ALL": "C"})
215+
logger.debug("[%s]$ %s", cwd, " ".join(cmd))
216+
result = run(cmd, cwd=str(cwd), check=False, stderr=DEVNULL, env={"LC_ALL": "C"})
216217
return result.returncode == 0
217218

218219

219-
def get_missing_at_revision(paths: Iterable[Path], rev2: str) -> Set[Path]:
220+
def get_missing_at_revision(paths: Iterable[Path], rev2: str, cwd: Path) -> Set[Path]:
220221
"""Return paths missing in the given revision
221222
222223
In case of ``WORKTREE``, just check if the files exist on the filesystem instead of
223224
asking Git.
224225
225226
:param paths: Paths to check
226227
:param rev2: The Git revision to look at, or ``WORKTREE`` for the working tree
228+
:param cwd: The Git repository root
227229
:return: The set of file or directory paths which are missing in the revision
228230
229231
"""
230232
if rev2 == WORKTREE:
231233
return {path for path in paths if not path.exists()}
232-
return {path for path in paths if not _git_exists_in_revision(path, rev2)}
234+
return {path for path in paths if not _git_exists_in_revision(path, rev2, cwd)}
233235

234236

235237
def _git_diff_name_only(

src/darker/tests/conftest.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""Configuration and fixtures for the Pytest based test suite"""
22

3-
import os
43
from pathlib import Path
54
from subprocess import check_call
65
from typing import Dict, Optional
@@ -19,9 +18,10 @@ def __init__(self, root: Path, env: Dict[str, str]):
1918
@classmethod
2019
def create_repository(cls, root: Path) -> "GitRepoFixture":
2120
"""Fixture method for creating a Git repository in the given directory"""
22-
env = os.environ.copy()
23-
# for testing, ignore ~/.gitconfig settings like templateDir and defaultBranch
24-
env["HOME"] = str(root)
21+
# For testing, ignore ~/.gitconfig settings like templateDir and defaultBranch.
22+
# Also, this makes sure GIT_DIR or other GIT_* variables are not set, and that
23+
# Git's messages are in English.
24+
env = {"HOME": str(root), "LC_ALL": "C"}
2525
instance = cls(root, env)
2626
# pylint: disable=protected-access
2727
instance._run("init")
@@ -87,6 +87,10 @@ def git_repo(tmp_path, monkeypatch):
8787
"""Create a temporary Git repository and change current working directory into it"""
8888
repository = GitRepoFixture.create_repository(tmp_path)
8989
monkeypatch.chdir(tmp_path)
90+
# While `GitRepoFixture.create_repository()` already deletes `GIT_*` environment
91+
# variables for any Git commands run by the fixture, let's explicitly remove
92+
# `GIT_DIR` in case a test should call Git directly:
93+
monkeypatch.delenv("GIT_DIR", raising=False)
9094
return repository
9195

9296

src/darker/tests/test_git.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -396,10 +396,11 @@ def test_git_exists_in_revision_git_call(retval, expect):
396396
with patch.object(git, "run") as run:
397397
run.return_value.returncode = retval
398398

399-
result = git._git_exists_in_revision(Path("path.py"), "rev2")
399+
result = git._git_exists_in_revision(Path("path.py"), "rev2", Path("."))
400400

401401
run.assert_called_once_with(
402402
["git", "cat-file", "-e", "rev2:path.py"],
403+
cwd=".",
403404
check=False,
404405
stderr=DEVNULL,
405406
env={"LC_ALL": "C"},
@@ -429,7 +430,9 @@ def test_git_exists_in_revision(git_repo, rev2, path, expect):
429430
del_a = git_repo.get_hash()
430431
git_repo.add({"dir/b.py": None}, commit="Delete dir/b.py")
431432

432-
result = git._git_exists_in_revision(Path(path), rev2.format(add=add, del_a=del_a))
433+
result = git._git_exists_in_revision(
434+
Path(path), rev2.format(add=add, del_a=del_a), git_repo.root
435+
)
433436

434437
assert result == expect
435438

@@ -450,6 +453,7 @@ def test_get_missing_at_revision(git_repo, rev2, expect):
450453
result = git.get_missing_at_revision(
451454
{Path("dir"), Path("dir/a.py"), Path("dir/b.py")},
452455
rev2.format(add=add, del_a=del_a),
456+
git_repo.root,
453457
)
454458

455459
assert result == expect
@@ -462,7 +466,7 @@ def test_get_missing_at_revision_worktree(git_repo):
462466
paths["dir/b.py"].unlink()
463467

464468
result = git.get_missing_at_revision(
465-
{Path("dir"), Path("dir/a.py"), Path("dir/b.py")}, git.WORKTREE
469+
{Path("dir"), Path("dir/a.py"), Path("dir/b.py")}, git.WORKTREE, git_repo.root
466470
)
467471

468472
assert result == {Path("dir/a.py"), Path("dir/b.py")}

0 commit comments

Comments
 (0)