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