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

Side by Side Diff: git_map_branches.py

Issue 576423002: Fix map-branches issues and add coloring for 'branch-heads', (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: fix url bug Created 6 years, 3 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 | « no previous file | man/html/git-map-branches.html » ('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 2014 The Chromium Authors. All rights reserved. 2 # Copyright 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 """Provides a short mapping of all the branches in your local repo, organized 6 """Provides a short mapping of all the branches in your local repo, organized
7 by their upstream ('tracking branch') layout. 7 by their upstream ('tracking branch') layout.
8 8
9 Example: 9 Example:
10 origin/master 10 origin/master
11 cool_feature 11 cool_feature
12 dependent_feature 12 dependent_feature
13 other_dependent_feature 13 other_dependent_feature
14 other_feature 14 other_feature
15 15
16 Branches are colorized as follows: 16 Branches are colorized as follows:
17 * Red - a remote branch (usually the root of all local branches) 17 * Red - a remote branch (usually the root of all local branches)
18 * Cyan - a local branch which is the same as HEAD 18 * Cyan - a local branch which is the same as HEAD
19 * Note that multiple branches may be Cyan, if they are all on the same 19 * Note that multiple branches may be Cyan, if they are all on the same
20 commit, and you have that commit checked out. 20 commit, and you have that commit checked out.
21 * Green - a local branch 21 * Green - a local branch
22 * Blue - a 'branch-heads' branch
22 * Magenta - a tag 23 * Magenta - a tag
23 * Magenta '{NO UPSTREAM}' - If you have local branches which do not track any 24 * Magenta '{NO UPSTREAM}' - If you have local branches which do not track any
24 upstream, then you will see this. 25 upstream, then you will see this.
25 """ 26 """
26 27
27 import argparse 28 import argparse
28 import collections 29 import collections
29 import sys 30 import sys
31 import subprocess2
30 32
31 from third_party import colorama 33 from third_party import colorama
32 from third_party.colorama import Fore, Style 34 from third_party.colorama import Fore, Style
33 35
34 from git_common import current_branch, upstream, tags, get_branches_info 36 from git_common import current_branch, upstream, tags, get_branches_info
35 from git_common import get_git_version, MIN_UPSTREAM_TRACK_GIT_VERSION, hash_one 37 from git_common import get_git_version, MIN_UPSTREAM_TRACK_GIT_VERSION, hash_one
36 38
37 DEFAULT_SEPARATOR = ' ' * 4 39 DEFAULT_SEPARATOR = ' ' * 4
38 40
39 41
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 self.__branches_info = get_branches_info( 121 self.__branches_info = get_branches_info(
120 include_tracking_status=self.verbosity >= 1) 122 include_tracking_status=self.verbosity >= 1)
121 roots = set() 123 roots = set()
122 124
123 # A map of parents to a list of their children. 125 # A map of parents to a list of their children.
124 for branch, branch_info in self.__branches_info.iteritems(): 126 for branch, branch_info in self.__branches_info.iteritems():
125 if not branch_info: 127 if not branch_info:
126 continue 128 continue
127 129
128 parent = branch_info.upstream 130 parent = branch_info.upstream
129 if parent and not self.__branches_info[parent]: 131 if not self.__branches_info[parent]:
130 branch_upstream = upstream(branch) 132 branch_upstream = upstream(branch)
131 # If git can't find the upstream, mark the upstream as gone. 133 # If git can't find the upstream, mark the upstream as gone.
132 if branch_upstream: 134 if branch_upstream:
133 parent = branch_upstream 135 parent = branch_upstream
134 else: 136 else:
135 self.__gone_branches.add(parent) 137 self.__gone_branches.add(parent)
136 # A parent that isn't in the branches info is a root. 138 # A parent that isn't in the branches info is a root.
137 roots.add(parent) 139 roots.add(parent)
138 140
139 self.__parent_map[parent].append(branch) 141 self.__parent_map[parent].append(branch)
140 142
141 self.__current_branch = current_branch() 143 self.__current_branch = current_branch()
142 self.__current_hash = hash_one('HEAD', short=True) 144 self.__current_hash = hash_one('HEAD', short=True)
143 self.__tag_set = tags() 145 self.__tag_set = tags()
144 146
145 if roots: 147 if roots:
146 for root in sorted(roots): 148 for root in sorted(roots):
147 self.__append_branch(root) 149 self.__append_branch(root)
148 else: 150 else:
149 no_branches = OutputLine() 151 no_branches = OutputLine()
150 no_branches.append('No User Branches') 152 no_branches.append('No User Branches')
151 self.output.append(no_branches) 153 self.output.append(no_branches)
152 154
153 def __is_invalid_parent(self, parent): 155 def __is_invalid_parent(self, parent):
154 return not parent or parent in self.__gone_branches 156 return not parent or parent in self.__gone_branches
155 157
156 def __color_for_branch(self, branch, branch_hash): 158 def __color_for_branch(self, branch, branch_hash):
157 if branch.startswith('origin'): 159 if branch.startswith('origin'):
158 color = Fore.RED 160 color = Fore.RED
161 elif branch.startswith('branch-heads'):
162 color = Fore.BLUE
159 elif self.__is_invalid_parent(branch) or branch in self.__tag_set: 163 elif self.__is_invalid_parent(branch) or branch in self.__tag_set:
160 color = Fore.MAGENTA 164 color = Fore.MAGENTA
161 elif self.__current_hash.startswith(branch_hash): 165 elif self.__current_hash.startswith(branch_hash):
162 color = Fore.CYAN 166 color = Fore.CYAN
163 else: 167 else:
164 color = Fore.GREEN 168 color = Fore.GREEN
165 169
166 if self.__current_hash.startswith(branch_hash): 170 if branch_hash and self.__current_hash.startswith(branch_hash):
167 color += Style.BRIGHT 171 color += Style.BRIGHT
168 else: 172 else:
169 color += Style.NORMAL 173 color += Style.NORMAL
170 174
171 return color 175 return color
172 176
173 def __append_branch(self, branch, depth=0): 177 def __append_branch(self, branch, depth=0):
174 """Recurses through the tree structure and appends an OutputLine to the 178 """Recurses through the tree structure and appends an OutputLine to the
175 OutputManager for each branch.""" 179 OutputManager for each branch."""
176 branch_info = self.__branches_info[branch] 180 branch_info = self.__branches_info[branch]
177 if branch_info: 181 if branch_info:
178 branch_hash = branch_info.hash 182 branch_hash = branch_info.hash
179 else: 183 else:
180 branch_hash = hash_one(branch, short=True) 184 try:
185 branch_hash = hash_one(branch, short=True)
186 except subprocess2.CalledProcessError:
187 branch_hash = None
181 188
182 line = OutputLine() 189 line = OutputLine()
183 190
184 # The branch name with appropriate indentation. 191 # The branch name with appropriate indentation.
185 suffix = '' 192 suffix = ''
186 if branch == self.__current_branch or ( 193 if branch == self.__current_branch or (
187 self.__current_branch == 'HEAD' and branch == self.__current_hash): 194 self.__current_branch == 'HEAD' and branch == self.__current_hash):
188 suffix = ' *' 195 suffix = ' *'
189 branch_string = branch 196 branch_string = branch
190 if branch in self.__gone_branches: 197 if branch in self.__gone_branches:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 line.append(front_separator, separator=' ') 233 line.append(front_separator, separator=' ')
227 line.append(ahead_string, separator=' ', color=Fore.MAGENTA) 234 line.append(ahead_string, separator=' ', color=Fore.MAGENTA)
228 line.append(center_separator, separator=' ') 235 line.append(center_separator, separator=' ')
229 line.append(behind_string, separator=' ', color=Fore.MAGENTA) 236 line.append(behind_string, separator=' ', color=Fore.MAGENTA)
230 line.append(back_separator) 237 line.append(back_separator)
231 238
232 # The Rietveld issue associated with the branch. 239 # The Rietveld issue associated with the branch.
233 if self.verbosity >= 2: 240 if self.verbosity >= 2:
234 import git_cl # avoid heavy import cost unless we need it 241 import git_cl # avoid heavy import cost unless we need it
235 none_text = '' if self.__is_invalid_parent(branch) else 'None' 242 none_text = '' if self.__is_invalid_parent(branch) else 'None'
236 url = git_cl.Changelist(branchref=branch).GetIssueURL() 243 url = git_cl.Changelist(
244 branchref=branch).GetIssueURL() if branch_hash else None
237 line.append(url or none_text, color=Fore.BLUE if url else Fore.WHITE) 245 line.append(url or none_text, color=Fore.BLUE if url else Fore.WHITE)
238 246
239 self.output.append(line) 247 self.output.append(line)
240 248
241 for child in sorted(self.__parent_map.pop(branch, ())): 249 for child in sorted(self.__parent_map.pop(branch, ())):
242 self.__append_branch(child, depth=depth + 1) 250 self.__append_branch(child, depth=depth + 1)
243 251
244 252
245 def main(argv): 253 def main(argv):
246 colorama.init() 254 colorama.init()
(...skipping 14 matching lines...) Expand all
261 opts = parser.parse_args(argv[1:]) 269 opts = parser.parse_args(argv[1:])
262 270
263 mapper = BranchMapper() 271 mapper = BranchMapper()
264 mapper.verbosity = opts.v 272 mapper.verbosity = opts.v
265 mapper.output.nocolor = opts.nocolor 273 mapper.output.nocolor = opts.nocolor
266 mapper.start() 274 mapper.start()
267 print mapper.output.as_formatted_string() 275 print mapper.output.as_formatted_string()
268 276
269 if __name__ == '__main__': 277 if __name__ == '__main__':
270 sys.exit(main(sys.argv)) 278 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | man/html/git-map-branches.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698