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