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

Side by Side Diff: gclient_utils.py

Issue 3117039: Refactor SubprocessCallAndFilter() to remove positional arguments. (Closed)
Patch Set: Created 10 years, 3 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 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 try: 244 try:
245 os.rmdir(file_path) 245 os.rmdir(file_path)
246 except OSError, e: 246 except OSError, e:
247 if e.errno != errno.EACCES or sys.platform != 'win32': 247 if e.errno != errno.EACCES or sys.platform != 'win32':
248 raise 248 raise
249 print 'Failed to remove %s: trying again' % file_path 249 print 'Failed to remove %s: trying again' % file_path
250 time.sleep(0.1) 250 time.sleep(0.1)
251 os.rmdir(file_path) 251 os.rmdir(file_path)
252 252
253 253
254 def SubprocessCall(command, in_directory, fail_status=None): 254 def SubprocessCall(args, **kwargs):
255 """Runs command, a list, in directory in_directory. 255 """Wraps SubprocessCallAndFilter() with different default arguments.
256 256
257 This function wraps SubprocessCallAndFilter, but does not perform the 257 Calls subprocess and capture nothing."""
258 filtering functions. See that function for a more complete usage 258 kwargs['print_messages'] = True
259 description. 259 kwargs['print_stdout'] = True
260 """ 260 return SubprocessCallAndFilter(args, **kwargs)
261 # Call subprocess and capture nothing:
262 SubprocessCallAndFilter(command, in_directory, True, True, fail_status)
263 261
264 262
265 def SubprocessCallAndFilter(command, 263 def SubprocessCallAndFilter(args, **kwargs):
266 in_directory, 264 """Runs a command and prints a header line if appropriate.
267 print_messages,
268 print_stdout,
269 fail_status=None,
270 filter_fn=None,
271 stdout=None):
272 """Runs command, a list, in directory in_directory.
273 265
274 If print_messages is true, a message indicating what is being done 266 If |print_messages| is True, a message indicating what is being done
275 is printed to stdout. If print_messages is false, the message is printed 267 is printed to stdout. Otherwise the message is printed only if the call
276 only if we actually need to print something else as well, so you can 268 generated any ouput. If both |print_messages| and |print_stdout| are False,
277 get the context of the output. If print_messages is false and print_stdout 269 no output at all is generated.
278 is false, no output at all is generated.
279 270
280 Also, if print_stdout is true, the command's stdout is also forwarded 271 If |print_stdout| is True, the command's stdout is also forwarded to stdout.
281 to stdout.
282 272
283 If a filter_fn function is specified, it is expected to take a single 273 If |filter_fn| function is specified, it is expected to take a single
284 string argument, and it will be called with each line of the 274 string argument, and it will be called with each line of the
285 subprocess's output. Each line has had the trailing newline character 275 subprocess's output. Each line has had the trailing newline character
286 trimmed. 276 trimmed.
287 277
288 If the command fails, as indicated by a nonzero exit status, gclient will 278 If the command fails, as indicated by a nonzero exit status, gclient will
289 exit with an exit status of fail_status. If fail_status is None (the 279 exit with an exit status of fail_status. If fail_status is None (the
290 default), gclient will raise an Error exception. 280 default), gclient will raise an Error exception.
281
282 Other subprocess.Popen parameters can be specified.
291 """ 283 """
292 stdout = stdout or sys.stdout 284 stdout = kwargs.pop('stdout', sys.stdout) or sys.stdout
293 logging.debug(command) 285 assert not 'stderr' in kwargs
286 filter_fn = kwargs.pop('filter_fn', None)
287 print_messages = kwargs.pop('print_messages', False)
288 print_stdout = kwargs.pop('print_stdout', False)
289 fail_status = kwargs.pop('fail_status', None)
290
291 logging.debug(args)
294 if print_messages: 292 if print_messages:
295 stdout.write('\n________ running \'%s\' in \'%s\'\n' 293 stdout.write('\n________ running \'%s\' in \'%s\'\n'
296 % (' '.join(command), in_directory)) 294 % (' '.join(args), kwargs['cwd']))
297 295
298 kid = Popen(command, bufsize=0, cwd=in_directory, 296 kid = Popen(args, bufsize=0,
299 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 297 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
298 **kwargs)
300 299
301 # Do a flush of sys.stdout before we begin reading from the subprocess's 300 # Do a flush of sys.stdout before we begin reading from the subprocess's
302 # stdout. 301 # stdout.
303 last_flushed_at = time.time() 302 last_flushed_at = time.time()
304 stdout.flush() 303 stdout.flush()
305 304
306 # Also, we need to forward stdout to prevent weird re-ordering of output. 305 # Also, we need to forward stdout to prevent weird re-ordering of output.
307 # This has to be done on a per byte basis to make sure it is not buffered: 306 # This has to be done on a per byte basis to make sure it is not buffered:
308 # normally buffering is done for each line, but if svn requests input, no 307 # normally buffering is done for each line, but if svn requests input, no
309 # end-of-line character is output after the prompt and it would not show up. 308 # end-of-line character is output after the prompt and it would not show up.
310 in_byte = kid.stdout.read(1) 309 in_byte = kid.stdout.read(1)
311 in_line = '' 310 in_line = ''
312 while in_byte: 311 while in_byte:
313 if in_byte != '\r': 312 if in_byte != '\r':
314 if print_stdout: 313 if print_stdout:
315 if not print_messages: 314 if not print_messages:
316 stdout.write('\n________ running \'%s\' in \'%s\'\n' 315 stdout.write('\n________ running \'%s\' in \'%s\'\n'
317 % (' '.join(command), in_directory)) 316 % (' '.join(args), kwargs['cwd']))
318 print_messages = True 317 print_messages = True
319 stdout.write(in_byte) 318 stdout.write(in_byte)
320 if in_byte != '\n': 319 if in_byte != '\n':
321 in_line += in_byte 320 in_line += in_byte
322 if in_byte == '\n': 321 if in_byte == '\n':
323 if filter_fn: 322 if filter_fn:
324 filter_fn(in_line) 323 filter_fn(in_line)
325 in_line = '' 324 in_line = ''
326 # Flush at least 10 seconds between line writes. We wait at least 10 325 # Flush at least 10 seconds between line writes. We wait at least 10
327 # seconds to avoid overloading the reader that called us with output, 326 # seconds to avoid overloading the reader that called us with output,
328 # which can slow busy readers down. 327 # which can slow busy readers down.
329 if (time.time() - last_flushed_at) > 10: 328 if (time.time() - last_flushed_at) > 10:
330 last_flushed_at = time.time() 329 last_flushed_at = time.time()
331 stdout.flush() 330 stdout.flush()
332 in_byte = kid.stdout.read(1) 331 in_byte = kid.stdout.read(1)
333 # Flush the rest of buffered output. This is only an issue with files not 332 # Flush the rest of buffered output. This is only an issue with files not
334 # ending with a \n. 333 # ending with a \n.
335 if len(in_line) and filter_fn: 334 if len(in_line) and filter_fn:
336 filter_fn(in_line) 335 filter_fn(in_line)
337 rv = kid.wait() 336 rv = kid.wait()
338 337
339 if rv: 338 if rv:
340 msg = 'failed to run command: %s' % ' '.join(command) 339 msg = 'failed to run command: %s' % ' '.join(args)
341 if fail_status != None: 340 if fail_status != None:
342 sys.stderr.write(msg + '\n') 341 sys.stderr.write(msg + '\n')
343 sys.exit(fail_status) 342 sys.exit(fail_status)
344 raise Error(msg) 343 raise Error(msg)
345 344
346 345
347 def FindGclientRoot(from_dir, filename='.gclient'): 346 def FindGclientRoot(from_dir, filename='.gclient'):
348 """Tries to find the gclient root.""" 347 """Tries to find the gclient root."""
349 path = os.path.realpath(from_dir) 348 path = os.path.realpath(from_dir)
350 while not os.path.exists(os.path.join(path, filename)): 349 while not os.path.exists(os.path.join(path, filename)):
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 if exception: 534 if exception:
536 self.parent.exceptions.append(exception) 535 self.parent.exceptions.append(exception)
537 if self.parent.progress: 536 if self.parent.progress:
538 self.parent.progress.update(1) 537 self.parent.progress.update(1)
539 assert not self.item.name in self.parent.ran 538 assert not self.item.name in self.parent.ran
540 if not self.item.name in self.parent.ran: 539 if not self.item.name in self.parent.ran:
541 self.parent.ran.append(self.item.name) 540 self.parent.ran.append(self.item.name)
542 finally: 541 finally:
543 self.parent.ready_cond.notifyAll() 542 self.parent.ready_cond.notifyAll()
544 self.parent.ready_cond.release() 543 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