7 # of the GNU General Public License, incorporated herein by reference. |
7 # of the GNU General Public License, incorporated herein by reference. |
8 |
8 |
9 import os, cgi, sys |
9 import os, cgi, sys |
10 from demandload import demandload |
10 from demandload import demandload |
11 demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser") |
11 demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser") |
12 demandload(globals(), "zipfile tempfile StringIO tarfile BaseHTTPServer") |
12 demandload(globals(), "zipfile tempfile StringIO tarfile BaseHTTPServer util") |
13 from node import * |
13 from node import * |
14 |
14 |
15 def templatepath(): |
15 def templatepath(): |
16 for f in "templates", "../templates": |
16 for f in "templates", "../templates": |
17 p = os.path.join(os.path.dirname(__file__), f) |
17 p = os.path.join(os.path.dirname(__file__), f) |
18 if os.path.isdir(p): |
18 if os.path.isdir(p): |
19 return p |
19 return p |
20 |
20 |
21 def age(t): |
21 def age(x): |
22 def plural(t, c): |
22 def plural(t, c): |
23 if c == 1: |
23 if c == 1: |
24 return t |
24 return t |
25 return t + "s" |
25 return t + "s" |
26 def fmt(t, c): |
26 def fmt(t, c): |
27 return "%d %s" % (c, plural(t, c)) |
27 return "%d %s" % (c, plural(t, c)) |
28 |
28 |
29 now = time.time() |
29 now = time.time() |
30 delta = max(1, int(now - t)) |
30 then = int(x[2].split(' ')[0]) |
|
31 delta = max(1, int(now - then)) |
31 |
32 |
32 scales = [["second", 1], |
33 scales = [["second", 1], |
33 ["minute", 60], |
34 ["minute", 60], |
34 ["hour", 3600], |
35 ["hour", 3600], |
35 ["day", 3600 * 24], |
36 ["day", 3600 * 24], |
149 tmpl = tmpl[m.end(0):] |
150 tmpl = tmpl[m.end(0):] |
150 else: |
151 else: |
151 yield tmpl |
152 yield tmpl |
152 return |
153 return |
153 |
154 |
154 def rfc822date(x): |
|
155 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(x)) |
|
156 |
|
157 common_filters = { |
155 common_filters = { |
158 "escape": cgi.escape, |
156 "escape": cgi.escape, |
159 "age": age, |
157 "age": age, |
160 "date": (lambda x: time.asctime(time.gmtime(x))), |
158 "date": util.datestr, |
161 "addbreaks": nl2br, |
159 "addbreaks": nl2br, |
162 "obfuscate": obfuscate, |
160 "obfuscate": obfuscate, |
163 "short": (lambda x: x[:12]), |
161 "short": (lambda x: x[:12]), |
164 "firstline": (lambda x: x.splitlines(1)[0]), |
162 "firstline": (lambda x: x.splitlines(1)[0]), |
165 "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"), |
163 "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"), |
166 "rfc822date": rfc822date, |
164 "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"), |
167 } |
165 } |
168 |
|
169 |
|
170 |
166 |
171 class hgweb: |
167 class hgweb: |
172 def __init__(self, repo, name=None): |
168 def __init__(self, repo, name=None): |
173 if type(repo) == type(""): |
169 if type(repo) == type(""): |
174 self.repo = hg.repository(ui.ui(), repo) |
170 self.repo = hg.repository(ui.ui(), repo) |
187 self.maxchanges = int(self.repo.ui.config("web", "maxchanges", 10)) |
183 self.maxchanges = int(self.repo.ui.config("web", "maxchanges", 10)) |
188 self.maxfiles = int(self.repo.ui.config("web", "maxfiles", 10)) |
184 self.maxfiles = int(self.repo.ui.config("web", "maxfiles", 10)) |
189 self.allowpull = self.repo.ui.configbool("web", "allowpull", True) |
185 self.allowpull = self.repo.ui.configbool("web", "allowpull", True) |
190 |
186 |
191 def date(self, cs): |
187 def date(self, cs): |
192 return time.asctime(time.gmtime(float(cs[2].split(' ')[0]))) |
188 return util.datestr(cs) |
193 |
189 |
194 def listfiles(self, files, mf): |
190 def listfiles(self, files, mf): |
195 for f in files[:self.maxfiles]: |
191 for f in files[:self.maxfiles]: |
196 yield self.t("filenodelink", node=hex(mf[f]), file=f) |
192 yield self.t("filenodelink", node=hex(mf[f]), file=f) |
197 if len(files) > self.maxfiles: |
193 if len(files) > self.maxfiles: |
305 l = [] # build a list in forward order for efficiency |
301 l = [] # build a list in forward order for efficiency |
306 for i in range(start, end): |
302 for i in range(start, end): |
307 n = cl.node(i) |
303 n = cl.node(i) |
308 changes = cl.read(n) |
304 changes = cl.read(n) |
309 hn = hex(n) |
305 hn = hex(n) |
310 t = float(changes[2].split(' ')[0]) |
|
311 |
306 |
312 l.insert(0, {"parity": parity, |
307 l.insert(0, {"parity": parity, |
313 "author": changes[1], |
308 "author": changes[1], |
314 "parent": self.parents("changelogparent", |
309 "parent": self.parents("changelogparent", |
315 cl.parents(n), cl.rev), |
310 cl.parents(n), cl.rev), |
316 "changelogtag": self.showtag("changelogtag",n), |
311 "changelogtag": self.showtag("changelogtag",n), |
317 "manifest": hex(changes[0]), |
312 "manifest": hex(changes[0]), |
318 "desc": changes[4], |
313 "desc": changes[4], |
319 "date": t, |
314 "date": changes, |
320 "files": self.listfilediffs(changes[3], n), |
315 "files": self.listfilediffs(changes[3], n), |
321 "rev": i, |
316 "rev": i, |
322 "node": hn}) |
317 "node": hn}) |
323 parity = 1 - parity |
318 parity = 1 - parity |
324 |
319 |
366 if miss: |
361 if miss: |
367 continue |
362 continue |
368 |
363 |
369 count += 1 |
364 count += 1 |
370 hn = hex(n) |
365 hn = hex(n) |
371 t = float(changes[2].split(' ')[0]) |
|
372 |
366 |
373 yield self.t('searchentry', |
367 yield self.t('searchentry', |
374 parity=count & 1, |
368 parity=count & 1, |
375 author=changes[1], |
369 author=changes[1], |
376 parent=self.parents("changelogparent", |
370 parent=self.parents("changelogparent", |
377 cl.parents(n), cl.rev), |
371 cl.parents(n), cl.rev), |
378 changelogtag=self.showtag("changelogtag",n), |
372 changelogtag=self.showtag("changelogtag",n), |
379 manifest=hex(changes[0]), |
373 manifest=hex(changes[0]), |
380 desc=changes[4], |
374 desc=changes[4], |
381 date=t, |
375 date=changes, |
382 files=self.listfilediffs(changes[3], n), |
376 files=self.listfilediffs(changes[3], n), |
383 rev=i, |
377 rev=i, |
384 node=hn) |
378 node=hn) |
385 |
379 |
386 if count >= self.maxchanges: |
380 if count >= self.maxchanges: |
397 def changeset(self, nodeid): |
391 def changeset(self, nodeid): |
398 n = bin(nodeid) |
392 n = bin(nodeid) |
399 cl = self.repo.changelog |
393 cl = self.repo.changelog |
400 changes = cl.read(n) |
394 changes = cl.read(n) |
401 p1 = cl.parents(n)[0] |
395 p1 = cl.parents(n)[0] |
402 t = float(changes[2].split(' ')[0]) |
|
403 |
396 |
404 files = [] |
397 files = [] |
405 mf = self.repo.manifest.read(changes[0]) |
398 mf = self.repo.manifest.read(changes[0]) |
406 for f in changes[3]: |
399 for f in changes[3]: |
407 files.append(self.t("filenodelink", |
400 files.append(self.t("filenodelink", |
423 cl.parents(n), cl.rev), |
416 cl.parents(n), cl.rev), |
424 changesettag=self.showtag("changesettag",n), |
417 changesettag=self.showtag("changesettag",n), |
425 manifest=hex(changes[0]), |
418 manifest=hex(changes[0]), |
426 author=changes[1], |
419 author=changes[1], |
427 desc=changes[4], |
420 desc=changes[4], |
428 date=t, |
421 date=changes, |
429 files=files, |
422 files=files, |
430 archives=archivelist()) |
423 archives=archivelist()) |
431 |
424 |
432 def filelog(self, f, filenode): |
425 def filelog(self, f, filenode): |
433 cl = self.repo.changelog |
426 cl = self.repo.changelog |
441 for i in range(count): |
434 for i in range(count): |
442 n = fl.node(i) |
435 n = fl.node(i) |
443 lr = fl.linkrev(n) |
436 lr = fl.linkrev(n) |
444 cn = cl.node(lr) |
437 cn = cl.node(lr) |
445 cs = cl.read(cl.node(lr)) |
438 cs = cl.read(cl.node(lr)) |
446 t = float(cs[2].split(' ')[0]) |
|
447 |
439 |
448 l.insert(0, {"parity": parity, |
440 l.insert(0, {"parity": parity, |
449 "filenode": hex(n), |
441 "filenode": hex(n), |
450 "filerev": i, |
442 "filerev": i, |
451 "file": f, |
443 "file": f, |
452 "node": hex(cn), |
444 "node": hex(cn), |
453 "author": cs[1], |
445 "author": cs[1], |
454 "date": t, |
446 "date": cs, |
455 "parent": self.parents("filelogparent", |
447 "parent": self.parents("filelogparent", |
456 fl.parents(n), |
448 fl.parents(n), |
457 fl.rev, file=f), |
449 fl.rev, file=f), |
458 "desc": cs[4]}) |
450 "desc": cs[4]}) |
459 parity = 1 - parity |
451 parity = 1 - parity |
469 text = fl.read(n) |
461 text = fl.read(n) |
470 changerev = fl.linkrev(n) |
462 changerev = fl.linkrev(n) |
471 cl = self.repo.changelog |
463 cl = self.repo.changelog |
472 cn = cl.node(changerev) |
464 cn = cl.node(changerev) |
473 cs = cl.read(cn) |
465 cs = cl.read(cn) |
474 t = float(cs[2].split(' ')[0]) |
|
475 mfn = cs[0] |
466 mfn = cs[0] |
476 |
467 |
477 def lines(): |
468 def lines(): |
478 for l, t in enumerate(text.splitlines(1)): |
469 for l, t in enumerate(text.splitlines(1)): |
479 yield {"line": t, |
470 yield {"line": t, |
487 text=lines(), |
478 text=lines(), |
488 rev=changerev, |
479 rev=changerev, |
489 node=hex(cn), |
480 node=hex(cn), |
490 manifest=hex(mfn), |
481 manifest=hex(mfn), |
491 author=cs[1], |
482 author=cs[1], |
492 date=t, |
483 date=cs, |
493 parent=self.parents("filerevparent", |
484 parent=self.parents("filerevparent", |
494 fl.parents(n), fl.rev, file=f), |
485 fl.parents(n), fl.rev, file=f), |
495 permissions=self.repo.manifest.readflags(mfn)[f]) |
486 permissions=self.repo.manifest.readflags(mfn)[f]) |
496 |
487 |
497 def fileannotate(self, f, node): |
488 def fileannotate(self, f, node): |
540 path=up(f), |
530 path=up(f), |
541 rev=changerev, |
531 rev=changerev, |
542 node=hex(cn), |
532 node=hex(cn), |
543 manifest=hex(mfn), |
533 manifest=hex(mfn), |
544 author=cs[1], |
534 author=cs[1], |
545 date=t, |
535 date=cs, |
546 parent=self.parents("fileannotateparent", |
536 parent=self.parents("fileannotateparent", |
547 fl.parents(n), fl.rev, file=f), |
537 fl.parents(n), fl.rev, file=f), |
548 permissions=self.repo.manifest.readflags(mfn)[f]) |
538 permissions=self.repo.manifest.readflags(mfn)[f]) |
549 |
539 |
550 def manifest(self, mnode, path): |
540 def manifest(self, mnode, path): |