Index: scripts/common/cros_chromite.py |
diff --git a/scripts/common/cros_chromite.py b/scripts/common/cros_chromite.py |
index ffe822a934eec166e7285240c0d91f99cd1cac83..9af09be6c049f7ab17b1a87ebdbbcc5a66743d48 100755 |
--- a/scripts/common/cros_chromite.py |
+++ b/scripts/common/cros_chromite.py |
@@ -21,6 +21,7 @@ import base64 |
import collections |
import json |
import logging |
+import os |
import sys |
try: |
@@ -35,30 +36,23 @@ except ImportError: |
# is missing so bots don't show errors. |
requests = None |
-from common import configcache |
+# Add 'common' to our path. |
+from common import configcache, env |
# The name of the branch associated with tip-of-tree. |
TOT_BRANCH = 'master' |
-# A map of branch names to their pinned commits. These are maintained through |
-# a DEPS hook in <build>/DEPS. In order to update a pinned revision: |
-# - Update the value here. |
+# Configure our pin locations. Because repository availability is dependent |
+# on checkout layout, pin descriptors are conditional on their repository's |
+# availability. |
+# |
+# These are maintained via a DEPS hook in <build>/DEPS. In order to update a |
+# pinned revision: |
+# - Update the value in the respective JSON file. |
# - Run "gclient runhooks --force". |
-PINS = collections.OrderedDict(( |
- (TOT_BRANCH, 'b2d341616f5043863449ad74d8e4fb06fe9a9b58'), |
- |
- # Release waterfall branches. |
- # |
- # Note that the release waterfall instantiates only three releases. We will |
- # keep one branch around for stability, since internal waterfall updates are |
- # not atomic. Therefore, we should prune all but the FOUR newest release |
- # branches. |
- ('release-R47-7520.B', 'd047e007037383c04c4453beca4f69b82ea74188'), |
- ('release-R46-7390.B', '33959980025b477366d0792a4e14bfd7c0f0810c'), |
- ('release-R45-7262.B', 'd06f185c5383e4ffe884ca30e55df060b96b0c59'), |
- ('release-R44-7077.B', '6b12acdd58a3a506f58fb32bd0b78cbfe72506a3'), |
-)) |
+PIN_JSON_PATH = os.path.join(env.Build, 'scripts', 'common', |
+ 'cros_chromite_pins.json') |
class ChromiteError(RuntimeError): |
@@ -351,7 +345,7 @@ class ChromiteConfig(collections.OrderedDict): |
class ChromitePinManager(object): |
"""Manages Chromite pinning associations.""" |
- def __init__(self, pinned, require=False): |
+ def __init__(self, cache_name, pinned, require=False): |
"""Instantiates a new ChromitePinManager. |
Args: |
@@ -360,9 +354,27 @@ class ChromitePinManager(object): |
require: (bool) If False, a requested branch without a pinned match will |
return that branch name; otherwise, a ChromiteError will be returned. |
""" |
+ self._cache_name = cache_name |
self._pinned = pinned |
self._require = require |
+ @property |
+ def cache_name(self): |
+ return self._cache_name |
+ |
+ @classmethod |
+ def LoadFromJSON(cls, cache_name, path, **kwargs): |
+ """Returns: (ChromitePinManager) a ChromitePinManager instance. |
+ |
+ Loads a ChromitePinManager configuration from a pin JSON file. |
+ """ |
+ logging.debug('Loading default pins from: %s', path) |
+ with open(path, 'r') as fd: |
+ pins = json.load(fd) |
+ if not isinstance(pins, dict): |
+ raise TypeError('JSON pins are not a dictionary: %s' % (path,)) |
+ return cls(cache_name, pins, **kwargs) |
+ |
def iterpins(self): |
"""Returns: an iterator over registered (pin, commit) tuples.""" |
return self._pinned.iteritems() |
@@ -384,6 +396,33 @@ class ChromitePinManager(object): |
value = branch |
return value |
+ def Get(self, branch=None, allow_fetch=True): |
+ """Returns: (ChromiteConfig) the Chromite configuration for a given branch. |
+ |
+ Args: |
+ branch: (str) The name of the branch to retrieve. If None, use |
+ tip-of-tree. |
+ allow_fetch: (bool) If True, allow a Get miss to fetch a new cache value. |
+ """ |
+ cache_manager = _GetCacheManager( |
+ self, |
+ allow_fetch=allow_fetch) |
+ |
+ try: |
+ _UpdateCache(cache_manager, self) |
+ except configcache.ReadOnlyError as e: |
+ raise ChromiteError("Cannot update read-only config cache. Run " |
+ "`gclient runhooks --force`: %s" % (e,)) |
+ |
+ return ChromiteConfigManager( |
+ cache_manager, |
+ pinned=self, |
+ ).GetConfig(branch) |
+ |
+ def List(self): |
+ """Returns: (list) a list of the configured Chromite pin branch names.""" |
+ return self._pinned.keys() |
+ |
class ChromiteConfigManager(object): |
"""Manages Chromite configuration options and Chromite config fetching.""" |
@@ -492,7 +531,13 @@ class ChromiteFetcher(object): |
# Default ChromitePinManager instance. |
-DefaultChromitePinManager = ChromitePinManager(PINS) |
+_DEFAULT_PIN_MANAGER = None |
+def DefaultChromitePinManager(): |
+ global _DEFAULT_PIN_MANAGER |
+ if not _DEFAULT_PIN_MANAGER: |
+ _DEFAULT_PIN_MANAGER = ChromitePinManager.LoadFromJSON('chromite', |
+ PIN_JSON_PATH) |
+ return _DEFAULT_PIN_MANAGER |
def Get(branch=None, allow_fetch=True): |
@@ -502,20 +547,14 @@ def Get(branch=None, allow_fetch=True): |
branch: (str) The name of the branch to retrieve. If None, use tip-of-tree. |
allow_fetch: (bool) If True, allow a Get miss to fetch a new cache value. |
""" |
- cache_manager = _GetCacheManager( |
- DefaultChromitePinManager, |
+ return DefaultChromitePinManager().Get( |
+ branch=branch, |
allow_fetch=allow_fetch) |
- try: |
- _UpdateCache(cache_manager, DefaultChromitePinManager) |
- except configcache.ReadOnlyError as e: |
- raise ChromiteError("Cannot update read-only config cache. Run " |
- "`gclient runhooks --force`: %s" % (e,)) |
- return ChromiteConfigManager( |
- cache_manager, |
- pinned=DefaultChromitePinManager, |
- ).GetConfig(branch) |
+def List(): |
+ """Returns: (list) a list of the configured Chromite pin branch names.""" |
+ return DefaultChromitePinManager().List() |
def _UpdateCache(cache_manager, pin_manager, force=False): |
@@ -553,14 +592,14 @@ def _GetCacheManager(pin_manager, allow_fetch=False, **kwargs): |
pin_manager: The ChromitePinManager to use. |
""" |
return configcache.CacheManager( |
- 'chromite', |
+ pin_manager.cache_name, |
# TODO(dnj): Remove the 'requests' test (crbug.com/452258). |
fetcher=(ChromiteFetcher(pin_manager) if allow_fetch and requests |
else None), |
**kwargs) |
-def main(): |
+def main(argv, pin_manager_gen): |
parser = argparse.ArgumentParser() |
parser.add_argument('-v', '--verbose', action='count', default=0, |
help='Increase process verbosity. This can be specified multiple times.') |
@@ -568,7 +607,7 @@ def main(): |
help='The base cache directory to download pinned configurations into.') |
parser.add_argument('-f', '--force', action='store_true', |
help='Forces an update, even if the cached already contains an artifact.') |
- args = parser.parse_args() |
+ args = parser.parse_args(argv) |
# Handle verbosity. |
if args.verbose == 0: |
@@ -579,7 +618,7 @@ def main(): |
loglevel = logging.DEBUG |
logging.getLogger().setLevel(loglevel) |
- pm = DefaultChromitePinManager |
+ pm = pin_manager_gen() |
cm = _GetCacheManager(pm, allow_fetch=True, cache_dir=args.cache_directory) |
updated = _UpdateCache(cm, pm, force=args.force) |
logging.info('Updated %d cache artifact(s).', len(updated)) |
@@ -591,7 +630,7 @@ def main(): |
if __name__ == '__main__': |
logging.basicConfig() |
try: |
- sys.exit(main()) |
+ sys.exit(main(sys.argv[1:], DefaultChromitePinManager)) |
except Exception as e: |
logging.exception("Uncaught execption: %s", e) |
sys.exit(1) |