diff --git a/git/util.py b/git/util.py index dee467dd3..636e79806 100644 --- a/git/util.py +++ b/git/util.py @@ -150,7 +150,10 @@ def wrapper(self: "Remote", *args: Any, **kwargs: Any) -> T: @contextlib.contextmanager def cwd(new_dir: PathLike) -> Generator[PathLike, None, None]: - """Context manager to temporarily change directory. Not reentrant.""" + """Context manager to temporarily change directory. + + This is similar to contextlib.chdir introduced in Python 3.11, but the context + manager object returned by a single call to this function is not reentrant.""" old_dir = os.getcwd() os.chdir(new_dir) try: diff --git a/test/fixtures/env_case.py b/test/fixtures/env_case.py index 120e59289..fe85ac41d 100644 --- a/test/fixtures/env_case.py +++ b/test/fixtures/env_case.py @@ -1,13 +1,18 @@ +# Steps 3 and 4 for test_it_avoids_upcasing_unrelated_environment_variable_names. + import subprocess import sys +# Step 3a: Import the module, in case that upcases the environment variable name. import git _, working_dir, env_var_name = sys.argv -# Importing git should be enough, but this really makes sure Git.execute is called. +# Step 3b: Use Git.execute explicitly, in case that upcases the environment variable. +# (Importing git should be enough, but this ensures Git.execute is called.) repo = git.Repo(working_dir) # Hold the reference. git.Git(repo.working_dir).execute(["git", "version"]) +# Step 4: Create the non-Python grandchild that accesses the variable case-sensitively. print(subprocess.check_output(["set", env_var_name], shell=True, text=True)) diff --git a/test/test_git.py b/test/test_git.py index f1d35a355..4d57a2d86 100644 --- a/test/test_git.py +++ b/test/test_git.py @@ -98,15 +98,23 @@ def test_it_avoids_upcasing_unrelated_environment_variable_names(self): old_name = "28f425ca_d5d8_4257_b013_8d63166c8158" if old_name == old_name.upper(): raise RuntimeError("test bug or strange locale: old_name invariant under upcasing") - os.putenv(old_name, "1") # It has to be done this lower-level way to set it lower-case. + # Step 1: Set the environment variable in this parent process. Because os.putenv is a thin + # wrapper around a system API, os.environ never sees the variable in this parent + # process, so the name is not upcased even on Windows. + os.putenv(old_name, "1") + + # Step 2: Create the child process that inherits the environment variable. The child uses + # GitPython, and we are testing that it passes the variable with the exact original + # name to its own child process (the grandchild). cmdline = [ sys.executable, - fixture_path("env_case.py"), + fixture_path("env_case.py"), # Contains steps 3 and 4. self.rorepo.working_dir, old_name, ] - pair_text = subprocess.check_output(cmdline, shell=False, text=True) + pair_text = subprocess.check_output(cmdline, shell=False, text=True) # Run steps 3 and 4. + new_name = pair_text.split("=")[0] self.assertEqual(new_name, old_name)