cros_setup_toolchains: regen cache when script changes
When we update MANUAL_PKGS, that doesn't make it out to the cache file
which leads us to updating an incomplete/old list of packages. Force
a regen of the cache file whenever the cros_setup_toolchains.py script
itself changes.
BUG=chromium:751740
TEST=cache is updated when cros_setup_toolchains.py changes, but not when it's the same
TEST=updating host packages works again as the complete list of packages is found
Change-Id: I63551e0e498d71535d119670641ed0d6e390d792
Reviewed-on: https://chromium-review.googlesource.com/606721
Commit-Ready: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Manoj Gupta <manojgupta@chromium.org>
diff --git a/scripts/cros_setup_toolchains.py b/scripts/cros_setup_toolchains.py
index 55be809..c905c3f 100644
--- a/scripts/cros_setup_toolchains.py
+++ b/scripts/cros_setup_toolchains.py
@@ -7,7 +7,9 @@
from __future__ import print_function
import copy
+import errno
import glob
+import hashlib
import json
import os
import re
@@ -110,14 +112,49 @@
@classmethod
def Load(cls, reconfig):
- """Load crossdev cache from disk."""
+ """Load crossdev cache from disk.
+
+ We invalidate the cache when crossdev updates or this script changes.
+ """
crossdev_version = GetStablePackageVersion('sys-devel/crossdev', True)
- cls._CACHE = {'crossdev_version': crossdev_version}
- if os.path.exists(cls._CACHE_FILE) and not reconfig:
- with open(cls._CACHE_FILE) as f:
- data = json.load(f)
- if crossdev_version == data.get('crossdev_version'):
- cls._CACHE = data
+ # If we run the compiled/cached .pyc file, we'll read/hash that when we
+ # really always want to track the source .py file.
+ script = os.path.abspath(__file__)
+ if script.endswith('.pyc'):
+ script = script[:-1]
+ setup_toolchains_hash = hashlib.md5(osutils.ReadFile(script)).hexdigest()
+
+ cls._CACHE = {
+ 'crossdev_version': crossdev_version,
+ 'setup_toolchains_hash': setup_toolchains_hash,
+ }
+
+ logging.debug('cache: checking file: %s', cls._CACHE_FILE)
+ if reconfig:
+ logging.debug('cache: forcing regen due to reconfig')
+ return
+
+ try:
+ file_data = osutils.ReadFile(cls._CACHE_FILE)
+ except IOError as e:
+ if e.errno != errno.ENOENT:
+ logging.warning('cache: reading failed: %s', e)
+ osutils.SafeUnlink(cls._CACHE_FILE)
+ return
+
+ try:
+ data = json.loads(file_data)
+ except ValueError as e:
+ logging.warning('cache: ignoring invalid content: %s', e)
+ return
+
+ if crossdev_version != data.get('crossdev_version'):
+ logging.debug('cache: rebuilding after crossdev upgrade')
+ elif setup_toolchains_hash != data.get('setup_toolchains_hash'):
+ logging.debug('cache: rebuilding after cros_setup_toolchains change')
+ else:
+ logging.debug('cache: content is up-to-date!')
+ cls._CACHE = data
@classmethod
def Save(cls):