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