Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / tools / push-to-trunk / auto_tag.py
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 GetOldestUntaggedVersion(Step):
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       GetOldestUntaggedVersion,
192       GetLKGRs,
193       CalculateTagRevision,
194       MakeTag,
195       CleanUp,
196     ]
197
198
199 if __name__ == "__main__":  # pragma: no cover
200   sys.exit(AutoTag(CONFIG).Run())