comparison mercurial/hgweb/hgweb_mod.py @ 7309:e74a9173c2d7

hgweb: use patch.diff() to make sensible diffs (issue1223, issue1258) This gets us git diffs when enabled and doesn't pick erratic file parents.
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Mon, 03 Nov 2008 20:05:03 +0100
parents 6e9fe4ff9c54
children bd522d09d5e3
comparison
equal deleted inserted replaced
7308:b6f5490effbf 7309:e74a9173c2d7
7 # of the GNU General Public License, incorporated herein by reference. 7 # of the GNU General Public License, incorporated herein by reference.
8 8
9 import os, mimetypes 9 import os, mimetypes
10 from mercurial.node import hex, nullid 10 from mercurial.node import hex, nullid
11 from mercurial.repo import RepoError 11 from mercurial.repo import RepoError
12 from mercurial import mdiff, ui, hg, util, patch, hook 12 from mercurial import ui, hg, util, patch, hook, match
13 from mercurial import revlog, templater, templatefilters 13 from mercurial import revlog, templater, templatefilters
14 from common import get_mtime, style_map, paritygen, countgen, ErrorResponse 14 from common import get_mtime, style_map, paritygen, countgen, ErrorResponse
15 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR 15 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
16 from common import HTTP_UNAUTHORIZED, HTTP_METHOD_NOT_ALLOWED 16 from common import HTTP_UNAUTHORIZED, HTTP_METHOD_NOT_ALLOWED
17 from request import wsgirequest 17 from request import wsgirequest
275 yield tmpl("filedifflink", node=hex(changeset), file=f) 275 yield tmpl("filedifflink", node=hex(changeset), file=f)
276 if len(files) > self.maxfiles: 276 if len(files) > self.maxfiles:
277 yield tmpl("fileellipses") 277 yield tmpl("fileellipses")
278 278
279 def diff(self, tmpl, node1, node2, files): 279 def diff(self, tmpl, node1, node2, files):
280 def filterfiles(filters, files):
281 l = [x for x in files if x in filters]
282
283 for t in filters:
284 if t and t[-1] != os.sep:
285 t += os.sep
286 l += [x for x in files if x.startswith(t)]
287 return l
288
289 parity = paritygen(self.stripecount)
290 def diffblock(diff, f, fn):
291 yield tmpl("diffblock",
292 lines=prettyprintlines(diff),
293 parity=parity.next(),
294 file=f,
295 filenode=hex(fn or nullid))
296 280
297 blockcount = countgen() 281 blockcount = countgen()
298 def prettyprintlines(diff): 282 def prettyprintlines(diff):
299 blockno = blockcount.next() 283 blockno = blockcount.next()
300 for lineno, l in enumerate(diff.splitlines(1)): 284 for lineno, l in enumerate(diff.splitlines(True)):
301 if blockno == 0: 285 if blockno == 0:
302 lineno = lineno + 1 286 lineno = lineno + 1
303 else: 287 else:
304 lineno = "%d.%d" % (blockno, lineno + 1) 288 lineno = "%d.%d" % (blockno, lineno + 1)
305 if l.startswith('+'): 289 if l.startswith('+'):
313 yield tmpl(ltype, 297 yield tmpl(ltype,
314 line=l, 298 line=l,
315 lineid="l%s" % lineno, 299 lineid="l%s" % lineno,
316 linenumber="% 8s" % lineno) 300 linenumber="% 8s" % lineno)
317 301
318 r = self.repo
319 c1 = r[node1]
320 c2 = r[node2]
321 date1 = util.datestr(c1.date())
322 date2 = util.datestr(c2.date())
323
324 modified, added, removed, deleted, unknown = r.status(node1, node2)[:5]
325 if files: 302 if files:
326 modified, added, removed = map(lambda x: filterfiles(files, x), 303 m = match.exact(self.repo.root, self.repo.getcwd(), files)
327 (modified, added, removed)) 304 else:
328 305 m = match.always(self.repo.root, self.repo.getcwd())
306
307 block = []
308 parity = paritygen(self.stripecount)
329 diffopts = patch.diffopts(self.repo.ui, untrusted=True) 309 diffopts = patch.diffopts(self.repo.ui, untrusted=True)
330 for f in modified: 310 for chunk in patch.diff(self.repo, node1, node2, m, opts=diffopts):
331 to = c1.filectx(f).data() 311 if chunk.startswith('diff') and block:
332 tn = c2.filectx(f).data() 312 yield tmpl('diffblock', parity=parity.next(),
333 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f, 313 lines=prettyprintlines(''.join(block)))
334 opts=diffopts), f, tn) 314 block = []
335 for f in added: 315 if chunk.startswith('diff'):
336 to = None 316 chunk = ''.join(chunk.splitlines(True)[1:])
337 tn = c2.filectx(f).data() 317 block.append(chunk)
338 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f, 318 yield tmpl('diffblock', parity=parity.next(),
339 opts=diffopts), f, tn) 319 lines=prettyprintlines(''.join(block)))
340 for f in removed:
341 to = c1.filectx(f).data()
342 tn = None
343 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f,
344 opts=diffopts), f, tn)
345 320
346 archive_specs = { 321 archive_specs = {
347 'bz2': ('application/x-tar', 'tbz2', '.tar.bz2', None), 322 'bz2': ('application/x-tar', 'tbz2', '.tar.bz2', None),
348 'gz': ('application/x-tar', 'tgz', '.tar.gz', None), 323 'gz': ('application/x-tar', 'tgz', '.tar.gz', None),
349 'zip': ('application/zip', 'zip', '.zip', None), 324 'zip': ('application/zip', 'zip', '.zip', None),