##// END OF EJS Templates
templatekw.showdiffstat: use ctx.diff() instead of calling patch
Alexander Solovyov -
r13114:8f29a08e default
parent child Browse files
Show More
@@ -1,270 +1,269
1 1 # templatekw.py - common changeset template keywords
2 2 #
3 3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import hex
9 9 import encoding, patch, util, error
10 10
11 11 def showlist(name, values, plural=None, **args):
12 12 '''expand set of values.
13 13 name is name of key in template map.
14 14 values is list of strings or dicts.
15 15 plural is plural of name, if not simply name + 's'.
16 16
17 17 expansion works like this, given name 'foo'.
18 18
19 19 if values is empty, expand 'no_foos'.
20 20
21 21 if 'foo' not in template map, return values as a string,
22 22 joined by space.
23 23
24 24 expand 'start_foos'.
25 25
26 26 for each value, expand 'foo'. if 'last_foo' in template
27 27 map, expand it instead of 'foo' for last key.
28 28
29 29 expand 'end_foos'.
30 30 '''
31 31 templ = args['templ']
32 32 if plural:
33 33 names = plural
34 34 else: names = name + 's'
35 35 if not values:
36 36 noname = 'no_' + names
37 37 if noname in templ:
38 38 yield templ(noname, **args)
39 39 return
40 40 if name not in templ:
41 41 if isinstance(values[0], str):
42 42 yield ' '.join(values)
43 43 else:
44 44 for v in values:
45 45 yield dict(v, **args)
46 46 return
47 47 startname = 'start_' + names
48 48 if startname in templ:
49 49 yield templ(startname, **args)
50 50 vargs = args.copy()
51 51 def one(v, tag=name):
52 52 try:
53 53 vargs.update(v)
54 54 except (AttributeError, ValueError):
55 55 try:
56 56 for a, b in v:
57 57 vargs[a] = b
58 58 except ValueError:
59 59 vargs[name] = v
60 60 return templ(tag, **vargs)
61 61 lastname = 'last_' + name
62 62 if lastname in templ:
63 63 last = values.pop()
64 64 else:
65 65 last = None
66 66 for v in values:
67 67 yield one(v)
68 68 if last is not None:
69 69 yield one(last, tag=lastname)
70 70 endname = 'end_' + names
71 71 if endname in templ:
72 72 yield templ(endname, **args)
73 73
74 74 def getfiles(repo, ctx, revcache):
75 75 if 'files' not in revcache:
76 76 revcache['files'] = repo.status(ctx.parents()[0].node(),
77 77 ctx.node())[:3]
78 78 return revcache['files']
79 79
80 80 def getlatesttags(repo, ctx, cache):
81 81 '''return date, distance and name for the latest tag of rev'''
82 82
83 83 if 'latesttags' not in cache:
84 84 # Cache mapping from rev to a tuple with tag date, tag
85 85 # distance and tag name
86 86 cache['latesttags'] = {-1: (0, 0, 'null')}
87 87 latesttags = cache['latesttags']
88 88
89 89 rev = ctx.rev()
90 90 todo = [rev]
91 91 while todo:
92 92 rev = todo.pop()
93 93 if rev in latesttags:
94 94 continue
95 95 ctx = repo[rev]
96 96 tags = [t for t in ctx.tags() if repo.tagtype(t) == 'global']
97 97 if tags:
98 98 latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
99 99 continue
100 100 try:
101 101 # The tuples are laid out so the right one can be found by
102 102 # comparison.
103 103 pdate, pdist, ptag = max(
104 104 latesttags[p.rev()] for p in ctx.parents())
105 105 except KeyError:
106 106 # Cache miss - recurse
107 107 todo.append(rev)
108 108 todo.extend(p.rev() for p in ctx.parents())
109 109 continue
110 110 latesttags[rev] = pdate, pdist + 1, ptag
111 111 return latesttags[rev]
112 112
113 113 def getrenamedfn(repo, endrev=None):
114 114 rcache = {}
115 115 if endrev is None:
116 116 endrev = len(repo)
117 117
118 118 def getrenamed(fn, rev):
119 119 '''looks up all renames for a file (up to endrev) the first
120 120 time the file is given. It indexes on the changerev and only
121 121 parses the manifest if linkrev != changerev.
122 122 Returns rename info for fn at changerev rev.'''
123 123 if fn not in rcache:
124 124 rcache[fn] = {}
125 125 fl = repo.file(fn)
126 126 for i in fl:
127 127 lr = fl.linkrev(i)
128 128 renamed = fl.renamed(fl.node(i))
129 129 rcache[fn][lr] = renamed
130 130 if lr >= endrev:
131 131 break
132 132 if rev in rcache[fn]:
133 133 return rcache[fn][rev]
134 134
135 135 # If linkrev != rev (i.e. rev not found in rcache) fallback to
136 136 # filectx logic.
137 137 try:
138 138 return repo[rev][fn].renamed()
139 139 except error.LookupError:
140 140 return None
141 141
142 142 return getrenamed
143 143
144 144
145 145 def showauthor(repo, ctx, templ, **args):
146 146 return ctx.user()
147 147
148 148 def showbranches(**args):
149 149 branch = args['ctx'].branch()
150 150 if branch != 'default':
151 151 return showlist('branch', [branch], plural='branches', **args)
152 152
153 153 def showchildren(**args):
154 154 ctx = args['ctx']
155 155 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
156 156 return showlist('children', childrevs, **args)
157 157
158 158 def showdate(repo, ctx, templ, **args):
159 159 return ctx.date()
160 160
161 161 def showdescription(repo, ctx, templ, **args):
162 162 return ctx.description().strip()
163 163
164 164 def showdiffstat(repo, ctx, templ, **args):
165 diff = patch.diff(repo, ctx.parents()[0].node(), ctx.node())
166 165 files, adds, removes = 0, 0, 0
167 for i in patch.diffstatdata(util.iterlines(diff)):
166 for i in patch.diffstatdata(util.iterlines(ctx.diff())):
168 167 files += 1
169 168 adds += i[1]
170 169 removes += i[2]
171 170 return '%s: +%s/-%s' % (files, adds, removes)
172 171
173 172 def showextras(**args):
174 173 templ = args['templ']
175 174 for key, value in sorted(args['ctx'].extra().items()):
176 175 args = args.copy()
177 176 args.update(dict(key=key, value=value))
178 177 yield templ('extra', **args)
179 178
180 179 def showfileadds(**args):
181 180 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
182 181 return showlist('file_add', getfiles(repo, ctx, revcache)[1], **args)
183 182
184 183 def showfilecopies(**args):
185 184 cache, ctx = args['cache'], args['ctx']
186 185 copies = args['revcache'].get('copies')
187 186 if copies is None:
188 187 if 'getrenamed' not in cache:
189 188 cache['getrenamed'] = getrenamedfn(args['repo'])
190 189 copies = []
191 190 getrenamed = cache['getrenamed']
192 191 for fn in ctx.files():
193 192 rename = getrenamed(fn, ctx.rev())
194 193 if rename:
195 194 copies.append((fn, rename[0]))
196 195
197 196 c = [{'name': x[0], 'source': x[1]} for x in copies]
198 197 return showlist('file_copy', c, plural='file_copies', **args)
199 198
200 199 # showfilecopiesswitch() displays file copies only if copy records are
201 200 # provided before calling the templater, usually with a --copies
202 201 # command line switch.
203 202 def showfilecopiesswitch(**args):
204 203 copies = args['revcache'].get('copies') or []
205 204 c = [{'name': x[0], 'source': x[1]} for x in copies]
206 205 return showlist('file_copy', c, plural='file_copies', **args)
207 206
208 207 def showfiledels(**args):
209 208 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
210 209 return showlist('file_del', getfiles(repo, ctx, revcache)[2], **args)
211 210
212 211 def showfilemods(**args):
213 212 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
214 213 return showlist('file_mod', getfiles(repo, ctx, revcache)[0], **args)
215 214
216 215 def showfiles(**args):
217 216 return showlist('file', args['ctx'].files(), **args)
218 217
219 218 def showlatesttag(repo, ctx, templ, cache, **args):
220 219 return getlatesttags(repo, ctx, cache)[2]
221 220
222 221 def showlatesttagdistance(repo, ctx, templ, cache, **args):
223 222 return getlatesttags(repo, ctx, cache)[1]
224 223
225 224 def showmanifest(**args):
226 225 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
227 226 args = args.copy()
228 227 args.update(dict(rev=repo.manifest.rev(ctx.changeset()[0]),
229 228 node=hex(ctx.changeset()[0])))
230 229 return templ('manifest', **args)
231 230
232 231 def shownode(repo, ctx, templ, **args):
233 232 return ctx.hex()
234 233
235 234 def showrev(repo, ctx, templ, **args):
236 235 return ctx.rev()
237 236
238 237 def showtags(**args):
239 238 return showlist('tag', args['ctx'].tags(), **args)
240 239
241 240 # keywords are callables like:
242 241 # fn(repo, ctx, templ, cache, revcache, **args)
243 242 # with:
244 243 # repo - current repository instance
245 244 # ctx - the changectx being displayed
246 245 # templ - the templater instance
247 246 # cache - a cache dictionary for the whole templater run
248 247 # revcache - a cache dictionary for the current revision
249 248 keywords = {
250 249 'author': showauthor,
251 250 'branches': showbranches,
252 251 'children': showchildren,
253 252 'date': showdate,
254 253 'desc': showdescription,
255 254 'diffstat': showdiffstat,
256 255 'extras': showextras,
257 256 'file_adds': showfileadds,
258 257 'file_copies': showfilecopies,
259 258 'file_copies_switch': showfilecopiesswitch,
260 259 'file_dels': showfiledels,
261 260 'file_mods': showfilemods,
262 261 'files': showfiles,
263 262 'latesttag': showlatesttag,
264 263 'latesttagdistance': showlatesttagdistance,
265 264 'manifest': showmanifest,
266 265 'node': shownode,
267 266 'rev': showrev,
268 267 'tags': showtags,
269 268 }
270 269
General Comments 0
You need to be logged in to leave comments. Login now