Update prebuilt.py to upload correctly when tracking branch is a revision.
This contains the following two commits.
1. Update prebuilt.py to sync to latest revision before pushing.
This fixes a bug where prebuilt.py is unable to push if it is using
manifest-versions to sync to an old revision. This bug occurs because
manifest-versions is pointing at an old version of the repository so
the prebuilt pusher is never able to push.
BUG=chrome-os-partner:3959
TEST=Test with --dry-run push. Also run unit test suite.
Reviewed-on: http://gerrit.chromium.org/gerrit/1239
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: David James <davidjames@chromium.org>
(cherry picked from commit 1b6e67aef79696d74bcee3d2fce252c8397e592a)
2. Update prebuilt.py to upload correctly when tracking branch is a revision.
If the tracking branch is a revision, we shouldn't push there. We need to
look in the manifest for the default branch and use that instead.
BUG=chrome-os-partner:4169
TEST=Run prebuilt.py when tracking branch is a revision and verify it pushes
to the right branch (i.e. the default branch defined in the manifest).
Reviewed-on: http://gerrit.chromium.org/gerrit/1702
Reviewed-by: Nick Sanders <nsanders@chromium.org>
Tested-by: David James <davidjames@chromium.org>
(cherry picked from commit d611f3d89a40ca74bb9218f341259a9a1b6f351b)
Change-Id: I553fc0931052ff51a5dcfd6fd5862da7115b4cb2
Reviewed-on: http://gerrit.chromium.org/gerrit/1699
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: David James <davidjames@chromium.org>
diff --git a/lib/cros_build_lib.py b/lib/cros_build_lib.py
index 9e35dbc..37a5673 100644
--- a/lib/cros_build_lib.py
+++ b/lib/cros_build_lib.py
@@ -10,11 +10,15 @@
import signal
import subprocess
import sys
+import time
from terminal import Color
_STDOUT_IS_TTY = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
+class GitPushFailed(Exception):
+ """Raised when a git push failed after retry."""
+ pass
class CommandResult(object):
"""An object to store various attributes of a child process."""
@@ -326,6 +330,64 @@
return new_path
+def GetPushBranch(branch, cwd):
+ """Gets the appropriate push branch for the specified branch / directory.
+
+ If branch has a valid tracking branch, we should push to that branch. If
+ the tracking branch is a revision, we can't push to that, so we should look
+ at the default branch from the manifest.
+
+ Args:
+ branch: Branch to examine for tracking branch.
+ cwd: Directory to look in.
+ """
+ info = {}
+ for key in ('remote', 'merge'):
+ cmd = ['git', 'config', 'branch.%s.%s' % (branch, key)]
+ info[key] = RunCommand(cmd, redirect_stdout=True, cwd=cwd).output.strip()
+ if not info['merge'].startswith('refs/heads/'):
+ output = RunCommand(['repo', 'manifest', '-o', '-'], redirect_stdout=True,
+ cwd=cwd).output
+ m = re.search(r'<default[^>]*revision="(refs/heads/[^"]*)"', output)
+ assert m
+ info['merge'] = m.group(1)
+ assert info['merge'].startswith('refs/heads/')
+ return info['remote'], info['merge'].replace('refs/heads/', '')
+
+
+def GitPushWithRetry(branch, cwd, dryrun=False, retries=5):
+ """General method to push local git changes.
+
+ Args:
+ branch: Local branch to push. Branch should have already been created
+ with a local change committed ready to push to the remote branch. Must
+ also already be checked out to that branch.
+ cwd: Directory to push in.
+ dryrun: Git push --dry-run if set to True.
+ retries: The number of times to retry before giving up, default: 5
+
+ Raises:
+ GitPushFailed if push was unsuccessful after retries
+ """
+ remote, push_branch = GetPushBranch(branch, cwd)
+ for retry in range(1, retries + 1):
+ try:
+ RunCommand(['git', 'remote', 'update'], cwd=cwd)
+ RunCommand(['git', 'rebase', '%s/%s' % (remote, push_branch)], cwd=cwd)
+ push_command = ['git', 'push', remote, '%s:%s' % (branch, push_branch)]
+ if dryrun:
+ push_command.append('--dry-run')
+
+ RunCommand(push_command, cwd=cwd)
+ break
+ except RunCommandError:
+ if retry < retries:
+ print 'Error pushing changes trying again (%s/%s)' % (retry, retries)
+ time.sleep(5 * retry)
+ else:
+ raise GitPushFailed('Failed to push change after %s retries' % retries)
+
+
def GetCallerName():
"""Returns the name of the calling module with __main__."""
top_frame = inspect.stack()[-1][0]