##// END OF EJS Templates
templatekw: give name to lambda that constructs variables map of templater...
Yuya Nishihara -
r24238:49cee6d8 default
parent child Browse files
Show More
@@ -1,449 +1,453 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 makemap = lambda v: {'bookmark': v, 'current': current}
204 c = [makemap(v) for v in bookmarks]
204 f = _showlist('bookmark', bookmarks, **args)
205 f = _showlist('bookmark', bookmarks, **args)
205 return _hybrid(f, c, lambda x: x['bookmark'])
206 return _hybrid(f, c, lambda x: x['bookmark'])
206
207
207 def showchildren(**args):
208 def showchildren(**args):
208 """:children: List of strings. The children of the changeset."""
209 """:children: List of strings. The children of the changeset."""
209 ctx = args['ctx']
210 ctx = args['ctx']
210 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
211 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
211 return showlist('children', childrevs, element='child', **args)
212 return showlist('children', childrevs, element='child', **args)
212
213
213 def showcurrentbookmark(**args):
214 def showcurrentbookmark(**args):
214 """:currentbookmark: String. The active bookmark, if it is
215 """:currentbookmark: String. The active bookmark, if it is
215 associated with the changeset"""
216 associated with the changeset"""
216 import bookmarks as bookmarks # to avoid circular import issues
217 import bookmarks as bookmarks # to avoid circular import issues
217 repo = args['repo']
218 repo = args['repo']
218 if bookmarks.iscurrent(repo):
219 if bookmarks.iscurrent(repo):
219 current = repo._bookmarkcurrent
220 current = repo._bookmarkcurrent
220 if current in args['ctx'].bookmarks():
221 if current in args['ctx'].bookmarks():
221 return current
222 return current
222 return ''
223 return ''
223
224
224 def showdate(repo, ctx, templ, **args):
225 def showdate(repo, ctx, templ, **args):
225 """:date: Date information. The date when the changeset was committed."""
226 """:date: Date information. The date when the changeset was committed."""
226 return ctx.date()
227 return ctx.date()
227
228
228 def showdescription(repo, ctx, templ, **args):
229 def showdescription(repo, ctx, templ, **args):
229 """:desc: String. The text of the changeset description."""
230 """:desc: String. The text of the changeset description."""
230 return ctx.description().strip()
231 return ctx.description().strip()
231
232
232 def showdiffstat(repo, ctx, templ, **args):
233 def showdiffstat(repo, ctx, templ, **args):
233 """:diffstat: String. Statistics of changes with the following format:
234 """:diffstat: String. Statistics of changes with the following format:
234 "modified files: +added/-removed lines"
235 "modified files: +added/-removed lines"
235 """
236 """
236 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
237 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
237 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
238 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
238 return '%s: +%s/-%s' % (len(stats), adds, removes)
239 return '%s: +%s/-%s' % (len(stats), adds, removes)
239
240
240 def showextras(**args):
241 def showextras(**args):
241 """:extras: List of dicts with key, value entries of the 'extras'
242 """:extras: List of dicts with key, value entries of the 'extras'
242 field of this changeset."""
243 field of this changeset."""
243 extras = args['ctx'].extra()
244 extras = args['ctx'].extra()
244 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
245 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
245 c = [{'key': k, 'value': extras[k]} for k in extras]
246 makemap = lambda k: {'key': k, 'value': extras[k]}
247 c = [makemap(k) for k in extras]
246 f = _showlist('extra', c, plural='extras', **args)
248 f = _showlist('extra', c, plural='extras', **args)
247 return _hybrid(f, c, lambda x: '%s=%s' % (x['key'], x['value']))
249 return _hybrid(f, c, lambda x: '%s=%s' % (x['key'], x['value']))
248
250
249 def showfileadds(**args):
251 def showfileadds(**args):
250 """:file_adds: List of strings. Files added by this changeset."""
252 """:file_adds: List of strings. Files added by this changeset."""
251 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
253 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
252 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
254 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
253 element='file', **args)
255 element='file', **args)
254
256
255 def showfilecopies(**args):
257 def showfilecopies(**args):
256 """:file_copies: List of strings. Files copied in this changeset with
258 """:file_copies: List of strings. Files copied in this changeset with
257 their sources.
259 their sources.
258 """
260 """
259 cache, ctx = args['cache'], args['ctx']
261 cache, ctx = args['cache'], args['ctx']
260 copies = args['revcache'].get('copies')
262 copies = args['revcache'].get('copies')
261 if copies is None:
263 if copies is None:
262 if 'getrenamed' not in cache:
264 if 'getrenamed' not in cache:
263 cache['getrenamed'] = getrenamedfn(args['repo'])
265 cache['getrenamed'] = getrenamedfn(args['repo'])
264 copies = []
266 copies = []
265 getrenamed = cache['getrenamed']
267 getrenamed = cache['getrenamed']
266 for fn in ctx.files():
268 for fn in ctx.files():
267 rename = getrenamed(fn, ctx.rev())
269 rename = getrenamed(fn, ctx.rev())
268 if rename:
270 if rename:
269 copies.append((fn, rename[0]))
271 copies.append((fn, rename[0]))
270
272
271 copies = util.sortdict(copies)
273 copies = util.sortdict(copies)
272 c = [{'name': k, 'source': copies[k]} for k in copies]
274 makemap = lambda k: {'name': k, 'source': copies[k]}
275 c = [makemap(k) for k in copies]
273 f = _showlist('file_copy', c, plural='file_copies', **args)
276 f = _showlist('file_copy', c, plural='file_copies', **args)
274 return _hybrid(f, c, lambda x: '%s (%s)' % (x['name'], x['source']))
277 return _hybrid(f, c, lambda x: '%s (%s)' % (x['name'], x['source']))
275
278
276 # showfilecopiesswitch() displays file copies only if copy records are
279 # showfilecopiesswitch() displays file copies only if copy records are
277 # provided before calling the templater, usually with a --copies
280 # provided before calling the templater, usually with a --copies
278 # command line switch.
281 # command line switch.
279 def showfilecopiesswitch(**args):
282 def showfilecopiesswitch(**args):
280 """:file_copies_switch: List of strings. Like "file_copies" but displayed
283 """:file_copies_switch: List of strings. Like "file_copies" but displayed
281 only if the --copied switch is set.
284 only if the --copied switch is set.
282 """
285 """
283 copies = args['revcache'].get('copies') or []
286 copies = args['revcache'].get('copies') or []
284 copies = util.sortdict(copies)
287 copies = util.sortdict(copies)
285 c = [{'name': k, 'source': copies[k]} for k in copies]
288 makemap = lambda k: {'name': k, 'source': copies[k]}
289 c = [makemap(k) for k in copies]
286 f = _showlist('file_copy', c, plural='file_copies', **args)
290 f = _showlist('file_copy', c, plural='file_copies', **args)
287 return _hybrid(f, c, lambda x: '%s (%s)' % (x['name'], x['source']))
291 return _hybrid(f, c, lambda x: '%s (%s)' % (x['name'], x['source']))
288
292
289 def showfiledels(**args):
293 def showfiledels(**args):
290 """:file_dels: List of strings. Files removed by this changeset."""
294 """:file_dels: List of strings. Files removed by this changeset."""
291 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
295 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
292 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
296 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
293 element='file', **args)
297 element='file', **args)
294
298
295 def showfilemods(**args):
299 def showfilemods(**args):
296 """:file_mods: List of strings. Files modified by this changeset."""
300 """:file_mods: List of strings. Files modified by this changeset."""
297 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
301 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
298 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
302 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
299 element='file', **args)
303 element='file', **args)
300
304
301 def showfiles(**args):
305 def showfiles(**args):
302 """:files: List of strings. All files modified, added, or removed by this
306 """:files: List of strings. All files modified, added, or removed by this
303 changeset.
307 changeset.
304 """
308 """
305 return showlist('file', args['ctx'].files(), **args)
309 return showlist('file', args['ctx'].files(), **args)
306
310
307 def showlatesttag(repo, ctx, templ, cache, **args):
311 def showlatesttag(repo, ctx, templ, cache, **args):
308 """:latesttag: String. Most recent global tag in the ancestors of this
312 """:latesttag: String. Most recent global tag in the ancestors of this
309 changeset.
313 changeset.
310 """
314 """
311 return getlatesttags(repo, ctx, cache)[2]
315 return getlatesttags(repo, ctx, cache)[2]
312
316
313 def showlatesttagdistance(repo, ctx, templ, cache, **args):
317 def showlatesttagdistance(repo, ctx, templ, cache, **args):
314 """:latesttagdistance: Integer. Longest path to the latest tag."""
318 """:latesttagdistance: Integer. Longest path to the latest tag."""
315 return getlatesttags(repo, ctx, cache)[1]
319 return getlatesttags(repo, ctx, cache)[1]
316
320
317 def showmanifest(**args):
321 def showmanifest(**args):
318 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
322 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
319 args = args.copy()
323 args = args.copy()
320 args.update({'rev': repo.manifest.rev(ctx.changeset()[0]),
324 args.update({'rev': repo.manifest.rev(ctx.changeset()[0]),
321 'node': hex(ctx.changeset()[0])})
325 'node': hex(ctx.changeset()[0])})
322 return templ('manifest', **args)
326 return templ('manifest', **args)
323
327
324 def shownode(repo, ctx, templ, **args):
328 def shownode(repo, ctx, templ, **args):
325 """:node: String. The changeset identification hash, as a 40 hexadecimal
329 """:node: String. The changeset identification hash, as a 40 hexadecimal
326 digit string.
330 digit string.
327 """
331 """
328 return ctx.hex()
332 return ctx.hex()
329
333
330 def showp1rev(repo, ctx, templ, **args):
334 def showp1rev(repo, ctx, templ, **args):
331 """:p1rev: Integer. The repository-local revision number of the changeset's
335 """:p1rev: Integer. The repository-local revision number of the changeset's
332 first parent, or -1 if the changeset has no parents."""
336 first parent, or -1 if the changeset has no parents."""
333 return ctx.p1().rev()
337 return ctx.p1().rev()
334
338
335 def showp2rev(repo, ctx, templ, **args):
339 def showp2rev(repo, ctx, templ, **args):
336 """:p2rev: Integer. The repository-local revision number of the changeset's
340 """:p2rev: Integer. The repository-local revision number of the changeset's
337 second parent, or -1 if the changeset has no second parent."""
341 second parent, or -1 if the changeset has no second parent."""
338 return ctx.p2().rev()
342 return ctx.p2().rev()
339
343
340 def showp1node(repo, ctx, templ, **args):
344 def showp1node(repo, ctx, templ, **args):
341 """:p1node: String. The identification hash of the changeset's first parent,
345 """:p1node: String. The identification hash of the changeset's first parent,
342 as a 40 digit hexadecimal string. If the changeset has no parents, all
346 as a 40 digit hexadecimal string. If the changeset has no parents, all
343 digits are 0."""
347 digits are 0."""
344 return ctx.p1().hex()
348 return ctx.p1().hex()
345
349
346 def showp2node(repo, ctx, templ, **args):
350 def showp2node(repo, ctx, templ, **args):
347 """:p2node: String. The identification hash of the changeset's second
351 """:p2node: String. The identification hash of the changeset's second
348 parent, as a 40 digit hexadecimal string. If the changeset has no second
352 parent, as a 40 digit hexadecimal string. If the changeset has no second
349 parent, all digits are 0."""
353 parent, all digits are 0."""
350 return ctx.p2().hex()
354 return ctx.p2().hex()
351
355
352 def showphase(repo, ctx, templ, **args):
356 def showphase(repo, ctx, templ, **args):
353 """:phase: String. The changeset phase name."""
357 """:phase: String. The changeset phase name."""
354 return ctx.phasestr()
358 return ctx.phasestr()
355
359
356 def showphaseidx(repo, ctx, templ, **args):
360 def showphaseidx(repo, ctx, templ, **args):
357 """:phaseidx: Integer. The changeset phase index."""
361 """:phaseidx: Integer. The changeset phase index."""
358 return ctx.phase()
362 return ctx.phase()
359
363
360 def showrev(repo, ctx, templ, **args):
364 def showrev(repo, ctx, templ, **args):
361 """:rev: Integer. The repository-local changeset revision number."""
365 """:rev: Integer. The repository-local changeset revision number."""
362 return ctx.rev()
366 return ctx.rev()
363
367
364 def showsubrepos(**args):
368 def showsubrepos(**args):
365 """:subrepos: List of strings. Updated subrepositories in the changeset."""
369 """:subrepos: List of strings. Updated subrepositories in the changeset."""
366 ctx = args['ctx']
370 ctx = args['ctx']
367 substate = ctx.substate
371 substate = ctx.substate
368 if not substate:
372 if not substate:
369 return showlist('subrepo', [], **args)
373 return showlist('subrepo', [], **args)
370 psubstate = ctx.parents()[0].substate or {}
374 psubstate = ctx.parents()[0].substate or {}
371 subrepos = []
375 subrepos = []
372 for sub in substate:
376 for sub in substate:
373 if sub not in psubstate or substate[sub] != psubstate[sub]:
377 if sub not in psubstate or substate[sub] != psubstate[sub]:
374 subrepos.append(sub) # modified or newly added in ctx
378 subrepos.append(sub) # modified or newly added in ctx
375 for sub in psubstate:
379 for sub in psubstate:
376 if sub not in substate:
380 if sub not in substate:
377 subrepos.append(sub) # removed in ctx
381 subrepos.append(sub) # removed in ctx
378 return showlist('subrepo', sorted(subrepos), **args)
382 return showlist('subrepo', sorted(subrepos), **args)
379
383
380 def shownames(namespace, **args):
384 def shownames(namespace, **args):
381 """helper method to generate a template keyword for a namespace"""
385 """helper method to generate a template keyword for a namespace"""
382 ctx = args['ctx']
386 ctx = args['ctx']
383 repo = ctx._repo
387 repo = ctx._repo
384 ns = repo.names[namespace]
388 ns = repo.names[namespace]
385 names = ns.names(repo, ctx.node())
389 names = ns.names(repo, ctx.node())
386 return showlist(ns.templatename, names, plural=namespace, **args)
390 return showlist(ns.templatename, names, plural=namespace, **args)
387
391
388 # don't remove "showtags" definition, even though namespaces will put
392 # don't remove "showtags" definition, even though namespaces will put
389 # a helper function for "tags" keyword into "keywords" map automatically,
393 # a helper function for "tags" keyword into "keywords" map automatically,
390 # because online help text is built without namespaces initialization
394 # because online help text is built without namespaces initialization
391 def showtags(**args):
395 def showtags(**args):
392 """:tags: List of strings. Any tags associated with the changeset."""
396 """:tags: List of strings. Any tags associated with the changeset."""
393 return shownames('tags', **args)
397 return shownames('tags', **args)
394
398
395 # keywords are callables like:
399 # keywords are callables like:
396 # fn(repo, ctx, templ, cache, revcache, **args)
400 # fn(repo, ctx, templ, cache, revcache, **args)
397 # with:
401 # with:
398 # repo - current repository instance
402 # repo - current repository instance
399 # ctx - the changectx being displayed
403 # ctx - the changectx being displayed
400 # templ - the templater instance
404 # templ - the templater instance
401 # cache - a cache dictionary for the whole templater run
405 # cache - a cache dictionary for the whole templater run
402 # revcache - a cache dictionary for the current revision
406 # revcache - a cache dictionary for the current revision
403 keywords = {
407 keywords = {
404 'author': showauthor,
408 'author': showauthor,
405 'bisect': showbisect,
409 'bisect': showbisect,
406 'branch': showbranch,
410 'branch': showbranch,
407 'branches': showbranches,
411 'branches': showbranches,
408 'bookmarks': showbookmarks,
412 'bookmarks': showbookmarks,
409 'children': showchildren,
413 'children': showchildren,
410 'currentbookmark': showcurrentbookmark,
414 'currentbookmark': showcurrentbookmark,
411 'date': showdate,
415 'date': showdate,
412 'desc': showdescription,
416 'desc': showdescription,
413 'diffstat': showdiffstat,
417 'diffstat': showdiffstat,
414 'extras': showextras,
418 'extras': showextras,
415 'file_adds': showfileadds,
419 'file_adds': showfileadds,
416 'file_copies': showfilecopies,
420 'file_copies': showfilecopies,
417 'file_copies_switch': showfilecopiesswitch,
421 'file_copies_switch': showfilecopiesswitch,
418 'file_dels': showfiledels,
422 'file_dels': showfiledels,
419 'file_mods': showfilemods,
423 'file_mods': showfilemods,
420 'files': showfiles,
424 'files': showfiles,
421 'latesttag': showlatesttag,
425 'latesttag': showlatesttag,
422 'latesttagdistance': showlatesttagdistance,
426 'latesttagdistance': showlatesttagdistance,
423 'manifest': showmanifest,
427 'manifest': showmanifest,
424 'node': shownode,
428 'node': shownode,
425 'p1rev': showp1rev,
429 'p1rev': showp1rev,
426 'p1node': showp1node,
430 'p1node': showp1node,
427 'p2rev': showp2rev,
431 'p2rev': showp2rev,
428 'p2node': showp2node,
432 'p2node': showp2node,
429 'phase': showphase,
433 'phase': showphase,
430 'phaseidx': showphaseidx,
434 'phaseidx': showphaseidx,
431 'rev': showrev,
435 'rev': showrev,
432 'subrepos': showsubrepos,
436 'subrepos': showsubrepos,
433 'tags': showtags,
437 'tags': showtags,
434 }
438 }
435
439
436 def _showparents(**args):
440 def _showparents(**args):
437 """:parents: List of strings. The parents of the changeset in "rev:node"
441 """:parents: List of strings. The parents of the changeset in "rev:node"
438 format. If the changeset has only one "natural" parent (the predecessor
442 format. If the changeset has only one "natural" parent (the predecessor
439 revision) nothing is shown."""
443 revision) nothing is shown."""
440 pass
444 pass
441
445
442 dockeywords = {
446 dockeywords = {
443 'parents': _showparents,
447 'parents': _showparents,
444 }
448 }
445 dockeywords.update(keywords)
449 dockeywords.update(keywords)
446 del dockeywords['branches']
450 del dockeywords['branches']
447
451
448 # tell hggettext to extract docstrings from these functions:
452 # tell hggettext to extract docstrings from these functions:
449 i18nfunctions = dockeywords.values()
453 i18nfunctions = dockeywords.values()
General Comments 0
You need to be logged in to leave comments. Login now