summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorMike Frysinger <vapier@chromium.org>2012-05-24 18:17:38 -0400
committerGerrit <chrome-bot@google.com>2012-05-31 09:49:15 -0700
commit6cb624a11596132868ee384ab1a2b0a1330bca5d (patch)
tree5f27c25f60ac7f5187d8f92d23cb744991934292 /scripts
parente522add7f9cf7d6d573a66e36a9c7e47fca0e1d6 (diff)
downloadchromite-6cb624a11596132868ee384ab1a2b0a1330bca5d.tar.gz
cros_mark_{chrome_,}as_stable: relocate to scripts/
We don't import these as modules, just execute them directly, so move them to the scripts/ subdir. BUG=None TEST=`./buildbot/run_tests` passes TEST=`cbuildbot arm-tegra2-paladin` with manual uprev works TEST=`cbuildbot x86-generic-tot-chrome-pfq-informational` passes Change-Id: I33b064aafa06b506022ba930c953f625bbb13795 Reviewed-on: https://gerrit.chromium.org/gerrit/23569 Commit-Ready: Mike Frysinger <vapier@chromium.org> Reviewed-by: Mike Frysinger <vapier@chromium.org> Tested-by: Mike Frysinger <vapier@chromium.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/cros_mark_as_stable.py329
-rwxr-xr-xscripts/cros_mark_as_stable_unittest.py112
-rw-r--r--scripts/cros_mark_chrome_as_stable.py509
-rwxr-xr-xscripts/cros_mark_chrome_as_stable_unittest.py326
4 files changed, 1276 insertions, 0 deletions
diff --git a/scripts/cros_mark_as_stable.py b/scripts/cros_mark_as_stable.py
new file mode 100644
index 000000000..beebccd56
--- /dev/null
+++ b/scripts/cros_mark_as_stable.py
@@ -0,0 +1,329 @@
+#!/usr/bin/python
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This module uprevs a given package's ebuild to the next revision."""
+
+import multiprocessing
+import optparse
+import os
+import sys
+
+from chromite.buildbot import constants
+from chromite.buildbot import cbuildbot_background as background
+from chromite.buildbot import portage_utilities
+from chromite.lib import cros_build_lib
+
+
+# TODO(sosa): Remove during OO refactor.
+VERBOSE = False
+
+# Dictionary of valid commands with usage information.
+COMMAND_DICTIONARY = {
+ 'commit':
+ 'Marks given ebuilds as stable locally',
+ 'push':
+ 'Pushes previous marking of ebuilds to remote repo',
+ }
+
+
+# ======================= Global Helper Functions ========================
+
+
+def _Print(message):
+ """Verbose print function."""
+ if VERBOSE:
+ cros_build_lib.Info(message)
+
+
+def CleanStalePackages(boards, package_atoms):
+ """Cleans up stale package info from a previous build.
+ Args:
+ boards: Boards to clean the packages from.
+ package_atoms: The actual package atom to unmerge.
+ """
+ if package_atoms:
+ cros_build_lib.Info('Cleaning up stale packages %s.' % package_atoms)
+
+ # First unmerge all the packages for a board, then eclean it.
+ # We need these two steps to run in order (unmerge/eclean),
+ # but we can let all the boards run in parallel.
+ def _CleanStalePackages(board):
+ if board:
+ suffix = '-' + board
+ runcmd = cros_build_lib.RunCommand
+ else:
+ suffix = ''
+ runcmd = cros_build_lib.SudoRunCommand
+
+ if package_atoms:
+ runcmd(['emerge' + suffix, '-q', '--unmerge'] + package_atoms);
+ runcmd(['eclean' + suffix, '-d', 'packages'],
+ redirect_stdout=True, redirect_stderr=True)
+
+ tasks = []
+ for board in boards:
+ tasks.append([board])
+ tasks.append([None])
+
+ background.RunTasksInProcessPool(_CleanStalePackages, tasks)
+
+
+# TODO(build): This code needs to be gutted and rebased to cros_build_lib.
+def _DoWeHaveLocalCommits(stable_branch, tracking_branch, cwd):
+ """Returns true if there are local commits."""
+ current_branch = cros_build_lib.GetCurrentBranch(cwd)
+
+ if current_branch != stable_branch:
+ return False
+ output = cros_build_lib.RunGitCommand(
+ cwd, ['rev-parse', 'HEAD', tracking_branch]).output.split()
+ return output[0] != output[1]
+
+
+def _CheckSaneArguments(package_list, command, options):
+ """Checks to make sure the flags are sane. Dies if arguments are not sane."""
+ if not command in COMMAND_DICTIONARY.keys():
+ _PrintUsageAndDie('%s is not a valid command' % command)
+ if not options.packages and command == 'commit' and not options.all:
+ _PrintUsageAndDie('Please specify at least one package')
+ if not options.boards and command == 'commit':
+ _PrintUsageAndDie('Please specify a board')
+ if not os.path.isdir(options.srcroot):
+ _PrintUsageAndDie('srcroot is not a valid path')
+ options.srcroot = os.path.abspath(options.srcroot)
+
+
+def _PrintUsageAndDie(error_message=''):
+ """Prints optional error_message the usage and returns an error exit code."""
+ command_usage = 'Commands: \n'
+ # Add keys and usage information from dictionary.
+ commands = sorted(COMMAND_DICTIONARY.keys())
+ for command in commands:
+ command_usage += ' %s: %s\n' % (command, COMMAND_DICTIONARY[command])
+ commands_str = '|'.join(commands)
+ cros_build_lib.Warning('Usage: %s FLAGS [%s]\n\n%s' % (
+ sys.argv[0], commands_str, command_usage))
+ if error_message:
+ cros_build_lib.Die(error_message)
+ else:
+ sys.exit(1)
+
+
+# ======================= End Global Helper Functions ========================
+
+
+def PushChange(stable_branch, tracking_branch, dryrun, cwd):
+ """Pushes commits in the stable_branch to the remote git repository.
+
+ Pushes local commits from calls to CommitChange to the remote git
+ repository specified by current working directory. If changes are
+ found to commit, they will be merged to the merge branch and pushed.
+ In that case, the local repository will be left on the merge branch.
+
+ Args:
+ stable_branch: The local branch with commits we want to push.
+ tracking_branch: The tracking branch of the local branch.
+ dryrun: Use git push --dryrun to emulate a push.
+ cwd: The directory to run commands in.
+ Raises:
+ OSError: Error occurred while pushing.
+ """
+ if not _DoWeHaveLocalCommits(stable_branch, tracking_branch, cwd):
+ cros_build_lib.Info('No work found to push in %s. Exiting', cwd)
+ return
+
+ # For the commit queue, our local branch may contain commits that were
+ # just tested and pushed during the CommitQueueCompletion stage. Sync
+ # and rebase our local branch on top of the remote commits.
+ remote, push_branch = cros_build_lib.GetTrackingBranch(cwd, for_push=True)
+ cros_build_lib.SyncPushBranch(cwd, remote, push_branch)
+
+ # Check whether any local changes remain after the sync.
+ if not _DoWeHaveLocalCommits(stable_branch, push_branch, cwd):
+ cros_build_lib.Info('All changes already pushed for %s. Exiting', cwd)
+ return
+
+ description = cros_build_lib.RunCommandCaptureOutput(
+ ['git', 'log', '--format=format:%s%n%n%b', '%s..%s' % (
+ push_branch, stable_branch)], cwd=cwd).output
+ description = 'Marking set of ebuilds as stable\n\n%s' % description
+ cros_build_lib.Info('For %s, using description %s', cwd, description)
+ cros_build_lib.CreatePushBranch(constants.MERGE_BRANCH, cwd)
+ cros_build_lib.RunGitCommand(cwd, ['merge', '--squash', stable_branch])
+ cros_build_lib.RunGitCommand(cwd, ['commit', '-m', description])
+ cros_build_lib.RunGitCommand(cwd, ['config', 'push.default', 'tracking'])
+ cros_build_lib.GitPushWithRetry(constants.MERGE_BRANCH, cwd,
+ dryrun=dryrun)
+
+
+class GitBranch(object):
+ """Wrapper class for a git branch."""
+
+ def __init__(self, branch_name, tracking_branch, cwd):
+ """Sets up variables but does not create the branch."""
+ self.branch_name = branch_name
+ self.tracking_branch = tracking_branch
+ self.cwd = cwd
+
+ def CreateBranch(self):
+ self.Checkout()
+
+ def Checkout(self, branch=None):
+ """Function used to check out to another GitBranch."""
+ if not branch:
+ branch = self.branch_name
+ if branch == self.tracking_branch or self.Exists(branch):
+ git_cmd = ['git', 'checkout', '-f', branch]
+ else:
+ git_cmd = ['repo', 'start', branch, '.']
+ cros_build_lib.RunCommandCaptureOutput(git_cmd, print_cmd=False,
+ cwd=self.cwd)
+
+ def Exists(self, branch=None):
+ """Returns True if the branch exists."""
+ if not branch:
+ branch = self.branch_name
+ branches = cros_build_lib.RunCommandCaptureOutput(['git', 'branch'],
+ print_cmd=False,
+ cwd=self.cwd).output
+ return branch in branches.split()
+
+
+def main(argv):
+ parser = optparse.OptionParser('cros_mark_as_stable OPTIONS packages')
+ parser.add_option('--all', action='store_true',
+ help='Mark all packages as stable.')
+ parser.add_option('-b', '--boards',
+ help='Colon-separated list of boards')
+ parser.add_option('--drop_file',
+ help='File to list packages that were revved.')
+ parser.add_option('--dryrun', action='store_true',
+ help='Passes dry-run to git push if pushing a change.')
+ parser.add_option('-o', '--overlays',
+ help='Colon-separated list of overlays to modify.')
+ parser.add_option('-p', '--packages',
+ help='Colon separated list of packages to rev.')
+ parser.add_option('-r', '--srcroot',
+ default='%s/trunk/src' % os.environ['HOME'],
+ help='Path to root src directory.')
+ parser.add_option('--verbose', action='store_true',
+ help='Prints out debug info.')
+ (options, args) = parser.parse_args()
+
+ global VERBOSE
+ VERBOSE = options.verbose
+ portage_utilities.EBuild.VERBOSE = options.verbose
+
+ if len(args) != 1:
+ _PrintUsageAndDie('Must specify a valid command [commit, push]')
+
+ command = args[0]
+ package_list = None
+ if options.packages:
+ package_list = options.packages.split(':')
+
+ _CheckSaneArguments(package_list, command, options)
+ if options.overlays:
+ overlays = {}
+ for path in options.overlays.split(':'):
+ if not os.path.isdir(path):
+ cros_build_lib.Die('Cannot find overlay: %s' % path)
+ overlays[path] = []
+ else:
+ cros_build_lib.Warning('Missing --overlays argument')
+ overlays = {
+ '%s/private-overlays/chromeos-overlay' % options.srcroot: [],
+ '%s/third_party/chromiumos-overlay' % options.srcroot: []
+ }
+
+ if command == 'commit':
+ portage_utilities.BuildEBuildDictionary(
+ overlays, options.all, package_list)
+
+ manifest = cros_build_lib.ManifestCheckout.Cached(options.srcroot)
+
+ # Contains the array of packages we actually revved.
+ revved_packages = []
+ new_package_atoms = []
+
+ # Slight optimization hack: process the chromiumos overlay before any other
+ # cros-workon overlay first so we can do background cache generation in it.
+ # A perfect solution would walk all the overlays, figure out any dependencies
+ # between them (with layout.conf), and then process them in dependency order.
+ # However, this operation isn't slow enough to warrant that level of
+ # complexity, so we'll just special case the main overlay.
+ #
+ # Similarly, generate the cache in the portage-stable tree asap. We know
+ # we won't have any cros-workon packages in there, so generating the cache
+ # is the only thing it'll be doing. The chromiumos overlay instead might
+ # have revbumping to do before it can generate the cache.
+ keys = overlays.keys()
+ for overlay in ('/third_party/chromiumos-overlay',
+ '/third_party/portage-stable'):
+ for k in keys:
+ if k.endswith(overlay):
+ keys.remove(k)
+ keys.insert(0, k)
+ break
+
+ cache_queue = multiprocessing.Queue()
+ with background.BackgroundTaskRunner(cache_queue,
+ portage_utilities.RegenCache):
+ for overlay in keys:
+ ebuilds = overlays[overlay]
+ if not os.path.isdir(overlay):
+ cros_build_lib.Warning("Skipping %s" % overlay)
+ continue
+
+ # Note we intentionally work from the non push tracking branch;
+ # everything built thus far has been against it (meaning, http mirrors),
+ # thus we should honor that. During the actual push, the code switches
+ # to the correct urls, and does an appropriate rebasing.
+ tracking_branch = cros_build_lib.GetTrackingBranchViaManifest(
+ overlay, manifest=manifest)[1]
+
+ if command == 'push':
+ PushChange(constants.STABLE_EBUILD_BRANCH, tracking_branch,
+ options.dryrun, cwd=overlay)
+ elif command == 'commit' and ebuilds:
+ existing_branch = cros_build_lib.GetCurrentBranch(overlay)
+ work_branch = GitBranch(constants.STABLE_EBUILD_BRANCH, tracking_branch,
+ cwd=overlay)
+ work_branch.CreateBranch()
+ if not work_branch.Exists():
+ cros_build_lib.Die('Unable to create stabilizing branch in %s' %
+ overlay)
+
+ # In the case of uprevving overlays that have patches applied to them,
+ # include the patched changes in the stabilizing branch.
+ if existing_branch:
+ cros_build_lib.RunCommand(['git', 'rebase', existing_branch],
+ print_cmd=False, cwd=overlay)
+
+ for ebuild in ebuilds:
+ try:
+ _Print('Working on %s' % ebuild.package)
+ new_package = ebuild.RevWorkOnEBuild(options.srcroot)
+ if new_package:
+ revved_packages.append(ebuild.package)
+ new_package_atoms.append('=%s' % new_package)
+ except (OSError, IOError):
+ cros_build_lib.Warning('Cannot rev %s\n' % ebuild.package +
+ 'Note you will have to go into %s '
+ 'and reset the git repo yourself.' % overlay)
+ raise
+
+ if command == 'commit':
+ # Regenerate caches if need be. We do this all the time to
+ # catch when users make changes without updating cache files.
+ cache_queue.put([overlay])
+
+ if command == 'commit':
+ CleanStalePackages(options.boards.split(':'), new_package_atoms)
+ if options.drop_file:
+ fh = open(options.drop_file, 'w')
+ fh.write(' '.join(revved_packages))
+ fh.close()
diff --git a/scripts/cros_mark_as_stable_unittest.py b/scripts/cros_mark_as_stable_unittest.py
new file mode 100755
index 000000000..635de287c
--- /dev/null
+++ b/scripts/cros_mark_as_stable_unittest.py
@@ -0,0 +1,112 @@
+#!/usr/bin/python
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for cros_mark_as_stable.py."""
+
+import mox
+import os
+import sys
+import unittest
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ '..', '..'))
+from chromite.buildbot import constants
+from chromite.buildbot import constants
+from chromite.lib import cros_build_lib
+from chromite.scripts import cros_mark_as_stable
+
+
+# pylint: disable=W0212,R0904
+class NonClassTests(mox.MoxTestBase):
+ def setUp(self):
+ mox.MoxTestBase.setUp(self)
+ self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
+ self.mox.StubOutWithMock(cros_build_lib, 'RunCommandCaptureOutput')
+ self._branch = 'test_branch'
+ self._target_manifest_branch = 'cros/master'
+
+ def testPushChange(self):
+ git_log = 'Marking test_one as stable\nMarking test_two as stable\n'
+ fake_description = 'Marking set of ebuilds as stable\n\n%s' % git_log
+ self.mox.StubOutWithMock(cros_mark_as_stable, '_DoWeHaveLocalCommits')
+ self.mox.StubOutWithMock(cros_mark_as_stable.GitBranch, 'CreateBranch')
+ self.mox.StubOutWithMock(cros_mark_as_stable.GitBranch, 'Exists')
+ self.mox.StubOutWithMock(cros_build_lib, 'GitPushWithRetry')
+ self.mox.StubOutWithMock(cros_build_lib, 'GetTrackingBranch')
+ self.mox.StubOutWithMock(cros_build_lib, 'SyncPushBranch')
+ self.mox.StubOutWithMock(cros_build_lib, 'CreatePushBranch')
+ self.mox.StubOutWithMock(cros_build_lib, 'RunGitCommand')
+
+ cros_mark_as_stable._DoWeHaveLocalCommits(
+ self._branch, self._target_manifest_branch, '.').AndReturn(True)
+ cros_build_lib.GetTrackingBranch('.', for_push=True).AndReturn(
+ ['gerrit', 'refs/remotes/gerrit/master'])
+ cros_build_lib.SyncPushBranch('.', 'gerrit', 'refs/remotes/gerrit/master')
+ cros_mark_as_stable._DoWeHaveLocalCommits(
+ self._branch, 'refs/remotes/gerrit/master', '.').AndReturn(True)
+ result = cros_build_lib.CommandResult(output=git_log)
+ cros_build_lib.RunCommandCaptureOutput(
+ ['git', 'log', '--format=format:%s%n%n%b',
+ 'refs/remotes/gerrit/master..%s' % self._branch],
+ cwd='.').AndReturn(result)
+ cros_build_lib.CreatePushBranch('merge_branch', '.')
+ cros_build_lib.RunGitCommand('.', ['merge', '--squash', self._branch])
+ cros_build_lib.RunGitCommand('.', ['commit', '-m', fake_description])
+ cros_build_lib.RunGitCommand('.', ['config', 'push.default', 'tracking'])
+ cros_build_lib.GitPushWithRetry('merge_branch', '.', dryrun=False)
+ self.mox.ReplayAll()
+ cros_mark_as_stable.PushChange(self._branch, self._target_manifest_branch,
+ False, '.')
+ self.mox.VerifyAll()
+
+
+class GitBranchTest(mox.MoxTestBase):
+
+ def setUp(self):
+ mox.MoxTestBase.setUp(self)
+ # Always stub RunCommmand out as we use it in every method.
+ self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
+ self.mox.StubOutWithMock(cros_build_lib, 'RunCommandCaptureOutput')
+ self._branch = self.mox.CreateMock(cros_mark_as_stable.GitBranch)
+ self._branch_name = 'test_branch'
+ self._branch.branch_name = self._branch_name
+ self._target_manifest_branch = 'cros/test'
+ self._branch.tracking_branch = self._target_manifest_branch
+ self._branch.cwd = '.'
+
+ def testCheckoutCreate(self):
+ # Test init with no previous branch existing.
+ self._branch.Exists(self._branch_name).AndReturn(False)
+ cros_build_lib.RunCommandCaptureOutput(['repo', 'start', self._branch_name,
+ '.'], print_cmd=False, cwd='.')
+ self.mox.ReplayAll()
+ cros_mark_as_stable.GitBranch.Checkout(self._branch)
+ self.mox.VerifyAll()
+
+ def testCheckoutNoCreate(self):
+ # Test init with previous branch existing.
+ self._branch.Exists(self._branch_name).AndReturn(True)
+ cros_build_lib.RunCommandCaptureOutput(['git', 'checkout', '-f',
+ self._branch_name], print_cmd=False,
+ cwd='.')
+ self.mox.ReplayAll()
+ cros_mark_as_stable.GitBranch.Checkout(self._branch)
+ self.mox.VerifyAll()
+
+ def testExists(self):
+ branch = cros_mark_as_stable.GitBranch(self._branch_name,
+ self._target_manifest_branch, '.')
+ # Test if branch exists that is created
+ result = cros_build_lib.CommandResult(output=self._branch_name + '\n')
+ cros_build_lib.RunCommandCaptureOutput(['git', 'branch'], print_cmd=False,
+ cwd='.').AndReturn(result)
+ self.mox.ReplayAll()
+ self.assertTrue(branch.Exists())
+ self.mox.VerifyAll()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/scripts/cros_mark_chrome_as_stable.py b/scripts/cros_mark_chrome_as_stable.py
new file mode 100644
index 000000000..6bc78795a
--- /dev/null
+++ b/scripts/cros_mark_chrome_as_stable.py
@@ -0,0 +1,509 @@
+#!/usr/bin/python
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This module uprevs Chrome for cbuildbot.
+
+After calling, it prints outs CHROME_VERSION_ATOM=(version atom string). A
+caller could then use this atom with emerge to build the newly uprevved version
+of Chrome e.g.
+
+./cros_mark_chrome_as_stable tot
+Returns chrome-base/chromeos-chrome-8.0.552.0_alpha_r1
+
+emerge-x86-generic =chrome-base/chromeos-chrome-8.0.552.0_alpha_r1
+"""
+
+import filecmp
+import optparse
+import os
+import re
+import sys
+import time
+
+from chromite.buildbot import constants
+from chromite.buildbot import portage_utilities
+from chromite.lib import cros_build_lib
+from chromite.lib.cros_build_lib import RunCommand, Info, Warning
+from chromite.scripts import cros_mark_as_stable
+
+BASE_CHROME_SVN_URL = 'http://src.chromium.org/svn'
+
+# Helper regex's for finding ebuilds.
+_CHROME_VERSION_REGEX = '\d+\.\d+\.\d+\.\d+'
+_NON_STICKY_REGEX = '%s[(_rc.*)|(_alpha.*)]+' % _CHROME_VERSION_REGEX
+
+# Dir where all the action happens.
+_CHROME_OVERLAY_DIR = ('%(srcroot)s/third_party/chromiumos-overlay'
+ '/chromeos-base/chromeos-chrome')
+
+_GIT_COMMIT_MESSAGE = ('Marking %(chrome_rev)s for chrome ebuild with version '
+ '%(chrome_version)s as stable.')
+
+# URLs that print lists of chrome revisions between two versions of the browser.
+_CHROME_VERSION_URL = ('http://omahaproxy.appspot.com/changelog?'
+ 'old_version=%(old)s&new_version=%(new)s')
+
+# Only print links when we rev these types.
+_REV_TYPES_FOR_LINKS = [constants.CHROME_REV_LATEST,
+ constants.CHROME_REV_STICKY]
+
+_CHROME_SVN_TAG = 'CROS_SVN_COMMIT'
+
+def _GetSvnUrl(base_url):
+ """Returns the path to the svn url for the given chrome branch."""
+ return os.path.join(base_url, 'trunk')
+
+
+def _GetTipOfTrunkSvnRevision(base_url):
+ """Returns the current svn revision for the chrome tree."""
+ svn_url = _GetSvnUrl(base_url)
+ svn_info = RunCommand(['svn', 'info', svn_url], redirect_stdout=True).output
+
+ revision_re = re.compile('^Revision:\s+(\d+).*')
+ for line in svn_info.splitlines():
+ match = revision_re.search(line)
+ if match:
+ svn_revision = match.group(1)
+ Info('Found SVN Revision %s' % svn_revision)
+ return svn_revision
+
+ raise Exception('Could not find revision information from %s' % svn_url)
+
+
+def _GetVersionContents(chrome_version_info):
+ """Returns the current Chromium version, from the contents of a VERSION file.
+
+ Args:
+ chrome_version_info: The contents of a chromium VERSION file.
+ """
+ chrome_version_array = []
+ for line in chrome_version_info.splitlines():
+ chrome_version_array.append(line.rpartition('=')[2])
+
+ return '.'.join(chrome_version_array)
+
+def _GetSpecificVersionUrl(base_url, revision, time_to_wait=600):
+ """Returns the Chromium version, from a repository URL and version.
+
+ Args:
+ base_url: URL for the root of the chromium checkout.
+ revision: the SVN revision we want to use.
+ time_to_wait: the minimum period before abandoning our wait for the
+ desired revision to be present.
+ """
+ svn_url = os.path.join(_GetSvnUrl(base_url), 'src', 'chrome', 'VERSION')
+ if not revision or not (int(revision) > 0):
+ raise Exception('Revision must be positive, got %s' % revision)
+
+ start = time.time()
+ # Use the fact we are SVN, hence ordered.
+ # Dodge the fact it will silently ignore the revision if it is not
+ # yet known. (i.e. too high)
+ repo_version = _GetTipOfTrunkSvnRevision(base_url)
+ while revision > repo_version:
+ if time.time() - start > time_to_wait:
+ raise Exception('Timeout Exceeeded')
+
+ Info('Repository only has version %s, looking for %s. Sleeping...' %
+ (repo_version, revision))
+ time.sleep(30)
+ repo_version = _GetTipOfTrunkSvnRevision(base_url)
+
+ chrome_version_info = RunCommand(
+ ['svn', 'cat', '-r', revision, svn_url],
+ redirect_stdout=True,
+ error_message='Could not read version file at %s revision %s.' %
+ (svn_url, revision)).output
+
+ return _GetVersionContents(chrome_version_info)
+
+
+def _GetTipOfTrunkVersionFile(root):
+ """Returns the current Chromium version, from a file in a checkout.
+
+ Args:
+ root: path to the root of the chromium checkout.
+ """
+ version_file = os.path.join(root, 'src', 'chrome', 'VERSION')
+ chrome_version_info = RunCommand(
+ ['cat', version_file],
+ redirect_stdout=True,
+ error_message='Could not read version file at %s.' % version_file).output
+
+ return _GetVersionContents(chrome_version_info)
+
+def _GetLatestRelease(base_url, branch=None):
+ """Gets the latest release version from the buildspec_url for the branch.
+
+ Args:
+ branch: If set, gets the latest release for branch, otherwise latest
+ release.
+ Returns:
+ Latest version string.
+ """
+ buildspec_url = os.path.join(base_url, 'releases')
+ svn_ls = RunCommand(['svn', 'ls', buildspec_url],
+ redirect_stdout=True).output
+ sorted_ls = RunCommand(['sort', '--version-sort', '-r'], input=svn_ls,
+ redirect_stdout=True).output
+ if branch:
+ chrome_version_re = re.compile('^%s\.\d+.*' % branch)
+ else:
+ chrome_version_re = re.compile('^[0-9]+\..*')
+
+ for chrome_version in sorted_ls.splitlines():
+ if chrome_version_re.match(chrome_version):
+ deps_url = os.path.join(buildspec_url, chrome_version, 'DEPS')
+ deps_check = RunCommand(['svn', 'ls', deps_url],
+ error_ok=True,
+ redirect_stdout=True).output
+ if deps_check == 'DEPS\n':
+ return chrome_version.rstrip('/')
+
+ return None
+
+
+def _GetStickyEBuild(stable_ebuilds):
+ """Returns the sticky ebuild."""
+ sticky_ebuilds = []
+ non_sticky_re = re.compile(_NON_STICKY_REGEX)
+ for ebuild in stable_ebuilds:
+ if not non_sticky_re.match(ebuild.version):
+ sticky_ebuilds.append(ebuild)
+
+ if not sticky_ebuilds:
+ raise Exception('No sticky ebuilds found')
+ elif len(sticky_ebuilds) > 1:
+ Warning('More than one sticky ebuild found')
+
+ return portage_utilities.BestEBuild(sticky_ebuilds)
+
+
+class ChromeEBuild(portage_utilities.EBuild):
+ """Thin sub-class of EBuild that adds a chrome_version field."""
+ chrome_version_re = re.compile('.*chromeos-chrome-(%s|9999).*' % (
+ _CHROME_VERSION_REGEX))
+ chrome_version = ''
+
+ def __init__(self, path):
+ portage_utilities.EBuild.__init__(self, path)
+ re_match = self.chrome_version_re.match(self.ebuild_path_no_revision)
+ if re_match:
+ self.chrome_version = re_match.group(1)
+
+ def __str__(self):
+ return self.ebuild_path
+
+
+def FindChromeCandidates(overlay_dir):
+ """Return a tuple of chrome's unstable ebuild and stable ebuilds.
+
+ Args:
+ overlay_dir: The path to chrome's portage overlay dir.
+ Returns:
+ Tuple [unstable_ebuild, stable_ebuilds].
+ Raises:
+ Exception: if no unstable ebuild exists for Chrome.
+ """
+ stable_ebuilds = []
+ unstable_ebuilds = []
+ for path in [
+ os.path.join(overlay_dir, entry) for entry in os.listdir(overlay_dir)]:
+ if path.endswith('.ebuild'):
+ ebuild = ChromeEBuild(path)
+ if not ebuild.chrome_version:
+ Warning('Poorly formatted ebuild found at %s' % path)
+ else:
+ if '9999' in ebuild.version:
+ unstable_ebuilds.append(ebuild)
+ else:
+ stable_ebuilds.append(ebuild)
+
+ # Apply some sanity checks.
+ if not unstable_ebuilds:
+ raise Exception('Missing 9999 ebuild for %s' % overlay_dir)
+ if not stable_ebuilds:
+ Warning('Missing stable ebuild for %s' % overlay_dir)
+
+ return portage_utilities.BestEBuild(unstable_ebuilds), stable_ebuilds
+
+
+def FindChromeUprevCandidate(stable_ebuilds, chrome_rev, sticky_branch):
+ """Finds the Chrome uprev candidate for the given chrome_rev.
+
+ Using the pre-flight logic, this means the stable ebuild you are uprevving
+ from. The difference here is that the version could be different and in
+ that case we want to find it to delete it.
+
+ Args:
+ stable_ebuilds: A list of stable ebuilds.
+ chrome_rev: The chrome_rev designating which candidate to find.
+ sticky_branch: The the branch that is currently sticky with Major/Minor
+ components. For example: 9.0.553. Can be None but not if chrome_rev
+ is CHROME_REV_STICKY.
+ Returns:
+ Returns the EBuild, otherwise None if none found.
+ """
+ candidates = []
+ if chrome_rev in [constants.CHROME_REV_LOCAL, constants.CHROME_REV_TOT,
+ constants.CHROME_REV_SPEC]:
+ # These are labelled alpha, for historic reasons,
+ # not just for the fun of confusion.
+ chrome_branch_re = re.compile('%s.*_alpha.*' % _CHROME_VERSION_REGEX)
+ for ebuild in stable_ebuilds:
+ if chrome_branch_re.search(ebuild.version):
+ candidates.append(ebuild)
+
+ elif chrome_rev == constants.CHROME_REV_STICKY:
+ assert sticky_branch is not None
+ chrome_branch_re = re.compile('%s\..*' % sticky_branch)
+ for ebuild in stable_ebuilds:
+ if chrome_branch_re.search(ebuild.version):
+ candidates.append(ebuild)
+
+ else:
+ chrome_branch_re = re.compile('%s.*_rc.*' % _CHROME_VERSION_REGEX)
+ for ebuild in stable_ebuilds:
+ if chrome_branch_re.search(ebuild.version):
+ candidates.append(ebuild)
+
+ if candidates:
+ return portage_utilities.BestEBuild(candidates)
+ else:
+ return None
+
+def _AnnotateAndPrint(text, url):
+ """Add buildbot trappings to print <a href='url'>text</a> in the waterfall.
+
+ Args:
+ text: Anchor text for the link
+ url: the URL to which to link
+ """
+ print >> sys.stderr, '\n@@@STEP_LINK@%(text)s@%(url)s@@@' % { 'text': text,
+ 'url': url }
+
+def GetChromeRevisionLinkFromVersions(old_chrome_version, chrome_version):
+ """Return appropriately formatted link to revision info, given versions
+
+ Given two chrome version strings (e.g. 9.0.533.0), generate a link to a
+ page that prints the Chromium revisions between those two versions.
+
+ Args:
+ old_chrome_version: version to diff from
+ chrome_version: version to which to diff
+ Returns:
+ The desired URL.
+ """
+ return _CHROME_VERSION_URL % { 'old': old_chrome_version,
+ 'new': chrome_version }
+
+def GetChromeRevisionListLink(old_chrome, new_chrome, chrome_rev):
+ """Returns a link to the list of revisions between two Chromium versions
+
+ Given two ChromeEBuilds and the kind of rev we're doing, generate a
+ link to a page that prints the Chromium changes between those two
+ revisions, inclusive.
+
+ Args:
+ old_chrome: ebuild for the version to diff from
+ new_chrome: ebuild for the version to which to diff
+ chrome_rev: one of constants.VALID_CHROME_REVISIONS
+ Returns:
+ The desired URL.
+ """
+ assert chrome_rev in _REV_TYPES_FOR_LINKS
+ return GetChromeRevisionLinkFromVersions(old_chrome.chrome_version,
+ new_chrome.chrome_version)
+
+def MarkChromeEBuildAsStable(stable_candidate, unstable_ebuild, chrome_rev,
+ chrome_version, commit, overlay_dir):
+ """Uprevs the chrome ebuild specified by chrome_rev.
+
+ This is the main function that uprevs the chrome_rev from a stable candidate
+ to its new version.
+
+ Args:
+ stable_candidate: ebuild that corresponds to the stable ebuild we are
+ revving from. If None, builds the a new ebuild given the version
+ and logic for chrome_rev type with revision set to 1.
+ unstable_ebuild: ebuild corresponding to the unstable ebuild for chrome.
+ chrome_rev: one of constants.VALID_CHROME_REVISIONS or LOCAL
+ constants.CHROME_REV_SPEC - Requires commit value. Revs the ebuild for
+ the specified version and uses the portage suffix of _alpha.
+ constants.CHROME_REV_TOT - Requires commit value. Revs the ebuild for
+ the TOT version and uses the portage suffix of _alpha.
+ constants.CHROME_REV_LOCAL - Requires a chrome_root. Revs the ebuild for
+ the local version and uses the portage suffix of _alpha.
+ constants.CHROME_REV_LATEST - This uses the portage suffix of _rc as they
+ are release candidates for the next sticky version.
+ constants.CHROME_REV_STICKY - Revs the sticky version.
+ chrome_version: The \d.\d.\d.\d version of Chrome.
+ commit: Used with constants.CHROME_REV_TOT. The svn revision of chrome.
+ overlay_dir: Path to the chromeos-chrome package dir.
+ Returns:
+ Full portage version atom (including rc's, etc) that was revved.
+ """
+ def IsTheNewEBuildRedundant(new_ebuild, stable_ebuild):
+ """Returns True if the new ebuild is redundant.
+
+ This is True if there if the current stable ebuild is the exact same copy
+ of the new one OR the chrome versions are the same and we're revving
+ constants.CHROME_REV_LATEST (as we don't care about 9999 changes for it).
+ """
+ if not stable_ebuild:
+ return False
+
+ if stable_candidate.chrome_version == new_ebuild.chrome_version:
+ if chrome_rev == constants.CHROME_REV_LATEST:
+ return True
+ else:
+ return filecmp.cmp(
+ new_ebuild.ebuild_path, stable_ebuild.ebuild_path, shallow=False)
+
+ base_path = os.path.join(overlay_dir, 'chromeos-chrome-%s' % chrome_version)
+ # Case where we have the last stable candidate with same version just rev.
+ if stable_candidate and stable_candidate.chrome_version == chrome_version:
+ new_ebuild_path = '%s-r%d.ebuild' % (
+ stable_candidate.ebuild_path_no_revision,
+ stable_candidate.current_revision + 1)
+ else:
+ if chrome_rev in [constants.CHROME_REV_LOCAL, constants.CHROME_REV_TOT,
+ constants.CHROME_REV_SPEC]:
+ portage_suffix = '_alpha'
+ else:
+ portage_suffix = '_rc'
+
+ new_ebuild_path = base_path + ('%s-r1.ebuild' % portage_suffix)
+
+ # Mark latest release and sticky branches as stable.
+ mark_stable = chrome_rev not in [constants.CHROME_REV_TOT,
+ constants.CHROME_REV_SPEC,
+ constants.CHROME_REV_LOCAL]
+
+ chrome_variables = dict()
+ if commit:
+ chrome_variables[_CHROME_SVN_TAG] = commit
+
+ portage_utilities.EBuild.MarkAsStable(
+ unstable_ebuild.ebuild_path, new_ebuild_path,
+ chrome_variables, make_stable=mark_stable)
+ new_ebuild = ChromeEBuild(new_ebuild_path)
+
+ # Determine whether this is ebuild is redundant.
+ if IsTheNewEBuildRedundant(new_ebuild, stable_candidate):
+ Info('Previous ebuild with same version found and ebuild is redundant.')
+ os.unlink(new_ebuild_path)
+ return None
+
+ if stable_candidate and chrome_rev in _REV_TYPES_FOR_LINKS:
+ _AnnotateAndPrint('Chromium revisions',
+ GetChromeRevisionListLink(stable_candidate,
+ new_ebuild,
+ chrome_rev))
+
+ RunCommand(['git', 'add', new_ebuild_path], cwd=overlay_dir)
+ if stable_candidate and not stable_candidate.IsSticky():
+ RunCommand(['git', 'rm', stable_candidate.ebuild_path], cwd=overlay_dir)
+
+ portage_utilities.EBuild.CommitChange(
+ _GIT_COMMIT_MESSAGE % {'chrome_rev': chrome_rev,
+ 'chrome_version': chrome_version},
+ overlay_dir)
+
+ return '%s-%s' % (new_ebuild.package, new_ebuild.version)
+
+
+def ParseMaxRevision(revision_list):
+ """Returns the max revision from a list of url@revision string."""
+ revision_re = re.compile('.*@(\d+)')
+
+ def RevisionKey(revision):
+ return revision_re.match(revision).group(1)
+
+ max_revision = max(revision_list.split(), key=RevisionKey)
+ return max_revision.rpartition('@')[2]
+
+
+def main(argv):
+ usage_options = '|'.join(constants.VALID_CHROME_REVISIONS)
+ usage = '%s OPTIONS [%s]' % (__file__, usage_options)
+ parser = optparse.OptionParser(usage)
+ parser.add_option('-b', '--boards', default='x86-generic')
+ parser.add_option('-c', '--chrome_url', default=BASE_CHROME_SVN_URL)
+ parser.add_option('-f', '--force_revision', default=None)
+ parser.add_option('-s', '--srcroot', default=os.path.join(os.environ['HOME'],
+ 'trunk', 'src'),
+ help='Path to the src directory')
+ parser.add_option('-t', '--tracking_branch', default='cros/master',
+ help='Branch we are tracking changes against')
+ (options, args) = parser.parse_args()
+
+ if len(args) != 1 or args[0] not in constants.VALID_CHROME_REVISIONS:
+ parser.error('Commit requires arg set to one of %s.'
+ % constants.VALID_CHROME_REVISIONS)
+
+ overlay_dir = os.path.abspath(_CHROME_OVERLAY_DIR %
+ {'srcroot': options.srcroot})
+ chrome_rev = args[0]
+ version_to_uprev = None
+ commit_to_use = None
+ sticky_branch = None
+
+ (unstable_ebuild, stable_ebuilds) = FindChromeCandidates(overlay_dir)
+
+ if chrome_rev == constants.CHROME_REV_LOCAL:
+ if 'CHROME_ROOT' in os.environ:
+ chrome_root = os.environ['CHROME_ROOT']
+ else:
+ chrome_root = os.path.join(os.environ['HOME'], 'chrome_root')
+
+ version_to_uprev = _GetTipOfTrunkVersionFile(chrome_root)
+ commit_to_use = 'Unknown'
+ Info('Using local source, versioning is untrustworthy.')
+ elif chrome_rev == constants.CHROME_REV_SPEC:
+ commit_to_use = options.force_revision
+ if '@' in commit_to_use: commit_to_use = ParseMaxRevision(commit_to_use)
+ version_to_uprev = _GetSpecificVersionUrl(options.chrome_url,
+ commit_to_use)
+ elif chrome_rev == constants.CHROME_REV_TOT:
+ commit_to_use = _GetTipOfTrunkSvnRevision(options.chrome_url)
+ version_to_uprev = _GetSpecificVersionUrl(options.chrome_url,
+ commit_to_use)
+ elif chrome_rev == constants.CHROME_REV_LATEST:
+ version_to_uprev = _GetLatestRelease(options.chrome_url)
+ else:
+ sticky_ebuild = _GetStickyEBuild(stable_ebuilds)
+ sticky_version = sticky_ebuild.chrome_version
+ sticky_branch = sticky_version.rpartition('.')[0]
+ version_to_uprev = _GetLatestRelease(options.chrome_url, sticky_branch)
+
+ stable_candidate = FindChromeUprevCandidate(stable_ebuilds, chrome_rev,
+ sticky_branch)
+
+ if stable_candidate:
+ Info('Stable candidate found %s' % stable_candidate)
+ else:
+ Info('No stable candidate found.')
+
+ tracking_branch = 'remotes/m/%s' % os.path.basename(options.tracking_branch)
+ existing_branch = cros_build_lib.GetCurrentBranch(overlay_dir)
+ work_branch = cros_mark_as_stable.GitBranch(constants.STABLE_EBUILD_BRANCH,
+ tracking_branch, overlay_dir)
+ work_branch.CreateBranch()
+
+ # In the case of uprevving overlays that have patches applied to them,
+ # include the patched changes in the stabilizing branch.
+ if existing_branch:
+ RunCommand(['git', 'rebase', existing_branch], cwd=overlay_dir)
+
+ chrome_version_atom = MarkChromeEBuildAsStable(
+ stable_candidate, unstable_ebuild, chrome_rev, version_to_uprev,
+ commit_to_use, overlay_dir)
+ # Explicit print to communicate to caller.
+ if chrome_version_atom:
+ cros_mark_as_stable.CleanStalePackages(options.boards.split(':'),
+ [chrome_version_atom])
+ print 'CHROME_VERSION_ATOM=%s' % chrome_version_atom
diff --git a/scripts/cros_mark_chrome_as_stable_unittest.py b/scripts/cros_mark_chrome_as_stable_unittest.py
new file mode 100755
index 000000000..89866b78b
--- /dev/null
+++ b/scripts/cros_mark_chrome_as_stable_unittest.py
@@ -0,0 +1,326 @@
+#!/usr/bin/python
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for cros_mark_chrome_as_stable.py."""
+
+# run with:
+# cros_sdk ../../chromite/buildbot/cros_mark_chrome_as_stable_unittest.py
+
+import mox
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ '..', '..'))
+from chromite.buildbot import constants
+from chromite.buildbot import portage_utilities
+from chromite.scripts import cros_mark_as_stable
+from chromite.scripts import cros_mark_chrome_as_stable
+
+# pylint: disable=W0212,R0904
+unstable_data = 'KEYWORDS=~x86 ~arm'
+stable_data = 'KEYWORDS=x86 arm'
+fake_svn_rev = '12345'
+new_fake_svn_rev = '23456'
+
+def _TouchAndWrite(path, data=None):
+ """Writes data (if it exists) to the file specified by the path."""
+ fh = open(path, 'w')
+ if data:
+ fh.write(data)
+
+ fh.close()
+
+
+class _StubCommandResult(object):
+ def __init__(self, msg):
+ self.output = msg
+
+
+class CrosMarkChromeAsStable(mox.MoxTestBase):
+
+ def setUp(self):
+ """Setup vars and create mock dir."""
+ mox.MoxTestBase.setUp(self)
+ self.tmp_overlay = tempfile.mkdtemp(prefix='chromiumos-overlay')
+ self.mock_chrome_dir = os.path.join(self.tmp_overlay, 'chromeos-base',
+ 'chromeos-chrome')
+ os.makedirs(self.mock_chrome_dir)
+
+ self.unstable = os.path.join(self.mock_chrome_dir,
+ 'chromeos-chrome-9999.ebuild')
+ self.sticky_branch = '8.0.224'
+ self.sticky_version = '%s.503' % self.sticky_branch
+ self.sticky = os.path.join(self.mock_chrome_dir,
+ 'chromeos-chrome-%s.ebuild' %
+ self.sticky_version)
+ self.sticky_rc_version = '%s.504' % self.sticky_branch
+ self.sticky_rc = os.path.join(self.mock_chrome_dir,
+ 'chromeos-chrome-%s_rc-r1.ebuild' %
+ self.sticky_rc_version)
+ self.latest_stable_version = '8.0.300.1'
+ self.latest_stable = os.path.join(self.mock_chrome_dir,
+ 'chromeos-chrome-%s_rc-r2.ebuild' %
+ self.latest_stable_version)
+ self.tot_stable_version = '9.0.305.0'
+ self.tot_stable = os.path.join(self.mock_chrome_dir,
+ 'chromeos-chrome-%s_alpha-r1.ebuild' %
+ self.tot_stable_version)
+
+ self.sticky_new_rc_version = '%s.520' % self.sticky_branch
+ self.sticky_new_rc = os.path.join(self.mock_chrome_dir,
+ 'chromeos-chrome-%s_rc-r1.ebuild' %
+ self.sticky_new_rc_version)
+ self.latest_new_version = '9.0.305.1'
+ self.latest_new = os.path.join(self.mock_chrome_dir,
+ 'chromeos-chrome-%s_rc-r1.ebuild' %
+ self.latest_new_version)
+ self.tot_new_version = '9.0.306.0'
+ self.tot_new = os.path.join(self.mock_chrome_dir,
+ 'chromeos-chrome-%s_alpha-r1.ebuild' %
+ self.tot_new_version)
+
+ _TouchAndWrite(self.unstable, unstable_data)
+ _TouchAndWrite(self.sticky, stable_data)
+ _TouchAndWrite(self.sticky_rc, stable_data)
+ _TouchAndWrite(self.latest_stable, stable_data)
+ _TouchAndWrite(self.tot_stable,
+ '\n'.join(
+ (stable_data,
+ '%s=%s' % (cros_mark_chrome_as_stable._CHROME_SVN_TAG,
+ fake_svn_rev))))
+
+ def tearDown(self):
+ """Cleans up mock dir."""
+ shutil.rmtree(self.tmp_overlay)
+
+ def testFindChromeCandidates(self):
+ """Test creation of stable ebuilds from mock dir."""
+ unstable, stable_ebuilds = cros_mark_chrome_as_stable.FindChromeCandidates(
+ self.mock_chrome_dir)
+
+ stable_ebuild_paths = map(lambda eb: eb.ebuild_path, stable_ebuilds)
+ self.assertEqual(unstable.ebuild_path, self.unstable)
+ self.assertEqual(len(stable_ebuilds), 4)
+ self.assertTrue(self.sticky in stable_ebuild_paths)
+ self.assertTrue(self.sticky_rc in stable_ebuild_paths)
+ self.assertTrue(self.latest_stable in stable_ebuild_paths)
+ self.assertTrue(self.tot_stable in stable_ebuild_paths)
+
+ def _GetStableEBuilds(self):
+ """Common helper to create a list of stable ebuilds."""
+ return [
+ cros_mark_chrome_as_stable.ChromeEBuild(self.sticky),
+ cros_mark_chrome_as_stable.ChromeEBuild(self.sticky_rc),
+ cros_mark_chrome_as_stable.ChromeEBuild(self.latest_stable),
+ cros_mark_chrome_as_stable.ChromeEBuild(self.tot_stable),
+ ]
+
+ def testTOTFindChromeUprevCandidate(self):
+ """Tests if we can find tot uprev candidate from our mock dir data."""
+ stable_ebuilds = self._GetStableEBuilds()
+
+ candidate = cros_mark_chrome_as_stable.FindChromeUprevCandidate(
+ stable_ebuilds, constants.CHROME_REV_TOT,
+ self.sticky_branch)
+
+ self.assertEqual(candidate.ebuild_path, self.tot_stable)
+
+ def testLatestFindChromeUprevCandidate(self):
+ """Tests if we can find latest uprev candidate from our mock dir data."""
+ stable_ebuilds = self._GetStableEBuilds()
+
+ candidate = cros_mark_chrome_as_stable.FindChromeUprevCandidate(
+ stable_ebuilds, constants.CHROME_REV_LATEST,
+ self.sticky_branch)
+
+ self.assertEqual(candidate.ebuild_path, self.latest_stable)
+
+ def testStickyFindChromeUprevCandidate(self):
+ """Tests if we can find sticky uprev candidate from our mock dir data."""
+ stable_ebuilds = self._GetStableEBuilds()
+
+ candidate = cros_mark_chrome_as_stable.FindChromeUprevCandidate(
+ stable_ebuilds, constants.CHROME_REV_STICKY,
+ self.sticky_branch)
+
+ self.assertEqual(candidate.ebuild_path, self.sticky_rc)
+
+ def testGetTipOfTrunkSvnRevision(self):
+ """Tests if we can get the latest svn revision from TOT."""
+ A_URL = 'dorf://mink/delaane/forkat/sertiunu.ortg./desk'
+ self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
+ cros_mark_chrome_as_stable.RunCommand(
+ ['svn', 'info', cros_mark_chrome_as_stable._GetSvnUrl(A_URL)],
+ redirect_stdout=True).AndReturn(
+ _StubCommandResult(
+ 'Some Junk 2134\nRevision: %s\nOtherInfo: test_data' %
+ fake_svn_rev))
+ self.mox.ReplayAll()
+ revision = cros_mark_chrome_as_stable._GetTipOfTrunkSvnRevision(A_URL)
+ self.mox.VerifyAll()
+ self.assertEquals(revision, fake_svn_rev)
+
+ def testGetTipOfTrunkVersion(self):
+ """Tests if we get the latest version from TOT."""
+ ARBITRARY_URL = 'Pratooey'
+ path = os.path.join(cros_mark_chrome_as_stable._GetSvnUrl(ARBITRARY_URL),
+ 'src', 'chrome', 'VERSION')
+ self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
+ cros_mark_chrome_as_stable.RunCommand(
+ ['svn', 'info', cros_mark_chrome_as_stable._GetSvnUrl(ARBITRARY_URL)],
+ redirect_stdout=True).AndReturn(
+ _StubCommandResult(
+ 'Some Junk 2134\nRevision: %s\nOtherInfo: test_data' %
+ fake_svn_rev))
+ cros_mark_chrome_as_stable.RunCommand(
+ ['svn', 'cat', '-r', fake_svn_rev, path], redirect_stdout=True,
+ error_message=mox.IsA(str)).AndReturn(
+ _StubCommandResult('A=8\nB=0\nC=256\nD=0'))
+
+ self.mox.ReplayAll()
+ version = cros_mark_chrome_as_stable._GetSpecificVersionUrl(ARBITRARY_URL,
+ fake_svn_rev)
+ self.mox.VerifyAll()
+ self.assertEquals(version, '8.0.256.0')
+
+ def testGetLatestRelease(self):
+ """Tests if we can find the latest release from our mock url data."""
+ ARBITRARY_URL = 'phthp://sores.chromium.org/tqs'
+ input_data = ['7.0.224.1/', '7.0.224.2/', '8.0.365.5/', 'LATEST.txt']
+ test_data = '\n'.join(input_data)
+ sorted_data = '\n'.join(reversed(input_data))
+ self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
+ cros_mark_chrome_as_stable.RunCommand(
+ ['svn', 'ls', ARBITRARY_URL + '/releases'],
+ redirect_stdout=True).AndReturn(_StubCommandResult(test_data))
+ cros_mark_chrome_as_stable.RunCommand(
+ ['sort', '--version-sort', '-r'], input=test_data,
+ redirect_stdout=True).AndReturn(_StubCommandResult(sorted_data))
+ # pretend this one is missing to test the skipping logic.
+ cros_mark_chrome_as_stable.RunCommand(
+ ['svn', 'ls', ARBITRARY_URL + '/releases/8.0.365.5/DEPS'],
+ error_ok=True, redirect_stdout=True).AndReturn(
+ _StubCommandResult('BAH BAH BAH'))
+ cros_mark_chrome_as_stable.RunCommand(
+ ['svn', 'ls', ARBITRARY_URL + '/releases/7.0.224.2/DEPS'],
+ error_ok=True, redirect_stdout=True).AndReturn(
+ _StubCommandResult('DEPS\n'))
+ self.mox.ReplayAll()
+ release = cros_mark_chrome_as_stable._GetLatestRelease(ARBITRARY_URL)
+ self.mox.VerifyAll()
+ self.assertEqual('7.0.224.2', release)
+
+ def testGetLatestStickyRelease(self):
+ """Tests if we can find the latest sticky release from our mock url data."""
+ ARBITRARY_URL = 'http://src.chromium.org/svn'
+ test_data = '\n'.join(['7.0.222.1/',
+ '8.0.224.2/',
+ '8.0.365.5/',
+ 'LATEST.txt'])
+ self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
+ cros_mark_chrome_as_stable.RunCommand(
+ ['svn', 'ls', ARBITRARY_URL + '/releases'],
+ redirect_stdout=True).AndReturn(_StubCommandResult('some_data'))
+ cros_mark_chrome_as_stable.RunCommand(
+ ['sort', '--version-sort', '-r'], input='some_data',
+ redirect_stdout=True).AndReturn(_StubCommandResult(test_data))
+ cros_mark_chrome_as_stable.RunCommand(
+ ['svn', 'ls', ARBITRARY_URL + '/releases/8.0.224.2/DEPS'],
+ error_ok=True, redirect_stdout=True).AndReturn(
+ _StubCommandResult('DEPS\n'))
+ self.mox.ReplayAll()
+ release = cros_mark_chrome_as_stable._GetLatestRelease(ARBITRARY_URL,
+ '8.0.224')
+ self.mox.VerifyAll()
+ self.assertEqual('8.0.224.2', release)
+
+ def testLatestChromeRevisionListLink(self):
+ """Tests that we can generate a link to the revision list between the
+ latest Chromium release and the last one we successfully built."""
+ _TouchAndWrite(self.latest_new, stable_data)
+ expected = cros_mark_chrome_as_stable.GetChromeRevisionLinkFromVersions(
+ self.latest_stable_version, self.latest_new_version)
+ made = cros_mark_chrome_as_stable.GetChromeRevisionListLink(
+ cros_mark_chrome_as_stable.ChromeEBuild(self.latest_stable),
+ cros_mark_chrome_as_stable.ChromeEBuild(self.latest_new),
+ constants.CHROME_REV_LATEST)
+ self.assertEqual(expected, made)
+
+ def testStickyEBuild(self):
+ """Tests if we can find the sticky ebuild from our mock directories."""
+ stable_ebuilds = self._GetStableEBuilds()
+ sticky_ebuild = cros_mark_chrome_as_stable._GetStickyEBuild(
+ stable_ebuilds)
+ self.assertEqual(sticky_ebuild.chrome_version, self.sticky_version)
+
+ def testChromeEBuildInit(self):
+ """Tests if the chrome_version is set correctly in a ChromeEBuild."""
+ ebuild = cros_mark_chrome_as_stable.ChromeEBuild(self.sticky)
+ self.assertEqual(ebuild.chrome_version, self.sticky_version)
+
+ def _CommonMarkAsStableTest(self, chrome_rev, new_version, old_ebuild_path,
+ new_ebuild_path, commit_string_indicator):
+ """Common function used for test functions for MarkChromeEBuildAsStable.
+
+ This function stubs out others calls, and runs MarkChromeEBuildAsStable
+ with the specified args.
+
+ Args:
+ chrome_rev: standard chrome_rev argument
+ new_version: version we are revving up to
+ old_ebuild_path: path to the stable ebuild
+ new_ebuild_path: path to the to be created path
+ commit_string_indicator: a string that the commit message must contain
+ """
+ self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
+ self.mox.StubOutWithMock(portage_utilities.EBuild, 'CommitChange')
+ stable_candidate = cros_mark_chrome_as_stable.ChromeEBuild(old_ebuild_path)
+ unstable_ebuild = cros_mark_chrome_as_stable.ChromeEBuild(self.unstable)
+ chrome_version = new_version
+ commit = None
+ overlay_dir = self.mock_chrome_dir
+
+ cros_mark_chrome_as_stable.RunCommand(['git', 'add', new_ebuild_path],
+ cwd=overlay_dir)
+ cros_mark_chrome_as_stable.RunCommand(['git', 'rm', old_ebuild_path],
+ cwd=overlay_dir)
+ portage_utilities.EBuild.CommitChange(
+ mox.StrContains(commit_string_indicator), overlay_dir)
+
+ self.mox.ReplayAll()
+ cros_mark_chrome_as_stable.MarkChromeEBuildAsStable(
+ stable_candidate, unstable_ebuild, chrome_rev, chrome_version, commit,
+ overlay_dir)
+ self.mox.VerifyAll()
+
+ def testStickyMarkAsStable(self):
+ """Tests to see if we can mark chrome as stable for a new sticky release."""
+ self._CommonMarkAsStableTest(
+ constants.CHROME_REV_STICKY,
+ self.sticky_new_rc_version, self.sticky_rc,
+ self.sticky_new_rc, 'stable_release')
+
+ def testLatestMarkAsStable(self):
+ """Tests to see if we can mark chrome for a latest release."""
+ self._CommonMarkAsStableTest(
+ constants.CHROME_REV_LATEST,
+ self.latest_new_version, self.latest_stable,
+ self.latest_new, 'latest_release')
+
+ def testTotMarkAsStable(self):
+ """Tests to see if we can mark chrome for tot."""
+ self._CommonMarkAsStableTest(
+ constants.CHROME_REV_TOT,
+ self.tot_new_version, self.tot_stable,
+ self.tot_new, 'tot')
+
+
+if __name__ == '__main__':
+ unittest.main()