• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright 2020 The ChromiumOS Authors
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
9
10import collections
11import os
12import re
13import subprocess
14import tempfile
15
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
49    subprocess.check_output(["git", "-C", repo, "reset", "HEAD", "--hard"])
50
51    subprocess.check_output(["repo", "start", branch], cwd=repo)
52
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
68    subprocess.check_output(["git", "-C", repo, "checkout", "cros/main"])
69
70    subprocess.check_output(["git", "-C", repo, "reset", "HEAD", "--hard"])
71
72    subprocess.check_output(["git", "-C", repo, "branch", "-D", branch])
73
74
75def UploadChanges(repo, branch, commit_messages, reviewers=None, cc=None):
76    """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.
83      reviewers: A list of reviewers to add to the CL.
84      cc: A list of contributors to CC about the CL.
85
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
103        subprocess.check_output(["git", "commit", "-F", f.name], cwd=repo)
104
105    # Upload the changes for review.
106    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
118    out = subprocess.check_output(
119        git_args,
120        stderr=subprocess.STDOUT,
121        cwd=repo,
122        encoding="utf-8",
123    )
124
125    print(out)
126
127    found_url = re.search(
128        r"https://chromium-review.googlesource.com/c/"
129        r"chromiumos/overlays/chromiumos-overlay/\+/([0-9]+)",
130        out.rstrip(),
131    )
132
133    if not found_url:
134        raise ValueError("Failed to find change list URL.")
135
136    return CommitContents(
137        url=found_url.group(0), cl_number=int(found_url.group(1))
138    )
139