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