comparison .svn/pristine/f4/f432e915d61be365be23bdde45bf8970694e63ec.svn-base @ 1517:dffacf8a6908 redmine-2.5

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