##// END OF EJS Templates
templatekw: convert list of key/value pairs to sortdict...
Yuya Nishihara -
r24237:9ad02823 default
parent child Browse files
Show More
@@ -1,446 +1,449 b''
1 # templatekw.py - common changeset template keywords
1 # templatekw.py - common changeset template keywords
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex
8 from node import hex
9 import patch, util, error
9 import patch, util, error
10 import hbisect
10 import hbisect
11
11
12 # This helper class allows us to handle both:
12 # This helper class allows us to handle both:
13 # "{files}" (legacy command-line-specific list hack) and
13 # "{files}" (legacy command-line-specific list hack) and
14 # "{files % '{file}\n'}" (hgweb-style with inlining and function support)
14 # "{files % '{file}\n'}" (hgweb-style with inlining and function support)
15
15
16 class _hybrid(object):
16 class _hybrid(object):
17 def __init__(self, gen, values, joinfmt=None):
17 def __init__(self, gen, values, joinfmt=None):
18 self.gen = gen
18 self.gen = gen
19 self.values = values
19 self.values = values
20 if joinfmt:
20 if joinfmt:
21 self.joinfmt = joinfmt
21 self.joinfmt = joinfmt
22 else:
22 else:
23 self.joinfmt = lambda x: x.values()[0]
23 self.joinfmt = lambda x: x.values()[0]
24 def __iter__(self):
24 def __iter__(self):
25 return self.gen
25 return self.gen
26 def __call__(self):
26 def __call__(self):
27 for x in self.values:
27 for x in self.values:
28 yield x
28 yield x
29 def __len__(self):
29 def __len__(self):
30 return len(self.values)
30 return len(self.values)
31
31
32 def showlist(name, values, plural=None, element=None, **args):
32 def showlist(name, values, plural=None, element=None, **args):
33 if not element:
33 if not element:
34 element = name
34 element = name
35 f = _showlist(name, values, plural, **args)
35 f = _showlist(name, values, plural, **args)
36 return _hybrid(f, [{element: x} for x in values])
36 return _hybrid(f, [{element: x} for x in values])
37
37
38 def _showlist(name, values, plural=None, **args):
38 def _showlist(name, values, plural=None, **args):
39 '''expand set of values.
39 '''expand set of values.
40 name is name of key in template map.
40 name is name of key in template map.
41 values is list of strings or dicts.
41 values is list of strings or dicts.
42 plural is plural of name, if not simply name + 's'.
42 plural is plural of name, if not simply name + 's'.
43
43
44 expansion works like this, given name 'foo'.
44 expansion works like this, given name 'foo'.
45
45
46 if values is empty, expand 'no_foos'.
46 if values is empty, expand 'no_foos'.
47
47
48 if 'foo' not in template map, return values as a string,
48 if 'foo' not in template map, return values as a string,
49 joined by space.
49 joined by space.
50
50
51 expand 'start_foos'.
51 expand 'start_foos'.
52
52
53 for each value, expand 'foo'. if 'last_foo' in template
53 for each value, expand 'foo'. if 'last_foo' in template
54 map, expand it instead of 'foo' for last key.
54 map, expand it instead of 'foo' for last key.
55
55
56 expand 'end_foos'.
56 expand 'end_foos'.
57 '''
57 '''
58 templ = args['templ']
58 templ = args['templ']
59 if plural:
59 if plural:
60 names = plural
60 names = plural
61 else: names = name + 's'
61 else: names = name + 's'
62 if not values:
62 if not values:
63 noname = 'no_' + names
63 noname = 'no_' + names
64 if noname in templ:
64 if noname in templ:
65 yield templ(noname, **args)
65 yield templ(noname, **args)
66 return
66 return
67 if name not in templ:
67 if name not in templ:
68 if isinstance(values[0], str):
68 if isinstance(values[0], str):
69 yield ' '.join(values)
69 yield ' '.join(values)
70 else:
70 else:
71 for v in values:
71 for v in values:
72 yield dict(v, **args)
72 yield dict(v, **args)
73 return
73 return
74 startname = 'start_' + names
74 startname = 'start_' + names
75 if startname in templ:
75 if startname in templ:
76 yield templ(startname, **args)
76 yield templ(startname, **args)
77 vargs = args.copy()
77 vargs = args.copy()
78 def one(v, tag=name):
78 def one(v, tag=name):
79 try:
79 try:
80 vargs.update(v)
80 vargs.update(v)
81 except (AttributeError, ValueError):
81 except (AttributeError, ValueError):
82 try:
82 try:
83 for a, b in v:
83 for a, b in v:
84 vargs[a] = b
84 vargs[a] = b
85 except ValueError:
85 except ValueError:
86 vargs[name] = v
86 vargs[name] = v
87 return templ(tag, **vargs)
87 return templ(tag, **vargs)
88 lastname = 'last_' + name
88 lastname = 'last_' + name
89 if lastname in templ:
89 if lastname in templ:
90 last = values.pop()
90 last = values.pop()
91 else:
91 else:
92 last = None
92 last = None
93 for v in values:
93 for v in values:
94 yield one(v)
94 yield one(v)
95 if last is not None:
95 if last is not None:
96 yield one(last, tag=lastname)
96 yield one(last, tag=lastname)
97 endname = 'end_' + names
97 endname = 'end_' + names
98 if endname in templ:
98 if endname in templ:
99 yield templ(endname, **args)
99 yield templ(endname, **args)
100
100
101 def getfiles(repo, ctx, revcache):
101 def getfiles(repo, ctx, revcache):
102 if 'files' not in revcache:
102 if 'files' not in revcache:
103 revcache['files'] = repo.status(ctx.p1().node(), ctx.node())[:3]
103 revcache['files'] = repo.status(ctx.p1().node(), ctx.node())[:3]
104 return revcache['files']
104 return revcache['files']
105
105
106 def getlatesttags(repo, ctx, cache):
106 def getlatesttags(repo, ctx, cache):
107 '''return date, distance and name for the latest tag of rev'''
107 '''return date, distance and name for the latest tag of rev'''
108
108
109 if 'latesttags' not in cache:
109 if 'latesttags' not in cache:
110 # Cache mapping from rev to a tuple with tag date, tag
110 # Cache mapping from rev to a tuple with tag date, tag
111 # distance and tag name
111 # distance and tag name
112 cache['latesttags'] = {-1: (0, 0, 'null')}
112 cache['latesttags'] = {-1: (0, 0, 'null')}
113 latesttags = cache['latesttags']
113 latesttags = cache['latesttags']
114
114
115 rev = ctx.rev()
115 rev = ctx.rev()
116 todo = [rev]
116 todo = [rev]
117 while todo:
117 while todo:
118 rev = todo.pop()
118 rev = todo.pop()
119 if rev in latesttags:
119 if rev in latesttags:
120 continue
120 continue
121 ctx = repo[rev]
121 ctx = repo[rev]
122 tags = [t for t in ctx.tags()
122 tags = [t for t in ctx.tags()
123 if (repo.tagtype(t) and repo.tagtype(t) != 'local')]
123 if (repo.tagtype(t) and repo.tagtype(t) != 'local')]
124 if tags:
124 if tags:
125 latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
125 latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
126 continue
126 continue
127 try:
127 try:
128 # The tuples are laid out so the right one can be found by
128 # The tuples are laid out so the right one can be found by
129 # comparison.
129 # comparison.
130 pdate, pdist, ptag = max(
130 pdate, pdist, ptag = max(
131 latesttags[p.rev()] for p in ctx.parents())
131 latesttags[p.rev()] for p in ctx.parents())
132 except KeyError:
132 except KeyError:
133 # Cache miss - recurse
133 # Cache miss - recurse
134 todo.append(rev)
134 todo.append(rev)
135 todo.extend(p.rev() for p in ctx.parents())
135 todo.extend(p.rev() for p in ctx.parents())
136 continue
136 continue
137 latesttags[rev] = pdate, pdist + 1, ptag
137 latesttags[rev] = pdate, pdist + 1, ptag
138 return latesttags[rev]
138 return latesttags[rev]
139
139
140 def getrenamedfn(repo, endrev=None):
140 def getrenamedfn(repo, endrev=None):
141 rcache = {}
141 rcache = {}
142 if endrev is None:
142 if endrev is None:
143 endrev = len(repo)
143 endrev = len(repo)
144
144
145 def getrenamed(fn, rev):
145 def getrenamed(fn, rev):
146 '''looks up all renames for a file (up to endrev) the first
146 '''looks up all renames for a file (up to endrev) the first
147 time the file is given. It indexes on the changerev and only
147 time the file is given. It indexes on the changerev and only
148 parses the manifest if linkrev != changerev.
148 parses the manifest if linkrev != changerev.
149 Returns rename info for fn at changerev rev.'''
149 Returns rename info for fn at changerev rev.'''
150 if fn not in rcache:
150 if fn not in rcache:
151 rcache[fn] = {}
151 rcache[fn] = {}
152 fl = repo.file(fn)
152 fl = repo.file(fn)
153 for i in fl:
153 for i in fl:
154 lr = fl.linkrev(i)
154 lr = fl.linkrev(i)
155 renamed = fl.renamed(fl.node(i))
155 renamed = fl.renamed(fl.node(i))
156 rcache[fn][lr] = renamed
156 rcache[fn][lr] = renamed
157 if lr >= endrev:
157 if lr >= endrev:
158 break
158 break
159 if rev in rcache[fn]:
159 if rev in rcache[fn]:
160 return rcache[fn][rev]
160 return rcache[fn][rev]
161
161
162 # If linkrev != rev (i.e. rev not found in rcache) fallback to
162 # If linkrev != rev (i.e. rev not found in rcache) fallback to
163 # filectx logic.
163 # filectx logic.
164 try:
164 try:
165 return repo[rev][fn].renamed()
165 return repo[rev][fn].renamed()
166 except error.LookupError:
166 except error.LookupError:
167 return None
167 return None
168
168
169 return getrenamed
169 return getrenamed
170
170
171
171
172 def showauthor(repo, ctx, templ, **args):
172 def showauthor(repo, ctx, templ, **args):
173 """:author: String. The unmodified author of the changeset."""
173 """:author: String. The unmodified author of the changeset."""
174 return ctx.user()
174 return ctx.user()
175
175
176 def showbisect(repo, ctx, templ, **args):
176 def showbisect(repo, ctx, templ, **args):
177 """:bisect: String. The changeset bisection status."""
177 """:bisect: String. The changeset bisection status."""
178 return hbisect.label(repo, ctx.node())
178 return hbisect.label(repo, ctx.node())
179
179
180 def showbranch(**args):
180 def showbranch(**args):
181 """:branch: String. The name of the branch on which the changeset was
181 """:branch: String. The name of the branch on which the changeset was
182 committed.
182 committed.
183 """
183 """
184 return args['ctx'].branch()
184 return args['ctx'].branch()
185
185
186 def showbranches(**args):
186 def showbranches(**args):
187 """:branches: List of strings. The name of the branch on which the
187 """:branches: List of strings. The name of the branch on which the
188 changeset was committed. Will be empty if the branch name was
188 changeset was committed. Will be empty if the branch name was
189 default.
189 default.
190 """
190 """
191 branch = args['ctx'].branch()
191 branch = args['ctx'].branch()
192 if branch != 'default':
192 if branch != 'default':
193 return showlist('branch', [branch], plural='branches', **args)
193 return showlist('branch', [branch], plural='branches', **args)
194 return showlist('branch', [], plural='branches', **args)
194 return showlist('branch', [], plural='branches', **args)
195
195
196 def showbookmarks(**args):
196 def showbookmarks(**args):
197 """:bookmarks: List of strings. Any bookmarks associated with the
197 """:bookmarks: List of strings. Any bookmarks associated with the
198 changeset.
198 changeset.
199 """
199 """
200 repo = args['ctx']._repo
200 repo = args['ctx']._repo
201 bookmarks = args['ctx'].bookmarks()
201 bookmarks = args['ctx'].bookmarks()
202 current = repo._bookmarkcurrent
202 current = repo._bookmarkcurrent
203 c = [{'bookmark': x, 'current': current} for x in bookmarks]
203 c = [{'bookmark': x, 'current': current} for x in bookmarks]
204 f = _showlist('bookmark', bookmarks, **args)
204 f = _showlist('bookmark', bookmarks, **args)
205 return _hybrid(f, c, lambda x: x['bookmark'])
205 return _hybrid(f, c, lambda x: x['bookmark'])
206
206
207 def showchildren(**args):
207 def showchildren(**args):
208 """:children: List of strings. The children of the changeset."""
208 """:children: List of strings. The children of the changeset."""
209 ctx = args['ctx']
209 ctx = args['ctx']
210 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
210 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
211 return showlist('children', childrevs, element='child', **args)
211 return showlist('children', childrevs, element='child', **args)
212
212
213 def showcurrentbookmark(**args):
213 def showcurrentbookmark(**args):
214 """:currentbookmark: String. The active bookmark, if it is
214 """:currentbookmark: String. The active bookmark, if it is
215 associated with the changeset"""
215 associated with the changeset"""
216 import bookmarks as bookmarks # to avoid circular import issues
216 import bookmarks as bookmarks # to avoid circular import issues
217 repo = args['repo']
217 repo = args['repo']
218 if bookmarks.iscurrent(repo):
218 if bookmarks.iscurrent(repo):
219 current = repo._bookmarkcurrent
219 current = repo._bookmarkcurrent
220 if current in args['ctx'].bookmarks():
220 if current in args['ctx'].bookmarks():
221 return current
221 return current
222 return ''
222 return ''
223
223
224 def showdate(repo, ctx, templ, **args):
224 def showdate(repo, ctx, templ, **args):
225 """:date: Date information. The date when the changeset was committed."""
225 """:date: Date information. The date when the changeset was committed."""
226 return ctx.date()
226 return ctx.date()
227
227
228 def showdescription(repo, ctx, templ, **args):
228 def showdescription(repo, ctx, templ, **args):
229 """:desc: String. The text of the changeset description."""
229 """:desc: String. The text of the changeset description."""
230 return ctx.description().strip()
230 return ctx.description().strip()
231
231
232 def showdiffstat(repo, ctx, templ, **args):
232 def showdiffstat(repo, ctx, templ, **args):
233 """:diffstat: String. Statistics of changes with the following format:
233 """:diffstat: String. Statistics of changes with the following format:
234 "modified files: +added/-removed lines"
234 "modified files: +added/-removed lines"
235 """
235 """
236 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
236 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
237 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
237 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
238 return '%s: +%s/-%s' % (len(stats), adds, removes)
238 return '%s: +%s/-%s' % (len(stats), adds, removes)
239
239
240 def showextras(**args):
240 def showextras(**args):
241 """:extras: List of dicts with key, value entries of the 'extras'
241 """:extras: List of dicts with key, value entries of the 'extras'
242 field of this changeset."""
242 field of this changeset."""
243 extras = args['ctx'].extra()
243 extras = args['ctx'].extra()
244 c = [{'key': x[0], 'value': x[1]} for x in sorted(extras.items())]
244 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
245 c = [{'key': k, 'value': extras[k]} for k in extras]
245 f = _showlist('extra', c, plural='extras', **args)
246 f = _showlist('extra', c, plural='extras', **args)
246 return _hybrid(f, c, lambda x: '%s=%s' % (x['key'], x['value']))
247 return _hybrid(f, c, lambda x: '%s=%s' % (x['key'], x['value']))
247
248
248 def showfileadds(**args):
249 def showfileadds(**args):
249 """:file_adds: List of strings. Files added by this changeset."""
250 """:file_adds: List of strings. Files added by this changeset."""
250 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
251 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
251 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
252 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
252 element='file', **args)
253 element='file', **args)
253
254
254 def showfilecopies(**args):
255 def showfilecopies(**args):
255 """:file_copies: List of strings. Files copied in this changeset with
256 """:file_copies: List of strings. Files copied in this changeset with
256 their sources.
257 their sources.
257 """
258 """
258 cache, ctx = args['cache'], args['ctx']
259 cache, ctx = args['cache'], args['ctx']
259 copies = args['revcache'].get('copies')
260 copies = args['revcache'].get('copies')
260 if copies is None:
261 if copies is None:
261 if 'getrenamed' not in cache:
262 if 'getrenamed' not in cache:
262 cache['getrenamed'] = getrenamedfn(args['repo'])
263 cache['getrenamed'] = getrenamedfn(args['repo'])
263 copies = []
264 copies = []
264 getrenamed = cache['getrenamed']
265 getrenamed = cache['getrenamed']
265 for fn in ctx.files():
266 for fn in ctx.files():
266 rename = getrenamed(fn, ctx.rev())
267 rename = getrenamed(fn, ctx.rev())
267 if rename:
268 if rename:
268 copies.append((fn, rename[0]))
269 copies.append((fn, rename[0]))
269
270
270 c = [{'name': x[0], 'source': x[1]} for x in copies]
271 copies = util.sortdict(copies)
272 c = [{'name': k, 'source': copies[k]} for k in copies]
271 f = _showlist('file_copy', c, plural='file_copies', **args)
273 f = _showlist('file_copy', c, plural='file_copies', **args)
272 return _hybrid(f, c, lambda x: '%s (%s)' % (x['name'], x['source']))
274 return _hybrid(f, c, lambda x: '%s (%s)' % (x['name'], x['source']))
273
275
274 # showfilecopiesswitch() displays file copies only if copy records are
276 # showfilecopiesswitch() displays file copies only if copy records are
275 # provided before calling the templater, usually with a --copies
277 # provided before calling the templater, usually with a --copies
276 # command line switch.
278 # command line switch.
277 def showfilecopiesswitch(**args):
279 def showfilecopiesswitch(**args):
278 """:file_copies_switch: List of strings. Like "file_copies" but displayed
280 """:file_copies_switch: List of strings. Like "file_copies" but displayed
279 only if the --copied switch is set.
281 only if the --copied switch is set.
280 """
282 """
281 copies = args['revcache'].get('copies') or []
283 copies = args['revcache'].get('copies') or []
282 c = [{'name': x[0], 'source': x[1]} for x in copies]
284 copies = util.sortdict(copies)
285 c = [{'name': k, 'source': copies[k]} for k in copies]
283 f = _showlist('file_copy', c, plural='file_copies', **args)
286 f = _showlist('file_copy', c, plural='file_copies', **args)
284 return _hybrid(f, c, lambda x: '%s (%s)' % (x['name'], x['source']))
287 return _hybrid(f, c, lambda x: '%s (%s)' % (x['name'], x['source']))
285
288
286 def showfiledels(**args):
289 def showfiledels(**args):
287 """:file_dels: List of strings. Files removed by this changeset."""
290 """:file_dels: List of strings. Files removed by this changeset."""
288 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
291 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
289 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
292 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
290 element='file', **args)
293 element='file', **args)
291
294
292 def showfilemods(**args):
295 def showfilemods(**args):
293 """:file_mods: List of strings. Files modified by this changeset."""
296 """:file_mods: List of strings. Files modified by this changeset."""
294 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
297 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
295 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
298 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
296 element='file', **args)
299 element='file', **args)
297
300
298 def showfiles(**args):
301 def showfiles(**args):
299 """:files: List of strings. All files modified, added, or removed by this
302 """:files: List of strings. All files modified, added, or removed by this
300 changeset.
303 changeset.
301 """
304 """
302 return showlist('file', args['ctx'].files(), **args)
305 return showlist('file', args['ctx'].files(), **args)
303
306
304 def showlatesttag(repo, ctx, templ, cache, **args):
307 def showlatesttag(repo, ctx, templ, cache, **args):
305 """:latesttag: String. Most recent global tag in the ancestors of this
308 """:latesttag: String. Most recent global tag in the ancestors of this
306 changeset.
309 changeset.
307 """
310 """
308 return getlatesttags(repo, ctx, cache)[2]
311 return getlatesttags(repo, ctx, cache)[2]
309
312
310 def showlatesttagdistance(repo, ctx, templ, cache, **args):
313 def showlatesttagdistance(repo, ctx, templ, cache, **args):
311 """:latesttagdistance: Integer. Longest path to the latest tag."""
314 """:latesttagdistance: Integer. Longest path to the latest tag."""
312 return getlatesttags(repo, ctx, cache)[1]
315 return getlatesttags(repo, ctx, cache)[1]
313
316
314 def showmanifest(**args):
317 def showmanifest(**args):
315 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
318 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
316 args = args.copy()
319 args = args.copy()
317 args.update({'rev': repo.manifest.rev(ctx.changeset()[0]),
320 args.update({'rev': repo.manifest.rev(ctx.changeset()[0]),
318 'node': hex(ctx.changeset()[0])})
321 'node': hex(ctx.changeset()[0])})
319 return templ('manifest', **args)
322 return templ('manifest', **args)
320
323
321 def shownode(repo, ctx, templ, **args):
324 def shownode(repo, ctx, templ, **args):
322 """:node: String. The changeset identification hash, as a 40 hexadecimal
325 """:node: String. The changeset identification hash, as a 40 hexadecimal
323 digit string.
326 digit string.
324 """
327 """
325 return ctx.hex()
328 return ctx.hex()
326
329
327 def showp1rev(repo, ctx, templ, **args):
330 def showp1rev(repo, ctx, templ, **args):
328 """:p1rev: Integer. The repository-local revision number of the changeset's
331 """:p1rev: Integer. The repository-local revision number of the changeset's
329 first parent, or -1 if the changeset has no parents."""
332 first parent, or -1 if the changeset has no parents."""
330 return ctx.p1().rev()
333 return ctx.p1().rev()
331
334
332 def showp2rev(repo, ctx, templ, **args):
335 def showp2rev(repo, ctx, templ, **args):
333 """:p2rev: Integer. The repository-local revision number of the changeset's
336 """:p2rev: Integer. The repository-local revision number of the changeset's
334 second parent, or -1 if the changeset has no second parent."""
337 second parent, or -1 if the changeset has no second parent."""
335 return ctx.p2().rev()
338 return ctx.p2().rev()
336
339
337 def showp1node(repo, ctx, templ, **args):
340 def showp1node(repo, ctx, templ, **args):
338 """:p1node: String. The identification hash of the changeset's first parent,
341 """:p1node: String. The identification hash of the changeset's first parent,
339 as a 40 digit hexadecimal string. If the changeset has no parents, all
342 as a 40 digit hexadecimal string. If the changeset has no parents, all
340 digits are 0."""
343 digits are 0."""
341 return ctx.p1().hex()
344 return ctx.p1().hex()
342
345
343 def showp2node(repo, ctx, templ, **args):
346 def showp2node(repo, ctx, templ, **args):
344 """:p2node: String. The identification hash of the changeset's second
347 """:p2node: String. The identification hash of the changeset's second
345 parent, as a 40 digit hexadecimal string. If the changeset has no second
348 parent, as a 40 digit hexadecimal string. If the changeset has no second
346 parent, all digits are 0."""
349 parent, all digits are 0."""
347 return ctx.p2().hex()
350 return ctx.p2().hex()
348
351
349 def showphase(repo, ctx, templ, **args):
352 def showphase(repo, ctx, templ, **args):
350 """:phase: String. The changeset phase name."""
353 """:phase: String. The changeset phase name."""
351 return ctx.phasestr()
354 return ctx.phasestr()
352
355
353 def showphaseidx(repo, ctx, templ, **args):
356 def showphaseidx(repo, ctx, templ, **args):
354 """:phaseidx: Integer. The changeset phase index."""
357 """:phaseidx: Integer. The changeset phase index."""
355 return ctx.phase()
358 return ctx.phase()
356
359
357 def showrev(repo, ctx, templ, **args):
360 def showrev(repo, ctx, templ, **args):
358 """:rev: Integer. The repository-local changeset revision number."""
361 """:rev: Integer. The repository-local changeset revision number."""
359 return ctx.rev()
362 return ctx.rev()
360
363
361 def showsubrepos(**args):
364 def showsubrepos(**args):
362 """:subrepos: List of strings. Updated subrepositories in the changeset."""
365 """:subrepos: List of strings. Updated subrepositories in the changeset."""
363 ctx = args['ctx']
366 ctx = args['ctx']
364 substate = ctx.substate
367 substate = ctx.substate
365 if not substate:
368 if not substate:
366 return showlist('subrepo', [], **args)
369 return showlist('subrepo', [], **args)
367 psubstate = ctx.parents()[0].substate or {}
370 psubstate = ctx.parents()[0].substate or {}
368 subrepos = []
371 subrepos = []
369 for sub in substate:
372 for sub in substate:
370 if sub not in psubstate or substate[sub] != psubstate[sub]:
373 if sub not in psubstate or substate[sub] != psubstate[sub]:
371 subrepos.append(sub) # modified or newly added in ctx
374 subrepos.append(sub) # modified or newly added in ctx
372 for sub in psubstate:
375 for sub in psubstate:
373 if sub not in substate:
376 if sub not in substate:
374 subrepos.append(sub) # removed in ctx
377 subrepos.append(sub) # removed in ctx
375 return showlist('subrepo', sorted(subrepos), **args)
378 return showlist('subrepo', sorted(subrepos), **args)
376
379
377 def shownames(namespace, **args):
380 def shownames(namespace, **args):
378 """helper method to generate a template keyword for a namespace"""
381 """helper method to generate a template keyword for a namespace"""
379 ctx = args['ctx']
382 ctx = args['ctx']
380 repo = ctx._repo
383 repo = ctx._repo
381 ns = repo.names[namespace]
384 ns = repo.names[namespace]
382 names = ns.names(repo, ctx.node())
385 names = ns.names(repo, ctx.node())
383 return showlist(ns.templatename, names, plural=namespace, **args)
386 return showlist(ns.templatename, names, plural=namespace, **args)
384
387
385 # don't remove "showtags" definition, even though namespaces will put
388 # don't remove "showtags" definition, even though namespaces will put
386 # a helper function for "tags" keyword into "keywords" map automatically,
389 # a helper function for "tags" keyword into "keywords" map automatically,
387 # because online help text is built without namespaces initialization
390 # because online help text is built without namespaces initialization
388 def showtags(**args):
391 def showtags(**args):
389 """:tags: List of strings. Any tags associated with the changeset."""
392 """:tags: List of strings. Any tags associated with the changeset."""
390 return shownames('tags', **args)
393 return shownames('tags', **args)
391
394
392 # keywords are callables like:
395 # keywords are callables like:
393 # fn(repo, ctx, templ, cache, revcache, **args)
396 # fn(repo, ctx, templ, cache, revcache, **args)
394 # with:
397 # with:
395 # repo - current repository instance
398 # repo - current repository instance
396 # ctx - the changectx being displayed
399 # ctx - the changectx being displayed
397 # templ - the templater instance
400 # templ - the templater instance
398 # cache - a cache dictionary for the whole templater run
401 # cache - a cache dictionary for the whole templater run
399 # revcache - a cache dictionary for the current revision
402 # revcache - a cache dictionary for the current revision
400 keywords = {
403 keywords = {
401 'author': showauthor,
404 'author': showauthor,
402 'bisect': showbisect,
405 'bisect': showbisect,
403 'branch': showbranch,
406 'branch': showbranch,
404 'branches': showbranches,
407 'branches': showbranches,
405 'bookmarks': showbookmarks,
408 'bookmarks': showbookmarks,
406 'children': showchildren,
409 'children': showchildren,
407 'currentbookmark': showcurrentbookmark,
410 'currentbookmark': showcurrentbookmark,
408 'date': showdate,
411 'date': showdate,
409 'desc': showdescription,
412 'desc': showdescription,
410 'diffstat': showdiffstat,
413 'diffstat': showdiffstat,
411 'extras': showextras,
414 'extras': showextras,
412 'file_adds': showfileadds,
415 'file_adds': showfileadds,
413 'file_copies': showfilecopies,
416 'file_copies': showfilecopies,
414 'file_copies_switch': showfilecopiesswitch,
417 'file_copies_switch': showfilecopiesswitch,
415 'file_dels': showfiledels,
418 'file_dels': showfiledels,
416 'file_mods': showfilemods,
419 'file_mods': showfilemods,
417 'files': showfiles,
420 'files': showfiles,
418 'latesttag': showlatesttag,
421 'latesttag': showlatesttag,
419 'latesttagdistance': showlatesttagdistance,
422 'latesttagdistance': showlatesttagdistance,
420 'manifest': showmanifest,
423 'manifest': showmanifest,
421 'node': shownode,
424 'node': shownode,
422 'p1rev': showp1rev,
425 'p1rev': showp1rev,
423 'p1node': showp1node,
426 'p1node': showp1node,
424 'p2rev': showp2rev,
427 'p2rev': showp2rev,
425 'p2node': showp2node,
428 'p2node': showp2node,
426 'phase': showphase,
429 'phase': showphase,
427 'phaseidx': showphaseidx,
430 'phaseidx': showphaseidx,
428 'rev': showrev,
431 'rev': showrev,
429 'subrepos': showsubrepos,
432 'subrepos': showsubrepos,
430 'tags': showtags,
433 'tags': showtags,
431 }
434 }
432
435
433 def _showparents(**args):
436 def _showparents(**args):
434 """:parents: List of strings. The parents of the changeset in "rev:node"
437 """:parents: List of strings. The parents of the changeset in "rev:node"
435 format. If the changeset has only one "natural" parent (the predecessor
438 format. If the changeset has only one "natural" parent (the predecessor
436 revision) nothing is shown."""
439 revision) nothing is shown."""
437 pass
440 pass
438
441
439 dockeywords = {
442 dockeywords = {
440 'parents': _showparents,
443 'parents': _showparents,
441 }
444 }
442 dockeywords.update(keywords)
445 dockeywords.update(keywords)
443 del dockeywords['branches']
446 del dockeywords['branches']
444
447
445 # tell hggettext to extract docstrings from these functions:
448 # tell hggettext to extract docstrings from these functions:
446 i18nfunctions = dockeywords.values()
449 i18nfunctions = dockeywords.values()
General Comments 0
You need to be logged in to leave comments. Login now