##// END OF EJS Templates
hgweb: fixes traceback for invalid files by removing top-level template...
wujek srujek -
r17302:5c64ce61 stable
parent child Browse files
Show More
@@ -1,936 +1,972 b''
1 1 #
2 2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 3 # Copyright 2005-2007 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 import os, mimetypes, re, cgi, copy
9 9 import webutil
10 10 from mercurial import error, encoding, archival, templater, templatefilters
11 from mercurial.node import short, hex
11 from mercurial.node import short, hex, nullid
12 12 from mercurial.util import binary
13 13 from common import paritygen, staticfile, get_contact, ErrorResponse
14 14 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
15 15 from mercurial import graphmod, patch
16 16 from mercurial import help as helpmod
17 17 from mercurial.i18n import _
18 18
19 19 # __all__ is populated with the allowed commands. Be sure to add to it if
20 20 # you're adding a new command, or the new command won't work.
21 21
22 22 __all__ = [
23 23 'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev',
24 24 'manifest', 'tags', 'bookmarks', 'branches', 'summary', 'filediff', 'diff',
25 25 'comparison', 'annotate', 'filelog', 'archive', 'static', 'graph', 'help',
26 26 ]
27 27
28 28 def log(web, req, tmpl):
29 29 if 'file' in req.form and req.form['file'][0]:
30 30 return filelog(web, req, tmpl)
31 31 else:
32 32 return changelog(web, req, tmpl)
33 33
34 34 def rawfile(web, req, tmpl):
35 35 guessmime = web.configbool('web', 'guessmime', False)
36 36
37 37 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
38 38 if not path:
39 39 content = manifest(web, req, tmpl)
40 40 req.respond(HTTP_OK, web.ctype)
41 41 return content
42 42
43 43 try:
44 44 fctx = webutil.filectx(web.repo, req)
45 45 except error.LookupError, inst:
46 46 try:
47 47 content = manifest(web, req, tmpl)
48 48 req.respond(HTTP_OK, web.ctype)
49 49 return content
50 50 except ErrorResponse:
51 51 raise inst
52 52
53 53 path = fctx.path()
54 54 text = fctx.data()
55 55 mt = 'application/binary'
56 56 if guessmime:
57 57 mt = mimetypes.guess_type(path)[0]
58 58 if mt is None:
59 59 mt = binary(text) and 'application/binary' or 'text/plain'
60 60 if mt.startswith('text/'):
61 61 mt += '; charset="%s"' % encoding.encoding
62 62
63 63 req.respond(HTTP_OK, mt, path, len(text))
64 64 return [text]
65 65
66 66 def _filerevision(web, tmpl, fctx):
67 67 f = fctx.path()
68 68 text = fctx.data()
69 69 parity = paritygen(web.stripecount)
70 70
71 71 if binary(text):
72 72 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
73 73 text = '(binary:%s)' % mt
74 74
75 75 def lines():
76 76 for lineno, t in enumerate(text.splitlines(True)):
77 77 yield {"line": t,
78 78 "lineid": "l%d" % (lineno + 1),
79 79 "linenumber": "% 6d" % (lineno + 1),
80 80 "parity": parity.next()}
81 81
82 82 return tmpl("filerevision",
83 83 file=f,
84 84 path=webutil.up(f),
85 85 text=lines(),
86 86 rev=fctx.rev(),
87 87 node=fctx.hex(),
88 88 author=fctx.user(),
89 89 date=fctx.date(),
90 90 desc=fctx.description(),
91 91 branch=webutil.nodebranchnodefault(fctx),
92 92 parent=webutil.parents(fctx),
93 93 child=webutil.children(fctx),
94 94 rename=webutil.renamelink(fctx),
95 95 permissions=fctx.manifest().flags(f))
96 96
97 97 def file(web, req, tmpl):
98 98 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
99 99 if not path:
100 100 return manifest(web, req, tmpl)
101 101 try:
102 102 return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
103 103 except error.LookupError, inst:
104 104 try:
105 105 return manifest(web, req, tmpl)
106 106 except ErrorResponse:
107 107 raise inst
108 108
109 109 def _search(web, req, tmpl):
110 110
111 111 query = req.form['rev'][0]
112 112 revcount = web.maxchanges
113 113 if 'revcount' in req.form:
114 114 revcount = int(req.form.get('revcount', [revcount])[0])
115 115 revcount = max(revcount, 1)
116 116 tmpl.defaults['sessionvars']['revcount'] = revcount
117 117
118 118 lessvars = copy.copy(tmpl.defaults['sessionvars'])
119 119 lessvars['revcount'] = max(revcount / 2, 1)
120 120 lessvars['rev'] = query
121 121 morevars = copy.copy(tmpl.defaults['sessionvars'])
122 122 morevars['revcount'] = revcount * 2
123 123 morevars['rev'] = query
124 124
125 125 def changelist(**map):
126 126 count = 0
127 127 lower = encoding.lower
128 128 qw = lower(query).split()
129 129
130 130 def revgen():
131 131 for i in xrange(len(web.repo) - 1, 0, -100):
132 132 l = []
133 133 for j in xrange(max(0, i - 100), i + 1):
134 134 ctx = web.repo[j]
135 135 l.append(ctx)
136 136 l.reverse()
137 137 for e in l:
138 138 yield e
139 139
140 140 for ctx in revgen():
141 141 miss = 0
142 142 for q in qw:
143 143 if not (q in lower(ctx.user()) or
144 144 q in lower(ctx.description()) or
145 145 q in lower(" ".join(ctx.files()))):
146 146 miss = 1
147 147 break
148 148 if miss:
149 149 continue
150 150
151 151 count += 1
152 152 n = ctx.node()
153 153 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
154 154 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
155 155
156 156 yield tmpl('searchentry',
157 157 parity=parity.next(),
158 158 author=ctx.user(),
159 159 parent=webutil.parents(ctx),
160 160 child=webutil.children(ctx),
161 161 changelogtag=showtags,
162 162 desc=ctx.description(),
163 163 date=ctx.date(),
164 164 files=files,
165 165 rev=ctx.rev(),
166 166 node=hex(n),
167 167 tags=webutil.nodetagsdict(web.repo, n),
168 168 bookmarks=webutil.nodebookmarksdict(web.repo, n),
169 169 inbranch=webutil.nodeinbranch(web.repo, ctx),
170 170 branches=webutil.nodebranchdict(web.repo, ctx))
171 171
172 172 if count >= revcount:
173 173 break
174 174
175 175 tip = web.repo['tip']
176 176 parity = paritygen(web.stripecount)
177 177
178 178 return tmpl('search', query=query, node=tip.hex(),
179 179 entries=changelist, archives=web.archivelist("tip"),
180 180 morevars=morevars, lessvars=lessvars)
181 181
182 182 def changelog(web, req, tmpl, shortlog=False):
183 183
184 184 if 'node' in req.form:
185 185 ctx = webutil.changectx(web.repo, req)
186 186 else:
187 187 if 'rev' in req.form:
188 188 hi = req.form['rev'][0]
189 189 else:
190 190 hi = len(web.repo) - 1
191 191 try:
192 192 ctx = web.repo[hi]
193 193 except error.RepoError:
194 194 return _search(web, req, tmpl) # XXX redirect to 404 page?
195 195
196 196 def changelist(limit=0, **map):
197 197 l = [] # build a list in forward order for efficiency
198 198 for i in xrange(start, end):
199 199 ctx = web.repo[i]
200 200 n = ctx.node()
201 201 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
202 202 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
203 203
204 204 l.insert(0, {"parity": parity.next(),
205 205 "author": ctx.user(),
206 206 "parent": webutil.parents(ctx, i - 1),
207 207 "child": webutil.children(ctx, i + 1),
208 208 "changelogtag": showtags,
209 209 "desc": ctx.description(),
210 210 "date": ctx.date(),
211 211 "files": files,
212 212 "rev": i,
213 213 "node": hex(n),
214 214 "tags": webutil.nodetagsdict(web.repo, n),
215 215 "bookmarks": webutil.nodebookmarksdict(web.repo, n),
216 216 "inbranch": webutil.nodeinbranch(web.repo, ctx),
217 217 "branches": webutil.nodebranchdict(web.repo, ctx)
218 218 })
219 219
220 220 if limit > 0:
221 221 l = l[:limit]
222 222
223 223 for e in l:
224 224 yield e
225 225
226 226 revcount = shortlog and web.maxshortchanges or web.maxchanges
227 227 if 'revcount' in req.form:
228 228 revcount = int(req.form.get('revcount', [revcount])[0])
229 229 revcount = max(revcount, 1)
230 230 tmpl.defaults['sessionvars']['revcount'] = revcount
231 231
232 232 lessvars = copy.copy(tmpl.defaults['sessionvars'])
233 233 lessvars['revcount'] = max(revcount / 2, 1)
234 234 morevars = copy.copy(tmpl.defaults['sessionvars'])
235 235 morevars['revcount'] = revcount * 2
236 236
237 237 count = len(web.repo)
238 238 pos = ctx.rev()
239 239 start = max(0, pos - revcount + 1)
240 240 end = min(count, start + revcount)
241 241 pos = end - 1
242 242 parity = paritygen(web.stripecount, offset=start - end)
243 243
244 244 changenav = webutil.revnavgen(pos, revcount, count, web.repo.changectx)
245 245
246 246 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
247 247 node=ctx.hex(), rev=pos, changesets=count,
248 248 entries=lambda **x: changelist(limit=0,**x),
249 249 latestentry=lambda **x: changelist(limit=1,**x),
250 250 archives=web.archivelist("tip"), revcount=revcount,
251 251 morevars=morevars, lessvars=lessvars)
252 252
253 253 def shortlog(web, req, tmpl):
254 254 return changelog(web, req, tmpl, shortlog = True)
255 255
256 256 def changeset(web, req, tmpl):
257 257 ctx = webutil.changectx(web.repo, req)
258 258 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
259 259 showbookmarks = webutil.showbookmark(web.repo, tmpl, 'changesetbookmark',
260 260 ctx.node())
261 261 showbranch = webutil.nodebranchnodefault(ctx)
262 262
263 263 files = []
264 264 parity = paritygen(web.stripecount)
265 265 for blockno, f in enumerate(ctx.files()):
266 266 template = f in ctx and 'filenodelink' or 'filenolink'
267 267 files.append(tmpl(template,
268 268 node=ctx.hex(), file=f, blockno=blockno + 1,
269 269 parity=parity.next()))
270 270
271 271 style = web.config('web', 'style', 'paper')
272 272 if 'style' in req.form:
273 273 style = req.form['style'][0]
274 274
275 275 parity = paritygen(web.stripecount)
276 276 diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity, style)
277 277
278 278 parity = paritygen(web.stripecount)
279 279 diffstatgen = webutil.diffstatgen(ctx)
280 280 diffstat = webutil.diffstat(tmpl, ctx, diffstatgen, parity)
281 281
282 282 return tmpl('changeset',
283 283 diff=diffs,
284 284 rev=ctx.rev(),
285 285 node=ctx.hex(),
286 286 parent=webutil.parents(ctx),
287 287 child=webutil.children(ctx),
288 288 changesettag=showtags,
289 289 changesetbookmark=showbookmarks,
290 290 changesetbranch=showbranch,
291 291 author=ctx.user(),
292 292 desc=ctx.description(),
293 293 date=ctx.date(),
294 294 files=files,
295 295 diffsummary=lambda **x: webutil.diffsummary(diffstatgen),
296 296 diffstat=diffstat,
297 297 archives=web.archivelist(ctx.hex()),
298 298 tags=webutil.nodetagsdict(web.repo, ctx.node()),
299 299 bookmarks=webutil.nodebookmarksdict(web.repo, ctx.node()),
300 300 branch=webutil.nodebranchnodefault(ctx),
301 301 inbranch=webutil.nodeinbranch(web.repo, ctx),
302 302 branches=webutil.nodebranchdict(web.repo, ctx))
303 303
304 304 rev = changeset
305 305
306 306 def decodepath(path):
307 307 """Hook for mapping a path in the repository to a path in the
308 308 working copy.
309 309
310 310 Extensions (e.g., largefiles) can override this to remap files in
311 311 the virtual file system presented by the manifest command below."""
312 312 return path
313 313
314 314 def manifest(web, req, tmpl):
315 315 ctx = webutil.changectx(web.repo, req)
316 316 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
317 317 mf = ctx.manifest()
318 318 node = ctx.node()
319 319
320 320 files = {}
321 321 dirs = {}
322 322 parity = paritygen(web.stripecount)
323 323
324 324 if path and path[-1] != "/":
325 325 path += "/"
326 326 l = len(path)
327 327 abspath = "/" + path
328 328
329 329 for full, n in mf.iteritems():
330 330 # the virtual path (working copy path) used for the full
331 331 # (repository) path
332 332 f = decodepath(full)
333 333
334 334 if f[:l] != path:
335 335 continue
336 336 remain = f[l:]
337 337 elements = remain.split('/')
338 338 if len(elements) == 1:
339 339 files[remain] = full
340 340 else:
341 341 h = dirs # need to retain ref to dirs (root)
342 342 for elem in elements[0:-1]:
343 343 if elem not in h:
344 344 h[elem] = {}
345 345 h = h[elem]
346 346 if len(h) > 1:
347 347 break
348 348 h[None] = None # denotes files present
349 349
350 350 if mf and not files and not dirs:
351 351 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
352 352
353 353 def filelist(**map):
354 354 for f in sorted(files):
355 355 full = files[f]
356 356
357 357 fctx = ctx.filectx(full)
358 358 yield {"file": full,
359 359 "parity": parity.next(),
360 360 "basename": f,
361 361 "date": fctx.date(),
362 362 "size": fctx.size(),
363 363 "permissions": mf.flags(full)}
364 364
365 365 def dirlist(**map):
366 366 for d in sorted(dirs):
367 367
368 368 emptydirs = []
369 369 h = dirs[d]
370 370 while isinstance(h, dict) and len(h) == 1:
371 371 k, v = h.items()[0]
372 372 if v:
373 373 emptydirs.append(k)
374 374 h = v
375 375
376 376 path = "%s%s" % (abspath, d)
377 377 yield {"parity": parity.next(),
378 378 "path": path,
379 379 "emptydirs": "/".join(emptydirs),
380 380 "basename": d}
381 381
382 382 return tmpl("manifest",
383 383 rev=ctx.rev(),
384 384 node=hex(node),
385 385 path=abspath,
386 386 up=webutil.up(abspath),
387 387 upparity=parity.next(),
388 388 fentries=filelist,
389 389 dentries=dirlist,
390 390 archives=web.archivelist(hex(node)),
391 391 tags=webutil.nodetagsdict(web.repo, node),
392 392 bookmarks=webutil.nodebookmarksdict(web.repo, node),
393 393 inbranch=webutil.nodeinbranch(web.repo, ctx),
394 394 branches=webutil.nodebranchdict(web.repo, ctx))
395 395
396 396 def tags(web, req, tmpl):
397 397 i = reversed(web.repo.tagslist())
398 398 parity = paritygen(web.stripecount)
399 399
400 400 def entries(notip=False, limit=0, **map):
401 401 count = 0
402 402 for k, n in i:
403 403 if notip and k == "tip":
404 404 continue
405 405 if limit > 0 and count >= limit:
406 406 continue
407 407 count = count + 1
408 408 yield {"parity": parity.next(),
409 409 "tag": k,
410 410 "date": web.repo[n].date(),
411 411 "node": hex(n)}
412 412
413 413 return tmpl("tags",
414 414 node=hex(web.repo.changelog.tip()),
415 415 entries=lambda **x: entries(False, 0, **x),
416 416 entriesnotip=lambda **x: entries(True, 0, **x),
417 417 latestentry=lambda **x: entries(True, 1, **x))
418 418
419 419 def bookmarks(web, req, tmpl):
420 420 i = web.repo._bookmarks.items()
421 421 parity = paritygen(web.stripecount)
422 422
423 423 def entries(limit=0, **map):
424 424 count = 0
425 425 for k, n in sorted(i):
426 426 if limit > 0 and count >= limit:
427 427 continue
428 428 count = count + 1
429 429 yield {"parity": parity.next(),
430 430 "bookmark": k,
431 431 "date": web.repo[n].date(),
432 432 "node": hex(n)}
433 433
434 434 return tmpl("bookmarks",
435 435 node=hex(web.repo.changelog.tip()),
436 436 entries=lambda **x: entries(0, **x),
437 437 latestentry=lambda **x: entries(1, **x))
438 438
439 439 def branches(web, req, tmpl):
440 440 tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems())
441 441 heads = web.repo.heads()
442 442 parity = paritygen(web.stripecount)
443 443 sortkey = lambda ctx: (not ctx.closesbranch(), ctx.rev())
444 444
445 445 def entries(limit, **map):
446 446 count = 0
447 447 for ctx in sorted(tips, key=sortkey, reverse=True):
448 448 if limit > 0 and count >= limit:
449 449 return
450 450 count += 1
451 451 if not web.repo.branchheads(ctx.branch()):
452 452 status = 'closed'
453 453 elif ctx.node() not in heads:
454 454 status = 'inactive'
455 455 else:
456 456 status = 'open'
457 457 yield {'parity': parity.next(),
458 458 'branch': ctx.branch(),
459 459 'status': status,
460 460 'node': ctx.hex(),
461 461 'date': ctx.date()}
462 462
463 463 return tmpl('branches', node=hex(web.repo.changelog.tip()),
464 464 entries=lambda **x: entries(0, **x),
465 465 latestentry=lambda **x: entries(1, **x))
466 466
467 467 def summary(web, req, tmpl):
468 468 i = reversed(web.repo.tagslist())
469 469
470 470 def tagentries(**map):
471 471 parity = paritygen(web.stripecount)
472 472 count = 0
473 473 for k, n in i:
474 474 if k == "tip": # skip tip
475 475 continue
476 476
477 477 count += 1
478 478 if count > 10: # limit to 10 tags
479 479 break
480 480
481 481 yield tmpl("tagentry",
482 482 parity=parity.next(),
483 483 tag=k,
484 484 node=hex(n),
485 485 date=web.repo[n].date())
486 486
487 487 def bookmarks(**map):
488 488 parity = paritygen(web.stripecount)
489 489 b = web.repo._bookmarks.items()
490 490 for k, n in sorted(b)[:10]: # limit to 10 bookmarks
491 491 yield {'parity': parity.next(),
492 492 'bookmark': k,
493 493 'date': web.repo[n].date(),
494 494 'node': hex(n)}
495 495
496 496 def branches(**map):
497 497 parity = paritygen(web.stripecount)
498 498
499 499 b = web.repo.branchtags()
500 500 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
501 501 for r, n, t in sorted(l):
502 502 yield {'parity': parity.next(),
503 503 'branch': t,
504 504 'node': hex(n),
505 505 'date': web.repo[n].date()}
506 506
507 507 def changelist(**map):
508 508 parity = paritygen(web.stripecount, offset=start - end)
509 509 l = [] # build a list in forward order for efficiency
510 510 for i in xrange(start, end):
511 511 ctx = web.repo[i]
512 512 n = ctx.node()
513 513 hn = hex(n)
514 514
515 515 l.insert(0, tmpl(
516 516 'shortlogentry',
517 517 parity=parity.next(),
518 518 author=ctx.user(),
519 519 desc=ctx.description(),
520 520 date=ctx.date(),
521 521 rev=i,
522 522 node=hn,
523 523 tags=webutil.nodetagsdict(web.repo, n),
524 524 bookmarks=webutil.nodebookmarksdict(web.repo, n),
525 525 inbranch=webutil.nodeinbranch(web.repo, ctx),
526 526 branches=webutil.nodebranchdict(web.repo, ctx)))
527 527
528 528 yield l
529 529
530 530 tip = web.repo['tip']
531 531 count = len(web.repo)
532 532 start = max(0, count - web.maxchanges)
533 533 end = min(count, start + web.maxchanges)
534 534
535 535 return tmpl("summary",
536 536 desc=web.config("web", "description", "unknown"),
537 537 owner=get_contact(web.config) or "unknown",
538 538 lastchange=tip.date(),
539 539 tags=tagentries,
540 540 bookmarks=bookmarks,
541 541 branches=branches,
542 542 shortlog=changelist,
543 543 node=tip.hex(),
544 544 archives=web.archivelist("tip"))
545 545
546 546 def filediff(web, req, tmpl):
547 547 fctx, ctx = None, None
548 548 try:
549 549 fctx = webutil.filectx(web.repo, req)
550 550 except LookupError:
551 551 ctx = webutil.changectx(web.repo, req)
552 552 path = webutil.cleanpath(web.repo, req.form['file'][0])
553 553 if path not in ctx.files():
554 554 raise
555 555
556 556 if fctx is not None:
557 557 n = fctx.node()
558 558 path = fctx.path()
559 559 ctx = fctx.changectx()
560 560 else:
561 561 n = ctx.node()
562 562 # path already defined in except clause
563 563
564 564 parity = paritygen(web.stripecount)
565 565 style = web.config('web', 'style', 'paper')
566 566 if 'style' in req.form:
567 567 style = req.form['style'][0]
568 568
569 569 diffs = webutil.diffs(web.repo, tmpl, ctx, [path], parity, style)
570 570 rename = fctx and webutil.renamelink(fctx) or []
571 571 ctx = fctx and fctx or ctx
572 572 return tmpl("filediff",
573 573 file=path,
574 574 node=hex(n),
575 575 rev=ctx.rev(),
576 576 date=ctx.date(),
577 577 desc=ctx.description(),
578 578 author=ctx.user(),
579 579 rename=rename,
580 580 branch=webutil.nodebranchnodefault(ctx),
581 581 parent=webutil.parents(ctx),
582 582 child=webutil.children(ctx),
583 583 diff=diffs)
584 584
585 585 diff = filediff
586 586
587 587 def comparison(web, req, tmpl):
588 588 ctx = webutil.changectx(web.repo, req)
589 589 if 'file' not in req.form:
590 590 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
591 591 path = webutil.cleanpath(web.repo, req.form['file'][0])
592 592 rename = path in ctx and webutil.renamelink(ctx[path]) or []
593 593
594 594 parsecontext = lambda v: v == 'full' and -1 or int(v)
595 595 if 'context' in req.form:
596 596 context = parsecontext(req.form['context'][0])
597 597 else:
598 598 context = parsecontext(web.config('web', 'comparisoncontext', '5'))
599 599
600 comparison = webutil.compare(tmpl, ctx, path, context)
600 def filelines(f):
601 if binary(f.data()):
602 mt = mimetypes.guess_type(f.path())[0]
603 if not mt:
604 mt = 'application/octet-stream'
605 return [_('(binary file %s, hash: %s)') % (mt, hex(f.filenode()))]
606 return f.data().splitlines()
607
608 if path in ctx:
609 fctx = ctx[path]
610 rightrev = fctx.filerev()
611 rightnode = fctx.filenode()
612 rightlines = filelines(fctx)
613 parents = fctx.parents()
614 if not parents:
615 leftrev = -1
616 leftnode = nullid
617 leftlines = ()
618 else:
619 pfctx = parents[0]
620 leftrev = pfctx.filerev()
621 leftnode = pfctx.filenode()
622 leftlines = filelines(pfctx)
623 else:
624 rightrev = -1
625 rightnode = nullid
626 rightlines = ()
627 fctx = ctx.parents()[0][path]
628 leftrev = fctx.filerev()
629 leftnode = fctx.filenode()
630 leftlines = filelines(fctx)
631
632 comparison = webutil.compare(tmpl, context, leftlines, rightlines)
601 633 return tmpl('filecomparison',
602 634 file=path,
603 635 node=hex(ctx.node()),
604 636 rev=ctx.rev(),
605 637 date=ctx.date(),
606 638 desc=ctx.description(),
607 639 author=ctx.user(),
608 640 rename=rename,
609 641 branch=webutil.nodebranchnodefault(ctx),
610 642 parent=webutil.parents(ctx),
611 643 child=webutil.children(ctx),
644 leftrev=leftrev,
645 leftnode=hex(leftnode),
646 rightrev=rightrev,
647 rightnode=hex(rightnode),
612 648 comparison=comparison)
613 649
614 650 def annotate(web, req, tmpl):
615 651 fctx = webutil.filectx(web.repo, req)
616 652 f = fctx.path()
617 653 parity = paritygen(web.stripecount)
618 654 diffopts = patch.diffopts(web.repo.ui, untrusted=True, section='annotate')
619 655
620 656 def annotate(**map):
621 657 last = None
622 658 if binary(fctx.data()):
623 659 mt = (mimetypes.guess_type(fctx.path())[0]
624 660 or 'application/octet-stream')
625 661 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
626 662 '(binary:%s)' % mt)])
627 663 else:
628 664 lines = enumerate(fctx.annotate(follow=True, linenumber=True,
629 665 diffopts=diffopts))
630 666 for lineno, ((f, targetline), l) in lines:
631 667 fnode = f.filenode()
632 668
633 669 if last != fnode:
634 670 last = fnode
635 671
636 672 yield {"parity": parity.next(),
637 673 "node": f.hex(),
638 674 "rev": f.rev(),
639 675 "author": f.user(),
640 676 "desc": f.description(),
641 677 "file": f.path(),
642 678 "targetline": targetline,
643 679 "line": l,
644 680 "lineid": "l%d" % (lineno + 1),
645 681 "linenumber": "% 6d" % (lineno + 1),
646 682 "revdate": f.date()}
647 683
648 684 return tmpl("fileannotate",
649 685 file=f,
650 686 annotate=annotate,
651 687 path=webutil.up(f),
652 688 rev=fctx.rev(),
653 689 node=fctx.hex(),
654 690 author=fctx.user(),
655 691 date=fctx.date(),
656 692 desc=fctx.description(),
657 693 rename=webutil.renamelink(fctx),
658 694 branch=webutil.nodebranchnodefault(fctx),
659 695 parent=webutil.parents(fctx),
660 696 child=webutil.children(fctx),
661 697 permissions=fctx.manifest().flags(f))
662 698
663 699 def filelog(web, req, tmpl):
664 700
665 701 try:
666 702 fctx = webutil.filectx(web.repo, req)
667 703 f = fctx.path()
668 704 fl = fctx.filelog()
669 705 except error.LookupError:
670 706 f = webutil.cleanpath(web.repo, req.form['file'][0])
671 707 fl = web.repo.file(f)
672 708 numrevs = len(fl)
673 709 if not numrevs: # file doesn't exist at all
674 710 raise
675 711 rev = webutil.changectx(web.repo, req).rev()
676 712 first = fl.linkrev(0)
677 713 if rev < first: # current rev is from before file existed
678 714 raise
679 715 frev = numrevs - 1
680 716 while fl.linkrev(frev) > rev:
681 717 frev -= 1
682 718 fctx = web.repo.filectx(f, fl.linkrev(frev))
683 719
684 720 revcount = web.maxshortchanges
685 721 if 'revcount' in req.form:
686 722 revcount = int(req.form.get('revcount', [revcount])[0])
687 723 revcount = max(revcount, 1)
688 724 tmpl.defaults['sessionvars']['revcount'] = revcount
689 725
690 726 lessvars = copy.copy(tmpl.defaults['sessionvars'])
691 727 lessvars['revcount'] = max(revcount / 2, 1)
692 728 morevars = copy.copy(tmpl.defaults['sessionvars'])
693 729 morevars['revcount'] = revcount * 2
694 730
695 731 count = fctx.filerev() + 1
696 732 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page
697 733 end = min(count, start + revcount) # last rev on this page
698 734 parity = paritygen(web.stripecount, offset=start - end)
699 735
700 736 def entries(limit=0, **map):
701 737 l = []
702 738
703 739 repo = web.repo
704 740 for i in xrange(start, end):
705 741 iterfctx = fctx.filectx(i)
706 742
707 743 l.insert(0, {"parity": parity.next(),
708 744 "filerev": i,
709 745 "file": f,
710 746 "node": iterfctx.hex(),
711 747 "author": iterfctx.user(),
712 748 "date": iterfctx.date(),
713 749 "rename": webutil.renamelink(iterfctx),
714 750 "parent": webutil.parents(iterfctx),
715 751 "child": webutil.children(iterfctx),
716 752 "desc": iterfctx.description(),
717 753 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
718 754 "bookmarks": webutil.nodebookmarksdict(
719 755 repo, iterfctx.node()),
720 756 "branch": webutil.nodebranchnodefault(iterfctx),
721 757 "inbranch": webutil.nodeinbranch(repo, iterfctx),
722 758 "branches": webutil.nodebranchdict(repo, iterfctx)})
723 759
724 760 if limit > 0:
725 761 l = l[:limit]
726 762
727 763 for e in l:
728 764 yield e
729 765
730 766 nodefunc = lambda x: fctx.filectx(fileid=x)
731 767 nav = webutil.revnavgen(end - 1, revcount, count, nodefunc)
732 768 return tmpl("filelog", file=f, node=fctx.hex(), nav=nav,
733 769 entries=lambda **x: entries(limit=0, **x),
734 770 latestentry=lambda **x: entries(limit=1, **x),
735 771 revcount=revcount, morevars=morevars, lessvars=lessvars)
736 772
737 773 def archive(web, req, tmpl):
738 774 type_ = req.form.get('type', [None])[0]
739 775 allowed = web.configlist("web", "allow_archive")
740 776 key = req.form['node'][0]
741 777
742 778 if type_ not in web.archives:
743 779 msg = 'Unsupported archive type: %s' % type_
744 780 raise ErrorResponse(HTTP_NOT_FOUND, msg)
745 781
746 782 if not ((type_ in allowed or
747 783 web.configbool("web", "allow" + type_, False))):
748 784 msg = 'Archive type not allowed: %s' % type_
749 785 raise ErrorResponse(HTTP_FORBIDDEN, msg)
750 786
751 787 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
752 788 cnode = web.repo.lookup(key)
753 789 arch_version = key
754 790 if cnode == key or key == 'tip':
755 791 arch_version = short(cnode)
756 792 name = "%s-%s" % (reponame, arch_version)
757 793 mimetype, artype, extension, encoding = web.archive_specs[type_]
758 794 headers = [
759 795 ('Content-Type', mimetype),
760 796 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
761 797 ]
762 798 if encoding:
763 799 headers.append(('Content-Encoding', encoding))
764 800 req.header(headers)
765 801 req.respond(HTTP_OK)
766 802 archival.archive(web.repo, req, cnode, artype, prefix=name)
767 803 return []
768 804
769 805
770 806 def static(web, req, tmpl):
771 807 fname = req.form['file'][0]
772 808 # a repo owner may set web.static in .hg/hgrc to get any file
773 809 # readable by the user running the CGI script
774 810 static = web.config("web", "static", None, untrusted=False)
775 811 if not static:
776 812 tp = web.templatepath or templater.templatepath()
777 813 if isinstance(tp, str):
778 814 tp = [tp]
779 815 static = [os.path.join(p, 'static') for p in tp]
780 816 return [staticfile(static, fname, req)]
781 817
782 818 def graph(web, req, tmpl):
783 819
784 820 rev = webutil.changectx(web.repo, req).rev()
785 821 bg_height = 39
786 822 revcount = web.maxshortchanges
787 823 if 'revcount' in req.form:
788 824 revcount = int(req.form.get('revcount', [revcount])[0])
789 825 revcount = max(revcount, 1)
790 826 tmpl.defaults['sessionvars']['revcount'] = revcount
791 827
792 828 lessvars = copy.copy(tmpl.defaults['sessionvars'])
793 829 lessvars['revcount'] = max(revcount / 2, 1)
794 830 morevars = copy.copy(tmpl.defaults['sessionvars'])
795 831 morevars['revcount'] = revcount * 2
796 832
797 833 max_rev = len(web.repo) - 1
798 834 revcount = min(max_rev, revcount)
799 835 revnode = web.repo.changelog.node(rev)
800 836 revnode_hex = hex(revnode)
801 837 uprev = min(max_rev, rev + revcount)
802 838 downrev = max(0, rev - revcount)
803 839 count = len(web.repo)
804 840 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
805 841 startrev = rev
806 842 # if starting revision is less than 60 set it to uprev
807 843 if rev < web.maxshortchanges:
808 844 startrev = uprev
809 845
810 846 dag = graphmod.dagwalker(web.repo, range(startrev, downrev - 1, -1))
811 847 tree = list(graphmod.colored(dag, web.repo))
812 848
813 849 def getcolumns(tree):
814 850 cols = 0
815 851 for (id, type, ctx, vtx, edges) in tree:
816 852 if type != graphmod.CHANGESET:
817 853 continue
818 854 cols = max(cols, max([edge[0] for edge in edges] or [0]),
819 855 max([edge[1] for edge in edges] or [0]))
820 856 return cols
821 857
822 858 def graphdata(usetuples, **map):
823 859 data = []
824 860
825 861 row = 0
826 862 for (id, type, ctx, vtx, edges) in tree:
827 863 if type != graphmod.CHANGESET:
828 864 continue
829 865 node = str(ctx)
830 866 age = templatefilters.age(ctx.date())
831 867 desc = templatefilters.firstline(ctx.description())
832 868 desc = cgi.escape(templatefilters.nonempty(desc))
833 869 user = cgi.escape(templatefilters.person(ctx.user()))
834 870 branch = ctx.branch()
835 871 try:
836 872 branchnode = web.repo.branchtip(branch)
837 873 except error.RepoLookupError:
838 874 branchnode = None
839 875 branch = branch, branchnode == ctx.node()
840 876
841 877 if usetuples:
842 878 data.append((node, vtx, edges, desc, user, age, branch,
843 879 ctx.tags(), ctx.bookmarks()))
844 880 else:
845 881 edgedata = [dict(col=edge[0], nextcol=edge[1],
846 882 color=(edge[2] - 1) % 6 + 1,
847 883 width=edge[3], bcolor=edge[4])
848 884 for edge in edges]
849 885
850 886 data.append(
851 887 dict(node=node,
852 888 col=vtx[0],
853 889 color=(vtx[1] - 1) % 6 + 1,
854 890 edges=edgedata,
855 891 row=row,
856 892 nextrow=row + 1,
857 893 desc=desc,
858 894 user=user,
859 895 age=age,
860 896 bookmarks=webutil.nodebookmarksdict(
861 897 web.repo, ctx.node()),
862 898 branches=webutil.nodebranchdict(web.repo, ctx),
863 899 inbranch=webutil.nodeinbranch(web.repo, ctx),
864 900 tags=webutil.nodetagsdict(web.repo, ctx.node())))
865 901
866 902 row += 1
867 903
868 904 return data
869 905
870 906 cols = getcolumns(tree)
871 907 rows = len(tree)
872 908 canvasheight = (rows + 1) * bg_height - 27
873 909
874 910 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
875 911 lessvars=lessvars, morevars=morevars, downrev=downrev,
876 912 cols=cols, rows=rows,
877 913 canvaswidth=(cols + 1) * bg_height,
878 914 truecanvasheight=rows * bg_height,
879 915 canvasheight=canvasheight, bg_height=bg_height,
880 916 jsdata=lambda **x: graphdata(True, **x),
881 917 nodes=lambda **x: graphdata(False, **x),
882 918 node=revnode_hex, changenav=changenav)
883 919
884 920 def _getdoc(e):
885 921 doc = e[0].__doc__
886 922 if doc:
887 923 doc = _(doc).split('\n')[0]
888 924 else:
889 925 doc = _('(no help text available)')
890 926 return doc
891 927
892 928 def help(web, req, tmpl):
893 929 from mercurial import commands # avoid cycle
894 930
895 931 topicname = req.form.get('node', [None])[0]
896 932 if not topicname:
897 933 def topics(**map):
898 934 for entries, summary, _ in helpmod.helptable:
899 935 entries = sorted(entries, key=len)
900 936 yield {'topic': entries[-1], 'summary': summary}
901 937
902 938 early, other = [], []
903 939 primary = lambda s: s.split('|')[0]
904 940 for c, e in commands.table.iteritems():
905 941 doc = _getdoc(e)
906 942 if 'DEPRECATED' in doc or c.startswith('debug'):
907 943 continue
908 944 cmd = primary(c)
909 945 if cmd.startswith('^'):
910 946 early.append((cmd[1:], doc))
911 947 else:
912 948 other.append((cmd, doc))
913 949
914 950 early.sort()
915 951 other.sort()
916 952
917 953 def earlycommands(**map):
918 954 for c, doc in early:
919 955 yield {'topic': c, 'summary': doc}
920 956
921 957 def othercommands(**map):
922 958 for c, doc in other:
923 959 yield {'topic': c, 'summary': doc}
924 960
925 961 return tmpl('helptopics', topics=topics, earlycommands=earlycommands,
926 962 othercommands=othercommands, title='Index')
927 963
928 964 u = webutil.wsgiui()
929 965 u.pushbuffer()
930 966 u.verbose = True
931 967 try:
932 968 commands.help_(u, topicname)
933 969 except error.UnknownCommand:
934 970 raise ErrorResponse(HTTP_NOT_FOUND)
935 971 doc = u.popbuffer()
936 972 return tmpl('help', topic=topicname, doc=doc)
@@ -1,370 +1,331 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 import os, mimetypes, copy
9 import os, copy
10 10 from mercurial import match, patch, scmutil, error, ui, util
11 11 from mercurial.i18n import _
12 12 from mercurial.node import hex, nullid
13 13 from common import ErrorResponse
14 14 from common import HTTP_NOT_FOUND
15 15 import difflib
16 16
17 17 def up(p):
18 18 if p[0] != "/":
19 19 p = "/" + p
20 20 if p[-1] == "/":
21 21 p = p[:-1]
22 22 up = os.path.dirname(p)
23 23 if up == "/":
24 24 return "/"
25 25 return up + "/"
26 26
27 27 def revnavgen(pos, pagelen, limit, nodefunc):
28 28 def seq(factor, limit=None):
29 29 if limit:
30 30 yield limit
31 31 if limit >= 20 and limit <= 40:
32 32 yield 50
33 33 else:
34 34 yield 1 * factor
35 35 yield 3 * factor
36 36 for f in seq(factor * 10):
37 37 yield f
38 38
39 39 navbefore = []
40 40 navafter = []
41 41
42 42 last = 0
43 43 for f in seq(1, pagelen):
44 44 if f < pagelen or f <= last:
45 45 continue
46 46 if f > limit:
47 47 break
48 48 last = f
49 49 if pos + f < limit:
50 50 navafter.append(("+%d" % f, hex(nodefunc(pos + f).node())))
51 51 if pos - f >= 0:
52 52 navbefore.insert(0, ("-%d" % f, hex(nodefunc(pos - f).node())))
53 53
54 54 navafter.append(("tip", "tip"))
55 55 try:
56 56 navbefore.insert(0, ("(0)", hex(nodefunc('0').node())))
57 57 except error.RepoError:
58 58 pass
59 59
60 60 def gen(l):
61 61 def f(**map):
62 62 for label, node in l:
63 63 yield {"label": label, "node": node}
64 64 return f
65 65
66 66 return (dict(before=gen(navbefore), after=gen(navafter)),)
67 67
68 68 def _siblings(siblings=[], hiderev=None):
69 69 siblings = [s for s in siblings if s.node() != nullid]
70 70 if len(siblings) == 1 and siblings[0].rev() == hiderev:
71 71 return
72 72 for s in siblings:
73 73 d = {'node': s.hex(), 'rev': s.rev()}
74 74 d['user'] = s.user()
75 75 d['date'] = s.date()
76 76 d['description'] = s.description()
77 77 d['branch'] = s.branch()
78 78 if util.safehasattr(s, 'path'):
79 79 d['file'] = s.path()
80 80 yield d
81 81
82 82 def parents(ctx, hide=None):
83 83 return _siblings(ctx.parents(), hide)
84 84
85 85 def children(ctx, hide=None):
86 86 return _siblings(ctx.children(), hide)
87 87
88 88 def renamelink(fctx):
89 89 r = fctx.renamed()
90 90 if r:
91 91 return [dict(file=r[0], node=hex(r[1]))]
92 92 return []
93 93
94 94 def nodetagsdict(repo, node):
95 95 return [{"name": i} for i in repo.nodetags(node)]
96 96
97 97 def nodebookmarksdict(repo, node):
98 98 return [{"name": i} for i in repo.nodebookmarks(node)]
99 99
100 100 def nodebranchdict(repo, ctx):
101 101 branches = []
102 102 branch = ctx.branch()
103 103 # If this is an empty repo, ctx.node() == nullid,
104 104 # ctx.branch() == 'default'.
105 105 try:
106 106 branchnode = repo.branchtip(branch)
107 107 except error.RepoLookupError:
108 108 branchnode = None
109 109 if branchnode == ctx.node():
110 110 branches.append({"name": branch})
111 111 return branches
112 112
113 113 def nodeinbranch(repo, ctx):
114 114 branches = []
115 115 branch = ctx.branch()
116 116 try:
117 117 branchnode = repo.branchtip(branch)
118 118 except error.RepoLookupError:
119 119 branchnode = None
120 120 if branch != 'default' and branchnode != ctx.node():
121 121 branches.append({"name": branch})
122 122 return branches
123 123
124 124 def nodebranchnodefault(ctx):
125 125 branches = []
126 126 branch = ctx.branch()
127 127 if branch != 'default':
128 128 branches.append({"name": branch})
129 129 return branches
130 130
131 131 def showtag(repo, tmpl, t1, node=nullid, **args):
132 132 for t in repo.nodetags(node):
133 133 yield tmpl(t1, tag=t, **args)
134 134
135 135 def showbookmark(repo, tmpl, t1, node=nullid, **args):
136 136 for t in repo.nodebookmarks(node):
137 137 yield tmpl(t1, bookmark=t, **args)
138 138
139 139 def cleanpath(repo, path):
140 140 path = path.lstrip('/')
141 141 return scmutil.canonpath(repo.root, '', path)
142 142
143 143 def changectx(repo, req):
144 144 changeid = "tip"
145 145 if 'node' in req.form:
146 146 changeid = req.form['node'][0]
147 147 elif 'manifest' in req.form:
148 148 changeid = req.form['manifest'][0]
149 149
150 150 try:
151 151 ctx = repo[changeid]
152 152 except error.RepoError:
153 153 man = repo.manifest
154 154 ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))]
155 155
156 156 return ctx
157 157
158 158 def filectx(repo, req):
159 159 if 'file' not in req.form:
160 160 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
161 161 path = cleanpath(repo, req.form['file'][0])
162 162 if 'node' in req.form:
163 163 changeid = req.form['node'][0]
164 164 elif 'filenode' in req.form:
165 165 changeid = req.form['filenode'][0]
166 166 else:
167 167 raise ErrorResponse(HTTP_NOT_FOUND, 'node or filenode not given')
168 168 try:
169 169 fctx = repo[changeid][path]
170 170 except error.RepoError:
171 171 fctx = repo.filectx(path, fileid=changeid)
172 172
173 173 return fctx
174 174
175 175 def listfilediffs(tmpl, files, node, max):
176 176 for f in files[:max]:
177 177 yield tmpl('filedifflink', node=hex(node), file=f)
178 178 if len(files) > max:
179 179 yield tmpl('fileellipses')
180 180
181 181 def diffs(repo, tmpl, ctx, files, parity, style):
182 182
183 183 def countgen():
184 184 start = 1
185 185 while True:
186 186 yield start
187 187 start += 1
188 188
189 189 blockcount = countgen()
190 190 def prettyprintlines(diff, blockno):
191 191 for lineno, l in enumerate(diff.splitlines(True)):
192 192 lineno = "%d.%d" % (blockno, lineno + 1)
193 193 if l.startswith('+'):
194 194 ltype = "difflineplus"
195 195 elif l.startswith('-'):
196 196 ltype = "difflineminus"
197 197 elif l.startswith('@'):
198 198 ltype = "difflineat"
199 199 else:
200 200 ltype = "diffline"
201 201 yield tmpl(ltype,
202 202 line=l,
203 203 lineid="l%s" % lineno,
204 204 linenumber="% 8s" % lineno)
205 205
206 206 if files:
207 207 m = match.exact(repo.root, repo.getcwd(), files)
208 208 else:
209 209 m = match.always(repo.root, repo.getcwd())
210 210
211 211 diffopts = patch.diffopts(repo.ui, untrusted=True)
212 212 parents = ctx.parents()
213 213 node1 = parents and parents[0].node() or nullid
214 214 node2 = ctx.node()
215 215
216 216 block = []
217 217 for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
218 218 if chunk.startswith('diff') and block:
219 219 blockno = blockcount.next()
220 220 yield tmpl('diffblock', parity=parity.next(), blockno=blockno,
221 221 lines=prettyprintlines(''.join(block), blockno))
222 222 block = []
223 223 if chunk.startswith('diff') and style != 'raw':
224 224 chunk = ''.join(chunk.splitlines(True)[1:])
225 225 block.append(chunk)
226 226 blockno = blockcount.next()
227 227 yield tmpl('diffblock', parity=parity.next(), blockno=blockno,
228 228 lines=prettyprintlines(''.join(block), blockno))
229 229
230 def compare(tmpl, ctx, path, context):
230 def compare(tmpl, context, leftlines, rightlines):
231 231 '''Generator function that provides side-by-side comparison data.'''
232 232
233 def filelines(f):
234 if util.binary(f.data()):
235 mt = mimetypes.guess_type(f.path())[0]
236 if not mt:
237 mt = 'application/octet-stream'
238 return [_('(binary file %s, hash: %s)') % (mt, hex(f.filenode()))]
239 return f.data().splitlines()
240
241 233 def compline(type, leftlineno, leftline, rightlineno, rightline):
242 234 lineid = leftlineno and ("l%s" % leftlineno) or ''
243 235 lineid += rightlineno and ("r%s" % rightlineno) or ''
244 236 return tmpl('comparisonline',
245 237 type=type,
246 238 lineid=lineid,
247 239 leftlinenumber="% 6s" % (leftlineno or ''),
248 240 leftline=leftline or '',
249 241 rightlinenumber="% 6s" % (rightlineno or ''),
250 242 rightline=rightline or '')
251 243
252 244 def getblock(opcodes):
253 245 for type, llo, lhi, rlo, rhi in opcodes:
254 246 len1 = lhi - llo
255 247 len2 = rhi - rlo
256 248 count = min(len1, len2)
257 249 for i in xrange(count):
258 250 yield compline(type=type,
259 251 leftlineno=llo + i + 1,
260 252 leftline=leftlines[llo + i],
261 253 rightlineno=rlo + i + 1,
262 254 rightline=rightlines[rlo + i])
263 255 if len1 > len2:
264 256 for i in xrange(llo + count, lhi):
265 257 yield compline(type=type,
266 258 leftlineno=i + 1,
267 259 leftline=leftlines[i],
268 260 rightlineno=None,
269 261 rightline=None)
270 262 elif len2 > len1:
271 263 for i in xrange(rlo + count, rhi):
272 264 yield compline(type=type,
273 265 leftlineno=None,
274 266 leftline=None,
275 267 rightlineno=i + 1,
276 268 rightline=rightlines[i])
277 269
278 if path in ctx:
279 fctx = ctx[path]
280 rightrev = fctx.filerev()
281 rightnode = fctx.filenode()
282 rightlines = filelines(fctx)
283 parents = fctx.parents()
284 if not parents:
285 leftrev = -1
286 leftnode = nullid
287 leftlines = ()
288 else:
289 pfctx = parents[0]
290 leftrev = pfctx.filerev()
291 leftnode = pfctx.filenode()
292 leftlines = filelines(pfctx)
293 else:
294 rightrev = -1
295 rightnode = nullid
296 rightlines = ()
297 fctx = ctx.parents()[0][path]
298 leftrev = fctx.filerev()
299 leftnode = fctx.filenode()
300 leftlines = filelines(fctx)
301
302 270 s = difflib.SequenceMatcher(None, leftlines, rightlines)
303 271 if context < 0:
304 blocks = [tmpl('comparisonblock', lines=getblock(s.get_opcodes()))]
272 yield tmpl('comparisonblock', lines=getblock(s.get_opcodes()))
305 273 else:
306 blocks = (tmpl('comparisonblock', lines=getblock(oc))
307 for oc in s.get_grouped_opcodes(n=context))
308
309 yield tmpl('comparison',
310 leftrev=leftrev,
311 leftnode=hex(leftnode),
312 rightrev=rightrev,
313 rightnode=hex(rightnode),
314 blocks=blocks)
274 for oc in s.get_grouped_opcodes(n=context):
275 yield tmpl('comparisonblock', lines=getblock(oc))
315 276
316 277 def diffstatgen(ctx):
317 278 '''Generator function that provides the diffstat data.'''
318 279
319 280 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
320 281 maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats)
321 282 while True:
322 283 yield stats, maxname, maxtotal, addtotal, removetotal, binary
323 284
324 285 def diffsummary(statgen):
325 286 '''Return a short summary of the diff.'''
326 287
327 288 stats, maxname, maxtotal, addtotal, removetotal, binary = statgen.next()
328 289 return _(' %d files changed, %d insertions(+), %d deletions(-)\n') % (
329 290 len(stats), addtotal, removetotal)
330 291
331 292 def diffstat(tmpl, ctx, statgen, parity):
332 293 '''Return a diffstat template for each file in the diff.'''
333 294
334 295 stats, maxname, maxtotal, addtotal, removetotal, binary = statgen.next()
335 296 files = ctx.files()
336 297
337 298 def pct(i):
338 299 if maxtotal == 0:
339 300 return 0
340 301 return (float(i) / maxtotal) * 100
341 302
342 303 fileno = 0
343 304 for filename, adds, removes, isbinary in stats:
344 305 template = filename in files and 'diffstatlink' or 'diffstatnolink'
345 306 total = adds + removes
346 307 fileno += 1
347 308 yield tmpl(template, node=ctx.hex(), file=filename, fileno=fileno,
348 309 total=total, addpct=pct(adds), removepct=pct(removes),
349 310 parity=parity.next())
350 311
351 312 class sessionvars(object):
352 313 def __init__(self, vars, start='?'):
353 314 self.start = start
354 315 self.vars = vars
355 316 def __getitem__(self, key):
356 317 return self.vars[key]
357 318 def __setitem__(self, key, value):
358 319 self.vars[key] = value
359 320 def __copy__(self):
360 321 return sessionvars(copy.copy(self.vars), self.start)
361 322 def __iter__(self):
362 323 separator = self.start
363 324 for key, value in self.vars.iteritems():
364 325 yield {'name': key, 'value': str(value), 'separator': separator}
365 326 separator = '&'
366 327
367 328 class wsgiui(ui.ui):
368 329 # default termwidth breaks under mod_wsgi
369 330 def termwidth(self):
370 331 return 80
@@ -1,235 +1,225 b''
1 1 default = 'shortlog'
2 2
3 3 mimetype = 'text/html; charset={encoding}'
4 4 header = header.tmpl
5 5 footer = ../paper/footer.tmpl
6 6 search = ../paper/search.tmpl
7 7
8 8 changelog = ../paper/shortlog.tmpl
9 9 shortlog = ../paper/shortlog.tmpl
10 10 shortlogentry = ../paper/shortlogentry.tmpl
11 11 graph = ../paper/graph.tmpl
12 12
13 13 help = ../paper/help.tmpl
14 14 helptopics = ../paper/helptopics.tmpl
15 15
16 16 helpentry = '<tr><td><a href="{url}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
17 17
18 18 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
19 19 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
20 20 navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
21 21 filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
22 22 filedifflink = '<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
23 23 filenodelink = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
24 24 filenolink = '{file|escape} '
25 25 fileellipses = '...'
26 26 diffstatlink = ../paper/diffstat.tmpl
27 27 diffstatnolink = ../paper/diffstat.tmpl
28 28 changelogentry = ../paper/shortlogentry.tmpl
29 29 searchentry = ../paper/shortlogentry.tmpl
30 30 changeset = ../paper/changeset.tmpl
31 31 manifest = ../paper/manifest.tmpl
32 32
33 33 nav = '{before%naventry} {after%naventry}'
34 34 navshort = '{before%navshortentry}{after%navshortentry}'
35 35 navgraph = '{before%navgraphentry}{after%navgraphentry}'
36 36 filenav = '{before%filenaventry}{after%filenaventry}'
37 37
38 38 direntry = '
39 39 <tr class="fileline parity{parity}">
40 40 <td class="name">
41 41 <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">
42 42 <img src="{staticurl}coal-folder.png" alt="dir."/> {basename|escape}/
43 43 </a>
44 44 <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">
45 45 {emptydirs|escape}
46 46 </a>
47 47 </td>
48 48 <td class="size"></td>
49 49 <td class="permissions">drwxr-xr-x</td>
50 50 </tr>'
51 51
52 52 fileentry = '
53 53 <tr class="fileline parity{parity}">
54 54 <td class="filename">
55 55 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
56 56 <img src="{staticurl}coal-file.png" alt="file"/> {basename|escape}
57 57 </a>
58 58 </td>
59 59 <td class="size">{size}</td>
60 60 <td class="permissions">{permissions|permissions}</td>
61 61 </tr>'
62 62
63 63 filerevision = ../paper/filerevision.tmpl
64 64 fileannotate = ../paper/fileannotate.tmpl
65 65 filediff = ../paper/filediff.tmpl
66 66 filecomparison = ../paper/filecomparison.tmpl
67 67 filelog = ../paper/filelog.tmpl
68 68 fileline = '
69 69 <div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
70 70 filelogentry = ../paper/filelogentry.tmpl
71 71
72 72 annotateline = '
73 73 <tr class="parity{parity}">
74 74 <td class="annotate">
75 75 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#{targetline}"
76 76 title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
77 77 </td>
78 78 <td class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</td>
79 79 </tr>'
80 80
81 81 diffblock = '<div class="source bottomline parity{parity}"><pre>{lines}</pre></div>'
82 82 difflineplus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="plusline">{line|escape}</span>'
83 83 difflineminus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="minusline">{line|escape}</span>'
84 84 difflineat = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="atline">{line|escape}</span>'
85 85 diffline = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}'
86 86
87 comparison = '
88 <table class="bigtable">
89 <thead class="header">
90 <tr>
91 <th>{leftrev}:{leftnode|short}</th>
92 <th>{rightrev}:{rightnode|short}</th>
93 </tr>
94 </thead>
95 {blocks}
96 </table>'
97 87 comparisonblock ='
98 88 <tbody class="block">
99 89 {lines}
100 90 </tbody>'
101 91 comparisonline = '
102 92 <tr>
103 93 <td class="source {type}"><a href="#{lineid}" id="{lineid}">{leftlinenumber}</a> {leftline|escape}</td>
104 94 <td class="source {type}"><a href="#{lineid}" id="{lineid}">{rightlinenumber}</a> {rightline|escape}</td>
105 95 </tr>'
106 96
107 97 changelogparent = '
108 98 <tr>
109 99 <th class="parent">parent {rev}:</th>
110 100 <td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
111 101 </tr>'
112 102
113 103 changesetparent = '<a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a> '
114 104
115 105 filerevparent = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a> '
116 106 filerevchild = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a> '
117 107
118 108 filerename = '{file|escape}@'
119 109 filelogrename = '
120 110 <span class="base">
121 111 base
122 112 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
123 113 {file|escape}@{node|short}
124 114 </a>
125 115 </span>'
126 116 fileannotateparent = '
127 117 <tr>
128 118 <td class="metatag">parent:</td>
129 119 <td>
130 120 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
131 121 {rename%filerename}{node|short}
132 122 </a>
133 123 </td>
134 124 </tr>'
135 125 changesetchild = ' <a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>'
136 126 changelogchild = '
137 127 <tr>
138 128 <th class="child">child</th>
139 129 <td class="child">
140 130 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
141 131 {node|short}
142 132 </a>
143 133 </td>
144 134 </tr>'
145 135 fileannotatechild = '
146 136 <tr>
147 137 <td class="metatag">child:</td>
148 138 <td>
149 139 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
150 140 {node|short}
151 141 </a>
152 142 </td>
153 143 </tr>'
154 144 tags = ../paper/tags.tmpl
155 145 tagentry = '
156 146 <tr class="tagEntry parity{parity}">
157 147 <td>
158 148 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
159 149 {tag|escape}
160 150 </a>
161 151 </td>
162 152 <td class="node">
163 153 {node|short}
164 154 </td>
165 155 </tr>'
166 156 bookmarks = ../paper/bookmarks.tmpl
167 157 bookmarkentry = '
168 158 <tr class="tagEntry parity{parity}">
169 159 <td>
170 160 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
171 161 {bookmark|escape}
172 162 </a>
173 163 </td>
174 164 <td class="node">
175 165 {node|short}
176 166 </td>
177 167 </tr>'
178 168 branches = ../paper/branches.tmpl
179 169 branchentry = '
180 170 <tr class="tagEntry parity{parity}">
181 171 <td>
182 172 <a href="{url}shortlog/{node|short}{sessionvars%urlparameter}" class="{status}">
183 173 {branch|escape}
184 174 </a>
185 175 </td>
186 176 <td class="node">
187 177 {node|short}
188 178 </td>
189 179 </tr>'
190 180 changelogtag = '<span class="tag">{name|escape}</span> '
191 181 changesettag = '<span class="tag">{tag|escape}</span> '
192 182 changesetbookmark = '<span class="tag">{bookmark|escape}</span> '
193 183 changelogbranchhead = '<span class="branchhead">{name|escape}</span> '
194 184 changelogbranchname = '<span class="branchname">{name|escape}</span> '
195 185
196 186 filediffparent = '
197 187 <tr>
198 188 <th class="parent">parent {rev}:</th>
199 189 <td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
200 190 </tr>'
201 191 filelogparent = '
202 192 <tr>
203 193 <th>parent {rev}:</th>
204 194 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
205 195 </tr>'
206 196 filediffchild = '
207 197 <tr>
208 198 <th class="child">child {rev}:</th>
209 199 <td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
210 200 </td>
211 201 </tr>'
212 202 filelogchild = '
213 203 <tr>
214 204 <th>child {rev}:</th>
215 205 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
216 206 </tr>'
217 207
218 208 indexentry = '
219 209 <tr class="parity{parity}">
220 210 <td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td>
221 211 <td>{description}</td>
222 212 <td>{contact|obfuscate}</td>
223 213 <td class="age">{lastchange|rfc822date}</td>
224 214 <td class="indexlinks">{archives%indexarchiveentry}</td>
225 215 </tr>\n'
226 216 indexarchiveentry = '<a href="{url}archive/{node|short}{extension|urlescape}">&nbsp;&darr;{type|escape}</a>'
227 217 index = ../paper/index.tmpl
228 218 archiveentry = '
229 219 <li>
230 220 <a href="{url}archive/{node|short}{extension|urlescape}">{type|escape}</a>
231 221 </li>'
232 222 notfound = ../paper/notfound.tmpl
233 223 error = ../paper/error.tmpl
234 224 urlparameter = '{separator}{name}={value|urlescape}'
235 225 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
@@ -1,63 +1,71 b''
1 1 {header}
2 2 <title>{repo|escape}: comparison {file|escape}</title>
3 3 <link rel="alternate" type="application/atom+xml"
4 4 href="{url}atom-log" title="Atom feed for {repo|escape}"/>
5 5 <link rel="alternate" type="application/rss+xml"
6 6 href="{url}rss-log" title="RSS feed for {repo|escape}"/>
7 7 </head>
8 8 <body>
9 9
10 10 <div class="page_header">
11 11 <a href="{logourl}" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / comparison
12 12 </div>
13 13
14 14 <div class="page_nav">
15 15 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
16 16 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
17 17 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
18 18 <a href="{url}graph{sessionvars%urlparameter}">graph</a> |
19 19 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
20 20 <a href="{url}bookmarks{sessionvars%urlparameter}">bookmarks</a> |
21 21 <a href="{url}branches{sessionvars%urlparameter}">branches</a> |
22 22 <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">files</a> |
23 23 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
24 24 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
25 25 <a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a> |
26 26 <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
27 27 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
28 28 <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
29 29 comparison |
30 30 <a href="{url}raw-diff/{node|short}/{file|urlescape}">raw</a> |
31 31 <a href="{url}help{sessionvars%urlparameter}">help</a>
32 32 <br/>
33 33 </div>
34 34
35 35 <div class="title">{file|escape}</div>
36 36
37 37 <table>
38 38 {branch%filerevbranch}
39 39 <tr>
40 40 <td>changeset {rev}</td>
41 41 <td style="font-family:monospace"><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>
42 42 {parent%filecompparent}
43 43 {child%filecompchild}
44 44 </table>
45 45
46 46 <div class="list_head"></div>
47 47
48 48 <div class="page_body">
49 49
50 50 <div class="legend">
51 51 <span class="legendinfo equal">equal</span>
52 52 <span class="legendinfo delete">deleted</span>
53 53 <span class="legendinfo insert">inserted</span>
54 54 <span class="legendinfo replace">replaced</span>
55 55 </div>
56 56
57 57 <div class="comparison">
58 {comparison}
58 <table style="border-collapse:collapse;">
59 <thead class="header">
60 <tr>
61 <th>{leftrev}:{leftnode|short}</th>
62 <th>{rightrev}:{rightnode|short}</th>
63 </tr>
64 </thead>
65 {comparison}
66 </table>
59 67 </div>
60 68
61 69 </div>
62 70
63 71 {footer}
@@ -1,312 +1,302 b''
1 1 default = 'summary'
2 2 mimetype = 'text/html; charset={encoding}'
3 3 header = header.tmpl
4 4 footer = footer.tmpl
5 5 search = search.tmpl
6 6 changelog = changelog.tmpl
7 7 summary = summary.tmpl
8 8 error = error.tmpl
9 9 notfound = notfound.tmpl
10 10
11 11 help = help.tmpl
12 12 helptopics = helptopics.tmpl
13 13
14 14 helpentry = '<tr><td><a href="{url}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
15 15
16 16 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
17 17 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
18 18 navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
19 19 filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
20 20 filedifflink = '<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
21 21 filenodelink = '
22 22 <tr class="parity{parity}">
23 23 <td><a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a></td>
24 24 <td></td>
25 25 <td class="link">
26 26 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
27 27 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
28 28 <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
29 29 <a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
30 30 <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
31 31 </td>
32 32 </tr>'
33 33 filenolink = '
34 34 <tr class="parity{parity}">
35 35 <td><a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a></td>
36 36 <td></td>
37 37 <td class="link">
38 38 file |
39 39 annotate |
40 40 <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
41 41 <a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
42 42 <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
43 43 </td>
44 44 </tr>'
45 45
46 46 nav = '{before%naventry} {after%naventry}'
47 47 navshort = '{before%navshortentry}{after%navshortentry}'
48 48 navgraph = '{before%navgraphentry}{after%navgraphentry}'
49 49 filenav = '{before%filenaventry}{after%filenaventry}'
50 50
51 51 fileellipses = '...'
52 52 changelogentry = changelogentry.tmpl
53 53 searchentry = changelogentry.tmpl
54 54 changeset = changeset.tmpl
55 55 manifest = manifest.tmpl
56 56 direntry = '
57 57 <tr class="parity{parity}">
58 58 <td style="font-family:monospace">drwxr-xr-x</td>
59 59 <td style="font-family:monospace"></td>
60 60 <td style="font-family:monospace"></td>
61 61 <td>
62 62 <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">{basename|escape}</a>
63 63 <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">{emptydirs|escape}</a>
64 64 </td>
65 65 <td class="link">
66 66 <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">files</a>
67 67 </td>
68 68 </tr>'
69 69 fileentry = '
70 70 <tr class="parity{parity}">
71 71 <td style="font-family:monospace">{permissions|permissions}</td>
72 72 <td style="font-family:monospace" align=right>{date|isodate}</td>
73 73 <td style="font-family:monospace" align=right>{size}</td>
74 74 <td class="list">
75 75 <a class="list" href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{basename|escape}</a>
76 76 </td>
77 77 <td class="link">
78 78 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
79 79 <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
80 80 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a>
81 81 </td>
82 82 </tr>'
83 83 filerevision = filerevision.tmpl
84 84 fileannotate = fileannotate.tmpl
85 85 filediff = filediff.tmpl
86 86 filecomparison = filecomparison.tmpl
87 87 filelog = filelog.tmpl
88 88 fileline = '
89 89 <div style="font-family:monospace" class="parity{parity}">
90 90 <pre><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</pre>
91 91 </div>'
92 92 annotateline = '
93 93 <tr style="font-family:monospace" class="parity{parity}">
94 94 <td class="linenr" style="text-align: right;">
95 95 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
96 96 title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
97 97 </td>
98 98 <td><pre><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a></pre></td>
99 99 <td><pre>{line|escape}</pre></td>
100 100 </tr>'
101 101 difflineplus = '<span style="color:#008800;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
102 102 difflineminus = '<span style="color:#cc0000;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
103 103 difflineat = '<span style="color:#990099;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
104 104 diffline = '<span><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
105 105
106 comparison = '
107 <table style="border-collapse:collapse;">
108 <thead class="header">
109 <tr>
110 <th>{leftrev}:{leftnode|short}</th>
111 <th>{rightrev}:{rightnode|short}</th>
112 </tr>
113 </thead>
114 {blocks}
115 </table>'
116 106 comparisonblock ='
117 107 <tbody class="block">
118 108 {lines}
119 109 </tbody>'
120 110 comparisonline = '
121 111 <tr style="font-family:monospace">
122 112 <td class="{type}"><pre><a class="linenr" href="#{lineid}" id="{lineid}">{leftlinenumber}</a> {leftline|escape}</pre></td>
123 113 <td class="{type}"><pre><a class="linenr" href="#{lineid}" id="{lineid}">{rightlinenumber}</a> {rightline|escape}</pre></td>
124 114 </tr>'
125 115
126 116 changelogparent = '
127 117 <tr>
128 118 <th class="parent">parent {rev}:</th>
129 119 <td class="parent">
130 120 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
131 121 </td>
132 122 </tr>'
133 123 changesetbranch = '<tr><td>branch</td><td>{name}</td></tr>'
134 124 changesetparent = '
135 125 <tr>
136 126 <td>parent {rev}</td>
137 127 <td style="font-family:monospace">
138 128 <a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
139 129 </td>
140 130 </tr>'
141 131 filerevbranch = '<tr><td>branch</td><td>{name}</td></tr>'
142 132 filerevparent = '
143 133 <tr>
144 134 <td>parent {rev}</td>
145 135 <td style="font-family:monospace">
146 136 <a class="list" href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
147 137 {rename%filerename}{node|short}
148 138 </a>
149 139 </td>
150 140 </tr>'
151 141 filerename = '{file|escape}@'
152 142 filelogrename = '| <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">base</a>'
153 143 fileannotateparent = '
154 144 <tr>
155 145 <td>parent {rev}</td>
156 146 <td style="font-family:monospace">
157 147 <a class="list" href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
158 148 {rename%filerename}{node|short}
159 149 </a>
160 150 </td>
161 151 </tr>'
162 152 changelogchild = '
163 153 <tr>
164 154 <th class="child">child {rev}:</th>
165 155 <td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
166 156 </tr>'
167 157 changesetchild = '
168 158 <tr>
169 159 <td>child {rev}</td>
170 160 <td style="font-family:monospace">
171 161 <a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
172 162 </td>
173 163 </tr>'
174 164 filerevchild = '
175 165 <tr>
176 166 <td>child {rev}</td>
177 167 <td style="font-family:monospace">
178 168 <a class="list" href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
179 169 </tr>'
180 170 fileannotatechild = '
181 171 <tr>
182 172 <td>child {rev}</td>
183 173 <td style="font-family:monospace">
184 174 <a class="list" href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
185 175 </tr>'
186 176 tags = tags.tmpl
187 177 tagentry = '
188 178 <tr class="parity{parity}">
189 179 <td class="age"><i class="age">{date|rfc822date}</i></td>
190 180 <td><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}"><b>{tag|escape}</b></a></td>
191 181 <td class="link">
192 182 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
193 183 <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> |
194 184 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
195 185 </td>
196 186 </tr>'
197 187 bookmarks = bookmarks.tmpl
198 188 bookmarkentry = '
199 189 <tr class="parity{parity}">
200 190 <td class="age"><i class="age">{date|rfc822date}</i></td>
201 191 <td><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}"><b>{bookmark|escape}</b></a></td>
202 192 <td class="link">
203 193 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
204 194 <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> |
205 195 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
206 196 </td>
207 197 </tr>'
208 198 branches = branches.tmpl
209 199 branchentry = '
210 200 <tr class="parity{parity}">
211 201 <td class="age"><i class="age">{date|rfc822date}</i></td>
212 202 <td><a class="list" href="{url}shortlog/{node|short}{sessionvars%urlparameter}"><b>{node|short}</b></a></td>
213 203 <td class="{status}">{branch|escape}</td>
214 204 <td class="link">
215 205 <a href="{url}changeset/{node|short}{sessionvars%urlparameter}">changeset</a> |
216 206 <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> |
217 207 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
218 208 </td>
219 209 </tr>'
220 210 diffblock = '<pre>{lines}</pre>'
221 211 filediffparent = '
222 212 <tr>
223 213 <td>parent {rev}</td>
224 214 <td style="font-family:monospace">
225 215 <a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
226 216 {node|short}
227 217 </a>
228 218 </td>
229 219 </tr>'
230 220 filecompparent = '
231 221 <tr>
232 222 <td>parent {rev}</td>
233 223 <td style="font-family:monospace">
234 224 <a class="list" href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
235 225 {node|short}
236 226 </a>
237 227 </td>
238 228 </tr>'
239 229 filelogparent = '
240 230 <tr>
241 231 <td align="right">parent {rev}:&nbsp;</td>
242 232 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
243 233 </tr>'
244 234 filediffchild = '
245 235 <tr>
246 236 <td>child {rev}</td>
247 237 <td style="font-family:monospace">
248 238 <a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a>
249 239 </td>
250 240 </tr>'
251 241 filecompchild = '
252 242 <tr>
253 243 <td>child {rev}</td>
254 244 <td style="font-family:monospace">
255 245 <a class="list" href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a>
256 246 </td>
257 247 </tr>'
258 248 filelogchild = '
259 249 <tr>
260 250 <td align="right">child {rev}:&nbsp;</td>
261 251 <td><a href="{url}file{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
262 252 </tr>'
263 253 shortlog = shortlog.tmpl
264 254 graph = graph.tmpl
265 255 tagtag = '<span class="tagtag" title="{name}">{name}</span> '
266 256 branchtag = '<span class="branchtag" title="{name}">{name}</span> '
267 257 inbranchtag = '<span class="inbranchtag" title="{name}">{name}</span> '
268 258 bookmarktag = '<span class="bookmarktag" title="{name}">{name}</span> '
269 259 shortlogentry = '
270 260 <tr class="parity{parity}">
271 261 <td class="age"><i class="age">{date|rfc822date}</i></td>
272 262 <td><i>{author|person}</i></td>
273 263 <td>
274 264 <a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">
275 265 <b>{desc|strip|firstline|escape|nonempty}</b>
276 266 <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}{bookmarks%bookmarktag}</span>
277 267 </a>
278 268 </td>
279 269 <td class="link" nowrap>
280 270 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
281 271 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
282 272 </td>
283 273 </tr>'
284 274 filelogentry = '
285 275 <tr class="parity{parity}">
286 276 <td class="age"><i class="age">{date|rfc822date}</i></td>
287 277 <td>
288 278 <a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">
289 279 <b>{desc|strip|firstline|escape|nonempty}</b>
290 280 </a>
291 281 </td>
292 282 <td class="link">
293 283 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a>&nbsp;|&nbsp;<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a>&nbsp;|&nbsp;<a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> {rename%filelogrename}</td>
294 284 </tr>'
295 285 archiveentry = ' | <a href="{url}archive/{node|short}{extension}">{type|escape}</a> '
296 286 indexentry = '
297 287 <tr class="parity{parity}">
298 288 <td>
299 289 <a class="list" href="{url}{sessionvars%urlparameter}">
300 290 <b>{name|escape}</b>
301 291 </a>
302 292 </td>
303 293 <td>{description}</td>
304 294 <td>{contact|obfuscate}</td>
305 295 <td class="age">{lastchange|rfc822date}</td>
306 296 <td class="indexlinks">{archives%indexarchiveentry}</td>
307 297 <td><div class="rss_logo"><a href="{url}rss-log">RSS</a> <a href="{url}atom-log">Atom</a></div></td>
308 298 </tr>\n'
309 299 indexarchiveentry = ' <a href="{url}archive/{node|short}{extension}">{type|escape}</a> '
310 300 index = index.tmpl
311 301 urlparameter = '{separator}{name}={value|urlescape}'
312 302 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
@@ -1,64 +1,72 b''
1 1 {header}
2 2 <title>{repo|escape}: comparison {file|escape}</title>
3 3 <link rel="alternate" type="application/atom+xml" href="{url}atom-log" title="Atom feed for {repo|escape}"/>
4 4 <link rel="alternate" type="application/rss+xml" href="{url}rss-log" title="RSS feed for {repo|escape}"/>
5 5 </head>
6 6
7 7 <body>
8 8 <div id="container">
9 9 <div class="page-header">
10 10 <h1><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / file comparison</h1>
11 11
12 12 <form action="{url}log">
13 13 {sessionvars%hiddenformentry}
14 14 <dl class="search">
15 15 <dt><label>Search: </label></dt>
16 16 <dd><input type="text" name="rev" /></dd>
17 17 </dl>
18 18 </form>
19 19
20 20 <ul class="page-nav">
21 21 <li><a href="{url}summary{sessionvars%urlparameter}">summary</a></li>
22 22 <li><a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a></li>
23 23 <li><a href="{url}log{sessionvars%urlparameter}">changelog</a></li>
24 24 <li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
25 25 <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
26 26 <li><a href="{url}bookmarks{sessionvars%urlparameter}">bookmarks</a></li>
27 27 <li><a href="{url}branches{sessionvars%urlparameter}">branches</a></li>
28 28 <li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">files</a></li>
29 29 <li><a href="{url}help{sessionvars%urlparameter}">help</a></li>
30 30 </ul>
31 31 </div>
32 32
33 33 <ul class="submenu">
34 34 <li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
35 35 <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a></li>
36 36 <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
37 37 <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
38 38 <li class="current">comparison</li>
39 39 <li><a href="{url}raw-diff/{node|short}/{file|urlescape}">raw</a></li>
40 40 </ul>
41 41
42 42 <h2 class="no-link no-border">comparison: {file|escape}</h2>
43 43 <h3 class="changeset">{file|escape}</h3>
44 44
45 45 <dl class="overview">
46 46 {branch%filerevbranch}
47 47 <dt>changeset {rev}</dt>
48 48 <dd><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></dd>
49 49 {parent%filecompparent}
50 50 {child%filecompchild}
51 51 </dl>
52 52
53 53 <div class="legend">
54 54 <span class="legendinfo equal">equal</span>
55 55 <span class="legendinfo delete">deleted</span>
56 56 <span class="legendinfo insert">inserted</span>
57 57 <span class="legendinfo replace">replaced</span>
58 58 </div>
59 59
60 60 <div class="comparison">
61 {comparison}
61 <table class="bigtable">
62 <thead class="header">
63 <tr>
64 <th>{leftrev}:{leftnode|short}</th>
65 <th>{rightrev}:{rightnode|short}</th>
66 </tr>
67 </thead>
68 {comparison}
69 </table>
62 70 </div>
63 71
64 72 {footer}
@@ -1,270 +1,260 b''
1 1 default = 'summary'
2 2 mimetype = 'text/html; charset={encoding}'
3 3 header = header.tmpl
4 4 footer = footer.tmpl
5 5 search = search.tmpl
6 6 changelog = changelog.tmpl
7 7 summary = summary.tmpl
8 8 error = error.tmpl
9 9 notfound = notfound.tmpl
10 10
11 11 help = help.tmpl
12 12 helptopics = helptopics.tmpl
13 13
14 14 helpentry = '<tr><td><a href="{url}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
15 15
16 16 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
17 17 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
18 18 navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
19 19 filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a>'
20 20 filedifflink = '<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
21 21 filenodelink = '
22 22 <tr class="parity{parity}">
23 23 <td><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a></td>
24 24 <td></td>
25 25 <td>
26 26 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
27 27 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
28 28 <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
29 29 <a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
30 30 <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
31 31 </td>
32 32 </tr>'
33 33 filenolink = '
34 34 <tr class="parity{parity}">
35 35 <td><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a></td>
36 36 <td></td>
37 37 <td>
38 38 file |
39 39 annotate |
40 40 <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
41 41 <a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a> |
42 42 <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
43 43 </td>
44 44 </tr>'
45 45
46 46 nav = '{before%naventry} {after%naventry}'
47 47 navshort = '{before%navshortentry}{after%navshortentry}'
48 48 navgraph = '{before%navgraphentry}{after%navgraphentry}'
49 49 filenav = '{before%filenaventry}{after%filenaventry}'
50 50
51 51 fileellipses = '...'
52 52 changelogentry = changelogentry.tmpl
53 53 searchentry = changelogentry.tmpl
54 54 changeset = changeset.tmpl
55 55 manifest = manifest.tmpl
56 56 direntry = '
57 57 <tr class="parity{parity}">
58 58 <td>drwxr-xr-x</td>
59 59 <td></td>
60 60 <td></td>
61 61 <td><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">{basename|escape}</a></td>
62 62 <td><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">files</a></td>
63 63 </tr>'
64 64 fileentry = '
65 65 <tr class="parity{parity}">
66 66 <td>{permissions|permissions}</td>
67 67 <td>{date|isodate}</td>
68 68 <td>{size}</td>
69 69 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{basename|escape}</a></td>
70 70 <td>
71 71 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
72 72 <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
73 73 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a>
74 74 </td>
75 75 </tr>'
76 76 filerevision = filerevision.tmpl
77 77 fileannotate = fileannotate.tmpl
78 78 filediff = filediff.tmpl
79 79 filecomparison = filecomparison.tmpl
80 80 filelog = filelog.tmpl
81 81 fileline = '
82 82 <div style="font-family:monospace" class="parity{parity}">
83 83 <pre><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</pre>
84 84 </div>'
85 85 annotateline = '
86 86 <tr class="parity{parity}">
87 87 <td class="linenr">
88 88 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
89 89 title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
90 90 </td>
91 91 <td class="lineno">
92 92 <a href="#{lineid}" id="{lineid}">{linenumber}</a>
93 93 </td>
94 94 <td class="source">{line|escape}</td>
95 95 </tr>'
96 96 difflineplus = '<span style="color:#008800;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
97 97 difflineminus = '<span style="color:#cc0000;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
98 98 difflineat = '<span style="color:#990099;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
99 99 diffline = '<span><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
100 100
101 comparison = '
102 <table class="bigtable">
103 <thead class="header">
104 <tr>
105 <th>{leftrev}:{leftnode|short}</th>
106 <th>{rightrev}:{rightnode|short}</th>
107 </tr>
108 </thead>
109 {blocks}
110 </table>'
111 101 comparisonblock ='
112 102 <tbody class="block">
113 103 {lines}
114 104 </tbody>'
115 105 comparisonline = '
116 106 <tr>
117 107 <td class="source {type}"><a class="linenr" href="#{lineid}" id="{lineid}">{leftlinenumber}</a> {leftline|escape}</td>
118 108 <td class="source {type}"><a class="linenr" href="#{lineid}" id="{lineid}">{rightlinenumber}</a> {rightline|escape}</td>
119 109 </tr>'
120 110
121 111 changelogparent = '
122 112 <tr>
123 113 <th class="parent">parent {rev}:</th>
124 114 <td class="parent">
125 115 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
126 116 </td>
127 117 </tr>'
128 118 changesetbranch = '<dt>branch</dt><dd>{name}</dd>'
129 119 changesetparent = '
130 120 <dt>parent {rev}</dt>
131 121 <dd><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></dd>'
132 122 filerevbranch = '<dt>branch</dt><dd>{name}</dd>'
133 123 filerevparent = '
134 124 <dt>parent {rev}</dt>
135 125 <dd>
136 126 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
137 127 {rename%filerename}{node|short}
138 128 </a>
139 129 </dd>'
140 130 filerename = '{file|escape}@'
141 131 filelogrename = '| <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">base</a>'
142 132 fileannotateparent = '
143 133 <dt>parent {rev}</dt>
144 134 <dd>
145 135 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
146 136 {rename%filerename}{node|short}
147 137 </a>
148 138 </dd>'
149 139 changelogchild = '
150 140 <dt>child {rev}:</dt>
151 141 <dd><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></dd>'
152 142 changesetchild = '
153 143 <dt>child {rev}</dt>
154 144 <dd><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></dd>'
155 145 filerevchild = '
156 146 <dt>child {rev}</dt>
157 147 <dd>
158 148 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a>
159 149 </dd>'
160 150 fileannotatechild = '
161 151 <dt>child {rev}</dt>
162 152 <dd>
163 153 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a>
164 154 </dd>'
165 155 tags = tags.tmpl
166 156 tagentry = '
167 157 <tr class="parity{parity}">
168 158 <td class="nowrap age">{date|rfc822date}</td>
169 159 <td><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{tag|escape}</a></td>
170 160 <td class="nowrap">
171 161 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
172 162 <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> |
173 163 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
174 164 </td>
175 165 </tr>'
176 166 bookmarks = bookmarks.tmpl
177 167 bookmarkentry = '
178 168 <tr class="parity{parity}">
179 169 <td class="nowrap date">{date|rfc822date}</td>
180 170 <td><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{bookmark|escape}</a></td>
181 171 <td class="nowrap">
182 172 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
183 173 <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> |
184 174 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
185 175 </td>
186 176 </tr>'
187 177 branches = branches.tmpl
188 178 branchentry = '
189 179 <tr class="parity{parity}">
190 180 <td class="nowrap age">{date|rfc822date}</td>
191 181 <td><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
192 182 <td class="{status}">{branch|escape}</td>
193 183 <td class="nowrap">
194 184 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
195 185 <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> |
196 186 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
197 187 </td>
198 188 </tr>'
199 189 diffblock = '<pre>{lines}</pre>'
200 190 filediffparent = '
201 191 <dt>parent {rev}</dt>
202 192 <dd><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></dd>'
203 193 filecompparent = '
204 194 <dt>parent {rev}</dt>
205 195 <dd><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></dd>'
206 196 filelogparent = '
207 197 <tr>
208 198 <td align="right">parent {rev}:&nbsp;</td>
209 199 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
210 200 </tr>'
211 201 filediffchild = '
212 202 <dt>child {rev}</dt>
213 203 <dd><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></dd>'
214 204 filecompchild = '
215 205 <dt>child {rev}</dt>
216 206 <dd><a href="{url}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></dd>'
217 207 filelogchild = '
218 208 <tr>
219 209 <td align="right">child {rev}:&nbsp;</td>
220 210 <td><a href="{url}file{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
221 211 </tr>'
222 212 shortlog = shortlog.tmpl
223 213 tagtag = '<span class="tagtag" title="{name}">{name}</span> '
224 214 branchtag = '<span class="branchtag" title="{name}">{name}</span> '
225 215 inbranchtag = '<span class="inbranchtag" title="{name}">{name}</span> '
226 216 bookmarktag = '<span class="bookmarktag" title="{name}">{name}</span> '
227 217 shortlogentry = '
228 218 <tr class="parity{parity}">
229 219 <td class="nowrap age">{date|rfc822date}</td>
230 220 <td>{author|person}</td>
231 221 <td>
232 222 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
233 223 {desc|strip|firstline|escape|nonempty}
234 224 <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}{bookmarks%bookmarktag}</span>
235 225 </a>
236 226 </td>
237 227 <td class="nowrap">
238 228 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
239 229 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
240 230 </td>
241 231 </tr>'
242 232 filelogentry = '
243 233 <tr class="parity{parity}">
244 234 <td class="nowrap age">{date|rfc822date}</td>
245 235 <td><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a></td>
246 236 <td class="nowrap">
247 237 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a>&nbsp;|&nbsp;<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a>&nbsp;|&nbsp;<a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a>
248 238 {rename%filelogrename}
249 239 </td>
250 240 </tr>'
251 241 archiveentry = '<li><a href="{url}archive/{node|short}{extension}">{type|escape}</a></li>'
252 242 indexentry = '
253 243 <tr class="parity{parity}">
254 244 <td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td>
255 245 <td>{description}</td>
256 246 <td>{contact|obfuscate}</td>
257 247 <td class="age">{lastchange|rfc822date}</td>
258 248 <td class="indexlinks">{archives%indexarchiveentry}</td>
259 249 <td>
260 250 <div class="rss_logo">
261 251 <a href="{url}rss-log">RSS</a>
262 252 <a href="{url}atom-log">Atom</a>
263 253 </div>
264 254 </td>
265 255 </tr>\n'
266 256 indexarchiveentry = '<a href="{url}archive/{node|short}{extension}">{type|escape}</a> '
267 257 index = index.tmpl
268 258 urlparameter = '{separator}{name}={value|urlescape}'
269 259 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
270 260 graph = graph.tmpl
@@ -1,85 +1,93 b''
1 1 {header}
2 2 <title>{repo|escape}: {file|escape} comparison</title>
3 3 </head>
4 4 <body>
5 5
6 6 <div class="container">
7 7 <div class="menu">
8 8 <div class="logo">
9 9 <a href="{logourl}">
10 10 <img src="{staticurl}{logoimg}" alt="mercurial" /></a>
11 11 </div>
12 12 <ul>
13 13 <li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
14 14 <li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
15 15 <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
16 16 <li><a href="{url}bookmarks{sessionvars%urlparameter}">bookmarks</a></li>
17 17 <li><a href="{url}branches{sessionvars%urlparameter}">branches</a></li>
18 18 </ul>
19 19 <ul>
20 20 <li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
21 21 <li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
22 22 </ul>
23 23 <ul>
24 24 <li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
25 25 <li><a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
26 26 <li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
27 27 <li class="active">comparison</li>
28 28 <li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
29 29 <li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
30 30 <li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
31 31 </ul>
32 32 <ul>
33 33 <li><a href="{url}help{sessionvars%urlparameter}">help</a></li>
34 34 </ul>
35 35 </div>
36 36
37 37 <div class="main">
38 38 <h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
39 39 <h3>comparison {file|escape} @ {rev}:{node|short}</h3>
40 40
41 41 <form class="search" action="{url}log">
42 42 <p>{sessionvars%hiddenformentry}</p>
43 43 <p><input name="rev" id="search1" type="text" size="30" /></p>
44 44 <div id="hint">find changesets by author, revision,
45 45 files, or words in the commit message</div>
46 46 </form>
47 47
48 48 <div class="description">{desc|strip|escape|nonempty}</div>
49 49
50 50 <table id="changesetEntry">
51 51 <tr>
52 52 <th>author</th>
53 53 <td>{author|obfuscate}</td>
54 54 </tr>
55 55 <tr>
56 56 <th>date</th>
57 57 <td class="date age">{date|rfc822date}</td>
58 58 </tr>
59 59 <tr>
60 60 <th>parents</th>
61 61 <td>{parent%filerevparent}</td>
62 62 </tr>
63 63 <tr>
64 64 <th>children</th>
65 65 <td>{child%filerevchild}</td>
66 66 </tr>
67 67 {changesettag}
68 68 </table>
69 69
70 70 <div class="overflow">
71 71 <div class="sourcefirst"> comparison</div>
72 72 <div class="legend">
73 73 <span class="legendinfo equal">equal</span>
74 74 <span class="legendinfo delete">deleted</span>
75 75 <span class="legendinfo insert">inserted</span>
76 76 <span class="legendinfo replace">replaced</span>
77 77 </div>
78 78
79 {comparison}
79 <table class="bigtable">
80 <thead class="header">
81 <tr>
82 <th>{leftrev}:{leftnode|short}</th>
83 <th>{rightrev}:{rightnode|short}</th>
84 </tr>
85 </thead>
86 {comparison}
87 </table>
80 88
81 89 </div>
82 90 </div>
83 91 </div>
84 92
85 93 {footer}
@@ -1,234 +1,224 b''
1 1 default = 'shortlog'
2 2
3 3 mimetype = 'text/html; charset={encoding}'
4 4 header = header.tmpl
5 5 footer = footer.tmpl
6 6 search = search.tmpl
7 7
8 8 changelog = shortlog.tmpl
9 9 shortlog = shortlog.tmpl
10 10 shortlogentry = shortlogentry.tmpl
11 11 graph = graph.tmpl
12 12 help = help.tmpl
13 13 helptopics = helptopics.tmpl
14 14
15 15 helpentry = '<tr><td><a href="{url}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
16 16
17 17 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
18 18 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
19 19 navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
20 20 filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
21 21 filedifflink = '<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
22 22 filenodelink = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
23 23 filenolink = '{file|escape} '
24 24 fileellipses = '...'
25 25 diffstatlink = diffstat.tmpl
26 26 diffstatnolink = diffstat.tmpl
27 27 changelogentry = shortlogentry.tmpl
28 28 searchentry = shortlogentry.tmpl
29 29 changeset = changeset.tmpl
30 30 manifest = manifest.tmpl
31 31
32 32 nav = '{before%naventry} {after%naventry}'
33 33 navshort = '{before%navshortentry}{after%navshortentry}'
34 34 navgraph = '{before%navgraphentry}{after%navgraphentry}'
35 35 filenav = '{before%filenaventry}{after%filenaventry}'
36 36
37 37 direntry = '
38 38 <tr class="fileline parity{parity}">
39 39 <td class="name">
40 40 <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">
41 41 <img src="{staticurl}coal-folder.png" alt="dir."/> {basename|escape}/
42 42 </a>
43 43 <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">
44 44 {emptydirs|escape}
45 45 </a>
46 46 </td>
47 47 <td class="size"></td>
48 48 <td class="permissions">drwxr-xr-x</td>
49 49 </tr>'
50 50
51 51 fileentry = '
52 52 <tr class="fileline parity{parity}">
53 53 <td class="filename">
54 54 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
55 55 <img src="{staticurl}coal-file.png" alt="file"/> {basename|escape}
56 56 </a>
57 57 </td>
58 58 <td class="size">{size}</td>
59 59 <td class="permissions">{permissions|permissions}</td>
60 60 </tr>'
61 61
62 62 filerevision = filerevision.tmpl
63 63 fileannotate = fileannotate.tmpl
64 64 filediff = filediff.tmpl
65 65 filecomparison = filecomparison.tmpl
66 66 filelog = filelog.tmpl
67 67 fileline = '
68 68 <div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
69 69 filelogentry = filelogentry.tmpl
70 70
71 71 annotateline = '
72 72 <tr class="parity{parity}">
73 73 <td class="annotate">
74 74 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
75 75 title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
76 76 </td>
77 77 <td class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</td>
78 78 </tr>'
79 79
80 80 diffblock = '<div class="source bottomline parity{parity}"><pre>{lines}</pre></div>'
81 81 difflineplus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="plusline">{line|escape}</span>'
82 82 difflineminus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="minusline">{line|escape}</span>'
83 83 difflineat = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="atline">{line|escape}</span>'
84 84 diffline = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}'
85 85
86 comparison = '
87 <table class="bigtable">
88 <thead class="header">
89 <tr>
90 <th>{leftrev}:{leftnode|short}</th>
91 <th>{rightrev}:{rightnode|short}</th>
92 </tr>
93 </thead>
94 {blocks}
95 </table>'
96 86 comparisonblock ='
97 87 <tbody class="block">
98 88 {lines}
99 89 </tbody>'
100 90 comparisonline = '
101 91 <tr>
102 92 <td class="source {type}"><a href="#{lineid}" id="{lineid}">{leftlinenumber}</a> {leftline|escape}</td>
103 93 <td class="source {type}"><a href="#{lineid}" id="{lineid}">{rightlinenumber}</a> {rightline|escape}</td>
104 94 </tr>'
105 95
106 96 changelogparent = '
107 97 <tr>
108 98 <th class="parent">parent {rev}:</th>
109 99 <td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
110 100 </tr>'
111 101
112 102 changesetparent = '<a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a> '
113 103
114 104 filerevparent = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a> '
115 105 filerevchild = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a> '
116 106
117 107 filerename = '{file|escape}@'
118 108 filelogrename = '
119 109 <span class="base">
120 110 base
121 111 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
122 112 {file|escape}@{node|short}
123 113 </a>
124 114 </span>'
125 115 fileannotateparent = '
126 116 <tr>
127 117 <td class="metatag">parent:</td>
128 118 <td>
129 119 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
130 120 {rename%filerename}{node|short}
131 121 </a>
132 122 </td>
133 123 </tr>'
134 124 changesetchild = ' <a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>'
135 125 changelogchild = '
136 126 <tr>
137 127 <th class="child">child</th>
138 128 <td class="child">
139 129 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
140 130 {node|short}
141 131 </a>
142 132 </td>
143 133 </tr>'
144 134 fileannotatechild = '
145 135 <tr>
146 136 <td class="metatag">child:</td>
147 137 <td>
148 138 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
149 139 {node|short}
150 140 </a>
151 141 </td>
152 142 </tr>'
153 143 tags = tags.tmpl
154 144 tagentry = '
155 145 <tr class="tagEntry parity{parity}">
156 146 <td>
157 147 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
158 148 {tag|escape}
159 149 </a>
160 150 </td>
161 151 <td class="node">
162 152 {node|short}
163 153 </td>
164 154 </tr>'
165 155 bookmarks = bookmarks.tmpl
166 156 bookmarkentry = '
167 157 <tr class="tagEntry parity{parity}">
168 158 <td>
169 159 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
170 160 {bookmark|escape}
171 161 </a>
172 162 </td>
173 163 <td class="node">
174 164 {node|short}
175 165 </td>
176 166 </tr>'
177 167 branches = branches.tmpl
178 168 branchentry = '
179 169 <tr class="tagEntry parity{parity}">
180 170 <td>
181 171 <a href="{url}shortlog/{node|short}{sessionvars%urlparameter}" class="{status}">
182 172 {branch|escape}
183 173 </a>
184 174 </td>
185 175 <td class="node">
186 176 {node|short}
187 177 </td>
188 178 </tr>'
189 179 changelogtag = '<span class="tag">{name|escape}</span> '
190 180 changesettag = '<span class="tag">{tag|escape}</span> '
191 181 changesetbookmark = '<span class="tag">{bookmark|escape}</span> '
192 182 changelogbranchhead = '<span class="branchhead">{name|escape}</span> '
193 183 changelogbranchname = '<span class="branchname">{name|escape}</span> '
194 184
195 185 filediffparent = '
196 186 <tr>
197 187 <th class="parent">parent {rev}:</th>
198 188 <td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
199 189 </tr>'
200 190 filelogparent = '
201 191 <tr>
202 192 <th>parent {rev}:</th>
203 193 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
204 194 </tr>'
205 195 filediffchild = '
206 196 <tr>
207 197 <th class="child">child {rev}:</th>
208 198 <td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
209 199 </td>
210 200 </tr>'
211 201 filelogchild = '
212 202 <tr>
213 203 <th>child {rev}:</th>
214 204 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
215 205 </tr>'
216 206
217 207 indexentry = '
218 208 <tr class="parity{parity}">
219 209 <td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td>
220 210 <td>{description}</td>
221 211 <td>{contact|obfuscate}</td>
222 212 <td class="age">{lastchange|rfc822date}</td>
223 213 <td class="indexlinks">{archives%indexarchiveentry}</td>
224 214 </tr>\n'
225 215 indexarchiveentry = '<a href="{url}archive/{node|short}{extension|urlescape}">&nbsp;&darr;{type|escape}</a>'
226 216 index = index.tmpl
227 217 archiveentry = '
228 218 <li>
229 219 <a href="{url}archive/{node|short}{extension|urlescape}">{type|escape}</a>
230 220 </li>'
231 221 notfound = notfound.tmpl
232 222 error = error.tmpl
233 223 urlparameter = '{separator}{name}={value|urlescape}'
234 224 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
@@ -1,989 +1,986 b''
1 1 $ "$TESTDIR/hghave" serve || exit 80
2 2
3 3 setting up repo
4 4
5 5 $ hg init test
6 6 $ cd test
7 7 $ echo a > a
8 8 $ echo b > b
9 9 $ hg ci -Ama
10 10 adding a
11 11 adding b
12 12
13 13 change permissions for git diffs
14 14
15 15 $ hg import -q --bypass - <<EOF
16 16 > # HG changeset patch
17 17 > # User test
18 18 > # Date 0 0
19 19 > b
20 20 >
21 21 > diff --git a/a b/a
22 22 > old mode 100644
23 23 > new mode 100755
24 24 > diff --git a/b b/b
25 25 > deleted file mode 100644
26 26 > --- a/b
27 27 > +++ /dev/null
28 28 > @@ -1,1 +0,0 @@
29 29 > -b
30 30 > EOF
31 31
32 32 set up hgweb
33 33
34 34 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
35 35 $ cat hg.pid >> $DAEMON_PIDS
36 36
37 37 revision
38 38
39 39 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/0'
40 40 200 Script output follows
41 41
42 42 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
43 43 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
44 44 <head>
45 45 <link rel="icon" href="/static/hgicon.png" type="image/png" />
46 46 <meta name="robots" content="index, nofollow" />
47 47 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
48 48 <script type="text/javascript" src="/static/mercurial.js"></script>
49 49
50 50 <title>test: 0cd96de13884</title>
51 51 </head>
52 52 <body>
53 53 <div class="container">
54 54 <div class="menu">
55 55 <div class="logo">
56 56 <a href="http://mercurial.selenic.com/">
57 57 <img src="/static/hglogo.png" alt="mercurial" /></a>
58 58 </div>
59 59 <ul>
60 60 <li><a href="/shortlog/0cd96de13884">log</a></li>
61 61 <li><a href="/graph/0cd96de13884">graph</a></li>
62 62 <li><a href="/tags">tags</a></li>
63 63 <li><a href="/bookmarks">bookmarks</a></li>
64 64 <li><a href="/branches">branches</a></li>
65 65 </ul>
66 66 <ul>
67 67 <li class="active">changeset</li>
68 68 <li><a href="/raw-rev/0cd96de13884">raw</a></li>
69 69 <li><a href="/file/0cd96de13884">browse</a></li>
70 70 </ul>
71 71 <ul>
72 72
73 73 </ul>
74 74 <ul>
75 75 <li><a href="/help">help</a></li>
76 76 </ul>
77 77 </div>
78 78
79 79 <div class="main">
80 80
81 81 <h2><a href="/">test</a></h2>
82 82 <h3>changeset 0:0cd96de13884 </h3>
83 83
84 84 <form class="search" action="/log">
85 85
86 86 <p><input name="rev" id="search1" type="text" size="30" /></p>
87 87 <div id="hint">find changesets by author, revision,
88 88 files, or words in the commit message</div>
89 89 </form>
90 90
91 91 <div class="description">a</div>
92 92
93 93 <table id="changesetEntry">
94 94 <tr>
95 95 <th class="author">author</th>
96 96 <td class="author">&#116;&#101;&#115;&#116;</td>
97 97 </tr>
98 98 <tr>
99 99 <th class="date">date</th>
100 100 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
101 101 <tr>
102 102 <th class="author">parents</th>
103 103 <td class="author"></td>
104 104 </tr>
105 105 <tr>
106 106 <th class="author">children</th>
107 107 <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
108 108 </tr>
109 109 <tr>
110 110 <th class="files">files</th>
111 111 <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
112 112 </tr>
113 113 <tr>
114 114 <th class="diffstat">diffstat</th>
115 115 <td class="diffstat">
116 116 2 files changed, 2 insertions(+), 0 deletions(-)
117 117
118 118 <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a>
119 119 <div id="diffstatdetails" style="display:none;">
120 120 <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a>
121 121 <p>
122 122 <table> <tr class="parity0">
123 123 <td class="diffstat-file"><a href="#l1.1">a</a></td>
124 124 <td class="diffstat-total" align="right">1</td>
125 125 <td class="diffstat-graph">
126 126 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
127 127 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
128 128 </td>
129 129 </tr>
130 130 <tr class="parity1">
131 131 <td class="diffstat-file"><a href="#l2.1">b</a></td>
132 132 <td class="diffstat-total" align="right">1</td>
133 133 <td class="diffstat-graph">
134 134 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
135 135 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
136 136 </td>
137 137 </tr>
138 138 </table>
139 139 </div>
140 140 </td>
141 141 </tr>
142 142 </table>
143 143
144 144 <div class="overflow">
145 145 <div class="sourcefirst"> line diff</div>
146 146
147 147 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
148 148 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ b/a Thu Jan 01 00:00:00 1970 +0000
149 149 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
150 150 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+a
151 151 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
152 152 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/b Thu Jan 01 00:00:00 1970 +0000
153 153 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
154 154 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+b
155 155 </span></pre></div>
156 156 </div>
157 157
158 158 </div>
159 159 </div>
160 160 <script type="text/javascript">process_dates()</script>
161 161
162 162
163 163 </body>
164 164 </html>
165 165
166 166
167 167 raw revision
168 168
169 169 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
170 170 200 Script output follows
171 171
172 172
173 173 # HG changeset patch
174 174 # User test
175 175 # Date 0 0
176 176 # Node ID 0cd96de13884b090099512d4794ae87ad067ea8e
177 177
178 178 a
179 179
180 180 diff -r 000000000000 -r 0cd96de13884 a
181 181 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
182 182 +++ b/a Thu Jan 01 00:00:00 1970 +0000
183 183 @@ -0,0 +1,1 @@
184 184 +a
185 185 diff -r 000000000000 -r 0cd96de13884 b
186 186 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
187 187 +++ b/b Thu Jan 01 00:00:00 1970 +0000
188 188 @@ -0,0 +1,1 @@
189 189 +b
190 190
191 191
192 192 diff removed file
193 193
194 194 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/b'
195 195 200 Script output follows
196 196
197 197 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
198 198 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
199 199 <head>
200 200 <link rel="icon" href="/static/hgicon.png" type="image/png" />
201 201 <meta name="robots" content="index, nofollow" />
202 202 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
203 203 <script type="text/javascript" src="/static/mercurial.js"></script>
204 204
205 205 <title>test: b diff</title>
206 206 </head>
207 207 <body>
208 208
209 209 <div class="container">
210 210 <div class="menu">
211 211 <div class="logo">
212 212 <a href="http://mercurial.selenic.com/">
213 213 <img src="/static/hglogo.png" alt="mercurial" /></a>
214 214 </div>
215 215 <ul>
216 216 <li><a href="/shortlog/559edbd9ed20">log</a></li>
217 217 <li><a href="/graph/559edbd9ed20">graph</a></li>
218 218 <li><a href="/tags">tags</a></li>
219 219 <li><a href="/bookmarks">bookmarks</a></li>
220 220 <li><a href="/branches">branches</a></li>
221 221 </ul>
222 222 <ul>
223 223 <li><a href="/rev/559edbd9ed20">changeset</a></li>
224 224 <li><a href="/file/559edbd9ed20">browse</a></li>
225 225 </ul>
226 226 <ul>
227 227 <li><a href="/file/559edbd9ed20/b">file</a></li>
228 228 <li><a href="/file/tip/b">latest</a></li>
229 229 <li class="active">diff</li>
230 230 <li><a href="/comparison/559edbd9ed20/b">comparison</a></li>
231 231 <li><a href="/annotate/559edbd9ed20/b">annotate</a></li>
232 232 <li><a href="/log/559edbd9ed20/b">file log</a></li>
233 233 <li><a href="/raw-file/559edbd9ed20/b">raw</a></li>
234 234 </ul>
235 235 <ul>
236 236 <li><a href="/help">help</a></li>
237 237 </ul>
238 238 </div>
239 239
240 240 <div class="main">
241 241 <h2><a href="/">test</a></h2>
242 242 <h3>diff b @ 1:559edbd9ed20</h3>
243 243
244 244 <form class="search" action="/log">
245 245 <p></p>
246 246 <p><input name="rev" id="search1" type="text" size="30" /></p>
247 247 <div id="hint">find changesets by author, revision,
248 248 files, or words in the commit message</div>
249 249 </form>
250 250
251 251 <div class="description">b</div>
252 252
253 253 <table id="changesetEntry">
254 254 <tr>
255 255 <th>author</th>
256 256 <td>&#116;&#101;&#115;&#116;</td>
257 257 </tr>
258 258 <tr>
259 259 <th>date</th>
260 260 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
261 261 </tr>
262 262 <tr>
263 263 <th>parents</th>
264 264 <td><a href="/file/0cd96de13884/b">0cd96de13884</a> </td>
265 265 </tr>
266 266 <tr>
267 267 <th>children</th>
268 268 <td></td>
269 269 </tr>
270 270
271 271 </table>
272 272
273 273 <div class="overflow">
274 274 <div class="sourcefirst"> line diff</div>
275 275
276 276 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- a/b Thu Jan 01 00:00:00 1970 +0000
277 277 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
278 278 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -1,1 +0,0 @@
279 279 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="minusline">-b
280 280 </span></pre></div>
281 281 </div>
282 282 </div>
283 283 </div>
284 284
285 285 <script type="text/javascript">process_dates()</script>
286 286
287 287
288 288 </body>
289 289 </html>
290 290
291 291
292 292 set up hgweb with git diffs
293 293
294 294 $ "$TESTDIR/killdaemons.py"
295 295 $ hg serve --config 'diff.git=1' -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
296 296 $ cat hg.pid >> $DAEMON_PIDS
297 297
298 298 revision
299 299
300 300 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/0'
301 301 200 Script output follows
302 302
303 303 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
304 304 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
305 305 <head>
306 306 <link rel="icon" href="/static/hgicon.png" type="image/png" />
307 307 <meta name="robots" content="index, nofollow" />
308 308 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
309 309 <script type="text/javascript" src="/static/mercurial.js"></script>
310 310
311 311 <title>test: 0cd96de13884</title>
312 312 </head>
313 313 <body>
314 314 <div class="container">
315 315 <div class="menu">
316 316 <div class="logo">
317 317 <a href="http://mercurial.selenic.com/">
318 318 <img src="/static/hglogo.png" alt="mercurial" /></a>
319 319 </div>
320 320 <ul>
321 321 <li><a href="/shortlog/0cd96de13884">log</a></li>
322 322 <li><a href="/graph/0cd96de13884">graph</a></li>
323 323 <li><a href="/tags">tags</a></li>
324 324 <li><a href="/bookmarks">bookmarks</a></li>
325 325 <li><a href="/branches">branches</a></li>
326 326 </ul>
327 327 <ul>
328 328 <li class="active">changeset</li>
329 329 <li><a href="/raw-rev/0cd96de13884">raw</a></li>
330 330 <li><a href="/file/0cd96de13884">browse</a></li>
331 331 </ul>
332 332 <ul>
333 333
334 334 </ul>
335 335 <ul>
336 336 <li><a href="/help">help</a></li>
337 337 </ul>
338 338 </div>
339 339
340 340 <div class="main">
341 341
342 342 <h2><a href="/">test</a></h2>
343 343 <h3>changeset 0:0cd96de13884 </h3>
344 344
345 345 <form class="search" action="/log">
346 346
347 347 <p><input name="rev" id="search1" type="text" size="30" /></p>
348 348 <div id="hint">find changesets by author, revision,
349 349 files, or words in the commit message</div>
350 350 </form>
351 351
352 352 <div class="description">a</div>
353 353
354 354 <table id="changesetEntry">
355 355 <tr>
356 356 <th class="author">author</th>
357 357 <td class="author">&#116;&#101;&#115;&#116;</td>
358 358 </tr>
359 359 <tr>
360 360 <th class="date">date</th>
361 361 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
362 362 <tr>
363 363 <th class="author">parents</th>
364 364 <td class="author"></td>
365 365 </tr>
366 366 <tr>
367 367 <th class="author">children</th>
368 368 <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
369 369 </tr>
370 370 <tr>
371 371 <th class="files">files</th>
372 372 <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
373 373 </tr>
374 374 <tr>
375 375 <th class="diffstat">diffstat</th>
376 376 <td class="diffstat">
377 377 2 files changed, 2 insertions(+), 0 deletions(-)
378 378
379 379 <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a>
380 380 <div id="diffstatdetails" style="display:none;">
381 381 <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a>
382 382 <p>
383 383 <table> <tr class="parity0">
384 384 <td class="diffstat-file"><a href="#l1.1">a</a></td>
385 385 <td class="diffstat-total" align="right">1</td>
386 386 <td class="diffstat-graph">
387 387 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
388 388 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
389 389 </td>
390 390 </tr>
391 391 <tr class="parity1">
392 392 <td class="diffstat-file"><a href="#l2.1">b</a></td>
393 393 <td class="diffstat-total" align="right">1</td>
394 394 <td class="diffstat-graph">
395 395 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
396 396 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
397 397 </td>
398 398 </tr>
399 399 </table>
400 400 </div>
401 401 </td>
402 402 </tr>
403 403 </table>
404 404
405 405 <div class="overflow">
406 406 <div class="sourcefirst"> line diff</div>
407 407
408 408 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> new file mode 100644
409 409 <a href="#l1.2" id="l1.2"> 1.2</a> <span class="minusline">--- /dev/null
410 410 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="plusline">+++ b/a
411 411 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="atline">@@ -0,0 +1,1 @@
412 412 </span><a href="#l1.5" id="l1.5"> 1.5</a> <span class="plusline">+a
413 413 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> new file mode 100644
414 414 <a href="#l2.2" id="l2.2"> 2.2</a> <span class="minusline">--- /dev/null
415 415 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="plusline">+++ b/b
416 416 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="atline">@@ -0,0 +1,1 @@
417 417 </span><a href="#l2.5" id="l2.5"> 2.5</a> <span class="plusline">+b
418 418 </span></pre></div>
419 419 </div>
420 420
421 421 </div>
422 422 </div>
423 423 <script type="text/javascript">process_dates()</script>
424 424
425 425
426 426 </body>
427 427 </html>
428 428
429 429
430 430 revision
431 431
432 432 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
433 433 200 Script output follows
434 434
435 435
436 436 # HG changeset patch
437 437 # User test
438 438 # Date 0 0
439 439 # Node ID 0cd96de13884b090099512d4794ae87ad067ea8e
440 440
441 441 a
442 442
443 443 diff --git a/a b/a
444 444 new file mode 100644
445 445 --- /dev/null
446 446 +++ b/a
447 447 @@ -0,0 +1,1 @@
448 448 +a
449 449 diff --git a/b b/b
450 450 new file mode 100644
451 451 --- /dev/null
452 452 +++ b/b
453 453 @@ -0,0 +1,1 @@
454 454 +b
455 455
456 456
457 457 diff removed file
458 458
459 459 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/a'
460 460 200 Script output follows
461 461
462 462 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
463 463 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
464 464 <head>
465 465 <link rel="icon" href="/static/hgicon.png" type="image/png" />
466 466 <meta name="robots" content="index, nofollow" />
467 467 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
468 468 <script type="text/javascript" src="/static/mercurial.js"></script>
469 469
470 470 <title>test: a diff</title>
471 471 </head>
472 472 <body>
473 473
474 474 <div class="container">
475 475 <div class="menu">
476 476 <div class="logo">
477 477 <a href="http://mercurial.selenic.com/">
478 478 <img src="/static/hglogo.png" alt="mercurial" /></a>
479 479 </div>
480 480 <ul>
481 481 <li><a href="/shortlog/559edbd9ed20">log</a></li>
482 482 <li><a href="/graph/559edbd9ed20">graph</a></li>
483 483 <li><a href="/tags">tags</a></li>
484 484 <li><a href="/bookmarks">bookmarks</a></li>
485 485 <li><a href="/branches">branches</a></li>
486 486 </ul>
487 487 <ul>
488 488 <li><a href="/rev/559edbd9ed20">changeset</a></li>
489 489 <li><a href="/file/559edbd9ed20">browse</a></li>
490 490 </ul>
491 491 <ul>
492 492 <li><a href="/file/559edbd9ed20/a">file</a></li>
493 493 <li><a href="/file/tip/a">latest</a></li>
494 494 <li class="active">diff</li>
495 495 <li><a href="/comparison/559edbd9ed20/a">comparison</a></li>
496 496 <li><a href="/annotate/559edbd9ed20/a">annotate</a></li>
497 497 <li><a href="/log/559edbd9ed20/a">file log</a></li>
498 498 <li><a href="/raw-file/559edbd9ed20/a">raw</a></li>
499 499 </ul>
500 500 <ul>
501 501 <li><a href="/help">help</a></li>
502 502 </ul>
503 503 </div>
504 504
505 505 <div class="main">
506 506 <h2><a href="/">test</a></h2>
507 507 <h3>diff a @ 1:559edbd9ed20</h3>
508 508
509 509 <form class="search" action="/log">
510 510 <p></p>
511 511 <p><input name="rev" id="search1" type="text" size="30" /></p>
512 512 <div id="hint">find changesets by author, revision,
513 513 files, or words in the commit message</div>
514 514 </form>
515 515
516 516 <div class="description">b</div>
517 517
518 518 <table id="changesetEntry">
519 519 <tr>
520 520 <th>author</th>
521 521 <td>&#116;&#101;&#115;&#116;</td>
522 522 </tr>
523 523 <tr>
524 524 <th>date</th>
525 525 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
526 526 </tr>
527 527 <tr>
528 528 <th>parents</th>
529 529 <td></td>
530 530 </tr>
531 531 <tr>
532 532 <th>children</th>
533 533 <td></td>
534 534 </tr>
535 535
536 536 </table>
537 537
538 538 <div class="overflow">
539 539 <div class="sourcefirst"> line diff</div>
540 540
541 541 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> old mode 100644
542 542 <a href="#l1.2" id="l1.2"> 1.2</a> new mode 100755
543 543 </pre></div>
544 544 </div>
545 545 </div>
546 546 </div>
547 547
548 548 <script type="text/javascript">process_dates()</script>
549 549
550 550
551 551 </body>
552 552 </html>
553 553
554 554
555 555 comparison new file
556 556
557 557 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/0/a'
558 558 200 Script output follows
559 559
560 560 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
561 561 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
562 562 <head>
563 563 <link rel="icon" href="/static/hgicon.png" type="image/png" />
564 564 <meta name="robots" content="index, nofollow" />
565 565 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
566 566 <script type="text/javascript" src="/static/mercurial.js"></script>
567 567
568 568 <title>test: a comparison</title>
569 569 </head>
570 570 <body>
571 571
572 572 <div class="container">
573 573 <div class="menu">
574 574 <div class="logo">
575 575 <a href="http://mercurial.selenic.com/">
576 576 <img src="/static/hglogo.png" alt="mercurial" /></a>
577 577 </div>
578 578 <ul>
579 579 <li><a href="/shortlog/0cd96de13884">log</a></li>
580 580 <li><a href="/graph/0cd96de13884">graph</a></li>
581 581 <li><a href="/tags">tags</a></li>
582 582 <li><a href="/bookmarks">bookmarks</a></li>
583 583 <li><a href="/branches">branches</a></li>
584 584 </ul>
585 585 <ul>
586 586 <li><a href="/rev/0cd96de13884">changeset</a></li>
587 587 <li><a href="/file/0cd96de13884">browse</a></li>
588 588 </ul>
589 589 <ul>
590 590 <li><a href="/file/0cd96de13884/a">file</a></li>
591 591 <li><a href="/file/tip/a">latest</a></li>
592 592 <li><a href="/diff/0cd96de13884/a">diff</a></li>
593 593 <li class="active">comparison</li>
594 594 <li><a href="/annotate/0cd96de13884/a">annotate</a></li>
595 595 <li><a href="/log/0cd96de13884/a">file log</a></li>
596 596 <li><a href="/raw-file/0cd96de13884/a">raw</a></li>
597 597 </ul>
598 598 <ul>
599 599 <li><a href="/help">help</a></li>
600 600 </ul>
601 601 </div>
602 602
603 603 <div class="main">
604 604 <h2><a href="/">test</a></h2>
605 605 <h3>comparison a @ 0:0cd96de13884</h3>
606 606
607 607 <form class="search" action="/log">
608 608 <p></p>
609 609 <p><input name="rev" id="search1" type="text" size="30" /></p>
610 610 <div id="hint">find changesets by author, revision,
611 611 files, or words in the commit message</div>
612 612 </form>
613 613
614 614 <div class="description">a</div>
615 615
616 616 <table id="changesetEntry">
617 617 <tr>
618 618 <th>author</th>
619 619 <td>&#116;&#101;&#115;&#116;</td>
620 620 </tr>
621 621 <tr>
622 622 <th>date</th>
623 623 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
624 624 </tr>
625 625 <tr>
626 626 <th>parents</th>
627 627 <td></td>
628 628 </tr>
629 629 <tr>
630 630 <th>children</th>
631 631 <td><a href="/file/559edbd9ed20/a">559edbd9ed20</a> </td>
632 632 </tr>
633 633
634 634 </table>
635 635
636 636 <div class="overflow">
637 637 <div class="sourcefirst"> comparison</div>
638 638 <div class="legend">
639 639 <span class="legendinfo equal">equal</span>
640 640 <span class="legendinfo delete">deleted</span>
641 641 <span class="legendinfo insert">inserted</span>
642 642 <span class="legendinfo replace">replaced</span>
643 643 </div>
644 644
645
646 645 <table class="bigtable">
647 <thead class="header">
648 <tr>
649 <th>-1:000000000000</th>
650 <th>0:b789fdd96dc2</th>
651 </tr>
652 </thead>
653
646 <thead class="header">
647 <tr>
648 <th>-1:000000000000</th>
649 <th>0:b789fdd96dc2</th>
650 </tr>
651 </thead>
652
654 653 <tbody class="block">
655 654
656 655 <tr>
657 656 <td class="source insert"><a href="#r1" id="r1"> </a> </td>
658 657 <td class="source insert"><a href="#r1" id="r1"> 1</a> a</td>
659 658 </tr>
660 659 </tbody>
661 660 </table>
662 661
663 662 </div>
664 663 </div>
665 664 </div>
666 665
667 666 <script type="text/javascript">process_dates()</script>
668 667
669 668
670 669 </body>
671 670 </html>
672 671
673 672
674 673 comparison existing file
675 674
676 675 $ hg up
677 676 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
678 677 $ echo a >> a
679 678 $ hg ci -mc
680 679 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
681 680 200 Script output follows
682 681
683 682 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
684 683 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
685 684 <head>
686 685 <link rel="icon" href="/static/hgicon.png" type="image/png" />
687 686 <meta name="robots" content="index, nofollow" />
688 687 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
689 688 <script type="text/javascript" src="/static/mercurial.js"></script>
690 689
691 690 <title>test: a comparison</title>
692 691 </head>
693 692 <body>
694 693
695 694 <div class="container">
696 695 <div class="menu">
697 696 <div class="logo">
698 697 <a href="http://mercurial.selenic.com/">
699 698 <img src="/static/hglogo.png" alt="mercurial" /></a>
700 699 </div>
701 700 <ul>
702 701 <li><a href="/shortlog/d73db4d812ff">log</a></li>
703 702 <li><a href="/graph/d73db4d812ff">graph</a></li>
704 703 <li><a href="/tags">tags</a></li>
705 704 <li><a href="/bookmarks">bookmarks</a></li>
706 705 <li><a href="/branches">branches</a></li>
707 706 </ul>
708 707 <ul>
709 708 <li><a href="/rev/d73db4d812ff">changeset</a></li>
710 709 <li><a href="/file/d73db4d812ff">browse</a></li>
711 710 </ul>
712 711 <ul>
713 712 <li><a href="/file/d73db4d812ff/a">file</a></li>
714 713 <li><a href="/file/tip/a">latest</a></li>
715 714 <li><a href="/diff/d73db4d812ff/a">diff</a></li>
716 715 <li class="active">comparison</li>
717 716 <li><a href="/annotate/d73db4d812ff/a">annotate</a></li>
718 717 <li><a href="/log/d73db4d812ff/a">file log</a></li>
719 718 <li><a href="/raw-file/d73db4d812ff/a">raw</a></li>
720 719 </ul>
721 720 <ul>
722 721 <li><a href="/help">help</a></li>
723 722 </ul>
724 723 </div>
725 724
726 725 <div class="main">
727 726 <h2><a href="/">test</a></h2>
728 727 <h3>comparison a @ 2:d73db4d812ff</h3>
729 728
730 729 <form class="search" action="/log">
731 730 <p></p>
732 731 <p><input name="rev" id="search1" type="text" size="30" /></p>
733 732 <div id="hint">find changesets by author, revision,
734 733 files, or words in the commit message</div>
735 734 </form>
736 735
737 736 <div class="description">c</div>
738 737
739 738 <table id="changesetEntry">
740 739 <tr>
741 740 <th>author</th>
742 741 <td>&#116;&#101;&#115;&#116;</td>
743 742 </tr>
744 743 <tr>
745 744 <th>date</th>
746 745 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
747 746 </tr>
748 747 <tr>
749 748 <th>parents</th>
750 749 <td><a href="/file/559edbd9ed20/a">559edbd9ed20</a> </td>
751 750 </tr>
752 751 <tr>
753 752 <th>children</th>
754 753 <td></td>
755 754 </tr>
756 755
757 756 </table>
758 757
759 758 <div class="overflow">
760 759 <div class="sourcefirst"> comparison</div>
761 760 <div class="legend">
762 761 <span class="legendinfo equal">equal</span>
763 762 <span class="legendinfo delete">deleted</span>
764 763 <span class="legendinfo insert">inserted</span>
765 764 <span class="legendinfo replace">replaced</span>
766 765 </div>
767 766
768
769 767 <table class="bigtable">
770 <thead class="header">
771 <tr>
772 <th>0:b789fdd96dc2</th>
773 <th>1:a80d06849b33</th>
774 </tr>
775 </thead>
776
768 <thead class="header">
769 <tr>
770 <th>0:b789fdd96dc2</th>
771 <th>1:a80d06849b33</th>
772 </tr>
773 </thead>
774
777 775 <tbody class="block">
778 776
779 777 <tr>
780 778 <td class="source equal"><a href="#l1r1" id="l1r1"> 1</a> a</td>
781 779 <td class="source equal"><a href="#l1r1" id="l1r1"> 1</a> a</td>
782 780 </tr>
783 781 <tr>
784 782 <td class="source insert"><a href="#r2" id="r2"> </a> </td>
785 783 <td class="source insert"><a href="#r2" id="r2"> 2</a> a</td>
786 784 </tr>
787 785 </tbody>
788 786 </table>
789 787
790 788 </div>
791 789 </div>
792 790 </div>
793 791
794 792 <script type="text/javascript">process_dates()</script>
795 793
796 794
797 795 </body>
798 796 </html>
799 797
800 798
801 799 comparison removed file
802 800
803 801 $ hg rm a
804 802 $ hg ci -md
805 803 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
806 804 200 Script output follows
807 805
808 806 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
809 807 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
810 808 <head>
811 809 <link rel="icon" href="/static/hgicon.png" type="image/png" />
812 810 <meta name="robots" content="index, nofollow" />
813 811 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
814 812 <script type="text/javascript" src="/static/mercurial.js"></script>
815 813
816 814 <title>test: a comparison</title>
817 815 </head>
818 816 <body>
819 817
820 818 <div class="container">
821 819 <div class="menu">
822 820 <div class="logo">
823 821 <a href="http://mercurial.selenic.com/">
824 822 <img src="/static/hglogo.png" alt="mercurial" /></a>
825 823 </div>
826 824 <ul>
827 825 <li><a href="/shortlog/20e80271eb7a">log</a></li>
828 826 <li><a href="/graph/20e80271eb7a">graph</a></li>
829 827 <li><a href="/tags">tags</a></li>
830 828 <li><a href="/bookmarks">bookmarks</a></li>
831 829 <li><a href="/branches">branches</a></li>
832 830 </ul>
833 831 <ul>
834 832 <li><a href="/rev/20e80271eb7a">changeset</a></li>
835 833 <li><a href="/file/20e80271eb7a">browse</a></li>
836 834 </ul>
837 835 <ul>
838 836 <li><a href="/file/20e80271eb7a/a">file</a></li>
839 837 <li><a href="/file/tip/a">latest</a></li>
840 838 <li><a href="/diff/20e80271eb7a/a">diff</a></li>
841 839 <li class="active">comparison</li>
842 840 <li><a href="/annotate/20e80271eb7a/a">annotate</a></li>
843 841 <li><a href="/log/20e80271eb7a/a">file log</a></li>
844 842 <li><a href="/raw-file/20e80271eb7a/a">raw</a></li>
845 843 </ul>
846 844 <ul>
847 845 <li><a href="/help">help</a></li>
848 846 </ul>
849 847 </div>
850 848
851 849 <div class="main">
852 850 <h2><a href="/">test</a></h2>
853 851 <h3>comparison a @ 3:20e80271eb7a</h3>
854 852
855 853 <form class="search" action="/log">
856 854 <p></p>
857 855 <p><input name="rev" id="search1" type="text" size="30" /></p>
858 856 <div id="hint">find changesets by author, revision,
859 857 files, or words in the commit message</div>
860 858 </form>
861 859
862 860 <div class="description">d</div>
863 861
864 862 <table id="changesetEntry">
865 863 <tr>
866 864 <th>author</th>
867 865 <td>&#116;&#101;&#115;&#116;</td>
868 866 </tr>
869 867 <tr>
870 868 <th>date</th>
871 869 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
872 870 </tr>
873 871 <tr>
874 872 <th>parents</th>
875 873 <td><a href="/file/d73db4d812ff/a">d73db4d812ff</a> </td>
876 874 </tr>
877 875 <tr>
878 876 <th>children</th>
879 877 <td></td>
880 878 </tr>
881 879
882 880 </table>
883 881
884 882 <div class="overflow">
885 883 <div class="sourcefirst"> comparison</div>
886 884 <div class="legend">
887 885 <span class="legendinfo equal">equal</span>
888 886 <span class="legendinfo delete">deleted</span>
889 887 <span class="legendinfo insert">inserted</span>
890 888 <span class="legendinfo replace">replaced</span>
891 889 </div>
892 890
893
894 891 <table class="bigtable">
895 <thead class="header">
896 <tr>
897 <th>1:a80d06849b33</th>
898 <th>-1:000000000000</th>
899 </tr>
900 </thead>
901
892 <thead class="header">
893 <tr>
894 <th>1:a80d06849b33</th>
895 <th>-1:000000000000</th>
896 </tr>
897 </thead>
898
902 899 <tbody class="block">
903 900
904 901 <tr>
905 902 <td class="source delete"><a href="#l1" id="l1"> 1</a> a</td>
906 903 <td class="source delete"><a href="#l1" id="l1"> </a> </td>
907 904 </tr>
908 905 <tr>
909 906 <td class="source delete"><a href="#l2" id="l2"> 2</a> a</td>
910 907 <td class="source delete"><a href="#l2" id="l2"> </a> </td>
911 908 </tr>
912 909 </tbody>
913 910 </table>
914 911
915 912 </div>
916 913 </div>
917 914 </div>
918 915
919 916 <script type="text/javascript">process_dates()</script>
920 917
921 918
922 919 </body>
923 920 </html>
924 921
925 922
926 923 $ cd ..
927 924
928 925 test import rev as raw-rev
929 926
930 927 $ hg clone -r0 test test1
931 928 adding changesets
932 929 adding manifests
933 930 adding file changes
934 931 added 1 changesets with 2 changes to 2 files
935 932 updating to branch default
936 933 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
937 934 $ cd test1
938 935 $ hg import -q --bypass --exact http://localhost:$HGPORT/rev/1
939 936
940 937 raw revision with diff block numbers
941 938
942 939 $ "$TESTDIR/killdaemons.py"
943 940 $ cat <<EOF > .hg/hgrc
944 941 > [web]
945 942 > templates = rawdiff
946 943 > EOF
947 944 $ mkdir rawdiff
948 945 $ cat <<EOF > rawdiff/map
949 946 > mimetype = 'text/plain; charset={encoding}'
950 947 > changeset = '{diff}'
951 948 > difflineplus = '{line}'
952 949 > difflineminus = '{line}'
953 950 > difflineat = '{line}'
954 951 > diffline = '{line}'
955 952 > filenodelink = ''
956 953 > filenolink = ''
957 954 > fileline = '{line}'
958 955 > diffblock = 'Block: {blockno}\n{lines}\n'
959 956 > EOF
960 957 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
961 958 $ cat hg.pid >> $DAEMON_PIDS
962 959 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
963 960 200 Script output follows
964 961
965 962 Block: 1
966 963 diff -r 000000000000 -r 0cd96de13884 a
967 964 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
968 965 +++ b/a Thu Jan 01 00:00:00 1970 +0000
969 966 @@ -0,0 +1,1 @@
970 967 +a
971 968
972 969 Block: 2
973 970 diff -r 000000000000 -r 0cd96de13884 b
974 971 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
975 972 +++ b/b Thu Jan 01 00:00:00 1970 +0000
976 973 @@ -0,0 +1,1 @@
977 974 +b
978 975
979 976 $ "$TESTDIR/killdaemons.py"
980 977 $ rm .hg/hgrc rawdiff/map
981 978 $ rmdir rawdiff
982 979 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
983 980 $ cat hg.pid >> $DAEMON_PIDS
984 981
985 982 errors
986 983
987 984 $ cat ../test/errors.log
988 985
989 986 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now