1#!/usr/bin/env python
2# Copyright 2014 the V8 project authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import argparse
7import os
8import sys
9
10from common_includes import *
11
12
13class Preparation(Step):
14  MESSAGE = "Preparation."
15
16  def RunStep(self):
17    # Update v8 remote tracking branches.
18    self.GitFetchOrigin()
19
20
21class DetectLastPush(Step):
22  MESSAGE = "Detect commit ID of last push to trunk."
23
24  def RunStep(self):
25    self["last_push"] = self._options.last_push or self.FindLastTrunkPush(
26        branch="origin/master", include_patches=True)
27    self["trunk_revision"] = self.GetCommitPositionNumber(self["last_push"])
28    self["push_title"] = self.GitLog(n=1, format="%s",
29                                     git_hash=self["last_push"])
30
31
32class SwitchChromium(Step):
33  MESSAGE = "Switch to Chromium checkout."
34
35  def RunStep(self):
36    self["v8_path"] = os.getcwd()
37    cwd = self._options.chromium
38    os.chdir(cwd)
39    self.InitialEnvironmentChecks(cwd)
40    # Check for a clean workdir.
41    if not self.GitIsWorkdirClean(cwd=cwd):  # pragma: no cover
42      self.Die("Workspace is not clean. Please commit or undo your changes.")
43    # Assert that the DEPS file is there.
44    if not os.path.exists(os.path.join(cwd, "DEPS")):  # pragma: no cover
45      self.Die("DEPS file not present.")
46
47
48class UpdateChromiumCheckout(Step):
49  MESSAGE = "Update the checkout and create a new branch."
50
51  def RunStep(self):
52    self.GitCheckout("master", cwd=self._options.chromium)
53    self.Command("gclient", "sync --nohooks", cwd=self._options.chromium)
54    self.GitPull(cwd=self._options.chromium)
55
56    # Update v8 remotes.
57    self.GitFetchOrigin()
58
59    self.GitCreateBranch("v8-roll-%s" % self["trunk_revision"],
60                         cwd=self._options.chromium)
61
62
63class UploadCL(Step):
64  MESSAGE = "Create and upload CL."
65
66  def RunStep(self):
67    # Patch DEPS file.
68    if self.Command(
69        "roll-dep", "v8 %s" % self["trunk_revision"],
70        cwd=self._options.chromium) is None:
71      self.Die("Failed to create deps for %s" % self["trunk_revision"])
72
73    commit_title = "Update V8 to %s." % self["push_title"].lower()
74    sheriff = ""
75    if self["sheriff"]:
76      sheriff = ("\n\nPlease reply to the V8 sheriff %s in case of problems."
77                 % self["sheriff"])
78    self.GitCommit("%s%s\n\nTBR=%s" %
79                       (commit_title, sheriff, self._options.reviewer),
80                   author=self._options.author,
81                   cwd=self._options.chromium)
82    if not self._options.dry_run:
83      self.GitUpload(author=self._options.author,
84                     force=True,
85                     cq=self._options.use_commit_queue,
86                     cwd=self._options.chromium)
87      print "CL uploaded."
88    else:
89      self.GitCheckout("master", cwd=self._options.chromium)
90      self.GitDeleteBranch("v8-roll-%s" % self["trunk_revision"],
91                           cwd=self._options.chromium)
92      print "Dry run - don't upload."
93
94
95# TODO(machenbach): Make this obsolete. We are only in the chromium chechout
96# for the initial .git check.
97class SwitchV8(Step):
98  MESSAGE = "Returning to V8 checkout."
99
100  def RunStep(self):
101    os.chdir(self["v8_path"])
102
103
104class CleanUp(Step):
105  MESSAGE = "Done!"
106
107  def RunStep(self):
108    print("Congratulations, you have successfully rolled the push r%s it into "
109          "Chromium. Please don't forget to update the v8rel spreadsheet."
110          % self["trunk_revision"])
111
112    # Clean up all temporary files.
113    Command("rm", "-f %s*" % self._config["PERSISTFILE_BASENAME"])
114
115
116class ChromiumRoll(ScriptsBase):
117  def _PrepareOptions(self, parser):
118    parser.add_argument("-c", "--chromium", required=True,
119                        help=("The path to your Chromium src/ "
120                              "directory to automate the V8 roll."))
121    parser.add_argument("-l", "--last-push",
122                        help="The git commit ID of the last push to trunk.")
123    parser.add_argument("--use-commit-queue",
124                        help="Check the CQ bit on upload.",
125                        default=False, action="store_true")
126
127  def _ProcessOptions(self, options):  # pragma: no cover
128    if not options.author or not options.reviewer:
129      print "A reviewer (-r) and an author (-a) are required."
130      return False
131
132    options.requires_editor = False
133    options.force = True
134    options.manual = False
135    return True
136
137  def _Config(self):
138    return {
139      "PERSISTFILE_BASENAME": "/tmp/v8-chromium-roll-tempfile",
140    }
141
142  def _Steps(self):
143    return [
144      Preparation,
145      DetectLastPush,
146      DetermineV8Sheriff,
147      SwitchChromium,
148      UpdateChromiumCheckout,
149      UploadCL,
150      SwitchV8,
151      CleanUp,
152    ]
153
154
155if __name__ == "__main__":  # pragma: no cover
156  sys.exit(ChromiumRoll().Run())
157