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