diff options
author | Shawn O. Pearce <sop@google.com> | 2009-04-10 16:02:48 -0700 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2009-04-10 16:02:48 -0700 |
commit | 27b07327bc9f4bcda2c29422e064bced092759e3 (patch) | |
tree | 3eeee2ebd7314a35e9fadb317912791eecb8dbdf /subcmds/branches.py | |
parent | 02d7945eb836f33f63b94fb2a556c844faf0ef8d (diff) | |
download | git-repo-27b07327bc9f4bcda2c29422e064bced092759e3.tar.gz |
Add a repo branches subcommand to describe current branches
We now display a summary of the available topic branches in this
client, based upon a sorted union of all existing projects.
Bug: REPO-21
Signed-off-by: Shawn O. Pearce <sop@google.com>
Diffstat (limited to 'subcmds/branches.py')
-rw-r--r-- | subcmds/branches.py | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/subcmds/branches.py b/subcmds/branches.py new file mode 100644 index 00000000..d5a0812f --- /dev/null +++ b/subcmds/branches.py | |||
@@ -0,0 +1,150 @@ | |||
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 | |||
16 | import sys | ||
17 | from color import Coloring | ||
18 | from command import Command | ||
19 | |||
20 | class BranchColoring(Coloring): | ||
21 | def __init__(self, config): | ||
22 | Coloring.__init__(self, config, 'branch') | ||
23 | self.current = self.printer('current', fg='green') | ||
24 | self.local = self.printer('local') | ||
25 | self.notinproject = self.printer('notinproject', fg='red') | ||
26 | |||
27 | class BranchInfo(object): | ||
28 | def __init__(self, name): | ||
29 | self.name = name | ||
30 | self.current = 0 | ||
31 | self.published = 0 | ||
32 | self.published_equal = 0 | ||
33 | self.projects = [] | ||
34 | |||
35 | def add(self, b): | ||
36 | if b.current: | ||
37 | self.current += 1 | ||
38 | if b.published: | ||
39 | self.published += 1 | ||
40 | if b.revision == b.published: | ||
41 | self.published_equal += 1 | ||
42 | self.projects.append(b) | ||
43 | |||
44 | @property | ||
45 | def IsCurrent(self): | ||
46 | return self.current > 0 | ||
47 | |||
48 | @property | ||
49 | def IsPublished(self): | ||
50 | return self.published > 0 | ||
51 | |||
52 | @property | ||
53 | def IsPublishedEqual(self): | ||
54 | return self.published_equal == len(self.projects) | ||
55 | |||
56 | |||
57 | class Branches(Command): | ||
58 | common = True | ||
59 | helpSummary = "View current topic branches" | ||
60 | helpUsage = """ | ||
61 | %prog [<project>...] | ||
62 | |||
63 | Summarizes the currently available topic branches. | ||
64 | """ | ||
65 | |||
66 | def _Options(self, p): | ||
67 | p.add_option('-a', '--all', | ||
68 | dest='all', action='store_true', | ||
69 | help='show all branches, not just the majority') | ||
70 | |||
71 | def Execute(self, opt, args): | ||
72 | projects = self.GetProjects(args) | ||
73 | out = BranchColoring(self.manifest.manifestProject.config) | ||
74 | all = {} | ||
75 | project_cnt = len(projects) | ||
76 | |||
77 | for project in projects: | ||
78 | for name, b in project.GetBranches().iteritems(): | ||
79 | b.project = project | ||
80 | if name not in all: | ||
81 | all[name] = BranchInfo(name) | ||
82 | all[name].add(b) | ||
83 | |||
84 | names = all.keys() | ||
85 | names.sort() | ||
86 | |||
87 | if not opt.all and not args: | ||
88 | # No -a and no specific projects listed; try to filter the | ||
89 | # results down to only the majority of projects. | ||
90 | # | ||
91 | n = [] | ||
92 | for name in names: | ||
93 | i = all[name] | ||
94 | if i.IsCurrent \ | ||
95 | or 80 <= (100 * len(i.projects)) / project_cnt: | ||
96 | n.append(name) | ||
97 | names = n | ||
98 | |||
99 | width = 25 | ||
100 | for name in names: | ||
101 | if width < len(name): | ||
102 | width = len(name) | ||
103 | |||
104 | for name in names: | ||
105 | i = all[name] | ||
106 | in_cnt = len(i.projects) | ||
107 | |||
108 | if i.IsCurrent: | ||
109 | current = '*' | ||
110 | hdr = out.current | ||
111 | else: | ||
112 | current = ' ' | ||
113 | hdr = out.local | ||
114 | |||
115 | if i.IsPublishedEqual: | ||
116 | published = 'P' | ||
117 | elif i.IsPublished: | ||
118 | published = 'p' | ||
119 | else: | ||
120 | published = ' ' | ||
121 | |||
122 | hdr('%c%c %-*s' % (current, published, width, name)) | ||
123 | out.write(' |') | ||
124 | |||
125 | if in_cnt < project_cnt and (in_cnt == 1 or opt.all): | ||
126 | fmt = out.write | ||
127 | paths = [] | ||
128 | if in_cnt < project_cnt - in_cnt: | ||
129 | type = 'in' | ||
130 | for b in i.projects: | ||
131 | paths.append(b.project.relpath) | ||
132 | else: | ||
133 | fmt = out.notinproject | ||
134 | type = 'not in' | ||
135 | have = set() | ||
136 | for b in i.projects: | ||
137 | have.add(b.project) | ||
138 | for p in projects: | ||
139 | paths.append(p.relpath) | ||
140 | |||
141 | s = ' %s %s' % (type, ', '.join(paths)) | ||
142 | if width + 7 + len(s) < 80: | ||
143 | fmt(s) | ||
144 | else: | ||
145 | out.nl() | ||
146 | fmt(' %s:' % type) | ||
147 | for p in paths: | ||
148 | out.nl() | ||
149 | fmt(' %s' % p) | ||
150 | out.nl() | ||