summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--git_command.py85
-rw-r--r--tests/test_git_command.py33
2 files changed, 89 insertions, 29 deletions
diff --git a/git_command.py b/git_command.py
index 01b9ecb3..3a3bb34d 100644
--- a/git_command.py
+++ b/git_command.py
@@ -16,6 +16,7 @@ import functools
16import os 16import os
17import sys 17import sys
18import subprocess 18import subprocess
19from typing import Any, Optional
19 20
20from error import GitError 21from error import GitError
21from git_refs import HEAD 22from git_refs import HEAD
@@ -157,6 +158,53 @@ def git_require(min_version, fail=False, msg=''):
157 return False 158 return False
158 159
159 160
161def _build_env(
162 _kwargs_only=(),
163 bare: Optional[bool] = False,
164 disable_editor: Optional[bool] = False,
165 ssh_proxy: Optional[Any] = None,
166 gitdir: Optional[str] = None,
167 objdir: Optional[str] = None
168):
169 """Constucts an env dict for command execution."""
170
171 assert _kwargs_only == (), '_build_env only accepts keyword arguments.'
172
173 env = GitCommand._GetBasicEnv()
174
175 if disable_editor:
176 env['GIT_EDITOR'] = ':'
177 if ssh_proxy:
178 env['REPO_SSH_SOCK'] = ssh_proxy.sock()
179 env['GIT_SSH'] = ssh_proxy.proxy
180 env['GIT_SSH_VARIANT'] = 'ssh'
181 if 'http_proxy' in env and 'darwin' == sys.platform:
182 s = "'http.proxy=%s'" % (env['http_proxy'],)
183 p = env.get('GIT_CONFIG_PARAMETERS')
184 if p is not None:
185 s = p + ' ' + s
186 env['GIT_CONFIG_PARAMETERS'] = s
187 if 'GIT_ALLOW_PROTOCOL' not in env:
188 env['GIT_ALLOW_PROTOCOL'] = (
189 'file:git:http:https:ssh:persistent-http:persistent-https:sso:rpc')
190 env['GIT_HTTP_USER_AGENT'] = user_agent.git
191
192 if objdir:
193 # Set to the place we want to save the objects.
194 env['GIT_OBJECT_DIRECTORY'] = objdir
195
196 alt_objects = os.path.join(gitdir, 'objects') if gitdir else None
197 if (alt_objects and
198 os.path.realpath(alt_objects) != os.path.realpath(objdir)):
199 # Allow git to search the original place in case of local or unique refs
200 # that git will attempt to resolve even if we aren't fetching them.
201 env['GIT_ALTERNATE_OBJECT_DIRECTORIES'] = alt_objects
202 if bare and gitdir is not None:
203 env[GIT_DIR] = gitdir
204
205 return env
206
207
160class GitCommand(object): 208class GitCommand(object):
161 """Wrapper around a single git invocation.""" 209 """Wrapper around a single git invocation."""
162 210
@@ -173,30 +221,13 @@ class GitCommand(object):
173 cwd=None, 221 cwd=None,
174 gitdir=None, 222 gitdir=None,
175 objdir=None): 223 objdir=None):
176 env = self._GetBasicEnv()
177
178 if disable_editor:
179 env['GIT_EDITOR'] = ':'
180 if ssh_proxy:
181 env['REPO_SSH_SOCK'] = ssh_proxy.sock()
182 env['GIT_SSH'] = ssh_proxy.proxy
183 env['GIT_SSH_VARIANT'] = 'ssh'
184 if 'http_proxy' in env and 'darwin' == sys.platform:
185 s = "'http.proxy=%s'" % (env['http_proxy'],)
186 p = env.get('GIT_CONFIG_PARAMETERS')
187 if p is not None:
188 s = p + ' ' + s
189 env['GIT_CONFIG_PARAMETERS'] = s
190 if 'GIT_ALLOW_PROTOCOL' not in env:
191 env['GIT_ALLOW_PROTOCOL'] = (
192 'file:git:http:https:ssh:persistent-http:persistent-https:sso:rpc')
193 env['GIT_HTTP_USER_AGENT'] = user_agent.git
194 224
195 if project: 225 if project:
196 if not cwd: 226 if not cwd:
197 cwd = project.worktree 227 cwd = project.worktree
198 if not gitdir: 228 if not gitdir:
199 gitdir = project.gitdir 229 gitdir = project.gitdir
230
200 # Git on Windows wants its paths only using / for reliability. 231 # Git on Windows wants its paths only using / for reliability.
201 if platform_utils.isWindows(): 232 if platform_utils.isWindows():
202 if objdir: 233 if objdir:
@@ -204,20 +235,16 @@ class GitCommand(object):
204 if gitdir: 235 if gitdir:
205 gitdir = gitdir.replace('\\', '/') 236 gitdir = gitdir.replace('\\', '/')
206 237
207 if objdir: 238 env = _build_env(
208 # Set to the place we want to save the objects. 239 disable_editor=disable_editor,
209 env['GIT_OBJECT_DIRECTORY'] = objdir 240 ssh_proxy=ssh_proxy,
210 241 objdir=objdir,
211 alt_objects = os.path.join(gitdir, 'objects') if gitdir else None 242 gitdir=gitdir,
212 if alt_objects and os.path.realpath(alt_objects) != os.path.realpath(objdir): 243 bare=bare,
213 # Allow git to search the original place in case of local or unique refs 244 )
214 # that git will attempt to resolve even if we aren't fetching them.
215 env['GIT_ALTERNATE_OBJECT_DIRECTORIES'] = alt_objects
216 245
217 command = [GIT] 246 command = [GIT]
218 if bare: 247 if bare:
219 if gitdir:
220 env[GIT_DIR] = gitdir
221 cwd = None 248 cwd = None
222 command.append(cmdv[0]) 249 command.append(cmdv[0])
223 # Need to use the --progress flag for fetch/clone so output will be 250 # Need to use the --progress flag for fetch/clone so output will be
diff --git a/tests/test_git_command.py b/tests/test_git_command.py
index 93300a6f..aaf21219 100644
--- a/tests/test_git_command.py
+++ b/tests/test_git_command.py
@@ -15,6 +15,7 @@
15"""Unittests for the git_command.py module.""" 15"""Unittests for the git_command.py module."""
16 16
17import re 17import re
18import os
18import unittest 19import unittest
19 20
20try: 21try:
@@ -26,6 +27,38 @@ import git_command
26import wrapper 27import wrapper
27 28
28 29
30class GitCommandTest(unittest.TestCase):
31 """Tests the GitCommand class (via git_command.git)."""
32
33 def setUp(self):
34
35 def realpath_mock(val):
36 return val
37
38 mock.patch.object(os.path, 'realpath', side_effect=realpath_mock).start()
39
40 def tearDown(self):
41 mock.patch.stopall()
42
43 def test_alternative_setting_when_matching(self):
44 r = git_command._build_env(
45 objdir = 'zap/objects',
46 gitdir = 'zap'
47 )
48
49 self.assertIsNone(r.get('GIT_ALTERNATE_OBJECT_DIRECTORIES'))
50 self.assertEqual(r.get('GIT_OBJECT_DIRECTORY'), 'zap/objects')
51
52 def test_alternative_setting_when_different(self):
53 r = git_command._build_env(
54 objdir = 'wow/objects',
55 gitdir = 'zap'
56 )
57
58 self.assertEqual(r.get('GIT_ALTERNATE_OBJECT_DIRECTORIES'), 'zap/objects')
59 self.assertEqual(r.get('GIT_OBJECT_DIRECTORY'), 'wow/objects')
60
61
29class GitCallUnitTest(unittest.TestCase): 62class GitCallUnitTest(unittest.TestCase):
30 """Tests the _GitCall class (via git_command.git).""" 63 """Tests the _GitCall class (via git_command.git)."""
31 64