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

Side by Side Diff: tools/git_utils.py

Issue 141483011: add_codereview_message script to append messages to a CL (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: linting Created 6 years, 10 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
OLDNEW
(Empty)
1 # Copyright 2014 Google Inc.
2 #
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Module to host the ChangeGitBranch class and test_git_executable function.
7 """
8
9 import os
10 import subprocess
11 from misc_utils import VerboseSubprocess
12
13
14 class ChangeGitBranch(object):
15 """Class to manage git branches.
16
17 This class allows one to create a new branch in a repository based
18 off of a given commit, and restore the original tree state.
19
20 Assumes current working directory is a git repository.
21
22 Example:
23 with ChangeGitBranch('git', 'newBranch'):
24 edit_files(files)
25 git_add(files)
26 git_commit()
27 git_format_patch('HEAD~')
28 # At this point, the repository is returned to its original
29 # state.
30
31 Constructor Args:
32 git: (string) git executable.
33 brach_name: (string) if not None, the name of the branch to
borenet 2014/01/30 14:36:35 "branch_name". Also, please document that this ex
hal.canary 2014/01/30 20:11:02 Done.
34 use. If None, then use a temporary branch that will be
35 deleted.
36 start_point: (string) if not None, the name of the branch or
37 commit to branch from. If None, then use origin/master
borenet 2014/01/30 14:36:35 I think upstream_branch or tracking_branch are bet
hal.canary 2014/01/30 20:11:02 Done.
38 verbose: (boolean) if true, makes debugging easier.
39 delete_branch: (boolean) delete the branch afterwards
40
41 Raises:
42 OSError: failed to execute git.
43 subprocess.CalledProcessError: git returned unexpected status.
44 Exception: if the given branch name exists, or if the repository
45 isn't clean on exit
46 """
47 # pylint: disable=I0011,R0903,R0902
48
49 def __init__(self,
50 git,
51 branch_name,
52 start_point=None,
53 verbose=False,
54 delete_branch=False):
55 # pylint: disable=I0011,R0913
56 self._branch_name = branch_name
57 if start_point:
58 self._start_point = start_point
59 else:
60 self._start_point = 'origin/master'
61 self._git = git
62 self._stash = None
63 self._original_branch = None
64 self._vsp = VerboseSubprocess(verbose)
65 self._delete_branch = delete_branch
66
67 def _has_git_diff(self):
68 """Return true iff repository has uncommited changes."""
69 return bool(self._vsp.call([self._git, 'diff', '--quiet', 'HEAD']))
70
71 def _branch_exists(self, branch):
72 """Return true iff branch exists."""
73 return 0 == self._vsp.call([self._git, 'show-ref', '--quiet', branch])
74
75 def __enter__(self):
76 git, vsp = self._git, self._vsp
77
78 while self._branch_exists(self._branch_name):
79 self._branch_name += '_'
80
81 self._stash = self._has_git_diff()
82 if self._stash:
83 vsp.check_call([git, 'stash', 'save'])
84 self._original_branch = git_branch_name(git, vsp.verbose)
85 vsp.check_call(
86 [git, 'checkout', '-q', '-b',
87 self._branch_name, self._start_point])
88
89 def __exit__(self, etype, value, traceback):
90 # pylint: disable=I0011,R0912
91 git, vsp = self._git, self._vsp
92
93 if self._has_git_diff():
94 status = vsp.check_output([git, 'status', '-s'])
95 raise Exception('git checkout not clean:\n%s' % status)
96 vsp.check_call([git, 'checkout', '-q', self._original_branch])
97 if self._stash:
98 vsp.check_call([git, 'stash', 'pop'])
99 if self._delete_branch:
100 assert self._original_branch != self._branch_name
101 vsp.check_call([git, 'branch', '-D', self._branch_name])
102
103
104 def git_branch_name(git, verbose):
105 """Return a description of the current branch.
106
107 Args:
108 git: (string) git executable.
109 verbose: (boolean) makes debugging easier
110
111 Returns:
112 A string suitable for passing to `git checkout` later.
113 """
114 vsp = VerboseSubprocess(verbose)
115 try:
116 full_branch = vsp.strip_output([git, 'symbolic-ref', 'HEAD'])
117 return full_branch.split('/')[-1]
118 except (subprocess.CalledProcessError,):
119 # "fatal: ref HEAD is not a symbolic ref"
120 return vsp.strip_output([git, 'rev-parse', 'HEAD'])
121
122
123 def test_git_executable(git_executable):
124 """Test the git executable.
125
126 Args:
127 git_executable: git executable path.
128 Returns:
129 True if test is successful.
130 """
131 with open(os.devnull, 'w') as devnull:
132 try:
133 subprocess.call([git_executable, '--version'], stdout=devnull)
134 except (OSError,):
135 return False
136 return True
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698