diff --git a/recipe_modules/bot_update/api.py b/recipe_modules/bot_update/api.py index 7571d0dec..47846859e 100644 --- a/recipe_modules/bot_update/api.py +++ b/recipe_modules/bot_update/api.py @@ -60,7 +60,8 @@ class BotUpdateApi(recipe_api.RecipeApi): patch_oauth2=False, use_site_config_creds=True, output_manifest=True, clobber=False, root_solution_revision=None, rietveld=None, issue=None, - patchset=None, gerrit_no_reset=False, **kwargs): + patchset=None, gerrit_no_reset=False, + gerrit_rebase_patch_ref=False, **kwargs): """ Args: use_site_config_creds: If the oauth2 credentials are in the buildbot @@ -216,6 +217,8 @@ class BotUpdateApi(recipe_api.RecipeApi): cmd.append('--with_branch_heads') if gerrit_no_reset: cmd.append('--gerrit_no_reset') + if gerrit_rebase_patch_ref: + cmd.append('--gerrit_rebase_patch_ref') # Inject Json output for testing. git_mode = self._mastername not in SVN_MASTERS diff --git a/recipe_modules/bot_update/example.expected/gerrit_rebase_patch_ref.json b/recipe_modules/bot_update/example.expected/gerrit_rebase_patch_ref.json new file mode 100644 index 000000000..105a47f07 --- /dev/null +++ b/recipe_modules/bot_update/example.expected/gerrit_rebase_patch_ref.json @@ -0,0 +1,44 @@ +[ + { + "cmd": [ + "python", + "-u", + "RECIPE_MODULE[depot_tools::bot_update]/resources/bot_update.py", + "--master", + "experimental", + "--builder", + "Experimental Builder", + "--slave", + "somehost", + "--spec", + "cache_dir = '[GIT_CACHE]'\nsolutions = [{'deps_file': '.DEPS.git', 'managed': True, 'name': 'src', 'url': 'svn://svn.chromium.org/chrome/trunk/src'}]", + "--root", + "src", + "--revision_mapping_file", + "{\"src\": \"got_cr_revision\"}", + "--git-cache-dir", + "[GIT_CACHE]", + "--output_json", + "/path/to/tmp/json", + "--revision", + "src@HEAD", + "--gerrit_rebase_patch_ref" + ], + "env": { + "PATH": "%(PATH)s:RECIPE_PACKAGE_REPO[depot_tools]" + }, + "name": "bot_update", + "~followup_annotations": [ + "@@@STEP_LOG_LINE@json.output@{@@@", + "@@@STEP_LOG_LINE@json.output@ \"did_run\": false, @@@", + "@@@STEP_LOG_LINE@json.output@ \"patch_failure\": false@@@", + "@@@STEP_LOG_LINE@json.output@}@@@", + "@@@STEP_LOG_END@json.output@@@" + ] + }, + { + "name": "$result", + "recipe_result": null, + "status_code": 0 + } +] \ No newline at end of file diff --git a/recipe_modules/bot_update/example.py b/recipe_modules/bot_update/example.py index 7bdef5ba0..10b4d1185 100644 --- a/recipe_modules/bot_update/example.py +++ b/recipe_modules/bot_update/example.py @@ -34,16 +34,19 @@ def RunSteps(api): root_solution_revision = api.properties.get('root_solution_revision') suffix = api.properties.get('suffix') gerrit_no_reset = True if api.properties.get('gerrit_no_reset') else False - api.bot_update.ensure_checkout(force=force, - no_shallow=no_shallow, - patch=patch, - with_branch_heads=with_branch_heads, - output_manifest=output_manifest, - refs=refs, patch_oauth2=oauth2, - clobber=clobber, - root_solution_revision=root_solution_revision, - suffix=suffix, - gerrit_no_reset=gerrit_no_reset) + gerrit_rebase_patch_ref = bool(api.properties.get('gerrit_rebase_patch_ref')) + api.bot_update.ensure_checkout( + force=force, + no_shallow=no_shallow, + patch=patch, + with_branch_heads=with_branch_heads, + output_manifest=output_manifest, + refs=refs, patch_oauth2=oauth2, + clobber=clobber, + root_solution_revision=root_solution_revision, + suffix=suffix, + gerrit_no_reset=gerrit_no_reset, + gerrit_rebase_patch_ref=gerrit_rebase_patch_ref) def GenTests(api): @@ -154,6 +157,12 @@ def GenTests(api): slavename='somehost', gerrit_no_reset=1 ) + yield api.test('gerrit_rebase_patch_ref') + api.properties( + mastername='experimental', + buildername='Experimental Builder', + slavename='somehost', + gerrit_rebase_patch_ref=True + ) yield api.test('tryjob_v8') + api.properties( mastername='tryserver.chromium.linux', buildername='linux_rel', diff --git a/recipe_modules/bot_update/resources/bot_update.py b/recipe_modules/bot_update/resources/bot_update.py index bfc7b7feb..1baf45fee 100755 --- a/recipe_modules/bot_update/resources/bot_update.py +++ b/recipe_modules/bot_update/resources/bot_update.py @@ -1138,7 +1138,8 @@ def apply_rietveld_issue(issue, patchset, root, server, _rev_map, _revision, except SubprocessFailed as e: raise PatchFailed(e.message, e.code, e.output) -def apply_gerrit_ref(gerrit_repo, gerrit_ref, root, gerrit_reset): +def apply_gerrit_ref(gerrit_repo, gerrit_ref, root, gerrit_reset, + gerrit_rebase_patch_ref): gerrit_repo = gerrit_repo or 'origin' assert gerrit_ref print '===Applying gerrit ref===' @@ -1147,6 +1148,27 @@ def apply_gerrit_ref(gerrit_repo, gerrit_ref, root, gerrit_reset): base_rev = git('rev-parse', 'HEAD', cwd=root).strip() git('retry', 'fetch', gerrit_repo, gerrit_ref, cwd=root, tries=1) git('checkout', 'FETCH_HEAD', cwd=root) + + if gerrit_rebase_patch_ref: + print '===Rebasing===' + # git rebase requires a branch to operate on. + temp_branch_name = 'tmp/' + uuid.uuid4().hex + try: + ok = False + git('checkout', '-b', temp_branch_name, cwd=root) + git('rebase', base_rev, cwd=root) + + # Get off of the temporary branch since it can't be deleted otherwise. + cur_rev = git('rev-parse', 'HEAD', cwd=root).strip() + git('checkout', cur_rev, cwd=root) + git('branch', '-D', temp_branch_name, cwd=root) + ok = True + finally: + if not ok: + # Get off of the temporary branch since it can't be deleted otherwise. + git('checkout', base_rev, cwd=root) + git('branch', '-D', temp_branch_name, cwd=root) + if gerrit_reset: git('reset', '--soft', base_rev, cwd=root) except SubprocessFailed as e: @@ -1304,10 +1326,10 @@ def ensure_deps_revisions(deps_url_mapping, solutions, revisions): def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, patch_root, issue, patchset, patch_url, rietveld_server, - gerrit_repo, gerrit_ref, revision_mapping, - apply_issue_email_file, apply_issue_key_file, buildspec, - gyp_env, shallow, runhooks, refs, git_cache_dir, - gerrit_reset): + gerrit_repo, gerrit_ref, gerrit_rebase_patch_ref, + revision_mapping, apply_issue_email_file, + apply_issue_key_file, buildspec, gyp_env, shallow, runhooks, + refs, git_cache_dir, gerrit_reset): # Get a checkout of each solution, without DEPS or hooks. # Calling git directly because there is no way to run Gclient without # invoking DEPS. @@ -1338,6 +1360,9 @@ def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, revision_mapping, git_ref, apply_issue_email_file, apply_issue_key_file, whitelist=[target]) already_patched.append(target) + elif gerrit_ref and gerrit_rebase_patch_ref: + apply_gerrit_ref(gerrit_repo, gerrit_ref, patch_root, gerrit_reset, + True) if not buildspec: # Run deps2git if there is a DEPS change after the last .DEPS.git commit. @@ -1376,8 +1401,8 @@ def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, apply_rietveld_issue(issue, patchset, patch_root, rietveld_server, revision_mapping, git_ref, apply_issue_email_file, apply_issue_key_file, blacklist=already_patched) - elif gerrit_ref: - apply_gerrit_ref(gerrit_repo, gerrit_ref, patch_root, gerrit_reset) + elif gerrit_ref and not gerrit_rebase_patch_ref: + apply_gerrit_ref(gerrit_repo, gerrit_ref, patch_root, gerrit_reset, False) # Reset the deps_file point in the solutions so that hooks get run properly. for sln in solutions: @@ -1456,6 +1481,8 @@ def parse_args(): parse.add_option('--gerrit_repo', help='Gerrit repository to pull the ref from.') parse.add_option('--gerrit_ref', help='Gerrit ref to apply.') + parse.add_option('--gerrit_rebase_patch_ref', action='store_true', + help='Rebase Gerrit patch ref after of checking it out.') parse.add_option('--gerrit_no_reset', action='store_true', help='Bypass calling reset after applying a gerrit ref.') parse.add_option('--specs', help='Gcilent spec.') @@ -1617,6 +1644,7 @@ def checkout(options, git_slns, specs, buildspec, master, rietveld_server=options.rietveld_server, gerrit_repo=options.gerrit_repo, gerrit_ref=options.gerrit_ref, + gerrit_rebase_patch_ref=options.gerrit_rebase_patch_ref, revision_mapping=options.revision_mapping, apply_issue_email_file=options.apply_issue_email_file, apply_issue_key_file=options.apply_issue_key_file,