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