##// END OF EJS Templates
Merged r12930 from trunk to 2.5-stable (#16177)...
Toshi MARUYAMA -
r12657:fcc1f198e783
parent child
Show More
@@ -1,220 +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'):
83 # Mercurial < 2.9
82 84 for t, n in repo.branchtags().iteritems():
83 85 yield t, n, repo.changelog.rev(n)
86 else:
87 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
88 yield tag, tip, repo.changelog.rev(tip)
84 89 def branchheads(branch):
85 90 try:
86 91 return repo.branchheads(branch, closed=False)
87 92 except TypeError: # Mercurial < 1.2
88 93 return repo.branchheads(branch)
89 94 for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True):
90 95 if repo.lookup(r) in branchheads(t):
91 96 ui.write('<branch revision="%d" node="%s" name="%s"/>\n'
92 97 % (r, _x(node.hex(n)), _x(t)))
93 98
94 99 def _manifest(ui, repo, path, rev):
95 100 ctx = repo.changectx(rev)
96 101 ui.write('<manifest revision="%d" path="%s">\n'
97 102 % (ctx.rev(), _u(path)))
98 103
99 104 known = set()
100 105 pathprefix = (path.rstrip('/') + '/').lstrip('/')
101 106 for f, n in sorted(ctx.manifest().iteritems(), key=lambda e: e[0]):
102 107 if not f.startswith(pathprefix):
103 108 continue
104 109 name = re.sub(r'/.*', '/', f[len(pathprefix):])
105 110 if name in known:
106 111 continue
107 112 known.add(name)
108 113
109 114 if name.endswith('/'):
110 115 ui.write('<dir name="%s"/>\n'
111 116 % _x(urllib.quote(name[:-1])))
112 117 else:
113 118 fctx = repo.filectx(f, fileid=n)
114 119 tm, tzoffset = fctx.date()
115 120 ui.write('<file name="%s" revision="%d" node="%s" '
116 121 'time="%d" size="%d"/>\n'
117 122 % (_u(name), fctx.rev(), _x(node.hex(fctx.node())),
118 123 tm, fctx.size(), ))
119 124
120 125 ui.write('</manifest>\n')
121 126
122 127 def rhannotate(ui, repo, *pats, **opts):
123 128 rev = urllib.unquote_plus(opts.pop('rev', None))
124 129 opts['rev'] = rev
125 130 return commands.annotate(ui, repo, *map(urllib.unquote_plus, pats), **opts)
126 131
127 132 def rhcat(ui, repo, file1, *pats, **opts):
128 133 rev = urllib.unquote_plus(opts.pop('rev', None))
129 134 opts['rev'] = rev
130 135 return commands.cat(ui, repo, urllib.unquote_plus(file1), *map(urllib.unquote_plus, pats), **opts)
131 136
132 137 def rhdiff(ui, repo, *pats, **opts):
133 138 """diff repository (or selected files)"""
134 139 change = opts.pop('change', None)
135 140 if change: # add -c option for Mercurial<1.1
136 141 base = repo.changectx(change).parents()[0].rev()
137 142 opts['rev'] = [str(base), change]
138 143 opts['nodates'] = True
139 144 return commands.diff(ui, repo, *map(urllib.unquote_plus, pats), **opts)
140 145
141 146 def rhlog(ui, repo, *pats, **opts):
142 147 rev = opts.pop('rev')
143 148 bra0 = opts.pop('branch')
144 149 from_rev = urllib.unquote_plus(opts.pop('from', None))
145 150 to_rev = urllib.unquote_plus(opts.pop('to' , None))
146 151 bra = urllib.unquote_plus(opts.pop('rhbranch', None))
147 152 from_rev = from_rev.replace('"', '\\"')
148 153 to_rev = to_rev.replace('"', '\\"')
149 154 if hg.util.version() >= '1.6':
150 155 opts['rev'] = ['"%s":"%s"' % (from_rev, to_rev)]
151 156 else:
152 157 opts['rev'] = ['%s:%s' % (from_rev, to_rev)]
153 158 opts['branch'] = [bra]
154 159 return commands.log(ui, repo, *map(urllib.unquote_plus, pats), **opts)
155 160
156 161 def rhmanifest(ui, repo, path='', **opts):
157 162 """output the sub-manifest of the specified directory"""
158 163 ui.write('<?xml version="1.0"?>\n')
159 164 ui.write('<rhmanifest>\n')
160 165 ui.write('<repository root="%s">\n' % _u(repo.root))
161 166 try:
162 167 _manifest(ui, repo, urllib.unquote_plus(path), urllib.unquote_plus(opts.get('rev')))
163 168 finally:
164 169 ui.write('</repository>\n')
165 170 ui.write('</rhmanifest>\n')
166 171
167 172 def rhsummary(ui, repo, **opts):
168 173 """output the summary of the repository"""
169 174 ui.write('<?xml version="1.0"?>\n')
170 175 ui.write('<rhsummary>\n')
171 176 ui.write('<repository root="%s">\n' % _u(repo.root))
172 177 try:
173 178 _tip(ui, repo)
174 179 _tags(ui, repo)
175 180 _branches(ui, repo)
176 181 # TODO: bookmarks in core (Mercurial>=1.8)
177 182 finally:
178 183 ui.write('</repository>\n')
179 184 ui.write('</rhsummary>\n')
180 185
181 186 cmdtable = {
182 187 'rhannotate': (rhannotate,
183 188 [('r', 'rev', '', 'revision'),
184 189 ('u', 'user', None, 'list the author (long with -v)'),
185 190 ('n', 'number', None, 'list the revision number (default)'),
186 191 ('c', 'changeset', None, 'list the changeset'),
187 192 ],
188 193 'hg rhannotate [-r REV] [-u] [-n] [-c] FILE...'),
189 194 'rhcat': (rhcat,
190 195 [('r', 'rev', '', 'revision')],
191 196 'hg rhcat ([-r REV] ...) FILE...'),
192 197 'rhdiff': (rhdiff,
193 198 [('r', 'rev', [], 'revision'),
194 199 ('c', 'change', '', 'change made by revision')],
195 200 'hg rhdiff ([-c REV] | [-r REV] ...) [FILE]...'),
196 201 'rhlog': (rhlog,
197 202 [
198 203 ('r', 'rev', [], 'show the specified revision'),
199 204 ('b', 'branch', [],
200 205 'show changesets within the given named branch'),
201 206 ('l', 'limit', '',
202 207 'limit number of changes displayed'),
203 208 ('d', 'date', '',
204 209 'show revisions matching date spec'),
205 210 ('u', 'user', [],
206 211 'revisions committed by user'),
207 212 ('', 'from', '',
208 213 ''),
209 214 ('', 'to', '',
210 215 ''),
211 216 ('', 'rhbranch', '',
212 217 ''),
213 218 ('', 'template', '',
214 219 'display with template')],
215 220 'hg rhlog [OPTION]... [FILE]'),
216 221 'rhmanifest': (rhmanifest,
217 222 [('r', 'rev', '', 'show the specified revision')],
218 223 'hg rhmanifest [-r REV] [PATH]'),
219 224 'rhsummary': (rhsummary, [], 'hg rhsummary'),
220 225 }
General Comments 0
You need to be logged in to leave comments. Login now