##// END OF EJS Templates
web: provide the file number to the diffstat templates...
Steven Brown -
r14562:fccd3b96 default
parent child Browse files
Show More
@@ -1,252 +1,254 b''
1 1 # hgweb/webutil.py - utility library for the web interface.
2 2 #
3 3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 import os, copy
10 10 from mercurial import match, patch, scmutil, error, ui, util
11 11 from mercurial.node import hex, nullid
12 12
13 13 def up(p):
14 14 if p[0] != "/":
15 15 p = "/" + p
16 16 if p[-1] == "/":
17 17 p = p[:-1]
18 18 up = os.path.dirname(p)
19 19 if up == "/":
20 20 return "/"
21 21 return up + "/"
22 22
23 23 def revnavgen(pos, pagelen, limit, nodefunc):
24 24 def seq(factor, limit=None):
25 25 if limit:
26 26 yield limit
27 27 if limit >= 20 and limit <= 40:
28 28 yield 50
29 29 else:
30 30 yield 1 * factor
31 31 yield 3 * factor
32 32 for f in seq(factor * 10):
33 33 yield f
34 34
35 35 navbefore = []
36 36 navafter = []
37 37
38 38 last = 0
39 39 for f in seq(1, pagelen):
40 40 if f < pagelen or f <= last:
41 41 continue
42 42 if f > limit:
43 43 break
44 44 last = f
45 45 if pos + f < limit:
46 46 navafter.append(("+%d" % f, hex(nodefunc(pos + f).node())))
47 47 if pos - f >= 0:
48 48 navbefore.insert(0, ("-%d" % f, hex(nodefunc(pos - f).node())))
49 49
50 50 navafter.append(("tip", "tip"))
51 51 try:
52 52 navbefore.insert(0, ("(0)", hex(nodefunc('0').node())))
53 53 except error.RepoError:
54 54 pass
55 55
56 56 def gen(l):
57 57 def f(**map):
58 58 for label, node in l:
59 59 yield {"label": label, "node": node}
60 60 return f
61 61
62 62 return (dict(before=gen(navbefore), after=gen(navafter)),)
63 63
64 64 def _siblings(siblings=[], hiderev=None):
65 65 siblings = [s for s in siblings if s.node() != nullid]
66 66 if len(siblings) == 1 and siblings[0].rev() == hiderev:
67 67 return
68 68 for s in siblings:
69 69 d = {'node': s.hex(), 'rev': s.rev()}
70 70 d['user'] = s.user()
71 71 d['date'] = s.date()
72 72 d['description'] = s.description()
73 73 d['branch'] = s.branch()
74 74 if hasattr(s, 'path'):
75 75 d['file'] = s.path()
76 76 yield d
77 77
78 78 def parents(ctx, hide=None):
79 79 return _siblings(ctx.parents(), hide)
80 80
81 81 def children(ctx, hide=None):
82 82 return _siblings(ctx.children(), hide)
83 83
84 84 def renamelink(fctx):
85 85 r = fctx.renamed()
86 86 if r:
87 87 return [dict(file=r[0], node=hex(r[1]))]
88 88 return []
89 89
90 90 def nodetagsdict(repo, node):
91 91 return [{"name": i} for i in repo.nodetags(node)]
92 92
93 93 def nodebookmarksdict(repo, node):
94 94 return [{"name": i} for i in repo.nodebookmarks(node)]
95 95
96 96 def nodebranchdict(repo, ctx):
97 97 branches = []
98 98 branch = ctx.branch()
99 99 # If this is an empty repo, ctx.node() == nullid,
100 100 # ctx.branch() == 'default', but branchtags() is
101 101 # an empty dict. Using dict.get avoids a traceback.
102 102 if repo.branchtags().get(branch) == ctx.node():
103 103 branches.append({"name": branch})
104 104 return branches
105 105
106 106 def nodeinbranch(repo, ctx):
107 107 branches = []
108 108 branch = ctx.branch()
109 109 if branch != 'default' and repo.branchtags().get(branch) != ctx.node():
110 110 branches.append({"name": branch})
111 111 return branches
112 112
113 113 def nodebranchnodefault(ctx):
114 114 branches = []
115 115 branch = ctx.branch()
116 116 if branch != 'default':
117 117 branches.append({"name": branch})
118 118 return branches
119 119
120 120 def showtag(repo, tmpl, t1, node=nullid, **args):
121 121 for t in repo.nodetags(node):
122 122 yield tmpl(t1, tag=t, **args)
123 123
124 124 def showbookmark(repo, tmpl, t1, node=nullid, **args):
125 125 for t in repo.nodebookmarks(node):
126 126 yield tmpl(t1, bookmark=t, **args)
127 127
128 128 def cleanpath(repo, path):
129 129 path = path.lstrip('/')
130 130 return scmutil.canonpath(repo.root, '', path)
131 131
132 132 def changectx(repo, req):
133 133 changeid = "tip"
134 134 if 'node' in req.form:
135 135 changeid = req.form['node'][0]
136 136 elif 'manifest' in req.form:
137 137 changeid = req.form['manifest'][0]
138 138
139 139 try:
140 140 ctx = repo[changeid]
141 141 except error.RepoError:
142 142 man = repo.manifest
143 143 ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))]
144 144
145 145 return ctx
146 146
147 147 def filectx(repo, req):
148 148 path = cleanpath(repo, req.form['file'][0])
149 149 if 'node' in req.form:
150 150 changeid = req.form['node'][0]
151 151 else:
152 152 changeid = req.form['filenode'][0]
153 153 try:
154 154 fctx = repo[changeid][path]
155 155 except error.RepoError:
156 156 fctx = repo.filectx(path, fileid=changeid)
157 157
158 158 return fctx
159 159
160 160 def listfilediffs(tmpl, files, node, max):
161 161 for f in files[:max]:
162 162 yield tmpl('filedifflink', node=hex(node), file=f)
163 163 if len(files) > max:
164 164 yield tmpl('fileellipses')
165 165
166 166 def diffs(repo, tmpl, ctx, files, parity, style):
167 167
168 168 def countgen():
169 169 start = 1
170 170 while True:
171 171 yield start
172 172 start += 1
173 173
174 174 blockcount = countgen()
175 175 def prettyprintlines(diff):
176 176 blockno = blockcount.next()
177 177 for lineno, l in enumerate(diff.splitlines(True)):
178 178 lineno = "%d.%d" % (blockno, lineno + 1)
179 179 if l.startswith('+'):
180 180 ltype = "difflineplus"
181 181 elif l.startswith('-'):
182 182 ltype = "difflineminus"
183 183 elif l.startswith('@'):
184 184 ltype = "difflineat"
185 185 else:
186 186 ltype = "diffline"
187 187 yield tmpl(ltype,
188 188 line=l,
189 189 lineid="l%s" % lineno,
190 190 linenumber="% 8s" % lineno)
191 191
192 192 if files:
193 193 m = match.exact(repo.root, repo.getcwd(), files)
194 194 else:
195 195 m = match.always(repo.root, repo.getcwd())
196 196
197 197 diffopts = patch.diffopts(repo.ui, untrusted=True)
198 198 parents = ctx.parents()
199 199 node1 = parents and parents[0].node() or nullid
200 200 node2 = ctx.node()
201 201
202 202 block = []
203 203 for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
204 204 if chunk.startswith('diff') and block:
205 205 yield tmpl('diffblock', parity=parity.next(),
206 206 lines=prettyprintlines(''.join(block)))
207 207 block = []
208 208 if chunk.startswith('diff') and style != 'raw':
209 209 chunk = ''.join(chunk.splitlines(True)[1:])
210 210 block.append(chunk)
211 211 yield tmpl('diffblock', parity=parity.next(),
212 212 lines=prettyprintlines(''.join(block)))
213 213
214 214 def diffstat(tmpl, ctx, parity):
215 215 '''Return a diffstat template for each file in the diff.'''
216 216
217 217 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
218 218 maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats)
219 219 files = ctx.files()
220 220
221 221 def pct(i):
222 222 if maxtotal == 0:
223 223 return 0
224 224 return (float(i) / maxtotal) * 100
225 225
226 fileno = 0
226 227 for filename, adds, removes, isbinary in stats:
227 228 template = filename in files and 'diffstatlink' or 'diffstatnolink'
228 229 total = adds + removes
229 yield tmpl(template, node=ctx.hex(), file=filename,
230 fileno += 1
231 yield tmpl(template, node=ctx.hex(), file=filename, fileno=fileno,
230 232 total=total, addpct=pct(adds), removepct=pct(removes),
231 233 parity=parity.next())
232 234
233 235 class sessionvars(object):
234 236 def __init__(self, vars, start='?'):
235 237 self.start = start
236 238 self.vars = vars
237 239 def __getitem__(self, key):
238 240 return self.vars[key]
239 241 def __setitem__(self, key, value):
240 242 self.vars[key] = value
241 243 def __copy__(self):
242 244 return sessionvars(copy.copy(self.vars), self.start)
243 245 def __iter__(self):
244 246 separator = self.start
245 247 for key, value in self.vars.iteritems():
246 248 yield {'name': key, 'value': str(value), 'separator': separator}
247 249 separator = '&'
248 250
249 251 class wsgiui(ui.ui):
250 252 # default termwidth breaks under mod_wsgi
251 253 def termwidth(self):
252 254 return 80
General Comments 0
You need to be logged in to leave comments. Login now