OLD | NEW |
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 |
(...skipping 17 matching lines...) Expand all Loading... |
28 import argparse | 28 import argparse |
29 import collections | 29 import collections |
30 import sys | 30 import sys |
31 import subprocess2 | 31 import subprocess2 |
32 | 32 |
33 from third_party import colorama | 33 from third_party import colorama |
34 from third_party.colorama import Fore, Style | 34 from third_party.colorama import Fore, Style |
35 | 35 |
36 from git_common import current_branch, upstream, tags, get_branches_info | 36 from git_common import current_branch, upstream, tags, get_branches_info |
37 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 |
| 38 from git_common import run |
38 | 39 |
39 DEFAULT_SEPARATOR = ' ' * 4 | 40 DEFAULT_SEPARATOR = ' ' * 4 |
40 | 41 |
41 | 42 |
42 class OutputManager(object): | 43 class OutputManager(object): |
43 """Manages a number of OutputLines and formats them into aligned columns.""" | 44 """Manages a number of OutputLines and formats them into aligned columns.""" |
44 | 45 |
45 def __init__(self): | 46 def __init__(self): |
46 self.lines = [] | 47 self.lines = [] |
47 self.nocolor = False | 48 self.nocolor = False |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 """A class which constructs output representing the tree's branch structure. | 104 """A class which constructs output representing the tree's branch structure. |
104 | 105 |
105 Attributes: | 106 Attributes: |
106 __branches_info: a map of branches to their BranchesInfo objects which | 107 __branches_info: a map of branches to their BranchesInfo objects which |
107 consist of the branch hash, upstream and ahead/behind status. | 108 consist of the branch hash, upstream and ahead/behind status. |
108 __gone_branches: a set of upstreams which are not fetchable by git""" | 109 __gone_branches: a set of upstreams which are not fetchable by git""" |
109 | 110 |
110 def __init__(self): | 111 def __init__(self): |
111 self.verbosity = 0 | 112 self.verbosity = 0 |
112 self.maxjobs = 0 | 113 self.maxjobs = 0 |
| 114 self.show_subject = False |
113 self.output = OutputManager() | 115 self.output = OutputManager() |
114 self.__gone_branches = set() | 116 self.__gone_branches = set() |
115 self.__branches_info = None | 117 self.__branches_info = None |
116 self.__parent_map = collections.defaultdict(list) | 118 self.__parent_map = collections.defaultdict(list) |
117 self.__current_branch = None | 119 self.__current_branch = None |
118 self.__current_hash = None | 120 self.__current_hash = None |
119 self.__tag_set = None | 121 self.__tag_set = None |
120 self.__status_info = {} | 122 self.__status_info = {} |
121 | 123 |
122 def start(self): | 124 def start(self): |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 line.append(center_separator, separator=' ') | 253 line.append(center_separator, separator=' ') |
252 line.append(behind_string, separator=' ', color=Fore.MAGENTA) | 254 line.append(behind_string, separator=' ', color=Fore.MAGENTA) |
253 line.append(back_separator) | 255 line.append(back_separator) |
254 | 256 |
255 # The Rietveld issue associated with the branch. | 257 # The Rietveld issue associated with the branch. |
256 if self.verbosity >= 2: | 258 if self.verbosity >= 2: |
257 none_text = '' if self.__is_invalid_parent(branch) else 'None' | 259 none_text = '' if self.__is_invalid_parent(branch) else 'None' |
258 (url, color) = self.__status_info[branch] | 260 (url, color) = self.__status_info[branch] |
259 line.append(url or none_text, color=color) | 261 line.append(url or none_text, color=color) |
260 | 262 |
| 263 # The subject of the most recent commit on the branch. |
| 264 if self.show_subject: |
| 265 line.append(run('log', '-n1', '--format=%s', branch)) |
| 266 |
261 self.output.append(line) | 267 self.output.append(line) |
262 | 268 |
263 for child in sorted(self.__parent_map.pop(branch, ())): | 269 for child in sorted(self.__parent_map.pop(branch, ())): |
264 self.__append_branch(child, depth=depth + 1) | 270 self.__append_branch(child, depth=depth + 1) |
265 | 271 |
266 | 272 |
267 def main(argv): | 273 def main(argv): |
268 colorama.init() | 274 colorama.init() |
269 if get_git_version() < MIN_UPSTREAM_TRACK_GIT_VERSION: | 275 if get_git_version() < MIN_UPSTREAM_TRACK_GIT_VERSION: |
270 print >> sys.stderr, ( | 276 print >> sys.stderr, ( |
271 'This tool will not show all tracking information for git version ' | 277 'This tool will not show all tracking information for git version ' |
272 'earlier than ' + | 278 'earlier than ' + |
273 '.'.join(str(x) for x in MIN_UPSTREAM_TRACK_GIT_VERSION) + | 279 '.'.join(str(x) for x in MIN_UPSTREAM_TRACK_GIT_VERSION) + |
274 '. Please consider upgrading.') | 280 '. Please consider upgrading.') |
275 | 281 |
276 parser = argparse.ArgumentParser( | 282 parser = argparse.ArgumentParser( |
277 description='Print a a tree of all branches parented by their upstreams') | 283 description='Print a a tree of all branches parented by their upstreams') |
278 parser.add_argument('-v', action='count', | 284 parser.add_argument('-v', action='count', |
279 help='Display branch hash and Rietveld URL') | 285 help='Display branch hash and Rietveld URL') |
280 parser.add_argument('--no-color', action='store_true', dest='nocolor', | 286 parser.add_argument('--no-color', action='store_true', dest='nocolor', |
281 help='Turn off colors.') | 287 help='Turn off colors.') |
282 parser.add_argument( | 288 parser.add_argument( |
283 '-j', '--maxjobs', action='store', type=int, | 289 '-j', '--maxjobs', action='store', type=int, |
284 help='The number of jobs to use when retrieving review status') | 290 help='The number of jobs to use when retrieving review status') |
| 291 parser.add_argument('--show-subject', action='store_true', |
| 292 dest='show_subject', help='Show the commit subject.') |
285 | 293 |
286 opts = parser.parse_args(argv) | 294 opts = parser.parse_args(argv) |
287 | 295 |
288 mapper = BranchMapper() | 296 mapper = BranchMapper() |
289 mapper.verbosity = opts.v | 297 mapper.verbosity = opts.v |
290 mapper.output.nocolor = opts.nocolor | 298 mapper.output.nocolor = opts.nocolor |
291 mapper.maxjobs = opts.maxjobs | 299 mapper.maxjobs = opts.maxjobs |
| 300 mapper.show_subject = opts.show_subject |
292 mapper.start() | 301 mapper.start() |
293 print mapper.output.as_formatted_string() | 302 print mapper.output.as_formatted_string() |
294 return 0 | 303 return 0 |
295 | 304 |
296 if __name__ == '__main__': | 305 if __name__ == '__main__': |
297 try: | 306 try: |
298 sys.exit(main(sys.argv[1:])) | 307 sys.exit(main(sys.argv[1:])) |
299 except KeyboardInterrupt: | 308 except KeyboardInterrupt: |
300 sys.stderr.write('interrupted\n') | 309 sys.stderr.write('interrupted\n') |
301 sys.exit(1) | 310 sys.exit(1) |
OLD | NEW |