1#!/usr/bin/env python
2#
3# Copyright 2019 Google Inc.
4#
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8
9from __future__ import print_function
10import os
11import re
12import subprocess
13import sys
14
15from infra import git
16from infra import go
17
18_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__))
19_REPO_ROOT = os.path.realpath(os.path.join(_TOOLS_DIR, os.pardir))
20_INFRA_BOTS = os.path.join(_REPO_ROOT, 'infra', 'bots')
21sys.path.insert(0, _INFRA_BOTS)
22import git_utils
23
24
25REFS_HEADS_PREFIX = 'refs/heads/'
26CHROME_REF_PREFIX = REFS_HEADS_PREFIX + 'chrome/m'
27SK_MILESTONE_H = os.path.join('include', 'core', 'SkMilestone.h')
28SK_MILESTONE_TMPL = r'#define SK_MILESTONE %s'
29SK_MILESTONE_RE = SK_MILESTONE_TMPL % r'(\d+)'
30SKIA_REPO = 'https://skia.googlesource.com/skia.git'
31SUPPORTED_CHROME_BRANCHES = 3
32UPDATE_MILESTONE_COMMIT_MSG = '''Update Skia milestone to %d'''
33
34
35def get_current_milestone():
36  '''Read SkMilestone.h and parse out the current milestone.'''
37  sk_milestone = os.path.join(_REPO_ROOT, SK_MILESTONE_H)
38  with open(sk_milestone, 'r') as f:
39    contents = f.read()
40  for line in contents.splitlines():
41    m = re.match(SK_MILESTONE_RE, line)
42    if m:
43      return int(m.groups()[0])
44  print >> sys.stderr, (
45      'Failed to parse %s; has the format changed?' % SK_MILESTONE_H)
46  sys.exit(1)
47
48
49def create_new_branch(new_branch, branch_at):
50  '''Create a temporary checkout of the repo, create the new branch and push.'''
51  b = new_branch[len(REFS_HEADS_PREFIX):]
52  with git_utils.NewGitCheckout(SKIA_REPO, local=_REPO_ROOT):
53    git.git('checkout', '-b', b)
54    git.git('reset', '--hard', branch_at)
55    git.git('push', '--set-upstream', 'origin', b)
56
57
58def update_milestone(m):
59  '''Update SkMilestone.h to match the given milestone number.'''
60  with git_utils.NewGitCheckout(SKIA_REPO, local=_REPO_ROOT):
61    with git_utils.GitBranch(
62        'update_milestone', UPDATE_MILESTONE_COMMIT_MSG % m):
63      with open(SK_MILESTONE_H, 'r+') as f:
64        contents = re.sub(
65            SK_MILESTONE_RE, SK_MILESTONE_TMPL % str(m), f.read(), flags=re.M)
66        f.seek(0)
67        f.write(contents)
68        f.truncate()
69      git.git('diff')
70
71
72def update_infra_config(old_branch, new_branch):
73  '''Create a CL to add infra support for the new branch and remove the old.'''
74  owner = git.git('config', 'user.email').rstrip()
75  if not owner:
76    print >> sys.stderr, ('No configured git user; please run '
77                          '"git config user.email <your email>".')
78    sys.exit(1)
79  go.mod_download()
80  go.install(go.INFRA_GO+'/go/supported_branches/cmd/new-branch')
81  subprocess.check_call(['new-branch',
82                         '--branch', new_branch[len(REFS_HEADS_PREFIX):],
83                         '--delete', old_branch[len(REFS_HEADS_PREFIX):],
84                         '--owner', owner,
85                         '--exclude-trybots=chromium.*',
86                         '--exclude-trybots=.*Android_Framework.*',
87                         '--exclude-trybots=.*G3_Framework.*',
88                         '--exclude-trybots=.*CanvasKit.*',
89                         '--exclude-trybots=.*PathKit.*',
90                         '--submit'])
91
92
93def main():
94  if len(sys.argv) != 2 or '--help' in sys.argv or '-h' in sys.argv:
95    print >> sys.stderr, 'Usage: %s <commit hash for branch>' % sys.argv[0]
96    sys.exit(1)
97  go.check()
98  branch_at = sys.argv[1]
99  m = get_current_milestone()
100  new_branch = '%s%d' % (CHROME_REF_PREFIX, m)
101  old_branch = '%s%d' % (CHROME_REF_PREFIX, m-SUPPORTED_CHROME_BRANCHES)
102  print('Creating branch %s and removing support (eg. CQ) for %s' % (
103      new_branch, old_branch))
104  create_new_branch(new_branch, branch_at)
105  update_milestone(m+1)
106  update_infra_config(old_branch, new_branch)
107
108
109if __name__ == '__main__':
110  main()
111