| 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 14 matching lines...) Expand all Loading... |
| 25 """ | 25 """ |
| 26 | 26 |
| 27 import argparse | 27 import argparse |
| 28 import collections | 28 import collections |
| 29 import sys | 29 import sys |
| 30 | 30 |
| 31 from third_party import colorama | 31 from third_party import colorama |
| 32 from third_party.colorama import Fore, Style | 32 from third_party.colorama import Fore, Style |
| 33 | 33 |
| 34 from git_common import current_branch, upstream, tags, get_branches_info | 34 from git_common import current_branch, upstream, tags, get_branches_info |
| 35 from git_common import get_git_version, MIN_UPSTREAM_TRACK_GIT_VERSION | 35 from git_common import get_git_version, MIN_UPSTREAM_TRACK_GIT_VERSION, hash_one |
| 36 | |
| 37 import git_cl | |
| 38 | 36 |
| 39 DEFAULT_SEPARATOR = ' ' * 4 | 37 DEFAULT_SEPARATOR = ' ' * 4 |
| 40 | 38 |
| 41 | 39 |
| 42 class OutputManager(object): | 40 class OutputManager(object): |
| 43 """Manages a number of OutputLines and formats them into aligned columns.""" | 41 """Manages a number of OutputLines and formats them into aligned columns.""" |
| 44 | 42 |
| 45 def __init__(self): | 43 def __init__(self): |
| 46 self.lines = [] | 44 self.lines = [] |
| 47 self.nocolor = False | 45 self.nocolor = False |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 if branch_upstream: | 132 if branch_upstream: |
| 135 parent = branch_upstream | 133 parent = branch_upstream |
| 136 else: | 134 else: |
| 137 self.__gone_branches.add(parent) | 135 self.__gone_branches.add(parent) |
| 138 # A parent that isn't in the branches info is a root. | 136 # A parent that isn't in the branches info is a root. |
| 139 roots.add(parent) | 137 roots.add(parent) |
| 140 | 138 |
| 141 self.__parent_map[parent].append(branch) | 139 self.__parent_map[parent].append(branch) |
| 142 | 140 |
| 143 self.__current_branch = current_branch() | 141 self.__current_branch = current_branch() |
| 144 self.__current_hash = self.__branches_info[self.__current_branch].hash | 142 self.__current_hash = hash_one('HEAD', short=True) |
| 145 self.__tag_set = tags() | 143 self.__tag_set = tags() |
| 146 | 144 |
| 147 for root in sorted(roots): | 145 if roots: |
| 148 self.__append_branch(root) | 146 for root in sorted(roots): |
| 147 self.__append_branch(root) |
| 148 else: |
| 149 no_branches = OutputLine() |
| 150 no_branches.append('No User Branches') |
| 151 self.output.append(no_branches) |
| 149 | 152 |
| 150 def __is_invalid_parent(self, parent): | 153 def __is_invalid_parent(self, parent): |
| 151 return not parent or parent in self.__gone_branches | 154 return not parent or parent in self.__gone_branches |
| 152 | 155 |
| 153 def __color_for_branch(self, branch, branch_hash): | 156 def __color_for_branch(self, branch, branch_hash): |
| 154 if branch.startswith('origin'): | 157 if branch.startswith('origin'): |
| 155 color = Fore.RED | 158 color = Fore.RED |
| 156 elif self.__is_invalid_parent(branch) or branch in self.__tag_set: | 159 elif self.__is_invalid_parent(branch) or branch in self.__tag_set: |
| 157 color = Fore.MAGENTA | 160 color = Fore.MAGENTA |
| 158 elif branch_hash == self.__current_hash: | 161 elif self.__current_hash.startswith(branch_hash): |
| 159 color = Fore.CYAN | 162 color = Fore.CYAN |
| 160 else: | 163 else: |
| 161 color = Fore.GREEN | 164 color = Fore.GREEN |
| 162 | 165 |
| 163 if branch_hash == self.__current_hash: | 166 if self.__current_hash.startswith(branch_hash): |
| 164 color += Style.BRIGHT | 167 color += Style.BRIGHT |
| 165 else: | 168 else: |
| 166 color += Style.NORMAL | 169 color += Style.NORMAL |
| 167 | 170 |
| 168 return color | 171 return color |
| 169 | 172 |
| 170 def __append_branch(self, branch, depth=0): | 173 def __append_branch(self, branch, depth=0): |
| 171 """Recurses through the tree structure and appends an OutputLine to the | 174 """Recurses through the tree structure and appends an OutputLine to the |
| 172 OutputManager for each branch.""" | 175 OutputManager for each branch.""" |
| 173 branch_info = self.__branches_info[branch] | 176 branch_info = self.__branches_info[branch] |
| 174 branch_hash = branch_info.hash if branch_info else None | 177 if branch_info: |
| 178 branch_hash = branch_info.hash |
| 179 else: |
| 180 branch_hash = hash_one(branch, short=True) |
| 175 | 181 |
| 176 line = OutputLine() | 182 line = OutputLine() |
| 177 | 183 |
| 178 # The branch name with appropriate indentation. | 184 # The branch name with appropriate indentation. |
| 179 suffix = '' | 185 suffix = '' |
| 180 if branch == self.__current_branch or ( | 186 if branch == self.__current_branch or ( |
| 181 self.__current_branch == 'HEAD' and branch == self.__current_hash): | 187 self.__current_branch == 'HEAD' and branch == self.__current_hash): |
| 182 suffix = ' *' | 188 suffix = ' *' |
| 183 branch_string = branch | 189 branch_string = branch |
| 184 if branch in self.__gone_branches: | 190 if branch in self.__gone_branches: |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 center_separator = '|' | 224 center_separator = '|' |
| 219 | 225 |
| 220 line.append(front_separator, separator=' ') | 226 line.append(front_separator, separator=' ') |
| 221 line.append(ahead_string, separator=' ', color=Fore.MAGENTA) | 227 line.append(ahead_string, separator=' ', color=Fore.MAGENTA) |
| 222 line.append(center_separator, separator=' ') | 228 line.append(center_separator, separator=' ') |
| 223 line.append(behind_string, separator=' ', color=Fore.MAGENTA) | 229 line.append(behind_string, separator=' ', color=Fore.MAGENTA) |
| 224 line.append(back_separator) | 230 line.append(back_separator) |
| 225 | 231 |
| 226 # The Rietveld issue associated with the branch. | 232 # The Rietveld issue associated with the branch. |
| 227 if self.verbosity >= 2: | 233 if self.verbosity >= 2: |
| 234 import git_cl # avoid heavy import cost unless we need it |
| 228 none_text = '' if self.__is_invalid_parent(branch) else 'None' | 235 none_text = '' if self.__is_invalid_parent(branch) else 'None' |
| 229 url = git_cl.Changelist(branchref=branch).GetIssueURL() | 236 url = git_cl.Changelist(branchref=branch).GetIssueURL() |
| 230 line.append(url or none_text, color=Fore.BLUE if url else Fore.WHITE) | 237 line.append(url or none_text, color=Fore.BLUE if url else Fore.WHITE) |
| 231 | 238 |
| 232 self.output.append(line) | 239 self.output.append(line) |
| 233 | 240 |
| 234 for child in sorted(self.__parent_map.pop(branch, ())): | 241 for child in sorted(self.__parent_map.pop(branch, ())): |
| 235 self.__append_branch(child, depth=depth + 1) | 242 self.__append_branch(child, depth=depth + 1) |
| 236 | 243 |
| 237 | 244 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 254 opts = parser.parse_args(argv[1:]) | 261 opts = parser.parse_args(argv[1:]) |
| 255 | 262 |
| 256 mapper = BranchMapper() | 263 mapper = BranchMapper() |
| 257 mapper.verbosity = opts.v | 264 mapper.verbosity = opts.v |
| 258 mapper.output.nocolor = opts.nocolor | 265 mapper.output.nocolor = opts.nocolor |
| 259 mapper.start() | 266 mapper.start() |
| 260 print mapper.output.as_formatted_string() | 267 print mapper.output.as_formatted_string() |
| 261 | 268 |
| 262 if __name__ == '__main__': | 269 if __name__ == '__main__': |
| 263 sys.exit(main(sys.argv)) | 270 sys.exit(main(sys.argv)) |
| OLD | NEW |