66# the BSD License: http://www.opensource.org/licenses/bsd-license.php
77from __future__ import print_function
88
9- import contextlib
9+ import contextlib2 as contextlib
10+ import ddt
1011import os
1112import shutil
1213import subprocess
3132 assert_equal ,
3233 assert_true ,
3334 assert_match ,
34- fixture_path
35+ fixture_path ,
36+ with_rw_directory ,
3537)
36- from git . test . lib import with_rw_directory
37- from git .util import finalize_process
38+
39+ from git .util import finalize_process , cwd
3840
3941import os .path as osp
4042
5153
5254from git .compat import is_win
5355
56+
5457@contextlib .contextmanager
5558def _chdir (new_dir ):
5659 """Context manager to temporarily change directory. Not reentrant."""
@@ -77,7 +80,7 @@ def _patch_out_env(name):
7780 os .environ [name ] = old_value
7881
7982
80-
83+ @ ddt . ddt
8184class TestGit (TestBase ):
8285
8386 @classmethod
@@ -137,23 +140,46 @@ def test_it_transforms_kwargs_into_git_command_arguments(self):
137140 def test_it_executes_git_to_shell_and_returns_result (self ):
138141 assert_match (r'^git version [\d\.]{2}.*$' , self .git .execute (["git" , "version" ]))
139142
140- def test_it_executes_git_not_from_cwd (self ):
141- with TemporaryDirectory () as tmpdir :
142- if is_win :
143- # Copy an actual binary executable that is not git.
144- other_exe_path = os .path .join (os .getenv ("WINDIR" ), "system32" , "hostname.exe" )
145- impostor_path = os .path .join (tmpdir , "git.exe" )
146- shutil .copy (other_exe_path , impostor_path )
147- else :
148- # Create a shell script that doesn't do anything.
149- impostor_path = os .path .join (tmpdir , "git" )
150- with open (impostor_path , mode = "w" ) as file :
151- print ("#!/bin/sh" , file = file )
152- os .chmod (impostor_path , 0o755 )
153-
154- with _chdir (tmpdir ):
155- # six.assertRegex(self.git.execute(["git", "version"]).encode("UTF-8"), r"^git version\b")
156- self .assertRegexpMatches (self .git .execute (["git" , "version" ]), r"^git version\b" )
143+ @ddt .data (
144+ # chdir_to_repo, shell, command, use_shell_impostor
145+ (False , False , ["git" , "version" ], False ),
146+ (False , True , "git version" , False ),
147+ (False , True , "git version" , True ),
148+ (True , False , ["git" , "version" ], False ),
149+ (True , True , "git version" , False ),
150+ (True , True , "git version" , True ),
151+ )
152+ def test_it_executes_git_not_from_cwd (self , case ):
153+ self .internal_it_executes_git_not_from_cwd (case )
154+
155+ @with_rw_directory
156+ def internal_it_executes_git_not_from_cwd (self , rw_dir , case ):
157+ chdir_to_repo , shell , command , use_shell_impostor = case
158+ repo = Repo .init (rw_dir )
159+ if os .name == "nt" :
160+ # Copy an actual binary executable that is not git. (On Windows, running
161+ # "hostname" only displays the hostname, it never tries to change it.)
162+ other_exe_path = Path (os .environ ["SystemRoot" ], "system32" , "hostname.exe" )
163+ impostor_path = Path (rw_dir , "git.exe" )
164+ shutil .copy (other_exe_path , str (impostor_path ))
165+ else :
166+ # Create a shell script that doesn't do anything.
167+ impostor_path = Path (rw_dir , "git" )
168+ impostor_path .write_text (u"#!/bin/sh\n " , encoding = "utf-8" )
169+ os .chmod (str (impostor_path ), 0o755 )
170+ if use_shell_impostor :
171+ shell_name = "cmd.exe" if os .name == "nt" else "sh"
172+ shutil .copy (str (impostor_path ), str (Path (rw_dir , shell_name )))
173+ with contextlib .ExitStack () as stack :
174+ if chdir_to_repo :
175+ stack .enter_context (cwd (rw_dir ))
176+ if use_shell_impostor :
177+ stack .enter_context (_patch_out_env ("ComSpec" ))
178+ # Run the command without raising an exception on failure, as the exception
179+ # message is currently misleading when the command is a string rather than a
180+ # sequence of strings (it really runs "git", but then wrongly reports "g").
181+ output = repo .git .execute (command , with_exceptions = False , shell = shell )
182+ self .assertRegexpMatches (output , r"^git version\b" )
157183
158184 def test_it_accepts_stdin (self ):
159185 filename = fixture_path ("cat_file_blob" )
@@ -325,7 +351,7 @@ def test_environment(self, rw_dir):
325351 self .assertIn ('FOO' , str (err ))
326352
327353 def test_handle_process_output (self ):
328- from git .cmd import handle_process_output
354+ from git .cmd import handle_process_output , safer_popen
329355
330356 line_count = 5002
331357 count = [None , 0 , 0 ]
@@ -337,13 +363,11 @@ def counter_stderr(line):
337363 count [2 ] += 1
338364
339365 cmdline = [sys .executable , fixture_path ('cat_file.py' ), str (fixture_path ('issue-301_stderr' ))]
340- proc = subprocess .Popen (cmdline ,
341- stdin = None ,
342- stdout = subprocess .PIPE ,
343- stderr = subprocess .PIPE ,
344- shell = False ,
345- # creationflags=cmd.PROC_CREATIONFLAGS,
346- )
366+ proc = safer_popen (cmdline ,
367+ stdin = None ,
368+ stdout = subprocess .PIPE ,
369+ stderr = subprocess .PIPE ,
370+ shell = False )
347371
348372 handle_process_output (proc , counter_stdout , counter_stderr , finalize_process )
349373
0 commit comments