Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: gclient_utils.py

Issue 3174020: Add stdout param to SubprocessCallAndFilter(). (Closed)
Patch Set: fix unit test Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gclient_scm.py ('k') | scm.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2009 Google Inc. All Rights Reserved. 1 # Copyright 2009 Google Inc. All Rights Reserved.
2 # 2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); 3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License. 4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at 5 # You may obtain a copy of the License at
6 # 6 #
7 # http://www.apache.org/licenses/LICENSE-2.0 7 # http://www.apache.org/licenses/LICENSE-2.0
8 # 8 #
9 # Unless required by applicable law or agreed to in writing, software 9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, 10 # distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 description. 259 description.
260 """ 260 """
261 # Call subprocess and capture nothing: 261 # Call subprocess and capture nothing:
262 SubprocessCallAndFilter(command, in_directory, True, True, fail_status) 262 SubprocessCallAndFilter(command, in_directory, True, True, fail_status)
263 263
264 264
265 def SubprocessCallAndFilter(command, 265 def SubprocessCallAndFilter(command,
266 in_directory, 266 in_directory,
267 print_messages, 267 print_messages,
268 print_stdout, 268 print_stdout,
269 fail_status=None, filter_fn=None): 269 fail_status=None,
270 filter_fn=None,
271 stdout=None):
270 """Runs command, a list, in directory in_directory. 272 """Runs command, a list, in directory in_directory.
271 273
272 If print_messages is true, a message indicating what is being done 274 If print_messages is true, a message indicating what is being done
273 is printed to stdout. If print_messages is false, the message is printed 275 is printed to stdout. If print_messages is false, the message is printed
274 only if we actually need to print something else as well, so you can 276 only if we actually need to print something else as well, so you can
275 get the context of the output. If print_messages is false and print_stdout 277 get the context of the output. If print_messages is false and print_stdout
276 is false, no output at all is generated. 278 is false, no output at all is generated.
277 279
278 Also, if print_stdout is true, the command's stdout is also forwarded 280 Also, if print_stdout is true, the command's stdout is also forwarded
279 to stdout. 281 to stdout.
280 282
281 If a filter_fn function is specified, it is expected to take a single 283 If a filter_fn function is specified, it is expected to take a single
282 string argument, and it will be called with each line of the 284 string argument, and it will be called with each line of the
283 subprocess's output. Each line has had the trailing newline character 285 subprocess's output. Each line has had the trailing newline character
284 trimmed. 286 trimmed.
285 287
286 If the command fails, as indicated by a nonzero exit status, gclient will 288 If the command fails, as indicated by a nonzero exit status, gclient will
287 exit with an exit status of fail_status. If fail_status is None (the 289 exit with an exit status of fail_status. If fail_status is None (the
288 default), gclient will raise an Error exception. 290 default), gclient will raise an Error exception.
289 """ 291 """
292 stdout = stdout or sys.stdout
290 logging.debug(command) 293 logging.debug(command)
291 if print_messages: 294 if print_messages:
292 print('\n________ running \'%s\' in \'%s\'' 295 stdout.write('\n________ running \'%s\' in \'%s\'\n'
293 % (' '.join(command), in_directory)) 296 % (' '.join(command), in_directory))
294 297
295 kid = Popen(command, bufsize=0, cwd=in_directory, 298 kid = Popen(command, bufsize=0, cwd=in_directory,
296 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 299 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
297 300
298 # Do a flush of sys.stdout before we begin reading from the subprocess's 301 # Do a flush of sys.stdout before we begin reading from the subprocess's
299 # stdout. 302 # stdout.
300 last_flushed_at = time.time() 303 last_flushed_at = time.time()
301 sys.stdout.flush() 304 stdout.flush()
302 305
303 # Also, we need to forward stdout to prevent weird re-ordering of output. 306 # Also, we need to forward stdout to prevent weird re-ordering of output.
304 # This has to be done on a per byte basis to make sure it is not buffered: 307 # This has to be done on a per byte basis to make sure it is not buffered:
305 # normally buffering is done for each line, but if svn requests input, no 308 # normally buffering is done for each line, but if svn requests input, no
306 # end-of-line character is output after the prompt and it would not show up. 309 # end-of-line character is output after the prompt and it would not show up.
307 in_byte = kid.stdout.read(1) 310 in_byte = kid.stdout.read(1)
308 in_line = '' 311 in_line = ''
309 while in_byte: 312 while in_byte:
310 if in_byte != '\r': 313 if in_byte != '\r':
311 if print_stdout: 314 if print_stdout:
312 if not print_messages: 315 if not print_messages:
313 print('\n________ running \'%s\' in \'%s\'' 316 stdout.write('\n________ running \'%s\' in \'%s\'\n'
314 % (' '.join(command), in_directory)) 317 % (' '.join(command), in_directory))
315 print_messages = True 318 print_messages = True
316 sys.stdout.write(in_byte) 319 stdout.write(in_byte)
317 if in_byte != '\n': 320 if in_byte != '\n':
318 in_line += in_byte 321 in_line += in_byte
319 if in_byte == '\n': 322 if in_byte == '\n':
320 if filter_fn: 323 if filter_fn:
321 filter_fn(in_line) 324 filter_fn(in_line)
322 in_line = '' 325 in_line = ''
323 # Flush at least 10 seconds between line writes. We wait at least 10 326 # Flush at least 10 seconds between line writes. We wait at least 10
324 # seconds to avoid overloading the reader that called us with output, 327 # seconds to avoid overloading the reader that called us with output,
325 # which can slow busy readers down. 328 # which can slow busy readers down.
326 if (time.time() - last_flushed_at) > 10: 329 if (time.time() - last_flushed_at) > 10:
327 last_flushed_at = time.time() 330 last_flushed_at = time.time()
328 sys.stdout.flush() 331 stdout.flush()
329 in_byte = kid.stdout.read(1) 332 in_byte = kid.stdout.read(1)
330 # Flush the rest of buffered output. This is only an issue with files not 333 # Flush the rest of buffered output. This is only an issue with files not
331 # ending with a \n. 334 # ending with a \n.
332 if len(in_line) and filter_fn: 335 if len(in_line) and filter_fn:
333 filter_fn(in_line) 336 filter_fn(in_line)
334 rv = kid.wait() 337 rv = kid.wait()
335 338
336 if rv: 339 if rv:
337 msg = 'failed to run command: %s' % ' '.join(command) 340 msg = 'failed to run command: %s' % ' '.join(command)
338
339 if fail_status != None: 341 if fail_status != None:
340 print >> sys.stderr, msg 342 sys.stderr.write(msg + '\n')
341 sys.exit(fail_status) 343 sys.exit(fail_status)
342
343 raise Error(msg) 344 raise Error(msg)
344 345
345 346
346 def FindGclientRoot(from_dir, filename='.gclient'): 347 def FindGclientRoot(from_dir, filename='.gclient'):
347 """Tries to find the gclient root.""" 348 """Tries to find the gclient root."""
348 path = os.path.realpath(from_dir) 349 path = os.path.realpath(from_dir)
349 while not os.path.exists(os.path.join(path, filename)): 350 while not os.path.exists(os.path.join(path, filename)):
350 split_path = os.path.split(path) 351 split_path = os.path.split(path)
351 if not split_path[1]: 352 if not split_path[1]:
352 return None 353 return None
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 if exception: 535 if exception:
535 self.parent.exceptions.append(exception) 536 self.parent.exceptions.append(exception)
536 if self.parent.progress: 537 if self.parent.progress:
537 self.parent.progress.update(1) 538 self.parent.progress.update(1)
538 assert not self.item.name in self.parent.ran 539 assert not self.item.name in self.parent.ran
539 if not self.item.name in self.parent.ran: 540 if not self.item.name in self.parent.ran:
540 self.parent.ran.append(self.item.name) 541 self.parent.ran.append(self.item.name)
541 finally: 542 finally:
542 self.parent.ready_cond.notifyAll() 543 self.parent.ready_cond.notifyAll()
543 self.parent.ready_cond.release() 544 self.parent.ready_cond.release()
OLDNEW
« no previous file with comments | « gclient_scm.py ('k') | scm.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698