From ec0087227ed37cf1df441e4f0f73daa25895c4b5 Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Wed, 21 May 2025 15:48:34 -0400 Subject: [PATCH 01/10] add tests for is_cygwin_git --- test/test_util.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/test_util.py b/test/test_util.py index dad2f3dcd..ed57dcbae 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -34,6 +34,7 @@ LockFile, cygpath, decygpath, + is_cygwin_git, get_user_id, remove_password_if_present, rmtree, @@ -349,6 +350,24 @@ def test_decygpath(self, wpath, cpath): assert wcpath == wpath.replace("/", "\\"), cpath +class TestIsCygwinGit: + """Tests for :func:`is_cygwin_git`""" + + def test_on_path_executable(self): + match sys.platform: + case "cygwin": + assert is_cygwin_git("git") + case _: + assert not is_cygwin_git("git") + + def test_none_executable(self): + assert not is_cygwin_git(None) + + def test_with_missing_uname(self): + """Test for handling when `uname` isn't in the same directory as `git`""" + assert not is_cygwin_git("/bogus_path/git") + + class _Member: """A member of an IterableList.""" From de5e57caf26e5f6772ac02a3944e58e0aba177f3 Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Wed, 21 May 2025 15:49:07 -0400 Subject: [PATCH 02/10] check for the existence/execute bit on the uname command before trying to run it --- git/util.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/git/util.py b/git/util.py index 9e8ac821d..f1a94c469 100644 --- a/git/util.py +++ b/git/util.py @@ -463,7 +463,13 @@ def _is_cygwin_git(git_executable: str) -> bool: git_dir = osp.dirname(res[0]) if res else "" # Just a name given, not a real path. + # Let's see if the same path has uname uname_cmd = osp.join(git_dir, "uname") + if not (osp.isfile(uname_cmd) and os.access(uname_cmd, os.X_OK)): + _logger.debug(f"File {uname_cmd} either does not exist or is not executable.") + _is_cygwin_cache[git_executable] = is_cygwin + return is_cygwin + process = subprocess.Popen([uname_cmd], stdout=subprocess.PIPE, universal_newlines=True) uname_out, _ = process.communicate() # retcode = process.poll() From 428be1a504e2b30c195786d5ca6708f4c39d90a7 Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Wed, 21 May 2025 15:51:29 -0400 Subject: [PATCH 03/10] adding self to authors --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 45b14c961..b57113edd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -55,5 +55,6 @@ Contributors are: -Eliah Kagan -Ethan Lin -Jonas Scharpf +-Gordon Marx Portions derived from other open source works and are clearly marked. From 58ff723e6757af3c508e2a9424d287e5016ac230 Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Thu, 22 May 2025 08:54:42 -0400 Subject: [PATCH 04/10] Revert "check for the existence/execute bit on the uname command before trying to run it" This reverts commit de5e57caf26e5f6772ac02a3944e58e0aba177f3. --- git/util.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/git/util.py b/git/util.py index f1a94c469..9e8ac821d 100644 --- a/git/util.py +++ b/git/util.py @@ -463,13 +463,7 @@ def _is_cygwin_git(git_executable: str) -> bool: git_dir = osp.dirname(res[0]) if res else "" # Just a name given, not a real path. - # Let's see if the same path has uname uname_cmd = osp.join(git_dir, "uname") - if not (osp.isfile(uname_cmd) and os.access(uname_cmd, os.X_OK)): - _logger.debug(f"File {uname_cmd} either does not exist or is not executable.") - _is_cygwin_cache[git_executable] = is_cygwin - return is_cygwin - process = subprocess.Popen([uname_cmd], stdout=subprocess.PIPE, universal_newlines=True) uname_out, _ = process.communicate() # retcode = process.poll() From 71879840b8a72890f63fcadf7a92694106610ef0 Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Thu, 22 May 2025 09:05:13 -0400 Subject: [PATCH 05/10] use pathlib.Path instead of os.path.isfile --- git/util.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/git/util.py b/git/util.py index 9e8ac821d..3b6917fc4 100644 --- a/git/util.py +++ b/git/util.py @@ -464,6 +464,12 @@ def _is_cygwin_git(git_executable: str) -> bool: # Just a name given, not a real path. uname_cmd = osp.join(git_dir, "uname") + + if not (pathlib.Path(uname_cmd).exists() and os.access(uname_cmd, os.X_OK)): + _logger.debug(f"Failed checking if running in CYGWIN: {uname_cmd} is not an executable") + _is_cygwin_cache[git_executable] = is_cygwin + return is_cygwin + process = subprocess.Popen([uname_cmd], stdout=subprocess.PIPE, universal_newlines=True) uname_out, _ = process.communicate() # retcode = process.poll() From 3f5a942be8293bb8c663631756885f877afc22e7 Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Thu, 22 May 2025 09:06:02 -0400 Subject: [PATCH 06/10] don't keep checking if sys.platform isn't 'cygwin' --- git/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/util.py b/git/util.py index 3b6917fc4..989f9196c 100644 --- a/git/util.py +++ b/git/util.py @@ -490,7 +490,7 @@ def is_cygwin_git(git_executable: PathLike) -> bool: ... def is_cygwin_git(git_executable: Union[None, PathLike]) -> bool: - if sys.platform == "win32": # TODO: See if we can use `sys.platform != "cygwin"`. + if sys.platform != "cygwin": return False elif git_executable is None: return False From 226f4ffcaf2deed4598b9ff53902a12f6483c069 Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Thu, 22 May 2025 09:15:50 -0400 Subject: [PATCH 07/10] check that uname_cmd points to a file; if uname_cmd were a directory, it could both exist and have os.X_OK but not work --- git/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/util.py b/git/util.py index 989f9196c..32a808c60 100644 --- a/git/util.py +++ b/git/util.py @@ -465,7 +465,7 @@ def _is_cygwin_git(git_executable: str) -> bool: # Just a name given, not a real path. uname_cmd = osp.join(git_dir, "uname") - if not (pathlib.Path(uname_cmd).exists() and os.access(uname_cmd, os.X_OK)): + if not (pathlib.Path(uname_cmd).isfile() and os.access(uname_cmd, os.X_OK)): _logger.debug(f"Failed checking if running in CYGWIN: {uname_cmd} is not an executable") _is_cygwin_cache[git_executable] = is_cygwin return is_cygwin From 22d6284b099e99716da101198ce113c96e35423a Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Thu, 22 May 2025 09:24:37 -0400 Subject: [PATCH 08/10] don't use match-case, since it's a 3.10 feature --- test/test_util.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/test_util.py b/test/test_util.py index ed57dcbae..de80ca3af 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -354,11 +354,10 @@ class TestIsCygwinGit: """Tests for :func:`is_cygwin_git`""" def test_on_path_executable(self): - match sys.platform: - case "cygwin": - assert is_cygwin_git("git") - case _: - assert not is_cygwin_git("git") + if sys.platform == "cygwin": + assert is_cygwin_git("git") + else: + assert not is_cygwin_git("git") def test_none_executable(self): assert not is_cygwin_git(None) From b1289eeb3676e63f4261518655ee90808e9d3d1f Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Thu, 22 May 2025 10:56:26 -0400 Subject: [PATCH 09/10] it's is_file(), not isfile() --- git/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/git/util.py b/git/util.py index 32a808c60..4071fdc14 100644 --- a/git/util.py +++ b/git/util.py @@ -465,7 +465,7 @@ def _is_cygwin_git(git_executable: str) -> bool: # Just a name given, not a real path. uname_cmd = osp.join(git_dir, "uname") - if not (pathlib.Path(uname_cmd).isfile() and os.access(uname_cmd, os.X_OK)): + if not (pathlib.Path(uname_cmd).is_file() and os.access(uname_cmd, os.X_OK)): _logger.debug(f"Failed checking if running in CYGWIN: {uname_cmd} is not an executable") _is_cygwin_cache[git_executable] = is_cygwin return is_cygwin @@ -490,6 +490,7 @@ def is_cygwin_git(git_executable: PathLike) -> bool: ... def is_cygwin_git(git_executable: Union[None, PathLike]) -> bool: + _logger.debug(f"{sys.platform=}, {git_executable=}") if sys.platform != "cygwin": return False elif git_executable is None: From cffa264bdc1dd09a13a85cc27417b85628273e14 Mon Sep 17 00:00:00 2001 From: Gordon Marx Date: Thu, 22 May 2025 11:11:48 -0400 Subject: [PATCH 10/10] turns out f-strings before 3.8 don't support {variable=} notation, take that out --- git/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/util.py b/git/util.py index 4071fdc14..66175ea33 100644 --- a/git/util.py +++ b/git/util.py @@ -490,7 +490,7 @@ def is_cygwin_git(git_executable: PathLike) -> bool: ... def is_cygwin_git(git_executable: Union[None, PathLike]) -> bool: - _logger.debug(f"{sys.platform=}, {git_executable=}") + _logger.debug(f"sys.platform = {sys.platform}, git_executable = {git_executable}") if sys.platform != "cygwin": return False elif git_executable is None: