comparison .svn/pristine/a2/a228c3d0b7910e4eb07f95e583bb22e9efe2f4c4.svn-base @ 1295:622f24f53b42 redmine-2.3

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