summaryrefslogtreecommitdiffstats
path: root/git_command.py
diff options
context:
space:
mode:
Diffstat (limited to 'git_command.py')
-rw-r--r--git_command.py64
1 files changed, 52 insertions, 12 deletions
diff --git a/git_command.py b/git_command.py
index 53b3e75c..259fb02c 100644
--- a/git_command.py
+++ b/git_command.py
@@ -14,7 +14,9 @@
14# limitations under the License. 14# limitations under the License.
15 15
16from __future__ import print_function 16from __future__ import print_function
17import fcntl
17import os 18import os
19import select
18import sys 20import sys
19import subprocess 21import subprocess
20import tempfile 22import tempfile
@@ -76,6 +78,16 @@ def terminate_ssh_clients():
76 78
77_git_version = None 79_git_version = None
78 80
81class _sfd(object):
82 """select file descriptor class"""
83 def __init__(self, fd, dest, std_name):
84 assert std_name in ('stdout', 'stderr')
85 self.fd = fd
86 self.dest = dest
87 self.std_name = std_name
88 def fileno(self):
89 return self.fd.fileno()
90
79class _GitCall(object): 91class _GitCall(object):
80 def version(self): 92 def version(self):
81 p = GitCommand(None, ['--version'], capture_stdout=True) 93 p = GitCommand(None, ['--version'], capture_stdout=True)
@@ -139,6 +151,9 @@ class GitCommand(object):
139 if key in env: 151 if key in env:
140 del env[key] 152 del env[key]
141 153
154 # If we are not capturing std* then need to print it.
155 self.tee = {'stdout': not capture_stdout, 'stderr': not capture_stderr}
156
142 if disable_editor: 157 if disable_editor:
143 _setenv(env, 'GIT_EDITOR', ':') 158 _setenv(env, 'GIT_EDITOR', ':')
144 if ssh_proxy: 159 if ssh_proxy:
@@ -162,22 +177,21 @@ class GitCommand(object):
162 if gitdir: 177 if gitdir:
163 _setenv(env, GIT_DIR, gitdir) 178 _setenv(env, GIT_DIR, gitdir)
164 cwd = None 179 cwd = None
165 command.extend(cmdv) 180 command.append(cmdv[0])
181 # Need to use the --progress flag for fetch/clone so output will be
182 # displayed as by default git only does progress output if stderr is a TTY.
183 if sys.stderr.isatty() and cmdv[0] in ('fetch', 'clone'):
184 if '--progress' not in cmdv and '--quiet' not in cmdv:
185 command.append('--progress')
186 command.extend(cmdv[1:])
166 187
167 if provide_stdin: 188 if provide_stdin:
168 stdin = subprocess.PIPE 189 stdin = subprocess.PIPE
169 else: 190 else:
170 stdin = None 191 stdin = None
171 192
172 if capture_stdout: 193 stdout = subprocess.PIPE
173 stdout = subprocess.PIPE 194 stderr = subprocess.PIPE
174 else:
175 stdout = None
176
177 if capture_stderr:
178 stderr = subprocess.PIPE
179 else:
180 stderr = None
181 195
182 if IsTrace(): 196 if IsTrace():
183 global LAST_CWD 197 global LAST_CWD
@@ -226,8 +240,34 @@ class GitCommand(object):
226 def Wait(self): 240 def Wait(self):
227 try: 241 try:
228 p = self.process 242 p = self.process
229 (self.stdout, self.stderr) = p.communicate() 243 rc = self._CaptureOutput()
230 rc = p.returncode
231 finally: 244 finally:
232 _remove_ssh_client(p) 245 _remove_ssh_client(p)
233 return rc 246 return rc
247
248 def _CaptureOutput(self):
249 p = self.process
250 s_in = [_sfd(p.stdout, sys.stdout, 'stdout'),
251 _sfd(p.stderr, sys.stderr, 'stderr')]
252 self.stdout = ''
253 self.stderr = ''
254
255 for s in s_in:
256 flags = fcntl.fcntl(s.fd, fcntl.F_GETFL)
257 fcntl.fcntl(s.fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
258
259 while s_in:
260 in_ready, _, _ = select.select(s_in, [], [])
261 for s in in_ready:
262 buf = s.fd.read(4096)
263 if not buf:
264 s_in.remove(s)
265 continue
266 if s.std_name == 'stdout':
267 self.stdout += buf
268 else:
269 self.stderr += buf
270 if self.tee[s.std_name]:
271 s.dest.write(buf)
272 s.dest.flush()
273 return p.wait()