blob: 22c7002aea51bfd0de82f221ee7ab3f08b564bbf [file] [log] [blame]
Jian Caic16daa12020-04-15 17:53:41 -07001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright 2020 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Git helper functions."""
8
9from __future__ import print_function
10
11import collections
12import os
13import re
14import subprocess
15import tempfile
16
17CommitContents = collections.namedtuple('CommitContents', ['url', 'cl_number'])
18
19
20def InChroot():
21 """Returns True if currently in the chroot."""
22 return 'CROS_WORKON_SRCROOT' in os.environ
23
24
25def VerifyOutsideChroot():
26 """Checks whether the script invoked was executed in the chroot.
27
28 Raises:
29 AssertionError: The script was run inside the chroot.
30 """
31
32 assert not InChroot(), 'Script should be run outside the chroot.'
33
34
35def CreateBranch(repo, branch):
36 """Creates a branch in the given repo.
37
38 Args:
39 repo: The absolute path to the repo.
40 branch: The name of the branch to create.
41
42 Raises:
43 ValueError: Failed to create a repo in that directory.
44 """
45
46 if not os.path.isdir(repo):
47 raise ValueError('Invalid directory path provided: %s' % repo)
48
Jian Caifbefdc42020-04-30 15:29:03 -070049 subprocess.check_output(['git', '-C', repo, 'reset', 'HEAD', '--hard'])
Jian Caic16daa12020-04-15 17:53:41 -070050
Jian Caifbefdc42020-04-30 15:29:03 -070051 subprocess.check_output(['repo', 'start', branch], cwd=repo)
Jian Caic16daa12020-04-15 17:53:41 -070052
53
54def DeleteBranch(repo, branch):
55 """Deletes a branch in the given repo.
56
57 Args:
58 repo: The absolute path of the repo.
59 branch: The name of the branch to delete.
60
61 Raises:
62 ValueError: Failed to delete the repo in that directory.
63 """
64
65 if not os.path.isdir(repo):
66 raise ValueError('Invalid directory path provided: %s' % repo)
67
Manoj Gupta22577142021-01-21 13:16:43 -080068 subprocess.check_output(['git', '-C', repo, 'checkout', 'cros/main'])
Jian Caic16daa12020-04-15 17:53:41 -070069
Jian Caifbefdc42020-04-30 15:29:03 -070070 subprocess.check_output(['git', '-C', repo, 'reset', 'HEAD', '--hard'])
Jian Caic16daa12020-04-15 17:53:41 -070071
Jian Caifbefdc42020-04-30 15:29:03 -070072 subprocess.check_output(['git', '-C', repo, 'branch', '-D', branch])
Jian Caic16daa12020-04-15 17:53:41 -070073
74
Christopher Di Bellaf5dbbbe2021-02-05 23:35:53 +000075def UploadChanges(repo, branch, commit_messages, reviewers=None, cc=None):
Jian Caic16daa12020-04-15 17:53:41 -070076 """Uploads the changes in the specifed branch of the given repo for review.
77
78 Args:
79 repo: The absolute path to the repo where changes were made.
80 branch: The name of the branch to upload.
81 commit_messages: A string of commit message(s) (i.e. '[message]'
82 of the changes made.
Christopher Di Bellaf5dbbbe2021-02-05 23:35:53 +000083 reviewers: A list of reviewers to add to the CL.
84 cc: A list of contributors to CC about the CL.
Jian Caic16daa12020-04-15 17:53:41 -070085
86 Returns:
87 A nametuple that has two (key, value) pairs, where the first pair is the
88 Gerrit commit URL and the second pair is the change list number.
89
90 Raises:
91 ValueError: Failed to create a commit or failed to upload the
92 changes for review.
93 """
94
95 if not os.path.isdir(repo):
96 raise ValueError('Invalid path provided: %s' % repo)
97
98 # Create a git commit.
99 with tempfile.NamedTemporaryFile(mode='w+t') as f:
100 f.write('\n'.join(commit_messages))
101 f.flush()
102
Jian Caifbefdc42020-04-30 15:29:03 -0700103 subprocess.check_output(['git', 'commit', '-F', f.name], cwd=repo)
Jian Caic16daa12020-04-15 17:53:41 -0700104
105 # Upload the changes for review.
Christopher Di Bellaf5dbbbe2021-02-05 23:35:53 +0000106 git_args = [
107 'repo',
108 'upload',
109 '--yes',
110 f'--reviewers={",".join(reviewers)}' if reviewers else '--ne',
111 '--no-verify',
112 f'--br={branch}',
113 ]
114
115 if cc:
116 git_args.append(f'--cc={",".join(cc)}')
117
Jian Caifbefdc42020-04-30 15:29:03 -0700118 out = subprocess.check_output(
Christopher Di Bellaf5dbbbe2021-02-05 23:35:53 +0000119 git_args,
Jian Caic16daa12020-04-15 17:53:41 -0700120 stderr=subprocess.STDOUT,
Jian Caifbefdc42020-04-30 15:29:03 -0700121 cwd=repo,
Christopher Di Bellaf5dbbbe2021-02-05 23:35:53 +0000122 encoding='utf-8',
123 )
Jian Caic16daa12020-04-15 17:53:41 -0700124
Jian Caifbefdc42020-04-30 15:29:03 -0700125 print(out)
Jian Caic16daa12020-04-15 17:53:41 -0700126
127 found_url = re.search(
128 r'https://chromium-review.googlesource.com/c/'
129 r'chromiumos/overlays/chromiumos-overlay/\+/([0-9]+)', out.rstrip())
130
131 if not found_url:
132 raise ValueError('Failed to find change list URL.')
133
134 return CommitContents(
135 url=found_url.group(0), cl_number=int(found_url.group(1)))