OLD | NEW |
---|---|
(Empty) | |
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 | |
6 import argparse | |
7 import sys | |
8 | |
9 from common_includes import * | |
10 | |
11 CONFIG = { | |
12 BRANCHNAME: "auto-tag-v8", | |
13 PERSISTFILE_BASENAME: "/tmp/v8-auto-tag-tempfile", | |
14 DOT_GIT_LOCATION: ".git", | |
15 VERSION_FILE: "src/version.cc", | |
16 } | |
17 | |
18 | |
19 class Preparation(Step): | |
20 MESSAGE = "Preparation." | |
21 | |
22 def RunStep(self): | |
23 self.CommonPrepare() | |
24 self.PrepareBranch() | |
25 self.GitCheckout("master") | |
26 self.GitSVNRebase() | |
27 | |
28 | |
29 class GetTags(Step): | |
30 MESSAGE = "Get all V8 tags." | |
31 | |
32 def RunStep(self): | |
33 self.GitCreateBranch(self._config[BRANCHNAME]) | |
34 | |
35 # Get remote tags. | |
36 tags = filter(lambda s: re.match(r"^svn/tags/[\d+\.]+$", s), | |
37 self.GitRemotes()) | |
38 | |
39 # Remove 'svn/tags/' prefix. | |
40 self["tags"] = map(lambda s: s[9:], tags) | |
41 | |
42 | |
43 class GetLastUntaggedVersion(Step): | |
Jarin
2014/07/18 10:05:40
Should not this be named Oldest rather than Last?
| |
44 MESSAGE = "Check if there's a version on bleeding edge without a tag." | |
45 | |
46 def RunStep(self): | |
47 tags = set(self["tags"]) | |
48 self["candidate"] = None | |
49 self["candidate_version"] = None | |
50 self["next"] = None | |
51 self["next_version"] = None | |
52 | |
53 # Iterate backwards through all automatic version updates. | |
54 for git_hash in self.GitLog( | |
55 format="%H", grep="\\[Auto\\-roll\\] Bump up version to").splitlines(): | |
56 | |
57 # Get the version. | |
58 if not self.GitCheckoutFileSafe(self._config[VERSION_FILE], git_hash): | |
59 continue | |
60 | |
61 self.ReadAndPersistVersion() | |
62 version = self.ArrayToVersion("") | |
63 | |
64 # Strip off trailing patch level (tags don't include tag level 0). | |
65 if version.endswith(".0"): | |
66 version = version[:-2] | |
67 | |
68 # Clean up checked-out version file. | |
69 self.GitCheckoutFileSafe(self._config[VERSION_FILE], "HEAD") | |
70 | |
71 if version in tags: | |
72 if self["candidate"]: | |
73 # Revision "git_hash" is tagged already and "candidate" was the next | |
74 # newer revision without a tag. | |
75 break | |
76 else: | |
77 print("Stop as %s is the latest version and it has been tagged." % | |
78 version) | |
79 self.CommonCleanup() | |
80 return True | |
81 else: | |
82 # This is the second oldest version without a tag. | |
83 self["next"] = self["candidate"] | |
84 self["next_version"] = self["candidate_version"] | |
85 | |
86 # This is the oldest version without a tag. | |
87 self["candidate"] = git_hash | |
88 self["candidate_version"] = version | |
89 | |
90 if not self["candidate"] or not self["candidate_version"]: | |
91 print "Nothing found to tag." | |
92 self.CommonCleanup() | |
93 return True | |
94 | |
95 print("Candidate for tagging is %s with version %s" % | |
96 (self["candidate"], self["candidate_version"])) | |
97 | |
98 | |
99 class GetLKGRs(Step): | |
100 MESSAGE = "Get the last lkgrs." | |
101 | |
102 def RunStep(self): | |
103 revision_url = "https://v8-status.appspot.com/revisions?format=json" | |
104 status_json = self.ReadURL(revision_url, wait_plan=[5, 20]) | |
105 self["lkgrs"] = [entry["revision"] | |
106 for entry in json.loads(status_json) if entry["status"]] | |
107 | |
108 | |
109 class CalculateTagRevision(Step): | |
110 MESSAGE = "Calculate the revision to tag." | |
111 | |
112 def LastLKGR(self, min_rev, max_rev): | |
113 """Finds the newest lkgr between min_rev (inclusive) and max_rev | |
114 (exclusive). | |
115 """ | |
116 for lkgr in self["lkgrs"]: | |
117 # LKGRs are reverse sorted. | |
118 if int(min_rev) <= int(lkgr) and int(lkgr) < int(max_rev): | |
119 return lkgr | |
120 return None | |
121 | |
122 def RunStep(self): | |
123 # Get the lkgr after the tag candidate and before the next tag candidate. | |
124 candidate_svn = self.GitSVNFindSVNRev(self["candidate"]) | |
125 if self["next"]: | |
126 next_svn = self.GitSVNFindSVNRev(self["next"]) | |
127 else: | |
128 # Don't include the version change commit itself if there is no upper | |
129 # limit yet. | |
130 candidate_svn = str(int(candidate_svn) + 1) | |
131 next_svn = sys.maxint | |
132 lkgr_svn = self.LastLKGR(candidate_svn, next_svn) | |
133 | |
134 if not lkgr_svn: | |
135 print "There is no lkgr since the candidate version yet." | |
136 self.CommonCleanup() | |
137 return True | |
138 | |
139 # Let's check if the lkgr is at least three hours old. | |
140 self["lkgr"] = self.GitSVNFindGitHash(lkgr_svn) | |
141 if not self["lkgr"]: | |
142 print "Couldn't find git hash for lkgr %s" % lkgr_svn | |
143 self.CommonCleanup() | |
144 return True | |
145 | |
146 lkgr_utc_time = int(self.GitLog(n=1, format="%at", git_hash=self["lkgr"])) | |
147 current_utc_time = self._side_effect_handler.GetUTCStamp() | |
148 | |
149 if current_utc_time < lkgr_utc_time + 10800: | |
150 print "Candidate lkgr %s is too recent for tagging." % lkgr_svn | |
151 self.CommonCleanup() | |
152 return True | |
153 | |
154 print "Tagging revision %s with %s" % (lkgr_svn, self["candidate_version"]) | |
155 | |
156 | |
157 class MakeTag(Step): | |
158 MESSAGE = "Tag the version." | |
159 | |
160 def RunStep(self): | |
161 if not self._options.dry_run: | |
162 self.GitReset(self["lkgr"]) | |
163 self.GitSVNTag(self["candidate_version"]) | |
164 | |
165 | |
166 class CleanUp(Step): | |
167 MESSAGE = "Clean up." | |
168 | |
169 def RunStep(self): | |
170 self.CommonCleanup() | |
171 | |
172 | |
173 class AutoTag(ScriptsBase): | |
174 def _PrepareOptions(self, parser): | |
175 parser.add_argument("--dry_run", help="Don't tag the new version.", | |
176 default=False, action="store_true") | |
177 | |
178 def _ProcessOptions(self, options): # pragma: no cover | |
179 if not options.dry_run and not options.author: | |
180 print "Specify your chromium.org email with -a" | |
181 return False | |
182 options.wait_for_lgtm = False | |
183 options.force_readline_defaults = True | |
184 options.force_upload = True | |
185 return True | |
186 | |
187 def _Steps(self): | |
188 return [ | |
189 Preparation, | |
190 GetTags, | |
191 GetLastUntaggedVersion, | |
192 GetLKGRs, | |
193 CalculateTagRevision, | |
194 MakeTag, | |
195 CleanUp, | |
196 ] | |
197 | |
198 | |
199 if __name__ == "__main__": # pragma: no cover | |
200 sys.exit(AutoTag(CONFIG).Run()) | |
OLD | NEW |