OLD | NEW |
(Empty) | |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import contextlib |
| 6 import os |
| 7 import shutil |
| 8 import tempfile |
| 9 |
| 10 |
| 11 from infra.tools.cros_pin import execute |
| 12 from infra.tools.cros_pin.logger import LOGGER |
| 13 |
| 14 |
| 15 class Checkout(object): |
| 16 """Checkout is a managed root checkout directory.""" |
| 17 |
| 18 GCLIENT_TEMPLATE = """ |
| 19 solutions = [ |
| 20 { |
| 21 "url": "https://chromium.googlesource.com/chromium/tools/build.git", |
| 22 "managed": False, |
| 23 "name": "build", |
| 24 "deps_file": ".DEPS.git", |
| 25 }, |
| 26 { |
| 27 "url": "https://chrome-internal.googlesource.com/chrome/tools/build.git", |
| 28 "managed": False, |
| 29 "name": "build_internal", |
| 30 "deps_file": ".DEPS.git", |
| 31 }, |
| 32 ] |
| 33 """ |
| 34 |
| 35 def __init__(self, path, delete=False): |
| 36 self._path = path |
| 37 self._delete = delete |
| 38 |
| 39 @property |
| 40 def path(self): |
| 41 return self._path |
| 42 |
| 43 def subpath(self, *components): |
| 44 return os.path.join(self._path, *components) |
| 45 |
| 46 def teardown(self): |
| 47 if self._delete: |
| 48 self._destroy_directory(self._path) |
| 49 |
| 50 @classmethod |
| 51 @contextlib.contextmanager |
| 52 def use(cls, *args, **kwargs): |
| 53 c = None |
| 54 try: |
| 55 c = cls.create(*args, **kwargs) |
| 56 LOGGER.debug('Using checkout at: %s', c.path) |
| 57 yield c |
| 58 finally: |
| 59 if c: |
| 60 c.teardown() |
| 61 |
| 62 @classmethod |
| 63 def create(cls, path=None): |
| 64 """Creates a new Checkout using the specified path. |
| 65 |
| 66 Args: |
| 67 path (str): The path of the checkout to use. If None, a temporary |
| 68 checkout will be created. |
| 69 """ |
| 70 delete = False |
| 71 if path: |
| 72 if os.path.isdir(path): |
| 73 return cls(path, delete=False) |
| 74 os.makedirs(path) |
| 75 else: |
| 76 path = tempfile.mkdtemp(prefix='tmp_cros_pin') |
| 77 delete = True |
| 78 |
| 79 try: |
| 80 cls.fetch(path) |
| 81 c = cls(path, delete=delete) |
| 82 path = None # Signal our "finally" clause not to clean up here. |
| 83 finally: |
| 84 if path: |
| 85 cls._destroy_directory(path) |
| 86 return c |
| 87 |
| 88 @classmethod |
| 89 def fetch(cls, path): |
| 90 LOGGER.info("Fetching => %s (This can take a while.)", path) |
| 91 gclient_path = os.path.join(path, '.gclient') |
| 92 with open(gclient_path, 'w') as fd: |
| 93 fd.write(cls.GCLIENT_TEMPLATE) |
| 94 |
| 95 execute.check_call( |
| 96 ['gclient', 'sync', '--nohooks', '--noprehooks'], |
| 97 cwd=path) |
| 98 |
| 99 @staticmethod |
| 100 def _destroy_directory(d): |
| 101 LOGGER.debug('Destorying directory: %s', d) |
| 102 def log_failure(_function, path, excinfo): |
| 103 LOGGER.warning('Failed when destroying [%s]: %s', |
| 104 path, excinfo[1].message) |
| 105 shutil.rmtree(d, onerror=log_failure) |
OLD | NEW |