| OLD | NEW |
| 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, |
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 # See the License for the specific language governing permissions and | 12 # See the License for the specific language governing permissions and |
| 13 # limitations under the License. | 13 # limitations under the License. |
| 14 | 14 |
| 15 """Generic utils.""" | 15 """Generic utils.""" |
| 16 | 16 |
| 17 import errno | 17 import errno |
| 18 import logging | 18 import logging |
| 19 import os | 19 import os |
| 20 import re | 20 import re |
| 21 import stat | 21 import stat |
| 22 import subprocess | 22 import subprocess |
| 23 import sys | 23 import sys |
| 24 import threading | 24 import threading |
| 25 import time | 25 import time |
| 26 import threading | |
| 27 import xml.dom.minidom | 26 import xml.dom.minidom |
| 28 import xml.parsers.expat | 27 import xml.parsers.expat |
| 29 | 28 |
| 30 | 29 |
| 31 class CheckCallError(OSError): | 30 class CheckCallError(OSError): |
| 32 """CheckCall() returned non-0.""" | 31 """CheckCall() returned non-0.""" |
| 33 def __init__(self, command, cwd, retcode, stdout, stderr=None): | 32 def __init__(self, command, cwd, retcode, stdout, stderr=None): |
| 34 OSError.__init__(self, command, cwd, retcode, stdout, stderr) | 33 OSError.__init__(self, command, cwd, retcode, stdout, stderr) |
| 35 self.command = command | 34 self.command = command |
| 36 self.cwd = cwd | 35 self.cwd = cwd |
| 37 self.retcode = retcode | 36 self.retcode = retcode |
| 38 self.stdout = stdout | 37 self.stdout = stdout |
| 39 self.stderr = stderr | 38 self.stderr = stderr |
| 40 | 39 |
| 41 | 40 |
| 41 def Popen(*args, **kwargs): |
| 42 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for the |
| 43 # executable, but shell=True makes subprocess on Linux fail when it's called |
| 44 # with a list because it only tries to execute the first item in the list. |
| 45 if not 'env' in kwargs: |
| 46 # It's easier to parse the stdout if it is always in English. |
| 47 kwargs['env'] = os.environ.copy() |
| 48 kwargs['env']['LANGUAGE'] = 'en' |
| 49 return subprocess.Popen(*args, shell=(sys.platform=='win32'), **kwargs) |
| 50 |
| 51 |
| 42 def CheckCall(command, cwd=None, print_error=True): | 52 def CheckCall(command, cwd=None, print_error=True): |
| 43 """Like subprocess.check_call() but returns stdout. | 53 """Similar subprocess.check_call() but redirects stdout and |
| 54 returns (stdout, stderr). |
| 44 | 55 |
| 45 Works on python 2.4 | 56 Works on python 2.4 |
| 46 """ | 57 """ |
| 47 logging.debug('%s, cwd=%s' % (str(command), str(cwd))) | 58 logging.debug('%s, cwd=%s' % (str(command), str(cwd))) |
| 48 try: | 59 try: |
| 49 stderr = None | 60 stderr = None |
| 50 if not print_error: | 61 if not print_error: |
| 51 stderr = subprocess.PIPE | 62 stderr = subprocess.PIPE |
| 52 env = os.environ.copy() | 63 process = Popen(command, cwd=cwd, stdout=subprocess.PIPE, stderr=stderr) |
| 53 env['LANGUAGE'] = 'en' | |
| 54 process = subprocess.Popen(command, cwd=cwd, | |
| 55 shell=sys.platform.startswith('win'), | |
| 56 stdout=subprocess.PIPE, | |
| 57 stderr=stderr, | |
| 58 env=env) | |
| 59 std_out, std_err = process.communicate() | 64 std_out, std_err = process.communicate() |
| 60 except OSError, e: | 65 except OSError, e: |
| 61 raise CheckCallError(command, cwd, e.errno, None) | 66 raise CheckCallError(command, cwd, e.errno, None) |
| 62 if process.returncode: | 67 if process.returncode: |
| 63 raise CheckCallError(command, cwd, process.returncode, std_out, std_err) | 68 raise CheckCallError(command, cwd, process.returncode, std_out, std_err) |
| 64 return std_out, std_err | 69 return std_out, std_err |
| 65 | 70 |
| 66 | 71 |
| 67 def SplitUrlRevision(url): | 72 def SplitUrlRevision(url): |
| 68 """Splits url and returns a two-tuple: url, rev""" | 73 """Splits url and returns a two-tuple: url, rev""" |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 trimmed. | 273 trimmed. |
| 269 | 274 |
| 270 If the command fails, as indicated by a nonzero exit status, gclient will | 275 If the command fails, as indicated by a nonzero exit status, gclient will |
| 271 exit with an exit status of fail_status. If fail_status is None (the | 276 exit with an exit status of fail_status. If fail_status is None (the |
| 272 default), gclient will raise an Error exception. | 277 default), gclient will raise an Error exception. |
| 273 """ | 278 """ |
| 274 logging.debug(command) | 279 logging.debug(command) |
| 275 if print_messages: | 280 if print_messages: |
| 276 print('\n________ running \'%s\' in \'%s\'' | 281 print('\n________ running \'%s\' in \'%s\'' |
| 277 % (' '.join(command), in_directory)) | 282 % (' '.join(command), in_directory)) |
| 278 env = os.environ.copy() | |
| 279 env['LANGUAGE'] = 'en' | |
| 280 | 283 |
| 281 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for the | 284 kid = Popen(command, bufsize=0, cwd=in_directory, |
| 282 # executable, but shell=True makes subprocess on Linux fail when it's called | 285 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 283 # with a list because it only tries to execute the first item in the list. | |
| 284 kid = subprocess.Popen(command, bufsize=0, cwd=in_directory, | |
| 285 shell=(sys.platform == 'win32'), stdout=subprocess.PIPE, | |
| 286 stderr=subprocess.STDOUT, env=env) | |
| 287 | 286 |
| 288 # Do a flush of sys.stdout before we begin reading from the subprocess's | 287 # Do a flush of sys.stdout before we begin reading from the subprocess's |
| 289 # stdout. | 288 # stdout. |
| 290 last_flushed_at = time.time() | 289 last_flushed_at = time.time() |
| 291 sys.stdout.flush() | 290 sys.stdout.flush() |
| 292 | 291 |
| 293 # Also, we need to forward stdout to prevent weird re-ordering of output. | 292 # Also, we need to forward stdout to prevent weird re-ordering of output. |
| 294 # This has to be done on a per byte basis to make sure it is not buffered: | 293 # This has to be done on a per byte basis to make sure it is not buffered: |
| 295 # normally buffering is done for each line, but if svn requests input, no | 294 # normally buffering is done for each line, but if svn requests input, no |
| 296 # end-of-line character is output after the prompt and it would not show up. | 295 # end-of-line character is output after the prompt and it would not show up. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 316 if (time.time() - last_flushed_at) > 10: | 315 if (time.time() - last_flushed_at) > 10: |
| 317 last_flushed_at = time.time() | 316 last_flushed_at = time.time() |
| 318 sys.stdout.flush() | 317 sys.stdout.flush() |
| 319 in_byte = kid.stdout.read(1) | 318 in_byte = kid.stdout.read(1) |
| 320 rv = kid.wait() | 319 rv = kid.wait() |
| 321 | 320 |
| 322 if rv: | 321 if rv: |
| 323 msg = 'failed to run command: %s' % ' '.join(command) | 322 msg = 'failed to run command: %s' % ' '.join(command) |
| 324 | 323 |
| 325 if fail_status != None: | 324 if fail_status != None: |
| 326 print >>sys.stderr, msg | 325 print >> sys.stderr, msg |
| 327 sys.exit(fail_status) | 326 sys.exit(fail_status) |
| 328 | 327 |
| 329 raise Error(msg) | 328 raise Error(msg) |
| 330 | 329 |
| 331 | 330 |
| 332 def FindGclientRoot(from_dir, filename='.gclient'): | 331 def FindGclientRoot(from_dir, filename='.gclient'): |
| 333 """Tries to find the gclient root.""" | 332 """Tries to find the gclient root.""" |
| 334 path = os.path.realpath(from_dir) | 333 path = os.path.realpath(from_dir) |
| 335 while not os.path.exists(os.path.join(path, filename)): | 334 while not os.path.exists(os.path.join(path, filename)): |
| 336 next = os.path.split(path) | 335 split_path = os.path.split(path) |
| 337 if not next[1]: | 336 if not split_path[1]: |
| 338 return None | 337 return None |
| 339 path = next[0] | 338 path = split_path[0] |
| 340 logging.info('Found gclient root at ' + path) | 339 logging.info('Found gclient root at ' + path) |
| 341 return path | 340 return path |
| 342 | 341 |
| 343 | 342 |
| 344 def PathDifference(root, subpath): | 343 def PathDifference(root, subpath): |
| 345 """Returns the difference subpath minus root.""" | 344 """Returns the difference subpath minus root.""" |
| 346 root = os.path.realpath(root) | 345 root = os.path.realpath(root) |
| 347 subpath = os.path.realpath(subpath) | 346 subpath = os.path.realpath(subpath) |
| 348 if not subpath.startswith(root): | 347 if not subpath.startswith(root): |
| 349 return None | 348 return None |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 if exception: | 519 if exception: |
| 521 self.parent.exceptions.append(exception) | 520 self.parent.exceptions.append(exception) |
| 522 if self.parent.progress: | 521 if self.parent.progress: |
| 523 self.parent.progress.update(1) | 522 self.parent.progress.update(1) |
| 524 assert not self.item.name in self.parent.ran | 523 assert not self.item.name in self.parent.ran |
| 525 if not self.item.name in self.parent.ran: | 524 if not self.item.name in self.parent.ran: |
| 526 self.parent.ran.append(self.item.name) | 525 self.parent.ran.append(self.item.name) |
| 527 finally: | 526 finally: |
| 528 self.parent.ready_cond.notifyAll() | 527 self.parent.ready_cond.notifyAll() |
| 529 self.parent.ready_cond.release() | 528 self.parent.ready_cond.release() |
| OLD | NEW |