Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: py/utils/git_utils.py

Issue 346743008: Update common.py.utils to be used in Skia repo (Closed) Base URL: https://skia.googlesource.com/common.git@master
Patch Set: comment Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « py/utils/find_depot_tools.py ('k') | py/utils/misc.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2014 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """This module contains functions for using git.""" 6 """This module contains functions for using git."""
7 7
8 8
9 import os 9 import re
10 import shell_utils 10 import shell_utils
11 11
12 12
13 GIT = 'git.bat' if os.name == 'nt' else 'git' 13 def _FindGit():
14 """Find the git executable.
15
16 Returns:
17 A string suitable for passing to subprocess functions, or None.
18 """
19 def test_git_executable(git):
20 """Test the git executable.
21
22 Args:
23 git: git executable path.
24 Returns:
25 True if test is successful.
26 """
27 try:
28 shell_utils.run([git, '--version'], echo=False)
29 return True
30 except (OSError,):
31 return False
32
33 for git in ('git', 'git.exe', 'git.bat'):
34 if test_git_executable(git):
35 return git
36 return None
37
38
39 GIT = _FindGit()
14 40
15 41
16 def Add(addition): 42 def Add(addition):
17 """Run 'git add <addition>'""" 43 """Run 'git add <addition>'"""
18 shell_utils.run([GIT, 'add', addition]) 44 shell_utils.run([GIT, 'add', addition])
19 45
46
20 def AIsAncestorOfB(a, b): 47 def AIsAncestorOfB(a, b):
21 """Return true if a is an ancestor of b.""" 48 """Return true if a is an ancestor of b."""
22 return shell_utils.run([GIT, 'merge-base', a, b]).rstrip() == FullHash(a) 49 return shell_utils.run([GIT, 'merge-base', a, b]).rstrip() == FullHash(a)
23 50
51
24 def FullHash(commit): 52 def FullHash(commit):
25 """Return full hash of specified commit.""" 53 """Return full hash of specified commit."""
26 return shell_utils.run([GIT, 'rev-parse', '--verify', commit]).rstrip() 54 return shell_utils.run([GIT, 'rev-parse', '--verify', commit]).rstrip()
27 55
56
28 def IsMerge(commit): 57 def IsMerge(commit):
29 """Return True if the commit is a merge, False otherwise.""" 58 """Return True if the commit is a merge, False otherwise."""
30 rev_parse = shell_utils.run([GIT, 'rev-parse', commit, '--max-count=1', 59 rev_parse = shell_utils.run([GIT, 'rev-parse', commit, '--max-count=1',
31 '--no-merges']) 60 '--no-merges'])
32 last_non_merge = rev_parse.split('\n')[0] 61 last_non_merge = rev_parse.split('\n')[0]
33 # Get full hash since that is what was returned by rev-parse. 62 # Get full hash since that is what was returned by rev-parse.
34 return FullHash(commit) != last_non_merge 63 return FullHash(commit) != last_non_merge
35 64
65
36 def MergeAbort(): 66 def MergeAbort():
37 """Abort in process merge.""" 67 """Abort in process merge."""
38 shell_utils.run([GIT, 'merge', '--abort']) 68 shell_utils.run([GIT, 'merge', '--abort'])
39 69
70
40 def ShortHash(commit): 71 def ShortHash(commit):
41 """Return short hash of the specified commit.""" 72 """Return short hash of the specified commit."""
42 return shell_utils.run([GIT, 'show', commit, '--format=%h', '-s']).rstrip() 73 return shell_utils.run([GIT, 'show', commit, '--format=%h', '-s']).rstrip()
43 74
75
76 def Fetch(remote=None):
77 """Run "git fetch". """
78 cmd = [GIT, 'fetch']
79 if remote:
80 cmd.append(remote)
81 shell_utils.run(cmd)
82
83
44 def GetRemoteMasterHash(git_url): 84 def GetRemoteMasterHash(git_url):
45 return shell_utils.run([GIT, 'ls-remote', git_url, '--verify', 85 return shell_utils.run([GIT, 'ls-remote', git_url, '--verify',
46 'refs/heads/master']) 86 'refs/heads/master']).rstrip()
87
88
89 def GetCurrentBranch():
90 return shell_utils.run([GIT, 'rev-parse', '--abbrev-ref', 'HEAD']).rstrip()
91
92
93 class GitBranch(object):
94 """Class to manage git branches.
95
96 This class allows one to create a new branch in a repository to make changes,
97 then it commits the changes, switches to master branch, and deletes the
98 created temporary branch upon exit.
99 """
100 def __init__(self, branch_name, commit_msg, upload=True, commit_queue=False,
101 delete_when_finished=True):
102 self._branch_name = branch_name
103 self._commit_msg = commit_msg
104 self._upload = upload
105 self._commit_queue = commit_queue
106 self._patch_set = 0
107 self._delete_when_finished = delete_when_finished
108
109 def __enter__(self):
110 shell_utils.run([GIT, 'reset', '--hard', 'HEAD'])
111 shell_utils.run([GIT, 'checkout', 'master'])
112 if self._branch_name in shell_utils.run([GIT, 'branch']):
113 shell_utils.run([GIT, 'branch', '-D', self._branch_name])
114 shell_utils.run([GIT, 'checkout', '-b', self._branch_name,
115 '-t', 'origin/master'])
116 return self
117
118 def commit_and_upload(self, use_commit_queue=False):
119 """Commit all changes and upload a CL, returning the issue URL."""
120 try:
121 shell_utils.run([GIT, 'commit', '-a', '-m', self._commit_msg])
122 except shell_utils.CommandFailedException as e:
123 if not 'nothing to commit' in e.output:
124 raise
125 upload_cmd = [GIT, 'cl', 'upload', '-f', '--bypass-hooks',
126 '--bypass-watchlists']
127 self._patch_set += 1
128 if self._patch_set > 1:
129 upload_cmd.extend(['-t', 'Patch set %d' % self._patch_set])
130 if use_commit_queue:
131 upload_cmd.append('--use-commit-queue')
132 shell_utils.run(upload_cmd)
133 output = shell_utils.run([GIT, 'cl', 'issue']).rstrip()
134 return re.match('^Issue number: (?P<issue>\d+) \((?P<issue_url>.+)\)$',
135 output).group('issue_url')
136
137 def __exit__(self, exc_type, _value, _traceback):
138 if self._upload:
139 # Only upload if no error occurred.
140 try:
141 if exc_type is None:
142 self.commit_and_upload(use_commit_queue=self._commit_queue)
143 finally:
144 shell_utils.run([GIT, 'checkout', 'master'])
145 if self._delete_when_finished:
146 shell_utils.run([GIT, 'branch', '-D', self._branch_name])
OLDNEW
« no previous file with comments | « py/utils/find_depot_tools.py ('k') | py/utils/misc.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698