##// END OF EJS Templates
hgweb: split "verbs" into methods.
Vadim Gelfer -
r2436:f910b91d default
parent child Browse files
Show More
@@ -1,828 +1,835
1 1 # hgweb/hgweb_mod.py - Web interface for a repository.
2 2 #
3 3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 4 # Copyright 2005 Matt Mackall <mpm@selenic.com>
5 5 #
6 6 # This software may be used and distributed according to the terms
7 7 # of the GNU General Public License, incorporated herein by reference.
8 8
9 9 import os
10 10 import os.path
11 11 import mimetypes
12 12 from mercurial.demandload import demandload
13 13 demandload(globals(), "re zlib ConfigParser cStringIO")
14 14 demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,templater")
15 15 demandload(globals(), "mercurial.hgweb.request:hgrequest")
16 16 demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile")
17 17 from mercurial.node import *
18 18 from mercurial.i18n import gettext as _
19 19
20 20 def _up(p):
21 21 if p[0] != "/":
22 22 p = "/" + p
23 23 if p[-1] == "/":
24 24 p = p[:-1]
25 25 up = os.path.dirname(p)
26 26 if up == "/":
27 27 return "/"
28 28 return up + "/"
29 29
30 30 class hgweb(object):
31 31 def __init__(self, repo, name=None):
32 32 if type(repo) == type(""):
33 33 self.repo = hg.repository(ui.ui(), repo)
34 34 else:
35 35 self.repo = repo
36 36
37 37 self.mtime = -1
38 38 self.reponame = name
39 39 self.archives = 'zip', 'gz', 'bz2'
40 self.templatepath = self.repo.ui.config("web", "templates",
41 templater.templatepath())
40 42
41 43 def refresh(self):
42 44 mtime = get_mtime(self.repo.root)
43 45 if mtime != self.mtime:
44 46 self.mtime = mtime
45 47 self.repo = hg.repository(self.repo.ui, self.repo.root)
46 48 self.maxchanges = int(self.repo.ui.config("web", "maxchanges", 10))
47 49 self.maxfiles = int(self.repo.ui.config("web", "maxfiles", 10))
48 50 self.allowpull = self.repo.ui.configbool("web", "allowpull", True)
49 51
50 52 def archivelist(self, nodeid):
51 53 allowed = (self.repo.ui.config("web", "allow_archive", "")
52 54 .replace(",", " ").split())
53 55 for i in self.archives:
54 56 if i in allowed or self.repo.ui.configbool("web", "allow" + i):
55 57 yield {"type" : i, "node" : nodeid, "url": ""}
56 58
57 59 def listfiles(self, files, mf):
58 60 for f in files[:self.maxfiles]:
59 61 yield self.t("filenodelink", node=hex(mf[f]), file=f)
60 62 if len(files) > self.maxfiles:
61 63 yield self.t("fileellipses")
62 64
63 65 def listfilediffs(self, files, changeset):
64 66 for f in files[:self.maxfiles]:
65 67 yield self.t("filedifflink", node=hex(changeset), file=f)
66 68 if len(files) > self.maxfiles:
67 69 yield self.t("fileellipses")
68 70
69 71 def siblings(self, siblings=[], rev=None, hiderev=None, **args):
70 72 if not rev:
71 73 rev = lambda x: ""
72 74 siblings = [s for s in siblings if s != nullid]
73 75 if len(siblings) == 1 and rev(siblings[0]) == hiderev:
74 76 return
75 77 for s in siblings:
76 78 yield dict(node=hex(s), rev=rev(s), **args)
77 79
78 80 def renamelink(self, fl, node):
79 81 r = fl.renamed(node)
80 82 if r:
81 83 return [dict(file=r[0], node=hex(r[1]))]
82 84 return []
83 85
84 86 def showtag(self, t1, node=nullid, **args):
85 87 for t in self.repo.nodetags(node):
86 88 yield self.t(t1, tag=t, **args)
87 89
88 90 def diff(self, node1, node2, files):
89 91 def filterfiles(filters, files):
90 92 l = [x for x in files if x in filters]
91 93
92 94 for t in filters:
93 95 if t and t[-1] != os.sep:
94 96 t += os.sep
95 97 l += [x for x in files if x.startswith(t)]
96 98 return l
97 99
98 100 parity = [0]
99 101 def diffblock(diff, f, fn):
100 102 yield self.t("diffblock",
101 103 lines=prettyprintlines(diff),
102 104 parity=parity[0],
103 105 file=f,
104 106 filenode=hex(fn or nullid))
105 107 parity[0] = 1 - parity[0]
106 108
107 109 def prettyprintlines(diff):
108 110 for l in diff.splitlines(1):
109 111 if l.startswith('+'):
110 112 yield self.t("difflineplus", line=l)
111 113 elif l.startswith('-'):
112 114 yield self.t("difflineminus", line=l)
113 115 elif l.startswith('@'):
114 116 yield self.t("difflineat", line=l)
115 117 else:
116 118 yield self.t("diffline", line=l)
117 119
118 120 r = self.repo
119 121 cl = r.changelog
120 122 mf = r.manifest
121 123 change1 = cl.read(node1)
122 124 change2 = cl.read(node2)
123 125 mmap1 = mf.read(change1[0])
124 126 mmap2 = mf.read(change2[0])
125 127 date1 = util.datestr(change1[2])
126 128 date2 = util.datestr(change2[2])
127 129
128 130 modified, added, removed, deleted, unknown = r.changes(node1, node2)
129 131 if files:
130 132 modified, added, removed = map(lambda x: filterfiles(files, x),
131 133 (modified, added, removed))
132 134
133 135 diffopts = self.repo.ui.diffopts()
134 136 showfunc = diffopts['showfunc']
135 137 ignorews = diffopts['ignorews']
136 138 for f in modified:
137 139 to = r.file(f).read(mmap1[f])
138 140 tn = r.file(f).read(mmap2[f])
139 141 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
140 142 showfunc=showfunc, ignorews=ignorews), f, tn)
141 143 for f in added:
142 144 to = None
143 145 tn = r.file(f).read(mmap2[f])
144 146 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
145 147 showfunc=showfunc, ignorews=ignorews), f, tn)
146 148 for f in removed:
147 149 to = r.file(f).read(mmap1[f])
148 150 tn = None
149 151 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
150 152 showfunc=showfunc, ignorews=ignorews), f, tn)
151 153
152 154 def changelog(self, pos):
153 155 def changenav(**map):
154 156 def seq(factor, maxchanges=None):
155 157 if maxchanges:
156 158 yield maxchanges
157 159 if maxchanges >= 20 and maxchanges <= 40:
158 160 yield 50
159 161 else:
160 162 yield 1 * factor
161 163 yield 3 * factor
162 164 for f in seq(factor * 10):
163 165 yield f
164 166
165 167 l = []
166 168 last = 0
167 169 for f in seq(1, self.maxchanges):
168 170 if f < self.maxchanges or f <= last:
169 171 continue
170 172 if f > count:
171 173 break
172 174 last = f
173 175 r = "%d" % f
174 176 if pos + f < count:
175 177 l.append(("+" + r, pos + f))
176 178 if pos - f >= 0:
177 179 l.insert(0, ("-" + r, pos - f))
178 180
179 181 yield {"rev": 0, "label": "(0)"}
180 182
181 183 for label, rev in l:
182 184 yield {"label": label, "rev": rev}
183 185
184 186 yield {"label": "tip", "rev": "tip"}
185 187
186 188 def changelist(**map):
187 189 parity = (start - end) & 1
188 190 cl = self.repo.changelog
189 191 l = [] # build a list in forward order for efficiency
190 192 for i in range(start, end):
191 193 n = cl.node(i)
192 194 changes = cl.read(n)
193 195 hn = hex(n)
194 196
195 197 l.insert(0, {"parity": parity,
196 198 "author": changes[1],
197 199 "parent": self.siblings(cl.parents(n), cl.rev,
198 200 cl.rev(n) - 1),
199 201 "child": self.siblings(cl.children(n), cl.rev,
200 202 cl.rev(n) + 1),
201 203 "changelogtag": self.showtag("changelogtag",n),
202 204 "manifest": hex(changes[0]),
203 205 "desc": changes[4],
204 206 "date": changes[2],
205 207 "files": self.listfilediffs(changes[3], n),
206 208 "rev": i,
207 209 "node": hn})
208 210 parity = 1 - parity
209 211
210 212 for e in l:
211 213 yield e
212 214
213 215 cl = self.repo.changelog
214 216 mf = cl.read(cl.tip())[0]
215 217 count = cl.count()
216 218 start = max(0, pos - self.maxchanges + 1)
217 219 end = min(count, start + self.maxchanges)
218 220 pos = end - 1
219 221
220 222 yield self.t('changelog',
221 223 changenav=changenav,
222 224 manifest=hex(mf),
223 225 rev=pos, changesets=count, entries=changelist,
224 226 archives=self.archivelist("tip"))
225 227
226 228 def search(self, query):
227 229
228 230 def changelist(**map):
229 231 cl = self.repo.changelog
230 232 count = 0
231 233 qw = query.lower().split()
232 234
233 235 def revgen():
234 236 for i in range(cl.count() - 1, 0, -100):
235 237 l = []
236 238 for j in range(max(0, i - 100), i):
237 239 n = cl.node(j)
238 240 changes = cl.read(n)
239 241 l.append((n, j, changes))
240 242 l.reverse()
241 243 for e in l:
242 244 yield e
243 245
244 246 for n, i, changes in revgen():
245 247 miss = 0
246 248 for q in qw:
247 249 if not (q in changes[1].lower() or
248 250 q in changes[4].lower() or
249 251 q in " ".join(changes[3][:20]).lower()):
250 252 miss = 1
251 253 break
252 254 if miss:
253 255 continue
254 256
255 257 count += 1
256 258 hn = hex(n)
257 259
258 260 yield self.t('searchentry',
259 261 parity=count & 1,
260 262 author=changes[1],
261 263 parent=self.siblings(cl.parents(n), cl.rev),
262 264 child=self.siblings(cl.children(n), cl.rev),
263 265 changelogtag=self.showtag("changelogtag",n),
264 266 manifest=hex(changes[0]),
265 267 desc=changes[4],
266 268 date=changes[2],
267 269 files=self.listfilediffs(changes[3], n),
268 270 rev=i,
269 271 node=hn)
270 272
271 273 if count >= self.maxchanges:
272 274 break
273 275
274 276 cl = self.repo.changelog
275 277 mf = cl.read(cl.tip())[0]
276 278
277 279 yield self.t('search',
278 280 query=query,
279 281 manifest=hex(mf),
280 282 entries=changelist)
281 283
282 284 def changeset(self, nodeid):
283 285 cl = self.repo.changelog
284 286 n = self.repo.lookup(nodeid)
285 287 nodeid = hex(n)
286 288 changes = cl.read(n)
287 289 p1 = cl.parents(n)[0]
288 290
289 291 files = []
290 292 mf = self.repo.manifest.read(changes[0])
291 293 for f in changes[3]:
292 294 files.append(self.t("filenodelink",
293 295 filenode=hex(mf.get(f, nullid)), file=f))
294 296
295 297 def diff(**map):
296 298 yield self.diff(p1, n, None)
297 299
298 300 yield self.t('changeset',
299 301 diff=diff,
300 302 rev=cl.rev(n),
301 303 node=nodeid,
302 304 parent=self.siblings(cl.parents(n), cl.rev),
303 305 child=self.siblings(cl.children(n), cl.rev),
304 306 changesettag=self.showtag("changesettag",n),
305 307 manifest=hex(changes[0]),
306 308 author=changes[1],
307 309 desc=changes[4],
308 310 date=changes[2],
309 311 files=files,
310 312 archives=self.archivelist(nodeid))
311 313
312 314 def filelog(self, f, filenode):
313 315 cl = self.repo.changelog
314 316 fl = self.repo.file(f)
315 317 filenode = hex(fl.lookup(filenode))
316 318 count = fl.count()
317 319
318 320 def entries(**map):
319 321 l = []
320 322 parity = (count - 1) & 1
321 323
322 324 for i in range(count):
323 325 n = fl.node(i)
324 326 lr = fl.linkrev(n)
325 327 cn = cl.node(lr)
326 328 cs = cl.read(cl.node(lr))
327 329
328 330 l.insert(0, {"parity": parity,
329 331 "filenode": hex(n),
330 332 "filerev": i,
331 333 "file": f,
332 334 "node": hex(cn),
333 335 "author": cs[1],
334 336 "date": cs[2],
335 337 "rename": self.renamelink(fl, n),
336 338 "parent": self.siblings(fl.parents(n),
337 339 fl.rev, file=f),
338 340 "child": self.siblings(fl.children(n),
339 341 fl.rev, file=f),
340 342 "desc": cs[4]})
341 343 parity = 1 - parity
342 344
343 345 for e in l:
344 346 yield e
345 347
346 348 yield self.t("filelog", file=f, filenode=filenode, entries=entries)
347 349
348 350 def filerevision(self, f, node):
349 351 fl = self.repo.file(f)
350 352 n = fl.lookup(node)
351 353 node = hex(n)
352 354 text = fl.read(n)
353 355 changerev = fl.linkrev(n)
354 356 cl = self.repo.changelog
355 357 cn = cl.node(changerev)
356 358 cs = cl.read(cn)
357 359 mfn = cs[0]
358 360
359 361 mt = mimetypes.guess_type(f)[0]
360 362 rawtext = text
361 363 if util.binary(text):
362 364 mt = mt or 'application/octet-stream'
363 365 text = "(binary:%s)" % mt
364 366 mt = mt or 'text/plain'
365 367
366 368 def lines():
367 369 for l, t in enumerate(text.splitlines(1)):
368 370 yield {"line": t,
369 371 "linenumber": "% 6d" % (l + 1),
370 372 "parity": l & 1}
371 373
372 374 yield self.t("filerevision",
373 375 file=f,
374 376 filenode=node,
375 377 path=_up(f),
376 378 text=lines(),
377 379 raw=rawtext,
378 380 mimetype=mt,
379 381 rev=changerev,
380 382 node=hex(cn),
381 383 manifest=hex(mfn),
382 384 author=cs[1],
383 385 date=cs[2],
384 386 parent=self.siblings(fl.parents(n), fl.rev, file=f),
385 387 child=self.siblings(fl.children(n), fl.rev, file=f),
386 388 rename=self.renamelink(fl, n),
387 389 permissions=self.repo.manifest.readflags(mfn)[f])
388 390
389 391 def fileannotate(self, f, node):
390 392 bcache = {}
391 393 ncache = {}
392 394 fl = self.repo.file(f)
393 395 n = fl.lookup(node)
394 396 node = hex(n)
395 397 changerev = fl.linkrev(n)
396 398
397 399 cl = self.repo.changelog
398 400 cn = cl.node(changerev)
399 401 cs = cl.read(cn)
400 402 mfn = cs[0]
401 403
402 404 def annotate(**map):
403 405 parity = 1
404 406 last = None
405 407 for r, l in fl.annotate(n):
406 408 try:
407 409 cnode = ncache[r]
408 410 except KeyError:
409 411 cnode = ncache[r] = self.repo.changelog.node(r)
410 412
411 413 try:
412 414 name = bcache[r]
413 415 except KeyError:
414 416 cl = self.repo.changelog.read(cnode)
415 417 bcache[r] = name = self.repo.ui.shortuser(cl[1])
416 418
417 419 if last != cnode:
418 420 parity = 1 - parity
419 421 last = cnode
420 422
421 423 yield {"parity": parity,
422 424 "node": hex(cnode),
423 425 "rev": r,
424 426 "author": name,
425 427 "file": f,
426 428 "line": l}
427 429
428 430 yield self.t("fileannotate",
429 431 file=f,
430 432 filenode=node,
431 433 annotate=annotate,
432 434 path=_up(f),
433 435 rev=changerev,
434 436 node=hex(cn),
435 437 manifest=hex(mfn),
436 438 author=cs[1],
437 439 date=cs[2],
438 440 rename=self.renamelink(fl, n),
439 441 parent=self.siblings(fl.parents(n), fl.rev, file=f),
440 442 child=self.siblings(fl.children(n), fl.rev, file=f),
441 443 permissions=self.repo.manifest.readflags(mfn)[f])
442 444
443 445 def manifest(self, mnode, path):
444 446 man = self.repo.manifest
445 447 mn = man.lookup(mnode)
446 448 mnode = hex(mn)
447 449 mf = man.read(mn)
448 450 rev = man.rev(mn)
449 451 changerev = man.linkrev(mn)
450 452 node = self.repo.changelog.node(changerev)
451 453 mff = man.readflags(mn)
452 454
453 455 files = {}
454 456
455 457 p = path[1:]
456 458 if p and p[-1] != "/":
457 459 p += "/"
458 460 l = len(p)
459 461
460 462 for f,n in mf.items():
461 463 if f[:l] != p:
462 464 continue
463 465 remain = f[l:]
464 466 if "/" in remain:
465 467 short = remain[:remain.find("/") + 1] # bleah
466 468 files[short] = (f, None)
467 469 else:
468 470 short = os.path.basename(remain)
469 471 files[short] = (f, n)
470 472
471 473 def filelist(**map):
472 474 parity = 0
473 475 fl = files.keys()
474 476 fl.sort()
475 477 for f in fl:
476 478 full, fnode = files[f]
477 479 if not fnode:
478 480 continue
479 481
480 482 yield {"file": full,
481 483 "manifest": mnode,
482 484 "filenode": hex(fnode),
483 485 "parity": parity,
484 486 "basename": f,
485 487 "permissions": mff[full]}
486 488 parity = 1 - parity
487 489
488 490 def dirlist(**map):
489 491 parity = 0
490 492 fl = files.keys()
491 493 fl.sort()
492 494 for f in fl:
493 495 full, fnode = files[f]
494 496 if fnode:
495 497 continue
496 498
497 499 yield {"parity": parity,
498 500 "path": os.path.join(path, f),
499 501 "manifest": mnode,
500 502 "basename": f[:-1]}
501 503 parity = 1 - parity
502 504
503 505 yield self.t("manifest",
504 506 manifest=mnode,
505 507 rev=rev,
506 508 node=hex(node),
507 509 path=path,
508 510 up=_up(path),
509 511 fentries=filelist,
510 512 dentries=dirlist,
511 513 archives=self.archivelist(hex(node)))
512 514
513 515 def tags(self):
514 516 cl = self.repo.changelog
515 517 mf = cl.read(cl.tip())[0]
516 518
517 519 i = self.repo.tagslist()
518 520 i.reverse()
519 521
520 522 def entries(notip=False, **map):
521 523 parity = 0
522 524 for k,n in i:
523 525 if notip and k == "tip": continue
524 526 yield {"parity": parity,
525 527 "tag": k,
526 528 "tagmanifest": hex(cl.read(n)[0]),
527 529 "date": cl.read(n)[2],
528 530 "node": hex(n)}
529 531 parity = 1 - parity
530 532
531 533 yield self.t("tags",
532 534 manifest=hex(mf),
533 535 entries=lambda **x: entries(False, **x),
534 536 entriesnotip=lambda **x: entries(True, **x))
535 537
536 538 def summary(self):
537 539 cl = self.repo.changelog
538 540 mf = cl.read(cl.tip())[0]
539 541
540 542 i = self.repo.tagslist()
541 543 i.reverse()
542 544
543 545 def tagentries(**map):
544 546 parity = 0
545 547 count = 0
546 548 for k,n in i:
547 549 if k == "tip": # skip tip
548 550 continue;
549 551
550 552 count += 1
551 553 if count > 10: # limit to 10 tags
552 554 break;
553 555
554 556 c = cl.read(n)
555 557 m = c[0]
556 558 t = c[2]
557 559
558 560 yield self.t("tagentry",
559 561 parity = parity,
560 562 tag = k,
561 563 node = hex(n),
562 564 date = t,
563 565 tagmanifest = hex(m))
564 566 parity = 1 - parity
565 567
566 568 def changelist(**map):
567 569 parity = 0
568 570 cl = self.repo.changelog
569 571 l = [] # build a list in forward order for efficiency
570 572 for i in range(start, end):
571 573 n = cl.node(i)
572 574 changes = cl.read(n)
573 575 hn = hex(n)
574 576 t = changes[2]
575 577
576 578 l.insert(0, self.t(
577 579 'shortlogentry',
578 580 parity = parity,
579 581 author = changes[1],
580 582 manifest = hex(changes[0]),
581 583 desc = changes[4],
582 584 date = t,
583 585 rev = i,
584 586 node = hn))
585 587 parity = 1 - parity
586 588
587 589 yield l
588 590
589 591 cl = self.repo.changelog
590 592 mf = cl.read(cl.tip())[0]
591 593 count = cl.count()
592 594 start = max(0, count - self.maxchanges)
593 595 end = min(count, start + self.maxchanges)
594 596
595 597 yield self.t("summary",
596 598 desc = self.repo.ui.config("web", "description", "unknown"),
597 599 owner = (self.repo.ui.config("ui", "username") or # preferred
598 600 self.repo.ui.config("web", "contact") or # deprecated
599 601 self.repo.ui.config("web", "author", "unknown")), # also
600 602 lastchange = (0, 0), # FIXME
601 603 manifest = hex(mf),
602 604 tags = tagentries,
603 605 shortlog = changelist)
604 606
605 607 def filediff(self, file, changeset):
606 608 cl = self.repo.changelog
607 609 n = self.repo.lookup(changeset)
608 610 changeset = hex(n)
609 611 p1 = cl.parents(n)[0]
610 612 cs = cl.read(n)
611 613 mf = self.repo.manifest.read(cs[0])
612 614
613 615 def diff(**map):
614 616 yield self.diff(p1, n, [file])
615 617
616 618 yield self.t("filediff",
617 619 file=file,
618 620 filenode=hex(mf.get(file, nullid)),
619 621 node=changeset,
620 622 rev=self.repo.changelog.rev(n),
621 623 parent=self.siblings(cl.parents(n), cl.rev),
622 624 child=self.siblings(cl.children(n), cl.rev),
623 625 diff=diff)
624 626
625 627 archive_specs = {
626 628 'bz2': ('application/x-tar', 'tbz2', '.tar.bz2', None),
627 629 'gz': ('application/x-tar', 'tgz', '.tar.gz', None),
628 630 'zip': ('application/zip', 'zip', '.zip', None),
629 631 }
630 632
631 633 def archive(self, req, cnode, type_):
632 634 reponame = re.sub(r"\W+", "-", os.path.basename(self.reponame))
633 635 name = "%s-%s" % (reponame, short(cnode))
634 636 mimetype, artype, extension, encoding = self.archive_specs[type_]
635 637 headers = [('Content-type', mimetype),
636 638 ('Content-disposition', 'attachment; filename=%s%s' %
637 639 (name, extension))]
638 640 if encoding:
639 641 headers.append(('Content-encoding', encoding))
640 642 req.header(headers)
641 643 archival.archive(self.repo, req.out, cnode, artype, prefix=name)
642 644
643 645 # add tags to things
644 646 # tags -> list of changesets corresponding to tags
645 647 # find tag, changeset, file
646 648
649 def cleanpath(self, path):
650 p = util.normpath(path)
651 if p[:2] == "..":
652 raise Exception("suspicious path")
653 return p
654
647 655 def run(self, req=hgrequest()):
648 def clean(path):
649 p = util.normpath(path)
650 if p[:2] == "..":
651 raise Exception("suspicious path")
652 return p
653
654 656 def header(**map):
655 657 yield self.t("header", **map)
656 658
657 659 def footer(**map):
658 660 yield self.t("footer",
659 661 motd=self.repo.ui.config("web", "motd", ""),
660 662 **map)
661 663
662 664 def expand_form(form):
663 665 shortcuts = {
664 666 'cl': [('cmd', ['changelog']), ('rev', None)],
665 667 'cs': [('cmd', ['changeset']), ('node', None)],
666 668 'f': [('cmd', ['file']), ('filenode', None)],
667 669 'fl': [('cmd', ['filelog']), ('filenode', None)],
668 670 'fd': [('cmd', ['filediff']), ('node', None)],
669 671 'fa': [('cmd', ['annotate']), ('filenode', None)],
670 672 'mf': [('cmd', ['manifest']), ('manifest', None)],
671 673 'ca': [('cmd', ['archive']), ('node', None)],
672 674 'tags': [('cmd', ['tags'])],
673 675 'tip': [('cmd', ['changeset']), ('node', ['tip'])],
674 676 'static': [('cmd', ['static']), ('file', None)]
675 677 }
676 678
677 679 for k in shortcuts.iterkeys():
678 680 if form.has_key(k):
679 681 for name, value in shortcuts[k]:
680 682 if value is None:
681 683 value = form[k]
682 684 form[name] = value
683 685 del form[k]
684 686
685 687 self.refresh()
686 688
687 689 expand_form(req.form)
688 690
689 t = self.repo.ui.config("web", "templates", templater.templatepath())
690 static = self.repo.ui.config("web", "static", os.path.join(t,"static"))
691 m = os.path.join(t, "map")
691 m = os.path.join(self.templatepath, "map")
692 692 style = self.repo.ui.config("web", "style", "")
693 693 if req.form.has_key('style'):
694 694 style = req.form['style'][0]
695 695 if style:
696 696 b = os.path.basename("map-" + style)
697 p = os.path.join(t, b)
697 p = os.path.join(self.templatepath, b)
698 698 if os.path.isfile(p):
699 699 m = p
700 700
701 701 port = req.env["SERVER_PORT"]
702 702 port = port != "80" and (":" + port) or ""
703 703 uri = req.env["REQUEST_URI"]
704 704 if "?" in uri:
705 705 uri = uri.split("?")[0]
706 706 url = "http://%s%s%s" % (req.env["SERVER_NAME"], port, uri)
707 707 if not self.reponame:
708 708 self.reponame = (self.repo.ui.config("web", "name")
709 709 or uri.strip('/') or self.repo.root)
710 710
711 711 self.t = templater.templater(m, templater.common_filters,
712 712 defaults={"url": url,
713 713 "repo": self.reponame,
714 714 "header": header,
715 715 "footer": footer,
716 716 })
717 717
718 718 if not req.form.has_key('cmd'):
719 719 req.form['cmd'] = [self.t.cache['default'],]
720 720
721 721 cmd = req.form['cmd'][0]
722 if cmd == 'changelog':
723 hi = self.repo.changelog.count() - 1
724 if req.form.has_key('rev'):
725 hi = req.form['rev'][0]
726 try:
727 hi = self.repo.changelog.rev(self.repo.lookup(hi))
728 except hg.RepoError:
729 req.write(self.search(hi)) # XXX redirect to 404 page?
730 return
731 722
732 req.write(self.changelog(hi))
733
734 elif cmd == 'changeset':
735 req.write(self.changeset(req.form['node'][0]))
736
737 elif cmd == 'manifest':
738 req.write(self.manifest(req.form['manifest'][0],
739 clean(req.form['path'][0])))
740
741 elif cmd == 'tags':
742 req.write(self.tags())
743
744 elif cmd == 'summary':
745 req.write(self.summary())
746
747 elif cmd == 'filediff':
748 req.write(self.filediff(clean(req.form['file'][0]),
749 req.form['node'][0]))
750
751 elif cmd == 'file':
752 req.write(self.filerevision(clean(req.form['file'][0]),
753 req.form['filenode'][0]))
754
755 elif cmd == 'annotate':
756 req.write(self.fileannotate(clean(req.form['file'][0]),
757 req.form['filenode'][0]))
758
759 elif cmd == 'filelog':
760 req.write(self.filelog(clean(req.form['file'][0]),
761 req.form['filenode'][0]))
762
763 elif cmd == 'heads':
764 resp = " ".join(map(hex, self.repo.heads())) + "\n"
765 req.httphdr("application/mercurial-0.1", length=len(resp))
766 req.write(resp)
767
768 elif cmd == 'branches':
769 nodes = []
770 if req.form.has_key('nodes'):
771 nodes = map(bin, req.form['nodes'][0].split(" "))
772 resp = cStringIO.StringIO()
773 for b in self.repo.branches(nodes):
774 resp.write(" ".join(map(hex, b)) + "\n")
775 resp = resp.getvalue()
776 req.httphdr("application/mercurial-0.1", length=len(resp))
777 req.write(resp)
778
779 elif cmd == 'between':
780 nodes = []
781 if req.form.has_key('pairs'):
782 pairs = [map(bin, p.split("-"))
783 for p in req.form['pairs'][0].split(" ")]
784 resp = cStringIO.StringIO()
785 for b in self.repo.between(pairs):
786 resp.write(" ".join(map(hex, b)) + "\n")
787 resp = resp.getvalue()
788 req.httphdr("application/mercurial-0.1", length=len(resp))
789 req.write(resp)
790
791 elif cmd == 'changegroup':
792 req.httphdr("application/mercurial-0.1")
793 nodes = []
794 if not self.allowpull:
795 return
796
797 if req.form.has_key('roots'):
798 nodes = map(bin, req.form['roots'][0].split(" "))
799
800 z = zlib.compressobj()
801 f = self.repo.changegroup(nodes, 'serve')
802 while 1:
803 chunk = f.read(4096)
804 if not chunk:
805 break
806 req.write(z.compress(chunk))
807
808 req.write(z.flush())
809
810 elif cmd == 'archive':
811 changeset = self.repo.lookup(req.form['node'][0])
812 type_ = req.form['type'][0]
813 allowed = self.repo.ui.config("web", "allow_archive", "").split()
814 if (type_ in self.archives and (type_ in allowed or
815 self.repo.ui.configbool("web", "allow" + type_, False))):
816 self.archive(req, changeset, type_)
817 return
818
819 req.write(self.t("error"))
820
821 elif cmd == 'static':
822 fname = req.form['file'][0]
823 req.write(staticfile(static, fname)
824 or self.t("error", error="%r not found" % fname))
825
723 method = getattr(self, 'do_' + cmd, None)
724 if method:
725 method(req)
826 726 else:
827 727 req.write(self.t("error"))
828 728 req.done()
729
730 def do_changelog(self, req):
731 hi = self.repo.changelog.count() - 1
732 if req.form.has_key('rev'):
733 hi = req.form['rev'][0]
734 try:
735 hi = self.repo.changelog.rev(self.repo.lookup(hi))
736 except hg.RepoError:
737 req.write(self.search(hi)) # XXX redirect to 404 page?
738 return
739
740 req.write(self.changelog(hi))
741
742 def do_changeset(self, req):
743 req.write(self.changeset(req.form['node'][0]))
744
745 def do_manifest(self, req):
746 req.write(self.manifest(req.form['manifest'][0],
747 self.cleanpath(req.form['path'][0])))
748
749 def do_tags(self, req):
750 req.write(self.tags())
751
752 def do_summary(self, req):
753 req.write(self.summary())
754
755 def do_filediff(self, req):
756 req.write(self.filediff(self.cleanpath(req.form['file'][0]),
757 req.form['node'][0]))
758
759 def do_file(self, req):
760 req.write(self.filerevision(self.cleanpath(req.form['file'][0]),
761 req.form['filenode'][0]))
762
763 def do_annotate(self, req):
764 req.write(self.fileannotate(self.cleanpath(req.form['file'][0]),
765 req.form['filenode'][0]))
766
767 def do_filelog(self, req):
768 req.write(self.filelog(self.cleanpath(req.form['file'][0]),
769 req.form['filenode'][0]))
770
771 def do_heads(self, req):
772 resp = " ".join(map(hex, self.repo.heads())) + "\n"
773 req.httphdr("application/mercurial-0.1", length=len(resp))
774 req.write(resp)
775
776 def do_branches(self, req):
777 nodes = []
778 if req.form.has_key('nodes'):
779 nodes = map(bin, req.form['nodes'][0].split(" "))
780 resp = cStringIO.StringIO()
781 for b in self.repo.branches(nodes):
782 resp.write(" ".join(map(hex, b)) + "\n")
783 resp = resp.getvalue()
784 req.httphdr("application/mercurial-0.1", length=len(resp))
785 req.write(resp)
786
787 def do_between(self, req):
788 nodes = []
789 if req.form.has_key('pairs'):
790 pairs = [map(bin, p.split("-"))
791 for p in req.form['pairs'][0].split(" ")]
792 resp = cStringIO.StringIO()
793 for b in self.repo.between(pairs):
794 resp.write(" ".join(map(hex, b)) + "\n")
795 resp = resp.getvalue()
796 req.httphdr("application/mercurial-0.1", length=len(resp))
797 req.write(resp)
798
799 def do_changegroup(self, req):
800 req.httphdr("application/mercurial-0.1")
801 nodes = []
802 if not self.allowpull:
803 return
804
805 if req.form.has_key('roots'):
806 nodes = map(bin, req.form['roots'][0].split(" "))
807
808 z = zlib.compressobj()
809 f = self.repo.changegroup(nodes, 'serve')
810 while 1:
811 chunk = f.read(4096)
812 if not chunk:
813 break
814 req.write(z.compress(chunk))
815
816 req.write(z.flush())
817
818 def do_archive(self, req):
819 changeset = self.repo.lookup(req.form['node'][0])
820 type_ = req.form['type'][0]
821 allowed = self.repo.ui.config("web", "allow_archive", "").split()
822 if (type_ in self.archives and (type_ in allowed or
823 self.repo.ui.configbool("web", "allow" + type_, False))):
824 self.archive(req, changeset, type_)
825 return
826
827 req.write(self.t("error"))
828
829 def do_static(self, req):
830 fname = req.form['file'][0]
831 static = self.repo.ui.config("web", "static",
832 os.path.join(self.templatepath,
833 "static"))
834 req.write(staticfile(static, fname)
835 or self.t("error", error="%r not found" % fname))
General Comments 0
You need to be logged in to leave comments. Login now