diff options
Diffstat (limited to 'git_command.py')
-rw-r--r-- | git_command.py | 64 |
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 | ||
16 | from __future__ import print_function | 16 | from __future__ import print_function |
17 | import fcntl | ||
17 | import os | 18 | import os |
19 | import select | ||
18 | import sys | 20 | import sys |
19 | import subprocess | 21 | import subprocess |
20 | import tempfile | 22 | import tempfile |
@@ -76,6 +78,16 @@ def terminate_ssh_clients(): | |||
76 | 78 | ||
77 | _git_version = None | 79 | _git_version = None |
78 | 80 | ||
81 | class _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 | |||
79 | class _GitCall(object): | 91 | class _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() | ||