OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Generic utils.""" | 5 """Generic utils.""" |
6 | 6 |
7 import codecs | 7 import codecs |
8 import errno | 8 import errno |
9 import logging | 9 import logging |
10 import os | 10 import os |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 os.makedirs(tree) | 185 os.makedirs(tree) |
186 except OSError, e: | 186 except OSError, e: |
187 # 17 POSIX, 183 Windows | 187 # 17 POSIX, 183 Windows |
188 if e.errno not in (17, 183): | 188 if e.errno not in (17, 183): |
189 raise | 189 raise |
190 if count > 40: | 190 if count > 40: |
191 # Give up. | 191 # Give up. |
192 raise | 192 raise |
193 | 193 |
194 | 194 |
195 def CheckCallAndFilterAndHeader(args, always=False, **kwargs): | 195 def CheckCallAndFilterAndHeader(args, always=False, header=None, **kwargs): |
196 """Adds 'header' support to CheckCallAndFilter. | 196 """Adds 'header' support to CheckCallAndFilter. |
197 | 197 |
198 If |always| is True, a message indicating what is being done | 198 If |always| is True, a message indicating what is being done |
199 is printed to stdout all the time even if not output is generated. Otherwise | 199 is printed to stdout all the time even if not output is generated. Otherwise |
200 the message header is printed only if the call generated any ouput. | 200 the message header is printed only if the call generated any ouput. |
201 """ | 201 """ |
202 stdout = kwargs.get('stdout', None) or sys.stdout | 202 stdout = kwargs.setdefault('stdout', sys.stdout) |
| 203 if header is None: |
| 204 header = "\n________ running '%s' in '%s'\n" % ( |
| 205 ' '.join(args), kwargs.get('cwd', '.')) |
| 206 |
203 if always: | 207 if always: |
204 stdout.write('\n________ running \'%s\' in \'%s\'\n' | 208 stdout.write(header) |
205 % (' '.join(args), kwargs.get('cwd', '.'))) | |
206 else: | 209 else: |
207 filter_fn = kwargs.get('filter_fn', None) | 210 filter_fn = kwargs.get('filter_fn') |
208 def filter_msg(line): | 211 def filter_msg(line): |
209 if line is None: | 212 if line is None: |
210 stdout.write('\n________ running \'%s\' in \'%s\'\n' | 213 stdout.write(header) |
211 % (' '.join(args), kwargs.get('cwd', '.'))) | |
212 elif filter_fn: | 214 elif filter_fn: |
213 filter_fn(line) | 215 filter_fn(line) |
214 kwargs['filter_fn'] = filter_msg | 216 kwargs['filter_fn'] = filter_msg |
215 kwargs['call_filter_on_first_line'] = True | 217 kwargs['call_filter_on_first_line'] = True |
216 # Obviously. | 218 # Obviously. |
217 kwargs['print_stdout'] = True | 219 kwargs.setdefault('print_stdout', True) |
218 return CheckCallAndFilter(args, **kwargs) | 220 return CheckCallAndFilter(args, **kwargs) |
219 | 221 |
220 | 222 |
221 class Wrapper(object): | 223 class Wrapper(object): |
222 """Wraps an object, acting as a transparent proxy for all properties by | 224 """Wraps an object, acting as a transparent proxy for all properties by |
223 default. | 225 default. |
224 """ | 226 """ |
225 def __init__(self, wrapped): | 227 def __init__(self, wrapped): |
226 self._wrapped = wrapped | 228 self._wrapped = wrapped |
227 | 229 |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 return None | 445 return None |
444 # If the root does not have a trailing \ or /, we add it so the returned | 446 # If the root does not have a trailing \ or /, we add it so the returned |
445 # path starts immediately after the seperator regardless of whether it is | 447 # path starts immediately after the seperator regardless of whether it is |
446 # provided. | 448 # provided. |
447 root = os.path.join(root, '') | 449 root = os.path.join(root, '') |
448 return subpath[len(root):] | 450 return subpath[len(root):] |
449 | 451 |
450 | 452 |
451 def FindFileUpwards(filename, path=None): | 453 def FindFileUpwards(filename, path=None): |
452 """Search upwards from the a directory (default: current) to find a file. | 454 """Search upwards from the a directory (default: current) to find a file. |
453 | 455 |
454 Returns nearest upper-level directory with the passed in file. | 456 Returns nearest upper-level directory with the passed in file. |
455 """ | 457 """ |
456 if not path: | 458 if not path: |
457 path = os.getcwd() | 459 path = os.getcwd() |
458 path = os.path.realpath(path) | 460 path = os.path.realpath(path) |
459 while True: | 461 while True: |
460 file_path = os.path.join(path, filename) | 462 file_path = os.path.join(path, filename) |
461 if os.path.exists(file_path): | 463 if os.path.exists(file_path): |
462 return path | 464 return path |
463 (new_path, _) = os.path.split(path) | 465 (new_path, _) = os.path.split(path) |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 class ExecutionQueue(object): | 521 class ExecutionQueue(object): |
520 """Runs a set of WorkItem that have interdependencies and were WorkItem are | 522 """Runs a set of WorkItem that have interdependencies and were WorkItem are |
521 added as they are processed. | 523 added as they are processed. |
522 | 524 |
523 In gclient's case, Dependencies sometime needs to be run out of order due to | 525 In gclient's case, Dependencies sometime needs to be run out of order due to |
524 From() keyword. This class manages that all the required dependencies are run | 526 From() keyword. This class manages that all the required dependencies are run |
525 before running each one. | 527 before running each one. |
526 | 528 |
527 Methods of this class are thread safe. | 529 Methods of this class are thread safe. |
528 """ | 530 """ |
529 def __init__(self, jobs, progress): | 531 def __init__(self, jobs, progress, ignore_requirements): |
530 """jobs specifies the number of concurrent tasks to allow. progress is a | 532 """jobs specifies the number of concurrent tasks to allow. progress is a |
531 Progress instance.""" | 533 Progress instance.""" |
532 # Set when a thread is done or a new item is enqueued. | 534 # Set when a thread is done or a new item is enqueued. |
533 self.ready_cond = threading.Condition() | 535 self.ready_cond = threading.Condition() |
534 # Maximum number of concurrent tasks. | 536 # Maximum number of concurrent tasks. |
535 self.jobs = jobs | 537 self.jobs = jobs |
536 # List of WorkItem, for gclient, these are Dependency instances. | 538 # List of WorkItem, for gclient, these are Dependency instances. |
537 self.queued = [] | 539 self.queued = [] |
538 # List of strings representing each Dependency.name that was run. | 540 # List of strings representing each Dependency.name that was run. |
539 self.ran = [] | 541 self.ran = [] |
540 # List of items currently running. | 542 # List of items currently running. |
541 self.running = [] | 543 self.running = [] |
542 # Exceptions thrown if any. | 544 # Exceptions thrown if any. |
543 self.exceptions = Queue.Queue() | 545 self.exceptions = Queue.Queue() |
544 # Progress status | 546 # Progress status |
545 self.progress = progress | 547 self.progress = progress |
546 if self.progress: | 548 if self.progress: |
547 self.progress.update(0) | 549 self.progress.update(0) |
548 | 550 |
| 551 self.ignore_requirements = ignore_requirements |
| 552 |
549 def enqueue(self, d): | 553 def enqueue(self, d): |
550 """Enqueue one Dependency to be executed later once its requirements are | 554 """Enqueue one Dependency to be executed later once its requirements are |
551 satisfied. | 555 satisfied. |
552 """ | 556 """ |
553 assert isinstance(d, WorkItem) | 557 assert isinstance(d, WorkItem) |
554 self.ready_cond.acquire() | 558 self.ready_cond.acquire() |
555 try: | 559 try: |
556 self.queued.append(d) | 560 self.queued.append(d) |
557 total = len(self.queued) + len(self.ran) + len(self.running) | 561 total = len(self.queued) + len(self.ran) + len(self.running) |
558 logging.debug('enqueued(%s)' % d.name) | 562 logging.debug('enqueued(%s)' % d.name) |
(...skipping 17 matching lines...) Expand all Loading... |
576 self.queued = [] | 580 self.queued = [] |
577 self._flush_terminated_threads() | 581 self._flush_terminated_threads() |
578 if (not self.queued and not self.running or | 582 if (not self.queued and not self.running or |
579 self.jobs == len(self.running)): | 583 self.jobs == len(self.running)): |
580 logging.debug('No more worker threads or can\'t queue anything.') | 584 logging.debug('No more worker threads or can\'t queue anything.') |
581 break | 585 break |
582 | 586 |
583 # Check for new tasks to start. | 587 # Check for new tasks to start. |
584 for i in xrange(len(self.queued)): | 588 for i in xrange(len(self.queued)): |
585 # Verify its requirements. | 589 # Verify its requirements. |
586 for r in self.queued[i].requirements: | 590 if (self.ignore_requirements or |
587 if not r in self.ran: | 591 not (set(self.queued[i].requirements) - set(self.ran))): |
588 # Requirement not met. | |
589 break | |
590 else: | |
591 # Start one work item: all its requirements are satisfied. | 592 # Start one work item: all its requirements are satisfied. |
592 self._run_one_task(self.queued.pop(i), args, kwargs) | 593 self._run_one_task(self.queued.pop(i), args, kwargs) |
593 break | 594 break |
594 else: | 595 else: |
595 # Couldn't find an item that could run. Break out the outher loop. | 596 # Couldn't find an item that could run. Break out the outher loop. |
596 break | 597 break |
597 | 598 |
598 if not self.queued and not self.running: | 599 if not self.queued and not self.running: |
599 # We're done. | 600 # We're done. |
600 break | 601 break |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 | 777 |
777 Python on OSX 10.6 raises a NotImplementedError exception. | 778 Python on OSX 10.6 raises a NotImplementedError exception. |
778 """ | 779 """ |
779 try: | 780 try: |
780 import multiprocessing | 781 import multiprocessing |
781 return multiprocessing.cpu_count() | 782 return multiprocessing.cpu_count() |
782 except: # pylint: disable=W0702 | 783 except: # pylint: disable=W0702 |
783 # Mac OS 10.6 only | 784 # Mac OS 10.6 only |
784 # pylint: disable=E1101 | 785 # pylint: disable=E1101 |
785 return int(os.sysconf('SC_NPROCESSORS_ONLN')) | 786 return int(os.sysconf('SC_NPROCESSORS_ONLN')) |
OLD | NEW |