1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#!/usr/bin/env python 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Copyright 2013 the V8 project authors. All rights reserved. 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Redistribution and use in source and binary forms, with or without 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# modification, are permitted provided that the following conditions are 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# met: 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# * Redistributions of source code must retain the above copyright 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# notice, this list of conditions and the following disclaimer. 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# * Redistributions in binary form must reproduce the above 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# copyright notice, this list of conditions and the following 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# disclaimer in the documentation and/or other materials provided 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# with the distribution. 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# * Neither the name of Google Inc. nor the names of its 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# contributors may be used to endorse or promote products derived 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# from this software without specific prior written permission. 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport argparse 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport datetime 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport httplib 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport glob 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport imp 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport json 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport os 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport re 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport shutil 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport subprocess 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport sys 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport textwrap 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport time 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport urllib 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport urllib2 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfrom git_recipes import GitRecipesMixin 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfrom git_recipes import GitFailedException 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierCHANGELOG_FILE = "ChangeLog" 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochDAY_IN_SECONDS = 24 * 60 * 60 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochPUSH_MSG_GIT_RE = re.compile(r".* \(based on (?P<git_rev>[a-fA-F0-9]+)\)$") 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochPUSH_MSG_NEW_RE = re.compile(r"^Version \d+\.\d+\.\d+$") 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochVERSION_FILE = os.path.join("include", "v8-version.h") 53342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen MurdochWATCHLISTS_FILE = "WATCHLISTS" 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# V8 base directory. 56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierV8_BASE = os.path.dirname( 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef TextToFile(text, file_name): 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch with open(file_name, "w") as f: 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch f.write(text) 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef AppendToFile(text, file_name): 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch with open(file_name, "a") as f: 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch f.write(text) 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef LinesInFile(file_name): 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch with open(file_name) as f: 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for line in f: 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch yield line 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef FileToText(file_name): 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch with open(file_name) as f: 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return f.read() 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef MSub(rexp, replacement, text): 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return re.sub(rexp, replacement, text, flags=re.MULTILINE) 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Fill80(line): 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Replace tabs and remove surrounding space. 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch line = re.sub(r"\t", r" ", line.strip()) 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Format with 8 characters indentation and line width 80. 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return textwrap.fill(line, width=80, initial_indent=" ", 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch subsequent_indent=" ") 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef MakeComment(text): 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MSub(r"^( ?)", "#", text) 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef StripComments(text): 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Use split not splitlines to keep terminal newlines. 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return "\n".join(filter(lambda x: not x.startswith("#"), text.split("\n"))) 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef MakeChangeLogBody(commit_messages, auto_format=False): 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = "" 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch added_titles = set() 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (title, body, author) in commit_messages: 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # TODO(machenbach): Better check for reverts. A revert should remove the 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # original CL from the actual log entry. 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch title = title.strip() 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if auto_format: 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Only add commits that set the LOG flag correctly. 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch log_exp = r"^[ \t]*LOG[ \t]*=[ \t]*(?:(?:Y(?:ES)?)|TRUE)" 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not re.search(log_exp, body, flags=re.I | re.M): 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Never include reverts. 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if title.startswith("Revert "): 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Don't include duplicates. 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if title in added_titles: 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Add and format the commit's title and bug reference. Move dot to the end. 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch added_titles.add(title) 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raw_title = re.sub(r"(\.|\?|!)$", "", title) 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bug_reference = MakeChangeLogBugReference(body) 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch space = " " if bug_reference else "" 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result += "%s\n" % Fill80("%s%s%s." % (raw_title, space, bug_reference)) 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Append the commit's author for reference if not in auto-format mode. 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not auto_format: 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result += "%s\n" % Fill80("(%s)" % author.strip()) 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result += "\n" 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef MakeChangeLogBugReference(body): 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch """Grep for "BUG=xxxx" lines in the commit message and convert them to 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(issue xxxx)". 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch """ 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch crbugs = [] 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8bugs = [] 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def AddIssues(text): 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ref = re.match(r"^BUG[ \t]*=[ \t]*(.+)$", text.strip()) 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not ref: 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for bug in ref.group(1).split(","): 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bug = bug.strip() 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match = re.match(r"^v8:(\d+)$", bug) 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if match: v8bugs.append(int(match.group(1))) 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else: 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match = re.match(r"^(?:chromium:)?(\d+)$", bug) 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if match: crbugs.append(int(match.group(1))) 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Add issues to crbugs and v8bugs. 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch map(AddIssues, body.splitlines()) 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Filter duplicates, sort, stringify. 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch crbugs = map(str, sorted(set(crbugs))) 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8bugs = map(str, sorted(set(v8bugs))) 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bug_groups = [] 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def FormatIssues(prefix, bugs): 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if len(bugs) > 0: 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch plural = "s" if len(bugs) > 1 else "" 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bug_groups.append("%sissue%s %s" % (prefix, plural, ", ".join(bugs))) 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FormatIssues("", v8bugs) 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FormatIssues("Chromium ", crbugs) 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if len(bug_groups) > 0: 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return "(%s)" % ", ".join(bug_groups) 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else: 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return "" 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef SortingKey(version): 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch """Key for sorting version number strings: '3.11' > '3.2.1.1'""" 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch version_keys = map(int, version.split(".")) 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Fill up to full version numbers to normalize comparison. 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while len(version_keys) < 4: # pragma: no cover 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch version_keys.append(0) 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Fill digits. 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ".".join(map("{0:04d}".format, version_keys)) 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Some commands don't like the pipe, e.g. calling vi from within the script or 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# from subscripts like git cl upload. 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Command(cmd, args="", prefix="", pipe=True, cwd=None): 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cwd = cwd or os.getcwd() 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # TODO(machenbach): Use timeout. 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmd_line = "%s %s %s" % (prefix, cmd, args) 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Command: %s" % cmd_line 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "in %s" % cwd 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sys.stdout.flush() 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch try: 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if pipe: 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return subprocess.check_output(cmd_line, shell=True, cwd=cwd) 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else: 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return subprocess.check_call(cmd_line, shell=True, cwd=cwd) 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch except subprocess.CalledProcessError: 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return None 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch finally: 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sys.stdout.flush() 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sys.stderr.flush() 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochdef SanitizeVersionTag(tag): 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch version_without_prefix = re.compile(r"^\d+\.\d+\.\d+(?:\.\d+)?$") 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch version_with_prefix = re.compile(r"^tags\/\d+\.\d+\.\d+(?:\.\d+)?$") 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if version_without_prefix.match(tag): 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return tag 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch elif version_with_prefix.match(tag): 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return tag[len("tags/"):] 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch else: 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return None 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochdef NormalizeVersionTags(version_tags): 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch normalized_version_tags = [] 223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Remove tags/ prefix because of packed refs. 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for current_tag in version_tags: 226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch version_tag = SanitizeVersionTag(current_tag) 227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if version_tag != None: 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch normalized_version_tags.append(version_tag) 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return normalized_version_tags 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Wrapper for side effects. 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SideEffectHandler(object): # pragma: no cover 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Call(self, fun, *args, **kwargs): 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return fun(*args, **kwargs) 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Command(self, cmd, args="", prefix="", pipe=True, cwd=None): 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Command(cmd, args, prefix, pipe, cwd=cwd) 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ReadLine(self): 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return sys.stdin.readline().strip() 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ReadURL(self, url, params=None): 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # pylint: disable=E1121 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch url_fh = urllib2.urlopen(url, params, 60) 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch try: 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return url_fh.read() 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch finally: 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch url_fh.close() 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ReadClusterFuzzAPI(self, api_key, **params): 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch params["api_key"] = api_key.strip() 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch params = urllib.urlencode(params) 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch headers = {"Content-type": "application/x-www-form-urlencoded"} 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch conn = httplib.HTTPSConnection("backend-dot-cluster-fuzz.appspot.com") 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch conn.request("POST", "/_api/", params, headers) 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch response = conn.getresponse() 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data = response.read() 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch try: 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return json.loads(data) 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch except: 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print data 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "ERROR: Could not read response. Is your key valid?" 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raise 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Sleep(self, seconds): 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time.sleep(seconds) 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def GetDate(self): 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return datetime.date.today().strftime("%Y-%m-%d") 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def GetUTCStamp(self): 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return time.mktime(datetime.datetime.utcnow().timetuple()) 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochDEFAULT_SIDE_EFFECT_HANDLER = SideEffectHandler() 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass NoRetryException(Exception): 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pass 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass VCInterface(object): 288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def InjectStep(self, step): 289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step=step 290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def Pull(self): 292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def Fetch(self): 295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def GetTags(self): 298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def GetBranches(self): 301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def MasterBranch(self): 304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def CandidateBranch(self): 307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def RemoteMasterBranch(self): 310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def RemoteCandidateBranch(self): 313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def RemoteBranch(self, name): 316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def CLLand(self): 319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def Tag(self, tag, remote, message): 322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier """Sets a tag for the current commit. 323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Assumptions: The commit already landed and the commit message is unique. 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier """ 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier raise NotImplementedError() 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass GitInterface(VCInterface): 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def Pull(self): 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step.GitPull() 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def Fetch(self): 334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step.Git("fetch") 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def GetTags(self): 337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return self.step.Git("tag").strip().splitlines() 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def GetBranches(self): 340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # Get relevant remote branches, e.g. "branch-heads/3.25". 341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier branches = filter( 342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier lambda s: re.match(r"^branch\-heads/\d+\.\d+$", s), 343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step.GitRemotes()) 344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # Remove 'branch-heads/' prefix. 345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return map(lambda s: s[13:], branches) 346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def MasterBranch(self): 348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return "master" 349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def CandidateBranch(self): 351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return "candidates" 352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def RemoteMasterBranch(self): 354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return "origin/master" 355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def RemoteCandidateBranch(self): 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return "origin/candidates" 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def RemoteBranch(self, name): 360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Assume that if someone "fully qualified" the ref, they know what they 361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # want. 362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if name.startswith('refs/'): 363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return name 364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if name in ["candidates", "master"]: 365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return "refs/remotes/origin/%s" % name 366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch try: 367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Check if branch is in heads. 368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if self.step.Git("show-ref refs/remotes/origin/%s" % name).strip(): 369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return "refs/remotes/origin/%s" % name 370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch except GitFailedException: 371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pass 372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch try: 373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Check if branch is in branch-heads. 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if self.step.Git("show-ref refs/remotes/branch-heads/%s" % name).strip(): 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return "refs/remotes/branch-heads/%s" % name 376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch except GitFailedException: 377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pass 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self.Die("Can't find remote of %s" % name) 379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def Tag(self, tag, remote, message): 381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # Wait for the commit to appear. Assumes unique commit message titles (this 382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # is the case for all automated merge and push commits - also no title is 383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # the prefix of another title). 384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier commit = None 3851b268ca467c924004286c97bac133db489cf43d0Ben Murdoch for wait_interval in [10, 30, 60, 60, 60, 60, 60]: 386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step.Git("fetch") 387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier commit = self.step.GitLog(n=1, format="%H", grep=message, branch=remote) 388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if commit: 389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break 390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("The commit has not replicated to git. Waiting for %s seconds." % 391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier wait_interval) 392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step._side_effect_handler.Sleep(wait_interval) 393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier else: 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step.Die("Couldn't determine commit for setting the tag. Maybe the " 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier "git updater is lagging behind?") 396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step.Git("tag %s %s" % (tag, commit)) 398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step.Git("push origin %s" % tag) 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def CLLand(self): 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.step.GitCLLand() 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Step(GitRecipesMixin): 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def __init__(self, text, number, config, state, options, handler): 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._text = text 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._number = number 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._config = config 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._state = state 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._options = options 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._side_effect_handler = handler 412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.vc = GitInterface() 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.vc.InjectStep(self) 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # The testing configuration might set a different default cwd. 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.default_cwd = (self._config.get("DEFAULT_CWD") or 417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier os.path.join(self._options.work_dir, "v8")) 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assert self._number >= 0 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assert self._config is not None 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assert self._state is not None 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assert self._side_effect_handler is not None 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def __getitem__(self, key): 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Convenience method to allow direct [] access on step classes for 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # manipulating the backed state dict. 427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return self._state.get(key) 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def __setitem__(self, key, value): 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Convenience method to allow direct [] access on step classes for 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # manipulating the backed state dict. 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._state[key] = value 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Config(self, key): 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return self._config[key] 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Run(self): 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Restore state. 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch state_file = "%s-state.json" % self._config["PERSISTFILE_BASENAME"] 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not self._state and os.path.exists(state_file): 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._state.update(json.loads(FileToText(state_file))) 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print ">>> Step %d: %s" % (self._number, self._text) 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch try: 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return self.RunStep() 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch finally: 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Persist state. 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TextToFile(json.dumps(self._state), state_file) 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def RunStep(self): # pragma: no cover 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raise NotImplementedError 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Retry(self, cb, retry_on=None, wait_plan=None): 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch """ Retry a function. 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Params: 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cb: The function to retry. 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch retry_on: A callback that takes the result of the function and returns 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch True if the function should be retried. A function throwing an 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch exception is always retried. 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wait_plan: A list of waiting delays between retries in seconds. The 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch maximum number of retries is len(wait_plan). 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch """ 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch retry_on = retry_on or (lambda x: False) 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wait_plan = list(wait_plan or []) 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wait_plan.reverse() 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while True: 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch got_exception = False 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch try: 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = cb() 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch except NoRetryException as e: 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raise e 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch except Exception as e: 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch got_exception = e 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if got_exception or retry_on(result): 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not wait_plan: # pragma: no cover 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raise Exception("Retried too often. Giving up. Reason: %s" % 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch str(got_exception)) 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wait_time = wait_plan.pop() 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Waiting for %f seconds." % wait_time 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._side_effect_handler.Sleep(wait_time) 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Retrying..." 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else: 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ReadLine(self, default=None): 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Don't prompt in forced mode. 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if self._options.force_readline_defaults and default is not None: 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "%s (forced)" % default 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return default 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else: 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return self._side_effect_handler.ReadLine() 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Command(self, name, args, cwd=None): 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmd = lambda: self._side_effect_handler.Command( 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, args, "", True, cwd=cwd or self.default_cwd) 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return self.Retry(cmd, None, [5]) 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Git(self, args="", prefix="", pipe=True, retry_on=None, cwd=None): 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmd = lambda: self._side_effect_handler.Command( 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "git", args, prefix, pipe, cwd=cwd or self.default_cwd) 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = self.Retry(cmd, retry_on, [5, 30]) 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if result is None: 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raise GitFailedException("'git %s' failed." % args) 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Editor(self, args): 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if self._options.requires_editor: 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return self._side_effect_handler.Command( 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.environ["EDITOR"], 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch args, 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pipe=False, 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cwd=self.default_cwd) 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ReadURL(self, url, params=None, retry_on=None, wait_plan=None): 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wait_plan = wait_plan or [3, 60, 600] 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmd = lambda: self._side_effect_handler.ReadURL(url, params) 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return self.Retry(cmd, retry_on, wait_plan) 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def GetDate(self): 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return self._side_effect_handler.GetDate() 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Die(self, msg=""): 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if msg != "": 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Error: %s" % msg 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Exiting" 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raise Exception(msg) 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def DieNoManualMode(self, msg=""): 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not self._options.manual: # pragma: no cover 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch msg = msg or "Only available in manual mode." 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.Die(msg) 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Confirm(self, msg): 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "%s [Y/n] " % msg, 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch answer = self.ReadLine(default="Y") 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return answer == "" or answer == "Y" or answer == "y" 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch def DeleteBranch(self, name, cwd=None): 539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for line in self.GitBranch(cwd=cwd).splitlines(): 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if re.match(r"\*?\s*%s$" % re.escape(name), line): 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch msg = "Branch %s exists, do you want to delete it?" % name 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if self.Confirm(msg): 543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self.GitDeleteBranch(name, cwd=cwd) 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Branch %s deleted." % name 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else: 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch msg = "Can't continue. Please delete branch %s and try again." % name 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.Die(msg) 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def InitialEnvironmentChecks(self, cwd): 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Cancel if this is not a git checkout. 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not os.path.exists(os.path.join(cwd, ".git")): # pragma: no cover 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.Die("This is not a git checkout, this script won't work for you.") 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Cancel if EDITOR is unset or not executable. 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (self._options.requires_editor and (not os.environ.get("EDITOR") or 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.Command( 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "which", os.environ["EDITOR"]) is None)): # pragma: no cover 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.Die("Please set your EDITOR environment variable, you'll need it.") 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def CommonPrepare(self): 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Check for a clean workdir. 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not self.GitIsWorkdirClean(): # pragma: no cover 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.Die("Workspace is not clean. Please commit or undo your changes.") 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Checkout master in case the script was left on a work branch. 566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self.GitCheckout('origin/master') 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Fetch unfetched revisions. 569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.vc.Fetch() 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def PrepareBranch(self): 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Delete the branch that will be created later if it exists already. 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.DeleteBranch(self._config["BRANCHNAME"]) 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def CommonCleanup(self): 576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self.GitCheckout('origin/master') 577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self.GitDeleteBranch(self._config["BRANCHNAME"]) 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Clean up all temporary files. 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for f in glob.iglob("%s*" % self._config["PERSISTFILE_BASENAME"]): 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if os.path.isfile(f): 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.remove(f) 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if os.path.isdir(f): 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shutil.rmtree(f) 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ReadAndPersistVersion(self, prefix=""): 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ReadAndPersist(var_name, def_name): 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match = re.match(r"^#define %s\s+(\d*)" % def_name, line) 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if match: 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value = match.group(1) 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self["%s%s" % (prefix, var_name)] = value 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for line in LinesInFile(os.path.join(self.default_cwd, VERSION_FILE)): 593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (var_name, def_name) in [("major", "V8_MAJOR_VERSION"), 594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ("minor", "V8_MINOR_VERSION"), 595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ("build", "V8_BUILD_NUMBER"), 596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ("patch", "V8_PATCH_LEVEL")]: 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ReadAndPersist(var_name, def_name) 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def WaitForLGTM(self): 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print ("Please wait for an LGTM, then type \"LGTM<Return>\" to commit " 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "your change. (If you need to iterate on the patch or double check " 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "that it's sane, do so in another shell, but remember to not " 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "change the headline of the uploaded CL.") 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch answer = "" 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while answer != "LGTM": 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "> ", 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch answer = self.ReadLine(None if self._options.wait_for_lgtm else "LGTM") 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if answer != "LGTM": 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "That was not 'LGTM'." 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def WaitForResolvingConflicts(self, patch_file): 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print("Applying the patch \"%s\" failed. Either type \"ABORT<Return>\", " 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "or resolve the conflicts, stage *all* touched files with " 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "'git add', and type \"RESOLVED<Return>\"") 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.DieNoManualMode() 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch answer = "" 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while answer != "RESOLVED": 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if answer == "ABORT": 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.Die("Applying the patch failed.") 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if answer != "": 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "That was not 'RESOLVED' or 'ABORT'." 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "> ", 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch answer = self.ReadLine() 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Takes a file containing the patch to apply as first argument. 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ApplyPatch(self, patch_file, revert=False): 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch try: 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.GitApplyPatch(patch_file, revert) 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch except GitFailedException: 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.WaitForResolvingConflicts(patch_file) 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch def GetVersionTag(self, revision): 633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch tag = self.Git("describe --tags %s" % revision).strip() 634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return SanitizeVersionTag(tag) 635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch def GetRecentReleases(self, max_age): 637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Make sure tags are fetched. 638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self.Git("fetch origin +refs/tags/*:refs/tags/*") 639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Current timestamp. 641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch time_now = int(self._side_effect_handler.GetUTCStamp()) 642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # List every tag from a given period. 644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch revisions = self.Git("rev-list --max-age=%d --tags" % 645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int(time_now - max_age)).strip() 646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Filter out revisions who's tag is off by one or more commits. 648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return filter(lambda r: self.GetVersionTag(r), revisions.splitlines()) 649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch def GetLatestVersion(self): 651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Use cached version if available. 652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if self["latest_version"]: 653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return self["latest_version"] 654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Make sure tags are fetched. 656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self.Git("fetch origin +refs/tags/*:refs/tags/*") 657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch all_tags = self.vc.GetTags() 659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch only_version_tags = NormalizeVersionTags(all_tags) 660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch version = sorted(only_version_tags, 662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch key=SortingKey, reverse=True)[0] 663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self["latest_version"] = version 664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return version 665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch def GetLatestRelease(self): 667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch """The latest release is the git hash of the latest tagged version. 668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch This revision should be rolled into chromium. 670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch """ 671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch latest_version = self.GetLatestVersion() 672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # The latest release. 674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch latest_hash = self.GitLog(n=1, format="%H", branch=latest_version) 675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assert latest_hash 676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return latest_hash 677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch def GetLatestReleaseBase(self, version=None): 679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch """The latest release base is the latest revision that is covered in the 680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch last change log file. It doesn't include cherry-picked patches. 681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch """ 682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch latest_version = version or self.GetLatestVersion() 683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Strip patch level if it exists. 685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch latest_version = ".".join(latest_version.split(".")[:3]) 686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # The latest release base. 688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch latest_hash = self.GitLog(n=1, format="%H", branch=latest_version) 689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assert latest_hash 690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch title = self.GitLog(n=1, format="%s", git_hash=latest_hash) 692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch match = PUSH_MSG_GIT_RE.match(title) 693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if match: 694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Legacy: In the old process there's one level of indirection. The 695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # version is on the candidates branch and points to the real release 696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # base on master through the commit message. 697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return match.group("git_rev") 698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch match = PUSH_MSG_NEW_RE.match(title) 699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if match: 700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # This is a new-style v8 version branched from master. The commit 701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # "latest_hash" is the version-file change. Its parent is the release 702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # base on master. 703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return self.GitLog(n=1, format="%H", git_hash="%s^" % latest_hash) 704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self.Die("Unknown latest release: %s" % latest_hash) 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ArrayToVersion(self, prefix): 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ".".join([self[prefix + "major"], 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self[prefix + "minor"], 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self[prefix + "build"], 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self[prefix + "patch"]]) 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch def StoreVersion(self, version, prefix): 714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch version_parts = version.split(".") 715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if len(version_parts) == 3: 716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch version_parts.append("0") 717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch major, minor, build, patch = version_parts 718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self[prefix + "major"] = major 719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self[prefix + "minor"] = minor 720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self[prefix + "build"] = build 721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self[prefix + "patch"] = patch 722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def SetVersion(self, version_file, prefix): 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch output = "" 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for line in FileToText(version_file).splitlines(): 726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if line.startswith("#define V8_MAJOR_VERSION"): 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch line = re.sub("\d+$", self[prefix + "major"], line) 728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch elif line.startswith("#define V8_MINOR_VERSION"): 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch line = re.sub("\d+$", self[prefix + "minor"], line) 730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch elif line.startswith("#define V8_BUILD_NUMBER"): 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch line = re.sub("\d+$", self[prefix + "build"], line) 732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch elif line.startswith("#define V8_PATCH_LEVEL"): 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch line = re.sub("\d+$", self[prefix + "patch"], line) 734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch elif (self[prefix + "candidate"] and 735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch line.startswith("#define V8_IS_CANDIDATE_VERSION")): 736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch line = re.sub("\d+$", self[prefix + "candidate"], line) 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch output += "%s\n" % line 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TextToFile(output, version_file) 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass BootstrapStep(Step): 742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MESSAGE = "Bootstrapping checkout and state." 743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def RunStep(self): 745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch # Reserve state entry for json output. 746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch self['json_output'] = {} 747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if os.path.realpath(self.default_cwd) == os.path.realpath(V8_BASE): 749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.Die("Can't use v8 checkout with calling script as work checkout.") 750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # Directory containing the working v8 checkout. 751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if not os.path.exists(self._options.work_dir): 752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier os.makedirs(self._options.work_dir) 753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if not os.path.exists(self.default_cwd): 754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.Command("fetch", "v8", cwd=self._options.work_dir) 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass UploadStep(Step): 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MESSAGE = "Upload for code review." 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def RunStep(self): 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if self._options.reviewer: 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Using account %s for review." % self._options.reviewer 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reviewer = self._options.reviewer 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else: 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Please enter the email address of a V8 reviewer for your patch: ", 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.DieNoManualMode("A reviewer must be specified in forced mode.") 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reviewer = self.ReadLine() 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self.GitUpload(reviewer, self._options.author, self._options.force_upload, 769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bypass_hooks=self._options.bypass_upload_hooks, 770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier cc=self._options.cc) 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef MakeStep(step_class=Step, number=0, state=None, config=None, 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options=None, side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Allow to pass in empty dictionaries. 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch state = state if state is not None else {} 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch config = config if config is not None else {} 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch try: 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch message = step_class.MESSAGE 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch except AttributeError: 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch message = step_class.__name__ 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return step_class(message, number=number, config=config, 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch state=state, options=options, 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handler=side_effect_handler) 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ScriptsBase(object): 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def __init__(self, 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch config=None, 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER, 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch state=None): 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._config = config or self._Config() 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._side_effect_handler = side_effect_handler 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._state = state if state is not None else {} 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def _Description(self): 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return None 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def _PrepareOptions(self, parser): 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pass 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def _ProcessOptions(self, options): 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return True 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def _Steps(self): # pragma: no cover 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raise Exception("Not implemented.") 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def _Config(self): 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return {} 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def MakeOptions(self, args=None): 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parser = argparse.ArgumentParser(description=self._Description()) 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parser.add_argument("-a", "--author", default="", 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch help="The author email used for rietveld.") 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parser.add_argument("--dry-run", default=False, action="store_true", 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch help="Perform only read-only actions.") 819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch parser.add_argument("--json-output", 820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch help="File to write results summary to.") 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parser.add_argument("-r", "--reviewer", default="", 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch help="The account name to be used for reviews.") 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parser.add_argument("-s", "--step", 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch help="Specify the step where to start work. Default: 0.", 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default=0, type=int) 826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier parser.add_argument("--work-dir", 827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier help=("Location where to bootstrap a working v8 " 828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier "checkout.")) 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self._PrepareOptions(parser) 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if args is None: # pragma: no cover 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = parser.parse_args() 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else: 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = parser.parse_args(args) 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Process common options. 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if options.step < 0: # pragma: no cover 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print "Bad step number %d" % options.step 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parser.print_help() 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return None 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Defaults for options, common to all scripts. 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options.manual = getattr(options, "manual", True) 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options.force = getattr(options, "force", False) 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options.bypass_upload_hooks = False 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Derived options. 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options.requires_editor = not options.force 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options.wait_for_lgtm = not options.force 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options.force_readline_defaults = not options.manual 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options.force_upload = not options.manual 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch # Process script specific options. 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not self._ProcessOptions(options): 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parser.print_help() 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return None 857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if not options.work_dir: 859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier options.work_dir = "/tmp/v8-release-scripts-work-dir" 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def RunSteps(self, step_classes, args=None): 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = self.MakeOptions(args) 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not options: 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch state_file = "%s-state.json" % self._config["PERSISTFILE_BASENAME"] 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if options.step == 0 and os.path.exists(state_file): 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.remove(state_file) 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch steps = [] 872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (number, step_class) in enumerate([BootstrapStep] + step_classes): 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch steps.append(MakeStep(step_class, number, self._state, self._config, 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, self._side_effect_handler)) 875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch try: 877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for step in steps[options.step:]: 878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if step.Run(): 879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return 0 880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch finally: 881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if options.json_output: 882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch with open(options.json_output, "w") as f: 883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch json.dump(self._state['json_output'], f) 884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def Run(self, args=None): 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return self.RunSteps(self._Steps(), args) 889