##// END OF EJS Templates
use Python getattr instead of hasattr (#16177)...
Toshi MARUYAMA -
r12660:0cf7a27b503d
parent child
Show More
@@ -1,225 +1,225
1 1 # redminehelper: Redmine helper extension for Mercurial
2 2 #
3 3 # Copyright 2010 Alessio Franceschelli (alefranz.net)
4 4 # Copyright 2010-2011 Yuya Nishihara <yuya@tcha.org>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8 """helper commands for Redmine to reduce the number of hg calls
9 9
10 10 To test this extension, please try::
11 11
12 12 $ hg --config extensions.redminehelper=redminehelper.py rhsummary
13 13
14 14 I/O encoding:
15 15
16 16 :file path: urlencoded, raw string
17 17 :tag name: utf-8
18 18 :branch name: utf-8
19 19 :node: hex string
20 20
21 21 Output example of rhsummary::
22 22
23 23 <?xml version="1.0"?>
24 24 <rhsummary>
25 25 <repository root="/foo/bar">
26 26 <tip revision="1234" node="abcdef0123..."/>
27 27 <tag revision="123" node="34567abc..." name="1.1.1"/>
28 28 <branch .../>
29 29 ...
30 30 </repository>
31 31 </rhsummary>
32 32
33 33 Output example of rhmanifest::
34 34
35 35 <?xml version="1.0"?>
36 36 <rhmanifest>
37 37 <repository root="/foo/bar">
38 38 <manifest revision="1234" path="lib">
39 39 <file name="diff.rb" revision="123" node="34567abc..." time="12345"
40 40 size="100"/>
41 41 ...
42 42 <dir name="redmine"/>
43 43 ...
44 44 </manifest>
45 45 </repository>
46 46 </rhmanifest>
47 47 """
48 48 import re, time, cgi, urllib
49 49 from mercurial import cmdutil, commands, node, error, hg
50 50
51 51 _x = cgi.escape
52 52 _u = lambda s: cgi.escape(urllib.quote(s))
53 53
54 54 def _tip(ui, repo):
55 55 # see mercurial/commands.py:tip
56 56 def tiprev():
57 57 try:
58 58 return len(repo) - 1
59 59 except TypeError: # Mercurial < 1.1
60 60 return repo.changelog.count() - 1
61 61 tipctx = repo.changectx(tiprev())
62 62 ui.write('<tip revision="%d" node="%s"/>\n'
63 63 % (tipctx.rev(), _x(node.hex(tipctx.node()))))
64 64
65 65 _SPECIAL_TAGS = ('tip',)
66 66
67 67 def _tags(ui, repo):
68 68 # see mercurial/commands.py:tags
69 69 for t, n in reversed(repo.tagslist()):
70 70 if t in _SPECIAL_TAGS:
71 71 continue
72 72 try:
73 73 r = repo.changelog.rev(n)
74 74 except error.LookupError:
75 75 continue
76 76 ui.write('<tag revision="%d" node="%s" name="%s"/>\n'
77 77 % (r, _x(node.hex(n)), _x(t)))
78 78
79 79 def _branches(ui, repo):
80 80 # see mercurial/commands.py:branches
81 81 def iterbranches():
82 if hasattr(repo, 'branchtags'):
82 if getattr(repo, 'branchtags', None) is not None:
83 83 # Mercurial < 2.9
84 84 for t, n in repo.branchtags().iteritems():
85 85 yield t, n, repo.changelog.rev(n)
86 86 else:
87 87 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
88 88 yield tag, tip, repo.changelog.rev(tip)
89 89 def branchheads(branch):
90 90 try:
91 91 return repo.branchheads(branch, closed=False)
92 92 except TypeError: # Mercurial < 1.2
93 93 return repo.branchheads(branch)
94 94 for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True):
95 95 if repo.lookup(r) in branchheads(t):
96 96 ui.write('<branch revision="%d" node="%s" name="%s"/>\n'
97 97 % (r, _x(node.hex(n)), _x(t)))
98 98
99 99 def _manifest(ui, repo, path, rev):
100 100 ctx = repo.changectx(rev)
101 101 ui.write('<manifest revision="%d" path="%s">\n'
102 102 % (ctx.rev(), _u(path)))
103 103
104 104 known = set()
105 105 pathprefix = (path.rstrip('/') + '/').lstrip('/')
106 106 for f, n in sorted(ctx.manifest().iteritems(), key=lambda e: e[0]):
107 107 if not f.startswith(pathprefix):
108 108 continue
109 109 name = re.sub(r'/.*', '/', f[len(pathprefix):])
110 110 if name in known:
111 111 continue
112 112 known.add(name)
113 113
114 114 if name.endswith('/'):
115 115 ui.write('<dir name="%s"/>\n'
116 116 % _x(urllib.quote(name[:-1])))
117 117 else:
118 118 fctx = repo.filectx(f, fileid=n)
119 119 tm, tzoffset = fctx.date()
120 120 ui.write('<file name="%s" revision="%d" node="%s" '
121 121 'time="%d" size="%d"/>\n'
122 122 % (_u(name), fctx.rev(), _x(node.hex(fctx.node())),
123 123 tm, fctx.size(), ))
124 124
125 125 ui.write('</manifest>\n')
126 126
127 127 def rhannotate(ui, repo, *pats, **opts):
128 128 rev = urllib.unquote_plus(opts.pop('rev', None))
129 129 opts['rev'] = rev
130 130 return commands.annotate(ui, repo, *map(urllib.unquote_plus, pats), **opts)
131 131
132 132 def rhcat(ui, repo, file1, *pats, **opts):
133 133 rev = urllib.unquote_plus(opts.pop('rev', None))
134 134 opts['rev'] = rev
135 135 return commands.cat(ui, repo, urllib.unquote_plus(file1), *map(urllib.unquote_plus, pats), **opts)
136 136
137 137 def rhdiff(ui, repo, *pats, **opts):
138 138 """diff repository (or selected files)"""
139 139 change = opts.pop('change', None)
140 140 if change: # add -c option for Mercurial<1.1
141 141 base = repo.changectx(change).parents()[0].rev()
142 142 opts['rev'] = [str(base), change]
143 143 opts['nodates'] = True
144 144 return commands.diff(ui, repo, *map(urllib.unquote_plus, pats), **opts)
145 145
146 146 def rhlog(ui, repo, *pats, **opts):
147 147 rev = opts.pop('rev')
148 148 bra0 = opts.pop('branch')
149 149 from_rev = urllib.unquote_plus(opts.pop('from', None))
150 150 to_rev = urllib.unquote_plus(opts.pop('to' , None))
151 151 bra = urllib.unquote_plus(opts.pop('rhbranch', None))
152 152 from_rev = from_rev.replace('"', '\\"')
153 153 to_rev = to_rev.replace('"', '\\"')
154 154 if hg.util.version() >= '1.6':
155 155 opts['rev'] = ['"%s":"%s"' % (from_rev, to_rev)]
156 156 else:
157 157 opts['rev'] = ['%s:%s' % (from_rev, to_rev)]
158 158 opts['branch'] = [bra]
159 159 return commands.log(ui, repo, *map(urllib.unquote_plus, pats), **opts)
160 160
161 161 def rhmanifest(ui, repo, path='', **opts):
162 162 """output the sub-manifest of the specified directory"""
163 163 ui.write('<?xml version="1.0"?>\n')
164 164 ui.write('<rhmanifest>\n')
165 165 ui.write('<repository root="%s">\n' % _u(repo.root))
166 166 try:
167 167 _manifest(ui, repo, urllib.unquote_plus(path), urllib.unquote_plus(opts.get('rev')))
168 168 finally:
169 169 ui.write('</repository>\n')
170 170 ui.write('</rhmanifest>\n')
171 171
172 172 def rhsummary(ui, repo, **opts):
173 173 """output the summary of the repository"""
174 174 ui.write('<?xml version="1.0"?>\n')
175 175 ui.write('<rhsummary>\n')
176 176 ui.write('<repository root="%s">\n' % _u(repo.root))
177 177 try:
178 178 _tip(ui, repo)
179 179 _tags(ui, repo)
180 180 _branches(ui, repo)
181 181 # TODO: bookmarks in core (Mercurial>=1.8)
182 182 finally:
183 183 ui.write('</repository>\n')
184 184 ui.write('</rhsummary>\n')
185 185
186 186 cmdtable = {
187 187 'rhannotate': (rhannotate,
188 188 [('r', 'rev', '', 'revision'),
189 189 ('u', 'user', None, 'list the author (long with -v)'),
190 190 ('n', 'number', None, 'list the revision number (default)'),
191 191 ('c', 'changeset', None, 'list the changeset'),
192 192 ],
193 193 'hg rhannotate [-r REV] [-u] [-n] [-c] FILE...'),
194 194 'rhcat': (rhcat,
195 195 [('r', 'rev', '', 'revision')],
196 196 'hg rhcat ([-r REV] ...) FILE...'),
197 197 'rhdiff': (rhdiff,
198 198 [('r', 'rev', [], 'revision'),
199 199 ('c', 'change', '', 'change made by revision')],
200 200 'hg rhdiff ([-c REV] | [-r REV] ...) [FILE]...'),
201 201 'rhlog': (rhlog,
202 202 [
203 203 ('r', 'rev', [], 'show the specified revision'),
204 204 ('b', 'branch', [],
205 205 'show changesets within the given named branch'),
206 206 ('l', 'limit', '',
207 207 'limit number of changes displayed'),
208 208 ('d', 'date', '',
209 209 'show revisions matching date spec'),
210 210 ('u', 'user', [],
211 211 'revisions committed by user'),
212 212 ('', 'from', '',
213 213 ''),
214 214 ('', 'to', '',
215 215 ''),
216 216 ('', 'rhbranch', '',
217 217 ''),
218 218 ('', 'template', '',
219 219 'display with template')],
220 220 'hg rhlog [OPTION]... [FILE]'),
221 221 'rhmanifest': (rhmanifest,
222 222 [('r', 'rev', '', 'show the specified revision')],
223 223 'hg rhmanifest [-r REV] [PATH]'),
224 224 'rhsummary': (rhsummary, [], 'hg rhsummary'),
225 225 }
General Comments 0
You need to be logged in to leave comments. Login now