Mercurial > public > mercurial-scm > hg
comparison mercurial/hgweb.py @ 1159:b6f5a947e62e
Change use of global sys.stdout, sys.stdin os.environ to a hgrequest object.
Note: also change hgrequest.write(str(thing)) to hgrequest.write(thing),
people should make sure they write strings.
author | Vincent Wagelaar <vincent@ricardis.tudelft.nl> |
---|---|
date | Tue, 30 Aug 2005 10:57:52 +0200 |
parents | 4fffb3d84b7c |
children | 0da98529a476 |
comparison
equal
deleted
inserted
replaced
1154:c3cb9f39a91f | 1159:b6f5a947e62e |
---|---|
58 up = os.path.dirname(p) | 58 up = os.path.dirname(p) |
59 if up == "/": | 59 if up == "/": |
60 return "/" | 60 return "/" |
61 return up + "/" | 61 return up + "/" |
62 | 62 |
63 def httphdr(type, file="", size=0): | 63 class hgrequest: |
64 sys.stdout.write('Content-type: %s\n' % type) | 64 def __init__(self, inp=None, out=None, env=None): |
65 if file: | 65 self.inp = inp or sys.stdin |
66 sys.stdout.write('Content-disposition: attachment; filename=%s\n' | 66 self.out = out or sys.stdout |
67 % file) | 67 self.env = env or os.environ |
68 if size > 0: | 68 self.form = cgi.parse(self.inp, self.env) |
69 sys.stdout.write('Content-length: %d\n' % size) | 69 |
70 sys.stdout.write('\n') | 70 def write(self, *things): |
71 | 71 for thing in things: |
72 def write(*things): | 72 if hasattr(thing, "__iter__"): |
73 for thing in things: | 73 for part in thing: |
74 if hasattr(thing, "__iter__"): | 74 self.write(part) |
75 for part in thing: | 75 else: |
76 write(part) | 76 try: |
77 else: | 77 self.out.write(thing) |
78 try: | 78 except socket.error, x: |
79 sys.stdout.write(str(thing)) | 79 if x[0] != errno.ECONNRESET: |
80 except socket.error, x: | 80 raise |
81 if x[0] != errno.ECONNRESET: | 81 |
82 raise | 82 def header(self, headers=[('Content-type','text/html')]): |
83 for header in headers: | |
84 self.out.write("%s: %s\r\n" % header) | |
85 self.out.write("\r\n") | |
86 | |
87 def httphdr(self, type, file="", size=0): | |
88 | |
89 headers = [('Content-type', type)] | |
90 if file: | |
91 headers.append(('Content-disposition', 'attachment; filename=%s' % file)) | |
92 if size > 0: | |
93 headers.append(('Content-length', str(size))) | |
94 self.header(headers) | |
83 | 95 |
84 class templater: | 96 class templater: |
85 def __init__(self, mapfile, filters={}, defaults={}): | 97 def __init__(self, mapfile, filters={}, defaults={}): |
86 self.cache = {} | 98 self.cache = {} |
87 self.map = {} | 99 self.map = {} |
151 "short": (lambda x: x[:12]), | 163 "short": (lambda x: x[:12]), |
152 "firstline": (lambda x: x.splitlines(1)[0]), | 164 "firstline": (lambda x: x.splitlines(1)[0]), |
153 "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"), | 165 "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"), |
154 "rfc822date": rfc822date, | 166 "rfc822date": rfc822date, |
155 } | 167 } |
168 | |
169 | |
156 | 170 |
157 class hgweb: | 171 class hgweb: |
158 def __init__(self, repo, name=None): | 172 def __init__(self, repo, name=None): |
159 if type(repo) == type(""): | 173 if type(repo) == type(""): |
160 self.repo = repository(ui(), repo) | 174 self.repo = repository(ui(), repo) |
633 rev=self.repo.changelog.rev(n), | 647 rev=self.repo.changelog.rev(n), |
634 parent=self.parents("filediffparent", | 648 parent=self.parents("filediffparent", |
635 cl.parents(n), cl.rev), | 649 cl.parents(n), cl.rev), |
636 diff=diff) | 650 diff=diff) |
637 | 651 |
638 def archive(self, cnode, type): | 652 def archive(self, req, cnode, type): |
639 cs = self.repo.changelog.read(cnode) | 653 cs = self.repo.changelog.read(cnode) |
640 mnode = cs[0] | 654 mnode = cs[0] |
641 mf = self.repo.manifest.read(mnode) | 655 mf = self.repo.manifest.read(mnode) |
642 rev = self.repo.manifest.rev(mnode) | 656 rev = self.repo.manifest.rev(mnode) |
643 reponame = re.sub(r"\W+", "-", self.reponame) | 657 reponame = re.sub(r"\W+", "-", self.reponame) |
656 for f in files: | 670 for f in files: |
657 zf.writestr(name + f, self.repo.file(f).read(mf[f])) | 671 zf.writestr(name + f, self.repo.file(f).read(mf[f])) |
658 zf.close() | 672 zf.close() |
659 | 673 |
660 f = open(tmp, 'r') | 674 f = open(tmp, 'r') |
661 httphdr('application/zip', name[:-1] + '.zip', | 675 req.httphdr('application/zip', name[:-1] + '.zip', |
662 os.path.getsize(tmp)) | 676 os.path.getsize(tmp)) |
663 sys.stdout.write(f.read()) | 677 req.write(f.read()) |
664 f.close() | 678 f.close() |
665 finally: | 679 finally: |
666 os.unlink(tmp) | 680 os.unlink(tmp) |
667 | 681 |
668 else: | 682 else: |
669 import StringIO | 683 import StringIO |
670 import time | 684 import time |
671 import tarfile | 685 import tarfile |
672 | 686 |
673 tf = tarfile.TarFile.open(mode='w|' + type, fileobj=sys.stdout) | 687 tf = tarfile.TarFile.open(mode='w|' + type, fileobj=req.out) |
674 mff = self.repo.manifest.readflags(mnode) | 688 mff = self.repo.manifest.readflags(mnode) |
675 mtime = int(time.time()) | 689 mtime = int(time.time()) |
676 | 690 |
677 httphdr('application/octet-stream', name[:-1] + '.tar.' + type) | 691 req.httphdr('application/octet-stream', name[:-1] + '.tar.' + type) |
678 for fname in files: | 692 for fname in files: |
679 rcont = self.repo.file(fname).read(mf[fname]) | 693 rcont = self.repo.file(fname).read(mf[fname]) |
680 finfo = tarfile.TarInfo(name + fname) | 694 finfo = tarfile.TarInfo(name + fname) |
681 finfo.mtime = mtime | 695 finfo.mtime = mtime |
682 finfo.size = len(rcont) | 696 finfo.size = len(rcont) |
686 | 700 |
687 # add tags to things | 701 # add tags to things |
688 # tags -> list of changesets corresponding to tags | 702 # tags -> list of changesets corresponding to tags |
689 # find tag, changeset, file | 703 # find tag, changeset, file |
690 | 704 |
691 def run(self): | 705 def run(self, req=hgrequest()): |
692 def header(**map): | 706 def header(**map): |
693 yield self.t("header", **map) | 707 yield self.t("header", **map) |
694 | 708 |
695 def footer(**map): | 709 def footer(**map): |
696 yield self.t("footer", **map) | 710 yield self.t("footer", **map) |
697 | 711 |
698 self.refresh() | 712 self.refresh() |
699 args = cgi.parse() | |
700 | 713 |
701 t = self.repo.ui.config("web", "templates", templatepath()) | 714 t = self.repo.ui.config("web", "templates", templatepath()) |
702 m = os.path.join(t, "map") | 715 m = os.path.join(t, "map") |
703 style = self.repo.ui.config("web", "style", "") | 716 style = self.repo.ui.config("web", "style", "") |
704 if args.has_key('style'): | 717 if req.form.has_key('style'): |
705 style = args['style'][0] | 718 style = req.form['style'][0] |
706 if style: | 719 if style: |
707 b = os.path.basename("map-" + style) | 720 b = os.path.basename("map-" + style) |
708 p = os.path.join(t, b) | 721 p = os.path.join(t, b) |
709 if os.path.isfile(p): | 722 if os.path.isfile(p): |
710 m = p | 723 m = p |
711 | 724 |
712 port = os.environ["SERVER_PORT"] | 725 port = req.env["SERVER_PORT"] |
713 port = port != "80" and (":" + port) or "" | 726 port = port != "80" and (":" + port) or "" |
714 uri = os.environ["REQUEST_URI"] | 727 uri = req.env["REQUEST_URI"] |
715 if "?" in uri: | 728 if "?" in uri: |
716 uri = uri.split("?")[0] | 729 uri = uri.split("?")[0] |
717 url = "http://%s%s%s" % (os.environ["SERVER_NAME"], port, uri) | 730 url = "http://%s%s%s" % (req.env["SERVER_NAME"], port, uri) |
718 | 731 |
719 self.t = templater(m, common_filters, | 732 self.t = templater(m, common_filters, |
720 {"url": url, | 733 {"url": url, |
721 "repo": self.reponame, | 734 "repo": self.reponame, |
722 "header": header, | 735 "header": header, |
723 "footer": footer, | 736 "footer": footer, |
724 }) | 737 }) |
725 | 738 |
726 if not args.has_key('cmd'): | 739 if not req.form.has_key('cmd'): |
727 args['cmd'] = [self.t.cache['default'],] | 740 req.form['cmd'] = [self.t.cache['default'],] |
728 | 741 |
729 if args['cmd'][0] == 'changelog': | 742 if req.form['cmd'][0] == 'changelog': |
730 c = self.repo.changelog.count() - 1 | 743 c = self.repo.changelog.count() - 1 |
731 hi = c | 744 hi = c |
732 if args.has_key('rev'): | 745 if req.form.has_key('rev'): |
733 hi = args['rev'][0] | 746 hi = req.form['rev'][0] |
734 try: | 747 try: |
735 hi = self.repo.changelog.rev(self.repo.lookup(hi)) | 748 hi = self.repo.changelog.rev(self.repo.lookup(hi)) |
736 except RepoError: | 749 except RepoError: |
737 write(self.search(hi)) | 750 req.write(self.search(hi)) |
738 return | 751 return |
739 | 752 |
740 write(self.changelog(hi)) | 753 req.write(self.changelog(hi)) |
741 | 754 |
742 elif args['cmd'][0] == 'changeset': | 755 elif req.form['cmd'][0] == 'changeset': |
743 write(self.changeset(args['node'][0])) | 756 req.write(self.changeset(req.form['node'][0])) |
744 | 757 |
745 elif args['cmd'][0] == 'manifest': | 758 elif req.form['cmd'][0] == 'manifest': |
746 write(self.manifest(args['manifest'][0], args['path'][0])) | 759 req.write(self.manifest(req.form['manifest'][0], req.form['path'][0])) |
747 | 760 |
748 elif args['cmd'][0] == 'tags': | 761 elif req.form['cmd'][0] == 'tags': |
749 write(self.tags()) | 762 req.write(self.tags()) |
750 | 763 |
751 elif args['cmd'][0] == 'filediff': | 764 elif req.form['cmd'][0] == 'filediff': |
752 write(self.filediff(args['file'][0], args['node'][0])) | 765 req.write(self.filediff(req.form['file'][0], req.form['node'][0])) |
753 | 766 |
754 elif args['cmd'][0] == 'file': | 767 elif req.form['cmd'][0] == 'file': |
755 write(self.filerevision(args['file'][0], args['filenode'][0])) | 768 req.write(self.filerevision(req.form['file'][0], req.form['filenode'][0])) |
756 | 769 |
757 elif args['cmd'][0] == 'annotate': | 770 elif req.form['cmd'][0] == 'annotate': |
758 write(self.fileannotate(args['file'][0], args['filenode'][0])) | 771 req.write(self.fileannotate(req.form['file'][0], req.form['filenode'][0])) |
759 | 772 |
760 elif args['cmd'][0] == 'filelog': | 773 elif req.form['cmd'][0] == 'filelog': |
761 write(self.filelog(args['file'][0], args['filenode'][0])) | 774 req.write(self.filelog(req.form['file'][0], req.form['filenode'][0])) |
762 | 775 |
763 elif args['cmd'][0] == 'heads': | 776 elif req.form['cmd'][0] == 'heads': |
764 httphdr("application/mercurial-0.1") | 777 req.httphdr("application/mercurial-0.1") |
765 h = self.repo.heads() | 778 h = self.repo.heads() |
766 sys.stdout.write(" ".join(map(hex, h)) + "\n") | 779 req.write(" ".join(map(hex, h)) + "\n") |
767 | 780 |
768 elif args['cmd'][0] == 'branches': | 781 elif req.form['cmd'][0] == 'branches': |
769 httphdr("application/mercurial-0.1") | 782 req.httphdr("application/mercurial-0.1") |
770 nodes = [] | 783 nodes = [] |
771 if args.has_key('nodes'): | 784 if req.form.has_key('nodes'): |
772 nodes = map(bin, args['nodes'][0].split(" ")) | 785 nodes = map(bin, req.form['nodes'][0].split(" ")) |
773 for b in self.repo.branches(nodes): | 786 for b in self.repo.branches(nodes): |
774 sys.stdout.write(" ".join(map(hex, b)) + "\n") | 787 req.write(" ".join(map(hex, b)) + "\n") |
775 | 788 |
776 elif args['cmd'][0] == 'between': | 789 elif req.form['cmd'][0] == 'between': |
777 httphdr("application/mercurial-0.1") | 790 req.httphdr("application/mercurial-0.1") |
778 nodes = [] | 791 nodes = [] |
779 if args.has_key('pairs'): | 792 if req.form.has_key('pairs'): |
780 pairs = [map(bin, p.split("-")) | 793 pairs = [map(bin, p.split("-")) |
781 for p in args['pairs'][0].split(" ")] | 794 for p in req.form['pairs'][0].split(" ")] |
782 for b in self.repo.between(pairs): | 795 for b in self.repo.between(pairs): |
783 sys.stdout.write(" ".join(map(hex, b)) + "\n") | 796 req.write(" ".join(map(hex, b)) + "\n") |
784 | 797 |
785 elif args['cmd'][0] == 'changegroup': | 798 elif req.form['cmd'][0] == 'changegroup': |
786 httphdr("application/mercurial-0.1") | 799 req.httphdr("application/mercurial-0.1") |
787 nodes = [] | 800 nodes = [] |
788 if not self.allowpull: | 801 if not self.allowpull: |
789 return | 802 return |
790 | 803 |
791 if args.has_key('roots'): | 804 if req.form.has_key('roots'): |
792 nodes = map(bin, args['roots'][0].split(" ")) | 805 nodes = map(bin, req.form['roots'][0].split(" ")) |
793 | 806 |
794 z = zlib.compressobj() | 807 z = zlib.compressobj() |
795 f = self.repo.changegroup(nodes) | 808 f = self.repo.changegroup(nodes) |
796 while 1: | 809 while 1: |
797 chunk = f.read(4096) | 810 chunk = f.read(4096) |
798 if not chunk: | 811 if not chunk: |
799 break | 812 break |
800 sys.stdout.write(z.compress(chunk)) | 813 req.write(z.compress(chunk)) |
801 | 814 |
802 sys.stdout.write(z.flush()) | 815 req.write(z.flush()) |
803 | 816 |
804 elif args['cmd'][0] == 'archive': | 817 elif req.form['cmd'][0] == 'archive': |
805 changeset = bin(args['node'][0]) | 818 changeset = bin(req.form['node'][0]) |
806 type = args['type'][0] | 819 type = req.form['type'][0] |
807 if (type in self.archives and | 820 if (type in self.archives and |
808 self.repo.ui.configbool("web", "allow" + type, False)): | 821 self.repo.ui.configbool("web", "allow" + type, False)): |
809 self.archive(changeset, type) | 822 self.archive(req, changeset, type) |
810 return | 823 return |
811 | 824 |
812 write(self.t("error")) | 825 req.write(self.t("error")) |
813 | 826 |
814 else: | 827 else: |
815 write(self.t("error")) | 828 req.write(self.t("error")) |
816 | 829 |
817 def create_server(repo): | 830 def create_server(repo): |
818 | 831 |
819 def openlog(opt, default): | 832 def openlog(opt, default): |
820 if opt and opt != '-': | 833 if opt and opt != '-': |
931 cp = ConfigParser.SafeConfigParser() | 944 cp = ConfigParser.SafeConfigParser() |
932 cp.read(config) | 945 cp.read(config) |
933 self.repos = cp.items("paths") | 946 self.repos = cp.items("paths") |
934 self.repos.sort() | 947 self.repos.sort() |
935 | 948 |
936 def run(self): | 949 def run(self, req=hgrequest()): |
937 def header(**map): | 950 def header(**map): |
938 yield tmpl("header", **map) | 951 yield tmpl("header", **map) |
939 | 952 |
940 def footer(**map): | 953 def footer(**map): |
941 yield tmpl("footer", **map) | 954 yield tmpl("footer", **map) |
949 for name, path in self.repos: | 962 for name, path in self.repos: |
950 u = ui() | 963 u = ui() |
951 u.readconfig(file(os.path.join(path, '.hg', 'hgrc'))) | 964 u.readconfig(file(os.path.join(path, '.hg', 'hgrc'))) |
952 get = u.config | 965 get = u.config |
953 | 966 |
954 url = ('/'.join([os.environ["REQUEST_URI"], name]) | 967 url = ('/'.join([req.env["REQUEST_URI"], name]) |
955 .replace("//", "/")) | 968 .replace("//", "/")) |
956 | 969 |
957 yield dict(contact=get("web", "contact") or | 970 yield dict(contact=get("web", "contact") or |
958 get("web", "author", "unknown"), | 971 get("web", "author", "unknown"), |
959 name=get("web", "name", name), | 972 name=get("web", "name", name), |
963 lastupdate=os.stat(os.path.join(path, ".hg", | 976 lastupdate=os.stat(os.path.join(path, ".hg", |
964 "00changelog.d")).st_mtime) | 977 "00changelog.d")).st_mtime) |
965 | 978 |
966 parity = 1 - parity | 979 parity = 1 - parity |
967 | 980 |
968 virtual = os.environ.get("PATH_INFO", "").strip('/') | 981 virtual = req.env.get("PATH_INFO", "").strip('/') |
969 if virtual: | 982 if virtual: |
970 real = dict(self.repos).get(virtual) | 983 real = dict(self.repos).get(virtual) |
971 if real: | 984 if real: |
972 hgweb(real).run() | 985 hgweb(real).run(req) |
973 else: | 986 else: |
974 write(tmpl("notfound", repo=virtual)) | 987 req.write(tmpl("notfound", repo=virtual)) |
975 else: | 988 else: |
976 write(tmpl("index", entries=entries)) | 989 req.write(tmpl("index", entries=entries)) |