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

Side by Side Diff: gclient_utils.py

Issue 3104036: Cleanup the code in gclient_utils to standardize on CheckCall nomenclature. (Closed)
Patch Set: Rewrote the patch in part as I had introduced regressions. Removed a lot of dead code 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 def GetNodeNamedAttributeText(node, node_name, attribute_name): 111 def GetNodeNamedAttributeText(node, node_name, attribute_name):
112 child_nodes = node.getElementsByTagName(node_name) 112 child_nodes = node.getElementsByTagName(node_name)
113 if not child_nodes: 113 if not child_nodes:
114 return None 114 return None
115 assert len(child_nodes) == 1 115 assert len(child_nodes) == 1
116 return child_nodes[0].getAttribute(attribute_name) 116 return child_nodes[0].getAttribute(attribute_name)
117 117
118 118
119 class Error(Exception): 119 class Error(Exception):
120 """gclient exception class.""" 120 """gclient exception class."""
121 # TODO(maruel): Merge with CheckCallError.
121 pass 122 pass
122 123
123 124
124 def SyntaxErrorToError(filename, e): 125 def SyntaxErrorToError(filename, e):
125 """Raises a gclient_utils.Error exception with the human readable message""" 126 """Raises a gclient_utils.Error exception with the human readable message"""
126 try: 127 try:
127 # Try to construct a human readable error message 128 # Try to construct a human readable error message
128 if filename: 129 if filename:
129 error_message = 'There is a syntax error in %s\n' % filename 130 error_message = 'There is a syntax error in %s\n' % filename
130 else: 131 else:
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 try: 245 try:
245 os.rmdir(file_path) 246 os.rmdir(file_path)
246 except OSError, e: 247 except OSError, e:
247 if e.errno != errno.EACCES or sys.platform != 'win32': 248 if e.errno != errno.EACCES or sys.platform != 'win32':
248 raise 249 raise
249 print 'Failed to remove %s: trying again' % file_path 250 print 'Failed to remove %s: trying again' % file_path
250 time.sleep(0.1) 251 time.sleep(0.1)
251 os.rmdir(file_path) 252 os.rmdir(file_path)
252 253
253 254
254 def SubprocessCall(args, **kwargs): 255 def CheckCallAndFilterAndHeader(args, always=False, **kwargs):
255 """Wraps SubprocessCallAndFilter() with different default arguments. 256 """Adds 'header' support to CheckCallAndFilter.
256 257
257 Calls subprocess and capture nothing.""" 258 If |always| is True, a message indicating what is being done
258 kwargs['print_messages'] = True 259 is printed to stdout all the time even if not output is generated. Otherwise
260 the message header is printed only if the call generated any ouput.
261 """
262 stdout = kwargs.get('stdout', None) or sys.stdout
263 if always:
264 stdout.write('\n________ running \'%s\' in \'%s\'\n'
265 % (' '.join(args), kwargs.get('cwd', '.')))
266 else:
267 filter_fn = kwargs.get('filter_fn', None)
268 def filter_msg(line):
269 if line is None:
270 stdout.write('\n________ running \'%s\' in \'%s\'\n'
271 % (' '.join(args), kwargs.get('cwd', '.')))
272 elif filter_fn:
273 filter_fn(line)
274 kwargs['filter_fn'] = filter_msg
275 kwargs['call_filter_on_first_line'] = True
276 # Obviously.
259 kwargs['print_stdout'] = True 277 kwargs['print_stdout'] = True
260 return SubprocessCallAndFilter(args, **kwargs) 278 return CheckCallAndFilter(args, **kwargs)
261 279
262 280
263 def SubprocessCallAndFilter(args, **kwargs): 281 def CheckCallAndFilter(args, stdout=None, filter_fn=None,
264 """Runs a command and prints a header line if appropriate. 282 print_stdout=None, call_filter_on_first_line=False,
283 **kwargs):
284 """Runs a command and calls back a filter function if needed.
265 285
266 If |print_messages| is True, a message indicating what is being done 286 Accepts all subprocess.Popen() parameters plus:
267 is printed to stdout. Otherwise the message is printed only if the call 287 print_stdout: If True, the command's stdout is forwarded to stdout.
268 generated any ouput. If both |print_messages| and |print_stdout| are False, 288 filter_fn: A function taking a single string argument called with each line
269 no output at all is generated. 289 of the subprocess's output. Each line has the trailing newline
290 character trimmed.
291 stdout: Can be any bufferable output.
270 292
271 If |print_stdout| is True, the command's stdout is also forwarded to stdout. 293 stderr is always redirected to stdout.
272
273 If |filter_fn| function is specified, it is expected to take a single
274 string argument, and it will be called with each line of the
275 subprocess's output. Each line has had the trailing newline character
276 trimmed.
277
278 If the command fails, as indicated by a nonzero exit status, gclient will
279 exit with an exit status of fail_status. If fail_status is None (the
280 default), gclient will raise an Error exception.
281
282 Other subprocess.Popen parameters can be specified.
283 """ 294 """
284 stdout = kwargs.pop('stdout', sys.stdout) or sys.stdout 295 assert print_stdout or filter_fn
296 stdout = stdout or sys.stdout
297 filter_fn = filter_fn or (lambda x: None)
285 assert not 'stderr' in kwargs 298 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) 299 logging.debug(args)
292 if print_messages:
293 stdout.write('\n________ running \'%s\' in \'%s\'\n'
294 % (' '.join(args), kwargs['cwd']))
295
296 kid = Popen(args, bufsize=0, 300 kid = Popen(args, bufsize=0,
297 stdout=subprocess.PIPE, stderr=subprocess.STDOUT, 301 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
298 **kwargs) 302 **kwargs)
299 303
300 # Do a flush of sys.stdout before we begin reading from the subprocess's 304 # Do a flush of stdout before we begin reading from the subprocess's stdout
301 # stdout.
302 last_flushed_at = time.time() 305 last_flushed_at = time.time()
303 stdout.flush() 306 stdout.flush()
304 307
305 # Also, we need to forward stdout to prevent weird re-ordering of output. 308 # Also, we need to forward stdout to prevent weird re-ordering of output.
306 # This has to be done on a per byte basis to make sure it is not buffered: 309 # This has to be done on a per byte basis to make sure it is not buffered:
307 # normally buffering is done for each line, but if svn requests input, no 310 # normally buffering is done for each line, but if svn requests input, no
308 # end-of-line character is output after the prompt and it would not show up. 311 # end-of-line character is output after the prompt and it would not show up.
309 in_byte = kid.stdout.read(1) 312 in_byte = kid.stdout.read(1)
310 in_line = '' 313 if in_byte:
311 while in_byte: 314 if call_filter_on_first_line:
312 if in_byte != '\r': 315 filter_fn(None)
313 if print_stdout: 316 in_line = ''
314 if not print_messages: 317 while in_byte:
315 stdout.write('\n________ running \'%s\' in \'%s\'\n' 318 if in_byte != '\r':
316 % (' '.join(args), kwargs['cwd'])) 319 if print_stdout:
317 print_messages = True 320 stdout.write(in_byte)
318 stdout.write(in_byte) 321 if in_byte != '\n':
319 if in_byte != '\n': 322 in_line += in_byte
320 in_line += in_byte 323 else:
321 if in_byte == '\n': 324 filter_fn(in_line)
322 if filter_fn: 325 in_line = ''
323 filter_fn(in_line) 326 # Flush at least 10 seconds between line writes. We wait at least 10
324 in_line = '' 327 # seconds to avoid overloading the reader that called us with output,
325 # Flush at least 10 seconds between line writes. We wait at least 10 328 # which can slow busy readers down.
326 # seconds to avoid overloading the reader that called us with output, 329 if (time.time() - last_flushed_at) > 10:
327 # which can slow busy readers down. 330 last_flushed_at = time.time()
328 if (time.time() - last_flushed_at) > 10: 331 stdout.flush()
329 last_flushed_at = time.time() 332 in_byte = kid.stdout.read(1)
330 stdout.flush() 333 # Flush the rest of buffered output. This is only an issue with
331 in_byte = kid.stdout.read(1) 334 # stdout/stderr not ending with a \n.
332 # Flush the rest of buffered output. This is only an issue with files not 335 if len(in_line):
333 # ending with a \n. 336 filter_fn(in_line)
334 if len(in_line) and filter_fn:
335 filter_fn(in_line)
336 rv = kid.wait() 337 rv = kid.wait()
337
338 if rv: 338 if rv:
339 msg = 'failed to run command: %s' % ' '.join(args) 339 raise Error('failed to run command: %s' % ' '.join(args))
340 if fail_status != None: 340 return 0
341 sys.stderr.write(msg + '\n')
342 sys.exit(fail_status)
343 raise Error(msg)
344 341
345 342
346 def FindGclientRoot(from_dir, filename='.gclient'): 343 def FindGclientRoot(from_dir, filename='.gclient'):
347 """Tries to find the gclient root.""" 344 """Tries to find the gclient root."""
348 path = os.path.realpath(from_dir) 345 path = os.path.realpath(from_dir)
349 while not os.path.exists(os.path.join(path, filename)): 346 while not os.path.exists(os.path.join(path, filename)):
350 split_path = os.path.split(path) 347 split_path = os.path.split(path)
351 if not split_path[1]: 348 if not split_path[1]:
352 return None 349 return None
353 path = split_path[0] 350 path = split_path[0]
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 if exception: 531 if exception:
535 self.parent.exceptions.append(exception) 532 self.parent.exceptions.append(exception)
536 if self.parent.progress: 533 if self.parent.progress:
537 self.parent.progress.update(1) 534 self.parent.progress.update(1)
538 assert not self.item.name in self.parent.ran 535 assert not self.item.name in self.parent.ran
539 if not self.item.name in self.parent.ran: 536 if not self.item.name in self.parent.ran:
540 self.parent.ran.append(self.item.name) 537 self.parent.ran.append(self.item.name)
541 finally: 538 finally:
542 self.parent.ready_cond.notifyAll() 539 self.parent.ready_cond.notifyAll()
543 self.parent.ready_cond.release() 540 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