branches.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #
  2. # Copyright (C) 2009 The Android Open Source Project
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from __future__ import print_function
  16. import sys
  17. from color import Coloring
  18. from command import Command
  19. class BranchColoring(Coloring):
  20. def __init__(self, config):
  21. Coloring.__init__(self, config, 'branch')
  22. self.current = self.printer('current', fg='green')
  23. self.local = self.printer('local')
  24. self.notinproject = self.printer('notinproject', fg='red')
  25. class BranchInfo(object):
  26. def __init__(self, name):
  27. self.name = name
  28. self.current = 0
  29. self.published = 0
  30. self.published_equal = 0
  31. self.projects = []
  32. def add(self, b):
  33. if b.current:
  34. self.current += 1
  35. if b.published:
  36. self.published += 1
  37. if b.revision == b.published:
  38. self.published_equal += 1
  39. self.projects.append(b)
  40. @property
  41. def IsCurrent(self):
  42. return self.current > 0
  43. @property
  44. def IsPublished(self):
  45. return self.published > 0
  46. @property
  47. def IsPublishedEqual(self):
  48. return self.published_equal == len(self.projects)
  49. class Branches(Command):
  50. common = True
  51. helpSummary = "View current topic branches"
  52. helpUsage = """
  53. %prog [<project>...]
  54. Summarizes the currently available topic branches.
  55. Branch Display
  56. --------------
  57. The branch display output by this command is organized into four
  58. columns of information; for example:
  59. *P nocolor | in repo
  60. repo2 |
  61. The first column contains a * if the branch is the currently
  62. checked out branch in any of the specified projects, or a blank
  63. if no project has the branch checked out.
  64. The second column contains either blank, p or P, depending upon
  65. the upload status of the branch.
  66. (blank): branch not yet published by repo upload
  67. P: all commits were published by repo upload
  68. p: only some commits were published by repo upload
  69. The third column contains the branch name.
  70. The fourth column (after the | separator) lists the projects that
  71. the branch appears in, or does not appear in. If no project list
  72. is shown, then the branch appears in all projects.
  73. """
  74. def Execute(self, opt, args):
  75. projects = self.GetProjects(args)
  76. out = BranchColoring(self.manifest.manifestProject.config)
  77. all_branches = {}
  78. project_cnt = len(projects)
  79. for project in projects:
  80. for name, b in project.GetBranches().iteritems():
  81. b.project = project
  82. if name not in all_branches:
  83. all_branches[name] = BranchInfo(name)
  84. all_branches[name].add(b)
  85. names = all_branches.keys()
  86. names.sort()
  87. if not names:
  88. print(' (no branches)', file=sys.stderr)
  89. return
  90. width = 25
  91. for name in names:
  92. if width < len(name):
  93. width = len(name)
  94. for name in names:
  95. i = all_branches[name]
  96. in_cnt = len(i.projects)
  97. if i.IsCurrent:
  98. current = '*'
  99. hdr = out.current
  100. else:
  101. current = ' '
  102. hdr = out.local
  103. if i.IsPublishedEqual:
  104. published = 'P'
  105. elif i.IsPublished:
  106. published = 'p'
  107. else:
  108. published = ' '
  109. hdr('%c%c %-*s' % (current, published, width, name))
  110. out.write(' |')
  111. if in_cnt < project_cnt:
  112. fmt = out.write
  113. paths = []
  114. if in_cnt < project_cnt - in_cnt:
  115. in_type = 'in'
  116. for b in i.projects:
  117. paths.append(b.project.relpath)
  118. else:
  119. fmt = out.notinproject
  120. in_type = 'not in'
  121. have = set()
  122. for b in i.projects:
  123. have.add(b.project)
  124. for p in projects:
  125. if not p in have:
  126. paths.append(p.relpath)
  127. s = ' %s %s' % (in_type, ', '.join(paths))
  128. if width + 7 + len(s) < 80:
  129. fmt(s)
  130. else:
  131. fmt(' %s:' % in_type)
  132. for p in paths:
  133. out.nl()
  134. fmt(width*' ' + ' %s' % p)
  135. else:
  136. out.write(' in all projects')
  137. out.nl()