##// END OF EJS Templates
hgweb.py: kill #! line, clean up copyright notice...
mpm@selenic.com -
r238:3b92f8fe default
parent child Browse files
Show More
@@ -1,711 +1,711 b''
1 #!/usr/bin/env python
1 # hgweb.py - web interface to a mercurial repository
2 2 #
3 # hgweb.py - 0.2 - 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 # - web interface to a mercurial repository
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
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 # useful for debugging
10 10 import cgitb
11 11 cgitb.enable()
12 12
13 13 import os, cgi, time, re, difflib, sys, zlib
14 14 from mercurial.hg import *
15 15 from mercurial.ui import *
16 16
17 17 def templatepath():
18 18 for f in "templates", "../templates":
19 19 p = os.path.join(os.path.dirname(__file__), f)
20 20 if os.path.isdir(p): return p
21 21
22 22 def age(t):
23 23 def plural(t, c):
24 24 if c == 1: return t
25 25 return t + "s"
26 26 def fmt(t, c):
27 27 return "%d %s" % (c, plural(t, c))
28 28
29 29 now = time.time()
30 30 delta = max(1, int(now - t))
31 31
32 32 scales = [["second", 1],
33 33 ["minute", 60],
34 34 ["hour", 3600],
35 35 ["day", 3600 * 24],
36 36 ["week", 3600 * 24 * 7],
37 37 ["month", 3600 * 24 * 30],
38 38 ["year", 3600 * 24 * 365]]
39 39
40 40 scales.reverse()
41 41
42 42 for t, s in scales:
43 43 n = delta / s
44 44 if n >= 2 or s == 1: return fmt(t, n)
45 45
46 46 def nl2br(text):
47 47 return text.replace('\n', '<br/>\n')
48 48
49 49 def obfuscate(text):
50 50 return ''.join([ '&#%d' % ord(c) for c in text ])
51 51
52 52 def up(p):
53 53 if p[0] != "/": p = "/" + p
54 54 if p[-1] == "/": p = p[:-1]
55 55 up = os.path.dirname(p)
56 56 if up == "/":
57 57 return "/"
58 58 return up + "/"
59 59
60 60 def httphdr(type):
61 61 print 'Content-type: %s\n' % type
62 62
63 63 def write(*things):
64 64 for thing in things:
65 65 if hasattr(thing, "__iter__"):
66 66 for part in thing:
67 67 write(part)
68 68 else:
69 69 sys.stdout.write(str(thing))
70 70
71 71 def template(tmpl, filters = {}, **map):
72 72 while tmpl:
73 73 m = re.search(r"#([a-zA-Z0-9]+)((\|[a-zA-Z0-9]+)*)#", tmpl)
74 74 if m:
75 75 yield tmpl[:m.start(0)]
76 76 v = map.get(m.group(1), "")
77 77 v = callable(v) and v() or v
78 78
79 79 fl = m.group(2)
80 80 if fl:
81 81 for f in fl.split("|")[1:]:
82 82 v = filters[f](v)
83 83
84 84 yield v
85 85 tmpl = tmpl[m.end(0):]
86 86 else:
87 87 yield tmpl
88 88 return
89 89
90 90 class templater:
91 91 def __init__(self, mapfile, filters = {}):
92 92 self.cache = {}
93 93 self.map = {}
94 94 self.base = os.path.dirname(mapfile)
95 95 self.filters = filters
96 96
97 97 for l in file(mapfile):
98 98 m = re.match(r'(\S+)\s*=\s*"(.*)"$', l)
99 99 if m:
100 100 self.cache[m.group(1)] = m.group(2)
101 101 else:
102 102 m = re.match(r'(\S+)\s*=\s*(\S+)', l)
103 103 if m:
104 104 self.map[m.group(1)] = os.path.join(self.base, m.group(2))
105 105 else:
106 106 raise "unknown map entry '%s'" % l
107 107
108 108 def __call__(self, t, **map):
109 109 try:
110 110 tmpl = self.cache[t]
111 111 except KeyError:
112 112 tmpl = self.cache[t] = file(self.map[t]).read()
113 113 return template(tmpl, self.filters, **map)
114 114
115 115 class hgweb:
116 116 maxchanges = 20
117 117 maxfiles = 10
118 118
119 119 def __init__(self, path, name, templates = ""):
120 120 self.templates = templates or templatepath()
121 121 self.reponame = name
122 122 self.repo = repository(ui(), path)
123 123 self.viewonly = 0
124 124
125 125 self.filters = {
126 126 "escape": cgi.escape,
127 127 "age": age,
128 128 "date": (lambda x: time.asctime(time.gmtime(x))),
129 129 "addbreaks": nl2br,
130 130 "obfuscate": obfuscate,
131 131 "firstline": (lambda x: x.splitlines(1)[0]),
132 132 }
133 133
134 134 def date(self, cs):
135 135 return time.asctime(time.gmtime(float(cs[2].split(' ')[0])))
136 136
137 137 def listfiles(self, files, mf):
138 138 for f in files[:self.maxfiles]:
139 139 yield self.t("filenodelink", node = hex(mf[f]), file = f)
140 140 if len(files) > self.maxfiles:
141 141 yield self.t("fileellipses")
142 142
143 143 def listfilediffs(self, files, changeset):
144 144 for f in files[:self.maxfiles]:
145 145 yield self.t("filedifflink", node = hex(changeset), file = f)
146 146 if len(files) > self.maxfiles:
147 147 yield self.t("fileellipses")
148 148
149 149 def parent(self, t1, node=nullid, rev=-1, **args):
150 150 if node != hex(nullid):
151 151 yield self.t(t1, node = node, rev = rev, **args)
152 152
153 153 def diff(self, node1, node2, files):
154 154 def filterfiles(list, files):
155 155 l = [ x for x in list if x in files ]
156 156
157 157 for f in files:
158 158 if f[-1] != os.sep: f += os.sep
159 159 l += [ x for x in list if x.startswith(f) ]
160 160 return l
161 161
162 162 parity = [0]
163 163 def diffblock(diff, f, fn):
164 164 yield self.t("diffblock",
165 165 lines = prettyprintlines(diff),
166 166 parity = parity[0],
167 167 file = f,
168 168 filenode = hex(fn))
169 169 parity[0] = 1 - parity[0]
170 170
171 171 def prettyprintlines(diff):
172 172 for l in diff.splitlines(1):
173 173 if l.startswith('+'):
174 174 yield self.t("difflineplus", line = l)
175 175 elif l.startswith('-'):
176 176 yield self.t("difflineminus", line = l)
177 177 elif l.startswith('@'):
178 178 yield self.t("difflineat", line = l)
179 179 else:
180 180 yield self.t("diffline", line = l)
181 181
182 182 r = self.repo
183 183 cl = r.changelog
184 184 mf = r.manifest
185 185 change1 = cl.read(node1)
186 186 change2 = cl.read(node2)
187 187 mmap1 = mf.read(change1[0])
188 188 mmap2 = mf.read(change2[0])
189 189 date1 = self.date(change1)
190 190 date2 = self.date(change2)
191 191
192 192 c, a, d = r.diffrevs(node1, node2)
193 193 c, a, d = map(lambda x: filterfiles(x, files), (c, a, d))
194 194
195 195 for f in c:
196 196 to = r.file(f).read(mmap1[f])
197 197 tn = r.file(f).read(mmap2[f])
198 198 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f), f, tn)
199 199 for f in a:
200 200 to = ""
201 201 tn = r.file(f).read(mmap2[f])
202 202 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f), f, tn)
203 203 for f in d:
204 204 to = r.file(f).read(mmap1[f])
205 205 tn = ""
206 206 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f), f, tn)
207 207
208 208 def header(self):
209 209 yield self.t("header", repo = self.reponame)
210 210
211 211 def footer(self):
212 212 yield self.t("footer", repo = self.reponame)
213 213
214 214 def changelog(self, pos):
215 215 def changenav():
216 216 def seq(factor = 1):
217 217 yield 1 * factor
218 218 yield 3 * factor
219 219 #yield 5 * factor
220 220 for f in seq(factor * 10):
221 221 yield f
222 222
223 223 l = []
224 224 for f in seq():
225 225 if f < self.maxchanges / 2: continue
226 226 if f > count: break
227 227 r = "%d" % f
228 228 if pos + f < count - (f/2): l.append(("+" + r, pos + f))
229 229 if pos - f >= 0 + (f/2): l.insert(0, ("-" + r, pos - f))
230 230
231 231 yield self.t("naventry", rev = 0, label="(0)")
232 232
233 233 for label, rev in l:
234 234 yield self.t("naventry", label = label, rev = rev)
235 235
236 236 yield self.t("naventry", label="tip")
237 237
238 238 def changelist():
239 239 parity = (start - end) & 1
240 240 cl = self.repo.changelog
241 241 l = [] # build a list in forward order for efficiency
242 242 for i in range(start, end + 1):
243 243 n = cl.node(i)
244 244 changes = cl.read(n)
245 245 hn = hex(n)
246 246 p1, p2 = cl.parents(n)
247 247 t = float(changes[2].split(' ')[0])
248 248
249 249 l.insert(0, self.t(
250 250 'changelogentry',
251 251 parity = parity,
252 252 author = changes[1],
253 253 parent1 = self.parent("changelogparent",
254 254 hex(p1), cl.rev(p1)),
255 255 parent2 = self.parent("changelogparent",
256 256 hex(p2), cl.rev(p2)),
257 257 p1 = hex(p1), p2 = hex(p2),
258 258 p1rev = cl.rev(p1), p2rev = cl.rev(p2),
259 259 manifest = hex(changes[0]),
260 260 desc = changes[4],
261 261 date = t,
262 262 files = self.listfilediffs(changes[3], n),
263 263 rev = i,
264 264 node = hn))
265 265 parity = 1 - parity
266 266
267 267 yield l
268 268
269 269 cl = self.repo.changelog
270 270 mf = cl.read(cl.tip())[0]
271 271 count = cl.count()
272 272 end = min(pos, count - 1)
273 273 start = max(0, pos - self.maxchanges)
274 274 end = min(count - 1, start + self.maxchanges)
275 275
276 276 yield self.t('changelog',
277 277 header = self.header(),
278 278 footer = self.footer(),
279 279 repo = self.reponame,
280 280 changenav = changenav,
281 281 manifest = hex(mf),
282 282 rev = pos, changesets = count, entries = changelist)
283 283
284 284 def changeset(self, nodeid):
285 285 n = bin(nodeid)
286 286 cl = self.repo.changelog
287 287 changes = cl.read(n)
288 288 p1, p2 = cl.parents(n)
289 289 p1rev, p2rev = cl.rev(p1), cl.rev(p2)
290 290 t = float(changes[2].split(' ')[0])
291 291
292 292 files = []
293 293 mf = self.repo.manifest.read(changes[0])
294 294 for f in changes[3]:
295 295 files.append(self.t("filenodelink",
296 296 filenode = hex(mf[f]), file = f))
297 297
298 298 def diff():
299 299 yield self.diff(p1, n, changes[3])
300 300
301 301 yield self.t('changeset',
302 302 header = self.header(),
303 303 footer = self.footer(),
304 304 repo = self.reponame,
305 305 diff = diff,
306 306 rev = cl.rev(n),
307 307 node = nodeid,
308 308 parent1 = self.parent("changesetparent",
309 309 hex(p1), cl.rev(p1)),
310 310 parent2 = self.parent("changesetparent",
311 311 hex(p2), cl.rev(p2)),
312 312 p1 = hex(p1), p2 = hex(p2),
313 313 p1rev = cl.rev(p1), p2rev = cl.rev(p2),
314 314 manifest = hex(changes[0]),
315 315 author = changes[1],
316 316 desc = changes[4],
317 317 date = t,
318 318 files = files)
319 319
320 320 def filelog(self, f, filenode):
321 321 cl = self.repo.changelog
322 322 fl = self.repo.file(f)
323 323 count = fl.count()
324 324
325 325 def entries():
326 326 l = []
327 327 parity = (count - 1) & 1
328 328
329 329 for i in range(count):
330 330
331 331 n = fl.node(i)
332 332 lr = fl.linkrev(n)
333 333 cn = cl.node(lr)
334 334 cs = cl.read(cl.node(lr))
335 335 p1, p2 = fl.parents(n)
336 336 t = float(cs[2].split(' ')[0])
337 337
338 338 l.insert(0, self.t("filelogentry",
339 339 parity = parity,
340 340 filenode = hex(n),
341 341 filerev = i,
342 342 file = f,
343 343 node = hex(cn),
344 344 author = cs[1],
345 345 date = t,
346 346 desc = cs[4],
347 347 p1 = hex(p1), p2 = hex(p2),
348 348 p1rev = fl.rev(p1), p2rev = fl.rev(p2)))
349 349 parity = 1 - parity
350 350
351 351 yield l
352 352
353 353 yield self.t("filelog",
354 354 header = self.header(),
355 355 footer = self.footer(),
356 356 repo = self.reponame,
357 357 file = f,
358 358 filenode = filenode,
359 359 entries = entries)
360 360
361 361 def filerevision(self, f, node):
362 362 fl = self.repo.file(f)
363 363 n = bin(node)
364 364 text = fl.read(n)
365 365 changerev = fl.linkrev(n)
366 366 cl = self.repo.changelog
367 367 cn = cl.node(changerev)
368 368 cs = cl.read(cn)
369 369 p1, p2 = fl.parents(n)
370 370 t = float(cs[2].split(' ')[0])
371 371 mfn = cs[0]
372 372
373 373 def lines():
374 374 for l, t in enumerate(text.splitlines(1)):
375 375 yield self.t("fileline", line = t,
376 376 linenumber = "% 6d" % (l + 1),
377 377 parity = l & 1)
378 378
379 379 yield self.t("filerevision", file = f,
380 380 header = self.header(),
381 381 footer = self.footer(),
382 382 repo = self.reponame,
383 383 filenode = node,
384 384 path = up(f),
385 385 text = lines(),
386 386 rev = changerev,
387 387 node = hex(cn),
388 388 manifest = hex(mfn),
389 389 author = cs[1],
390 390 date = t,
391 391 parent1 = self.parent("filerevparent",
392 392 hex(p1), fl.rev(p1), file=f),
393 393 parent2 = self.parent("filerevparent",
394 394 hex(p2), fl.rev(p2), file=f),
395 395 p1 = hex(p1), p2 = hex(p2),
396 396 p1rev = fl.rev(p1), p2rev = fl.rev(p2))
397 397
398 398 def fileannotate(self, f, node):
399 399 bcache = {}
400 400 ncache = {}
401 401 fl = self.repo.file(f)
402 402 n = bin(node)
403 403 changerev = fl.linkrev(n)
404 404
405 405 cl = self.repo.changelog
406 406 cn = cl.node(changerev)
407 407 cs = cl.read(cn)
408 408 p1, p2 = fl.parents(n)
409 409 t = float(cs[2].split(' ')[0])
410 410 mfn = cs[0]
411 411
412 412 def annotate():
413 413 parity = 1
414 414 last = None
415 415 for r, l in fl.annotate(n):
416 416 try:
417 417 cnode = ncache[r]
418 418 except KeyError:
419 419 cnode = ncache[r] = self.repo.changelog.node(r)
420 420
421 421 try:
422 422 name = bcache[r]
423 423 except KeyError:
424 424 cl = self.repo.changelog.read(cnode)
425 425 name = cl[1]
426 426 f = name.find('@')
427 427 if f >= 0:
428 428 name = name[:f]
429 429 bcache[r] = name
430 430
431 431 if last != cnode:
432 432 parity = 1 - parity
433 433 last = cnode
434 434
435 435 yield self.t("annotateline",
436 436 parity = parity,
437 437 node = hex(cnode),
438 438 rev = r,
439 439 author = name,
440 440 file = f,
441 441 line = l)
442 442
443 443 yield self.t("fileannotate",
444 444 header = self.header(),
445 445 footer = self.footer(),
446 446 repo = self.reponame,
447 447 file = f,
448 448 filenode = node,
449 449 annotate = annotate,
450 450 path = up(f),
451 451 rev = changerev,
452 452 node = hex(cn),
453 453 manifest = hex(mfn),
454 454 author = cs[1],
455 455 date = t,
456 456 parent1 = self.parent("fileannotateparent",
457 457 hex(p1), fl.rev(p1), file=f),
458 458 parent2 = self.parent("fileannotateparent",
459 459 hex(p2), fl.rev(p2), file=f),
460 460 p1 = hex(p1), p2 = hex(p2),
461 461 p1rev = fl.rev(p1), p2rev = fl.rev(p2))
462 462
463 463 def manifest(self, mnode, path):
464 464 mf = self.repo.manifest.read(bin(mnode))
465 465 rev = self.repo.manifest.rev(bin(mnode))
466 466 node = self.repo.changelog.node(rev)
467 467
468 468 files = {}
469 469
470 470 p = path[1:]
471 471 l = len(p)
472 472
473 473 for f,n in mf.items():
474 474 if f[:l] != p:
475 475 continue
476 476 remain = f[l:]
477 477 if "/" in remain:
478 478 short = remain[:remain.find("/") + 1] # bleah
479 479 files[short] = (f, None)
480 480 else:
481 481 short = os.path.basename(remain)
482 482 files[short] = (f, n)
483 483
484 484 def filelist():
485 485 parity = 0
486 486 fl = files.keys()
487 487 fl.sort()
488 488 for f in fl:
489 489 full, fnode = files[f]
490 490 if fnode:
491 491 yield self.t("manifestfileentry",
492 492 file = full,
493 493 manifest = mnode,
494 494 filenode = hex(fnode),
495 495 parity = parity,
496 496 basename = f)
497 497 else:
498 498 yield self.t("manifestdirentry",
499 499 parity = parity,
500 500 path = os.path.join(path, f),
501 501 manifest = mnode, basename = f[:-1])
502 502 parity = 1 - parity
503 503
504 504 yield self.t("manifest",
505 505 header = self.header(),
506 506 footer = self.footer(),
507 507 repo = self.reponame,
508 508 manifest = mnode,
509 509 rev = rev,
510 510 node = hex(node),
511 511 path = path,
512 512 up = up(path),
513 513 entries = filelist)
514 514
515 515 def tags(self):
516 516 cl = self.repo.changelog
517 517 mf = cl.read(cl.tip())[0]
518 518
519 519 self.repo.lookup(0) # prime the cache
520 520 i = self.repo.tags.items()
521 521 n = [ (cl.rev(e[1]), e) for e in i ] # sort by revision
522 522 n.sort()
523 523 n.reverse()
524 524 i = [ e[1] for e in n ]
525 525
526 526 def entries():
527 527 parity = 0
528 528 for k,n in i:
529 529 yield self.t("tagentry",
530 530 parity = parity,
531 531 tag = k,
532 532 node = hex(n))
533 533 parity = 1 - parity
534 534
535 535 yield self.t("tags",
536 536 header = self.header(),
537 537 footer = self.footer(),
538 538 repo = self.reponame,
539 539 manifest = hex(mf),
540 540 entries = entries)
541 541
542 542 def filediff(self, file, changeset):
543 543 n = bin(changeset)
544 544 cl = self.repo.changelog
545 545 p1 = cl.parents(n)[0]
546 546 cs = cl.read(n)
547 547 mf = self.repo.manifest.read(cs[0])
548 548
549 549 def diff():
550 550 yield self.diff(p1, n, file)
551 551
552 552 yield self.t("filediff",
553 553 header = self.header(),
554 554 footer = self.footer(),
555 555 repo = self.reponame,
556 556 file = file,
557 557 filenode = hex(mf[file]),
558 558 node = changeset,
559 559 rev = self.repo.changelog.rev(n),
560 560 p1 = hex(p1),
561 561 p1rev = self.repo.changelog.rev(p1),
562 562 diff = diff)
563 563
564 564 # add tags to things
565 565 # tags -> list of changesets corresponding to tags
566 566 # find tag, changeset, file
567 567
568 568 def run(self):
569 569 args = cgi.parse()
570 570
571 571 m = os.path.join(self.templates, "map")
572 572 if args.has_key('style'):
573 573 b = os.path.basename("map-" + args['style'][0])
574 574 p = os.path.join(self.templates, b)
575 575 if os.path.isfile(p): m = p
576 576
577 577 self.t = templater(m, self.filters)
578 578
579 579 if not args.has_key('cmd') or args['cmd'][0] == 'changelog':
580 580 hi = self.repo.changelog.count()
581 581 if args.has_key('rev'):
582 582 hi = args['rev'][0]
583 583 try:
584 584 hi = self.repo.changelog.rev(self.repo.lookup(hi))
585 585 except KeyError:
586 586 hi = self.repo.changelog.count()
587 587
588 588 write(self.changelog(hi))
589 589
590 590 elif args['cmd'][0] == 'changeset':
591 591 write(self.changeset(args['node'][0]))
592 592
593 593 elif args['cmd'][0] == 'manifest':
594 594 write(self.manifest(args['manifest'][0], args['path'][0]))
595 595
596 596 elif args['cmd'][0] == 'tags':
597 597 write(self.tags())
598 598
599 599 elif args['cmd'][0] == 'filediff':
600 600 write(self.filediff(args['file'][0], args['node'][0]))
601 601
602 602 elif args['cmd'][0] == 'file':
603 603 write(self.filerevision(args['file'][0], args['filenode'][0]))
604 604
605 605 elif args['cmd'][0] == 'annotate':
606 606 write(self.fileannotate(args['file'][0], args['filenode'][0]))
607 607
608 608 elif args['cmd'][0] == 'filelog':
609 609 write(self.filelog(args['file'][0], args['filenode'][0]))
610 610
611 611 elif args['cmd'][0] == 'heads':
612 612 httphdr("text/plain")
613 613 h = self.repo.heads()
614 614 sys.stdout.write(" ".join(map(hex, h)) + "\n")
615 615
616 616 elif args['cmd'][0] == 'branches':
617 617 httphdr("text/plain")
618 618 nodes = []
619 619 if args.has_key('nodes'):
620 620 nodes = map(bin, args['nodes'][0].split(" "))
621 621 for b in self.repo.branches(nodes):
622 622 sys.stdout.write(" ".join(map(hex, b)) + "\n")
623 623
624 624 elif args['cmd'][0] == 'between':
625 625 httphdr("text/plain")
626 626 nodes = []
627 627 if args.has_key('pairs'):
628 628 pairs = [ map(bin, p.split("-"))
629 629 for p in args['pairs'][0].split(" ") ]
630 630 for b in self.repo.between(pairs):
631 631 sys.stdout.write(" ".join(map(hex, b)) + "\n")
632 632
633 633 elif args['cmd'][0] == 'changegroup':
634 634 httphdr("application/hg-changegroup")
635 635 nodes = []
636 636 if self.viewonly:
637 637 return
638 638
639 639 if args.has_key('roots'):
640 640 nodes = map(bin, args['roots'][0].split(" "))
641 641
642 642 z = zlib.compressobj()
643 643 for chunk in self.repo.changegroup(nodes):
644 644 sys.stdout.write(z.compress(chunk))
645 645
646 646 sys.stdout.write(z.flush())
647 647
648 648 else:
649 649 write(self.t("error"))
650 650
651 651 def server(path, name, templates, address, port):
652 652
653 653 import BaseHTTPServer
654 654 import sys, os
655 655
656 656 class hgwebhandler(BaseHTTPServer.BaseHTTPRequestHandler):
657 657 def do_POST(self):
658 658 self.do_hgweb()
659 659
660 660 def do_GET(self):
661 661 self.do_hgweb()
662 662
663 663 def do_hgweb(self):
664 664 query = ""
665 665 p = self.path.find("?")
666 666 if p:
667 667 query = self.path[p + 1:]
668 668 query = query.replace('+', ' ')
669 669
670 670 env = {}
671 671 env['GATEWAY_INTERFACE'] = 'CGI/1.1'
672 672 env['REQUEST_METHOD'] = self.command
673 673 if query:
674 674 env['QUERY_STRING'] = query
675 675 host = self.address_string()
676 676 if host != self.client_address[0]:
677 677 env['REMOTE_HOST'] = host
678 678 env['REMOTE_ADDR'] = self.client_address[0]
679 679
680 680 if self.headers.typeheader is None:
681 681 env['CONTENT_TYPE'] = self.headers.type
682 682 else:
683 683 env['CONTENT_TYPE'] = self.headers.typeheader
684 684 length = self.headers.getheader('content-length')
685 685 if length:
686 686 env['CONTENT_LENGTH'] = length
687 687 accept = []
688 688 for line in self.headers.getallmatchingheaders('accept'):
689 689 if line[:1] in "\t\n\r ":
690 690 accept.append(line.strip())
691 691 else:
692 692 accept = accept + line[7:].split(',')
693 693 env['HTTP_ACCEPT'] = ','.join(accept)
694 694
695 695 os.environ.update(env)
696 696
697 697 save = sys.argv, sys.stdin, sys.stdout, sys.stderr
698 698 try:
699 699 sys.stdin = self.rfile
700 700 sys.stdout = self.wfile
701 701 sys.argv = ["hgweb.py"]
702 702 if '=' not in query:
703 703 sys.argv.append(query)
704 704 self.send_response(200, "Script output follows")
705 705 hg.run()
706 706 finally:
707 707 sys.argv, sys.stdin, sys.stdout, sys.stderr = save
708 708
709 709 hg = hgweb(path, name, templates)
710 710 httpd = BaseHTTPServer.HTTPServer((address, port), hgwebhandler)
711 711 httpd.serve_forever()
General Comments 0
You need to be logged in to leave comments. Login now