| Index: native_client_sdk/src/build_tools/update_nacl_manifest.py
|
| diff --git a/native_client_sdk/src/build_tools/update_nacl_manifest.py b/native_client_sdk/src/build_tools/update_nacl_manifest.py
|
| index 154f827f585633b32dc8a657c899fc06e4ef8464..52349c46445f29edce7d01d2ea602f312ee3f92b 100755
|
| --- a/native_client_sdk/src/build_tools/update_nacl_manifest.py
|
| +++ b/native_client_sdk/src/build_tools/update_nacl_manifest.py
|
| @@ -13,6 +13,7 @@ in manifest.
|
| import buildbot_common
|
| import csv
|
| import cStringIO
|
| +import difflib
|
| import email
|
| import json
|
| import manifest_util
|
| @@ -308,6 +309,38 @@ class VersionFinder(object):
|
| return self._DoGetMostRecentSharedVersion(platforms,
|
| shared_version_generator, allow_trunk_revisions=True)
|
|
|
| + def GetAvailablePlatformArchivesFor(self, version, platforms,
|
| + allow_trunk_revisions):
|
| + """Returns a sequence of archives that exist for a given version, on the
|
| + given platforms.
|
| +
|
| + The second element of the returned tuple is a list of all platforms that do
|
| + not have an archive for the given version.
|
| +
|
| + Args:
|
| + version: The version to find archives for. (e.g. "18.0.1025.164")
|
| + platforms: A sequence of platforms to consider, e.g.
|
| + ('mac', 'linux', 'win')
|
| + allow_trunk_revisions: If True, will search for archives using the
|
| + trunk revision that matches the branch version.
|
| + Returns:
|
| + A tuple (archives, missing_platforms). |archives| is a list of archive
|
| + URLs, |missing_platforms| is a list of platform names.
|
| + """
|
| + archives = self._GetAvailableArchivesFor(version)
|
| + missing_platforms = set(platforms) - set(GetPlatformsFromArchives(archives))
|
| + if allow_trunk_revisions and missing_platforms:
|
| + # Try to find trunk archives for platforms that are missing archives.
|
| + trunk_version = self.delegate.GetTrunkRevision(version)
|
| + trunk_archives = self._GetAvailableArchivesFor(trunk_version)
|
| + for trunk_archive in trunk_archives:
|
| + trunk_archive_platform = GetPlatformFromArchiveUrl(trunk_archive)
|
| + if trunk_archive_platform in missing_platforms:
|
| + archives.append(trunk_archive)
|
| + missing_platforms.discard(trunk_archive_platform)
|
| +
|
| + return archives, missing_platforms
|
| +
|
| def _DoGetMostRecentSharedVersion(self, platforms, shared_version_generator,
|
| allow_trunk_revisions):
|
| """Returns the most recent version of a pepper bundle that exists on all
|
| @@ -321,7 +354,7 @@ class VersionFinder(object):
|
| shared_version_generator: A generator that will yield (version, channel)
|
| tuples in order of most recent to least recent.
|
| allow_trunk_revisions: If True, will search for archives using the
|
| - trunk revision that matches the branch version.
|
| + trunk revision that matches the branch version.
|
| Returns:
|
| A tuple (version, channel, archives). The version is a string such as
|
| "19.0.1084.41". The channel is one of ('stable', 'beta', 'dev',
|
| @@ -345,18 +378,8 @@ class VersionFinder(object):
|
| msg += ' %s (%s) %s\n' % (version, channel, archive_msg)
|
| raise Exception(msg)
|
|
|
| - archives = self._GetAvailableNaClSDKArchivesFor(version)
|
| - missing_platforms = set(platforms) - \
|
| - set(GetPlatformsFromArchives(archives))
|
| - if allow_trunk_revisions and missing_platforms:
|
| - # Try to find trunk archives for platforms that are missing archives.
|
| - trunk_version = self.delegate.GetTrunkRevision(version)
|
| - trunk_archives = self._GetAvailableNaClSDKArchivesFor(trunk_version)
|
| - for trunk_archive in trunk_archives:
|
| - trunk_archive_platform = GetPlatformFromArchiveUrl(trunk_archive)
|
| - if trunk_archive_platform in missing_platforms:
|
| - archives.append(trunk_archive)
|
| - missing_platforms.discard(trunk_archive_platform)
|
| + archives, missing_platforms = self.GetAvailablePlatformArchivesFor(
|
| + version, platforms, allow_trunk_revisions)
|
|
|
| if not missing_platforms:
|
| return version, channel, archives
|
| @@ -438,7 +461,7 @@ class VersionFinder(object):
|
| # force increment to next version for all platforms
|
| shared_version = None
|
|
|
| - def _GetAvailableNaClSDKArchivesFor(self, version_string):
|
| + def _GetAvailableArchivesFor(self, version_string):
|
| """Downloads a list of all available archives for a given version.
|
|
|
| Args:
|
| @@ -464,6 +487,8 @@ class Updater(object):
|
| def __init__(self, delegate):
|
| self.delegate = delegate
|
| self.versions_to_update = []
|
| + self.online_manifest = manifest_util.SDKManifest()
|
| + self._FetchOnlineManifest()
|
|
|
| def AddVersionToUpdate(self, bundle_name, version, channel, archives):
|
| """Add a pepper version to update in the uploaded manifest.
|
| @@ -478,6 +503,10 @@ class Updater(object):
|
| def Update(self, manifest):
|
| """Update a manifest and upload it.
|
|
|
| + Note that bundles will not be updated if the current version is newer.
|
| + That is, the updater will never automatically update to an older version of
|
| + a bundle.
|
| +
|
| Args:
|
| manifest: The manifest used as a template for updating. Only pepper
|
| bundles that contain no archives will be considered for auto-updating."""
|
| @@ -499,6 +528,16 @@ class Updater(object):
|
| platform_bundle.name = bundle_name
|
| bundle.MergeWithBundle(platform_bundle)
|
|
|
| + # Check to ensure this bundle is newer than the online bundle.
|
| + online_bundle = self.online_manifest.GetBundle(bundle_name)
|
| + if online_bundle and online_bundle.revision >= bundle.revision:
|
| + self.delegate.Print(
|
| + ' Revision %s is not newer than than online revision %s. '
|
| + 'Skipping.' % (bundle.revision, online_bundle.revision))
|
| +
|
| + manifest.MergeBundle(online_bundle)
|
| + continue
|
| +
|
| major_version = SplitVersion(version)[0]
|
| if major_version < max_stable_version and channel == 'stable':
|
| bundle.stability = 'post_stable'
|
| @@ -541,18 +580,21 @@ class Updater(object):
|
| Args:
|
| manifest: The new manifest to upload.
|
| """
|
| + new_manifest_string = manifest.GetDataAsString()
|
| + online_manifest_string = self.online_manifest.GetDataAsString()
|
| +
|
| if self.delegate.dryrun:
|
| - name = MANIFEST_BASENAME + ".new"
|
| - self.delegate.Print("Writing new manifest: %s" % name)
|
| - with open(name, 'w') as f:
|
| - f.write(manifest.GetDataAsString())
|
| - stdout = self.delegate.GsUtil_cat(GS_SDK_MANIFEST)
|
| -
|
| - online = MANIFEST_BASENAME + ".online"
|
| - self.delegate.Print("Writing online manifest: %s" % online)
|
| - with open(online, 'w') as f:
|
| - f.write(stdout)
|
| - os.system('diff -u %s %s' % (online, name))
|
| + self.delegate.Print(''.join(list(difflib.unified_diff(
|
| + online_manifest_string.splitlines(1),
|
| + new_manifest_string.splitlines(1)))))
|
| + else:
|
| + online_manifest = manifest_util.SDKManifest()
|
| + online_manifest.LoadDataFromString(online_manifest_string)
|
| +
|
| + if online_manifest == manifest:
|
| + self.delegate.Print('New manifest doesn\'t differ from online manifest.'
|
| + 'Skipping upload.')
|
| + return
|
|
|
| timestamp_manifest_path = GS_MANIFEST_BACKUP_DIR + \
|
| GetTimestampManifestName()
|
| @@ -562,9 +604,32 @@ class Updater(object):
|
| # copy from timestampped copy over the official manifest.
|
| self.delegate.GsUtil_cp(timestamp_manifest_path, GS_SDK_MANIFEST)
|
|
|
| + def _FetchOnlineManifest(self):
|
| + try:
|
| + online_manifest_string = self.delegate.GsUtil_cat(GS_SDK_MANIFEST)
|
| + except subprocess.CalledProcessError:
|
| + # It is not a failure if the online manifest doesn't exist.
|
| + online_manifest_string = ''
|
| +
|
| + if online_manifest_string:
|
| + self.online_manifest.LoadDataFromString(online_manifest_string)
|
| +
|
| +
|
| +def Run(delegate, platforms, fixed_bundle_versions=None):
|
| + """Entry point for the auto-updater.
|
| +
|
| + Args:
|
| + delegate: The Delegate object to use for reading Urls, files, etc.
|
| + platforms: A sequence of platforms to consider, e.g.
|
| + ('mac', 'linux', 'win')
|
| + fixed_bundle_versions: A sequence of tuples (bundle_name, version_string).
|
| + e.g. ('pepper_21', '21.0.1145.0')
|
| + """
|
| + if fixed_bundle_versions:
|
| + fixed_bundle_versions = dict(fixed_bundle_versions)
|
| + else:
|
| + fixed_bundle_versions = {}
|
|
|
| -def Run(delegate, platforms):
|
| - """Entry point for the auto-updater."""
|
| manifest = delegate.GetRepoManifest()
|
| auto_update_bundles = []
|
| for bundle in manifest.GetBundles():
|
| @@ -589,6 +654,21 @@ def Run(delegate, platforms):
|
| version, channel, archives = version_finder.GetMostRecentSharedVersion(
|
| bundle.version, platforms)
|
|
|
| + if bundle.name in fixed_bundle_versions:
|
| + # Ensure this version is valid for all platforms.
|
| + # If it is, use the channel found above (because the channel for this
|
| + # version may not be in the history.)
|
| + version = fixed_bundle_versions[bundle.name]
|
| + delegate.Print('Fixed bundle version: %s, %s' % (bundle.name, version))
|
| + allow_trunk_revisions = bundle.name == CANARY_BUNDLE_NAME
|
| + archives, missing = version_finder.GetAvailablePlatformArchivesFor(
|
| + version, platforms, allow_trunk_revisions)
|
| + if missing:
|
| + delegate.Print(
|
| + 'An archive for version %s of bundle %s doesn\'t exist '
|
| + 'for platform(s): %s' % (version, bundle.name, ', '.join(missing)))
|
| + return
|
| +
|
| updater.AddVersionToUpdate(bundle.name, version, channel, archives)
|
|
|
| updater.Update(manifest)
|
| @@ -642,6 +722,9 @@ def main(args):
|
| action='store_true')
|
| parser.add_option('-v', '--verbose', help='print more diagnotic messages.',
|
| action='store_true')
|
| + parser.add_option('--bundle-version',
|
| + help='Manually set a bundle version. This can be passed more than once. '
|
| + 'format: --bundle-version pepper_24=24.0.1312.25', action='append')
|
| options, args = parser.parse_args(args[1:])
|
|
|
| if (options.mailfrom is None) != (not options.mailto):
|
| @@ -650,6 +733,13 @@ def main(args):
|
| sys.stderr.write('warning: Disabling email, one of --mailto or --mailfrom '
|
| 'was missing.\n')
|
|
|
| + # Parse bundle versions.
|
| + fixed_bundle_versions = {}
|
| + if options.bundle_version:
|
| + for bundle_version_string in options.bundle_version:
|
| + bundle_name, version = bundle_version_string.split('=')
|
| + fixed_bundle_versions[bundle_name] = version
|
| +
|
| if options.mailfrom and options.mailto:
|
| # Capture stderr so it can be emailed, if necessary.
|
| sys.stderr = CapturedFile(sys.stderr)
|
| @@ -657,7 +747,7 @@ def main(args):
|
| try:
|
| try:
|
| delegate = RealDelegate(options.dryrun, options.gsutil, options.verbose)
|
| - Run(delegate, ('mac', 'win', 'linux'))
|
| + Run(delegate, ('mac', 'win', 'linux'), fixed_bundle_versions)
|
| except Exception:
|
| if options.mailfrom and options.mailto:
|
| traceback.print_exc()
|
|
|