Show More
@@ -0,0 +1,107 b'' | |||||
|
1 | from demandload import demandload | |||
|
2 | demandload(globals(), "cgi os re time urllib util") | |||
|
3 | ||||
|
4 | class templater(object): | |||
|
5 | def __init__(self, mapfile, filters={}, defaults={}): | |||
|
6 | self.cache = {} | |||
|
7 | self.map = {} | |||
|
8 | self.base = os.path.dirname(mapfile) | |||
|
9 | self.filters = filters | |||
|
10 | self.defaults = defaults | |||
|
11 | ||||
|
12 | for l in file(mapfile): | |||
|
13 | m = re.match(r'(\S+)\s*=\s*"(.*)"$', l) | |||
|
14 | if m: | |||
|
15 | self.cache[m.group(1)] = m.group(2) | |||
|
16 | else: | |||
|
17 | m = re.match(r'(\S+)\s*=\s*(\S+)', l) | |||
|
18 | if m: | |||
|
19 | self.map[m.group(1)] = os.path.join(self.base, m.group(2)) | |||
|
20 | else: | |||
|
21 | raise LookupError(_("unknown map entry '%s'") % l) | |||
|
22 | ||||
|
23 | def __call__(self, t, **map): | |||
|
24 | m = self.defaults.copy() | |||
|
25 | m.update(map) | |||
|
26 | try: | |||
|
27 | tmpl = self.cache[t] | |||
|
28 | except KeyError: | |||
|
29 | tmpl = self.cache[t] = file(self.map[t]).read() | |||
|
30 | return self.template(tmpl, self.filters, **m) | |||
|
31 | ||||
|
32 | def template(self, tmpl, filters={}, **map): | |||
|
33 | while tmpl: | |||
|
34 | m = re.search(r"#([a-zA-Z0-9]+)((%[a-zA-Z0-9]+)*)((\|[a-zA-Z0-9]+)*)#", tmpl) | |||
|
35 | if m: | |||
|
36 | yield tmpl[:m.start(0)] | |||
|
37 | v = map.get(m.group(1), "") | |||
|
38 | v = callable(v) and v(**map) or v | |||
|
39 | ||||
|
40 | format = m.group(2) | |||
|
41 | fl = m.group(4) | |||
|
42 | ||||
|
43 | if format: | |||
|
44 | q = v.__iter__ | |||
|
45 | for i in q(): | |||
|
46 | lm = map.copy() | |||
|
47 | lm.update(i) | |||
|
48 | yield self(format[1:], **lm) | |||
|
49 | ||||
|
50 | v = "" | |||
|
51 | ||||
|
52 | elif fl: | |||
|
53 | for f in fl.split("|")[1:]: | |||
|
54 | v = filters[f](v) | |||
|
55 | ||||
|
56 | yield v | |||
|
57 | tmpl = tmpl[m.end(0):] | |||
|
58 | else: | |||
|
59 | yield tmpl | |||
|
60 | return | |||
|
61 | ||||
|
62 | def age(x): | |||
|
63 | def plural(t, c): | |||
|
64 | if c == 1: | |||
|
65 | return t | |||
|
66 | return t + "s" | |||
|
67 | def fmt(t, c): | |||
|
68 | return "%d %s" % (c, plural(t, c)) | |||
|
69 | ||||
|
70 | now = time.time() | |||
|
71 | then = x[0] | |||
|
72 | delta = max(1, int(now - then)) | |||
|
73 | ||||
|
74 | scales = [["second", 1], | |||
|
75 | ["minute", 60], | |||
|
76 | ["hour", 3600], | |||
|
77 | ["day", 3600 * 24], | |||
|
78 | ["week", 3600 * 24 * 7], | |||
|
79 | ["month", 3600 * 24 * 30], | |||
|
80 | ["year", 3600 * 24 * 365]] | |||
|
81 | ||||
|
82 | scales.reverse() | |||
|
83 | ||||
|
84 | for t, s in scales: | |||
|
85 | n = delta / s | |||
|
86 | if n >= 2 or s == 1: | |||
|
87 | return fmt(t, n) | |||
|
88 | ||||
|
89 | def nl2br(text): | |||
|
90 | return text.replace('\n', '<br/>\n') | |||
|
91 | ||||
|
92 | def obfuscate(text): | |||
|
93 | return ''.join(['&#%d;' % ord(c) for c in text]) | |||
|
94 | ||||
|
95 | common_filters = { | |||
|
96 | "escape": lambda x: cgi.escape(x, True), | |||
|
97 | "urlescape": urllib.quote, | |||
|
98 | "strip": lambda x: x.strip(), | |||
|
99 | "age": age, | |||
|
100 | "date": lambda x: util.datestr(x), | |||
|
101 | "addbreaks": nl2br, | |||
|
102 | "obfuscate": obfuscate, | |||
|
103 | "short": (lambda x: x[:12]), | |||
|
104 | "firstline": (lambda x: x.splitlines(1)[0]), | |||
|
105 | "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"), | |||
|
106 | "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"), | |||
|
107 | } |
@@ -6,12 +6,12 b'' | |||||
6 | # This software may be used and distributed according to the terms |
|
6 | # This software may be used and distributed according to the terms | |
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 | import mimetypes |
|
10 | import mimetypes | |
11 | from demandload import demandload |
|
11 | from demandload import demandload | |
12 | demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser") |
|
12 | demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser") | |
13 | demandload(globals(), "zipfile tempfile StringIO tarfile BaseHTTPServer util") |
|
13 | demandload(globals(), "zipfile tempfile StringIO tarfile BaseHTTPServer util") | |
14 | demandload(globals(), "mimetypes") |
|
14 | demandload(globals(), "mimetypes templater") | |
15 | from node import * |
|
15 | from node import * | |
16 | from i18n import gettext as _ |
|
16 | from i18n import gettext as _ | |
17 |
|
17 | |||
@@ -21,39 +21,6 b' def templatepath():' | |||||
21 | if os.path.isdir(p): |
|
21 | if os.path.isdir(p): | |
22 | return os.path.normpath(p) |
|
22 | return os.path.normpath(p) | |
23 |
|
23 | |||
24 | def age(x): |
|
|||
25 | def plural(t, c): |
|
|||
26 | if c == 1: |
|
|||
27 | return t |
|
|||
28 | return t + "s" |
|
|||
29 | def fmt(t, c): |
|
|||
30 | return "%d %s" % (c, plural(t, c)) |
|
|||
31 |
|
||||
32 | now = time.time() |
|
|||
33 | then = x[0] |
|
|||
34 | delta = max(1, int(now - then)) |
|
|||
35 |
|
||||
36 | scales = [["second", 1], |
|
|||
37 | ["minute", 60], |
|
|||
38 | ["hour", 3600], |
|
|||
39 | ["day", 3600 * 24], |
|
|||
40 | ["week", 3600 * 24 * 7], |
|
|||
41 | ["month", 3600 * 24 * 30], |
|
|||
42 | ["year", 3600 * 24 * 365]] |
|
|||
43 |
|
||||
44 | scales.reverse() |
|
|||
45 |
|
||||
46 | for t, s in scales: |
|
|||
47 | n = delta / s |
|
|||
48 | if n >= 2 or s == 1: |
|
|||
49 | return fmt(t, n) |
|
|||
50 |
|
||||
51 | def nl2br(text): |
|
|||
52 | return text.replace('\n', '<br/>\n') |
|
|||
53 |
|
||||
54 | def obfuscate(text): |
|
|||
55 | return ''.join(['&#%d;' % ord(c) for c in text]) |
|
|||
56 |
|
||||
57 | def up(p): |
|
24 | def up(p): | |
58 | if p[0] != "/": |
|
25 | if p[0] != "/": | |
59 | p = "/" + p |
|
26 | p = "/" + p | |
@@ -132,78 +99,6 b' class hgrequest(object):' | |||||
132 | headers.append(('Content-length', str(size))) |
|
99 | headers.append(('Content-length', str(size))) | |
133 | self.header(headers) |
|
100 | self.header(headers) | |
134 |
|
101 | |||
135 | class templater(object): |
|
|||
136 | def __init__(self, mapfile, filters={}, defaults={}): |
|
|||
137 | self.cache = {} |
|
|||
138 | self.map = {} |
|
|||
139 | self.base = os.path.dirname(mapfile) |
|
|||
140 | self.filters = filters |
|
|||
141 | self.defaults = defaults |
|
|||
142 |
|
||||
143 | for l in file(mapfile): |
|
|||
144 | m = re.match(r'(\S+)\s*=\s*"(.*)"$', l) |
|
|||
145 | if m: |
|
|||
146 | self.cache[m.group(1)] = m.group(2) |
|
|||
147 | else: |
|
|||
148 | m = re.match(r'(\S+)\s*=\s*(\S+)', l) |
|
|||
149 | if m: |
|
|||
150 | self.map[m.group(1)] = os.path.join(self.base, m.group(2)) |
|
|||
151 | else: |
|
|||
152 | raise LookupError(_("unknown map entry '%s'") % l) |
|
|||
153 |
|
||||
154 | def __call__(self, t, **map): |
|
|||
155 | m = self.defaults.copy() |
|
|||
156 | m.update(map) |
|
|||
157 | try: |
|
|||
158 | tmpl = self.cache[t] |
|
|||
159 | except KeyError: |
|
|||
160 | tmpl = self.cache[t] = file(self.map[t]).read() |
|
|||
161 | return self.template(tmpl, self.filters, **m) |
|
|||
162 |
|
||||
163 | def template(self, tmpl, filters={}, **map): |
|
|||
164 | while tmpl: |
|
|||
165 | m = re.search(r"#([a-zA-Z0-9]+)((%[a-zA-Z0-9]+)*)((\|[a-zA-Z0-9]+)*)#", tmpl) |
|
|||
166 | if m: |
|
|||
167 | yield tmpl[:m.start(0)] |
|
|||
168 | v = map.get(m.group(1), "") |
|
|||
169 | v = callable(v) and v(**map) or v |
|
|||
170 |
|
||||
171 | format = m.group(2) |
|
|||
172 | fl = m.group(4) |
|
|||
173 |
|
||||
174 | if format: |
|
|||
175 | q = v.__iter__ |
|
|||
176 | for i in q(): |
|
|||
177 | lm = map.copy() |
|
|||
178 | lm.update(i) |
|
|||
179 | yield self(format[1:], **lm) |
|
|||
180 |
|
||||
181 | v = "" |
|
|||
182 |
|
||||
183 | elif fl: |
|
|||
184 | for f in fl.split("|")[1:]: |
|
|||
185 | v = filters[f](v) |
|
|||
186 |
|
||||
187 | yield v |
|
|||
188 | tmpl = tmpl[m.end(0):] |
|
|||
189 | else: |
|
|||
190 | yield tmpl |
|
|||
191 | return |
|
|||
192 |
|
||||
193 | common_filters = { |
|
|||
194 | "escape": lambda x: cgi.escape(x, True), |
|
|||
195 | "urlescape": urllib.quote, |
|
|||
196 | "strip": lambda x: x.strip(), |
|
|||
197 | "age": age, |
|
|||
198 | "date": lambda x: util.datestr(x), |
|
|||
199 | "addbreaks": nl2br, |
|
|||
200 | "obfuscate": obfuscate, |
|
|||
201 | "short": (lambda x: x[:12]), |
|
|||
202 | "firstline": (lambda x: x.splitlines(1)[0]), |
|
|||
203 | "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"), |
|
|||
204 | "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"), |
|
|||
205 | } |
|
|||
206 |
|
||||
207 | class hgweb(object): |
|
102 | class hgweb(object): | |
208 | def __init__(self, repo, name=None): |
|
103 | def __init__(self, repo, name=None): | |
209 | if type(repo) == type(""): |
|
104 | if type(repo) == type(""): | |
@@ -910,12 +805,12 b' class hgweb(object):' | |||||
910 | self.reponame = (self.repo.ui.config("web", "name") |
|
805 | self.reponame = (self.repo.ui.config("web", "name") | |
911 | or uri.strip('/') or self.repo.root) |
|
806 | or uri.strip('/') or self.repo.root) | |
912 |
|
807 | |||
913 | self.t = templater(m, common_filters, |
|
808 | self.t = templater.templater(m, templater.common_filters, | |
914 | {"url": url, |
|
809 | {"url": url, | |
915 | "repo": self.reponame, |
|
810 | "repo": self.reponame, | |
916 | "header": header, |
|
811 | "header": header, | |
917 | "footer": footer, |
|
812 | "footer": footer, | |
918 | }) |
|
813 | }) | |
919 |
|
814 | |||
920 | if not req.form.has_key('cmd'): |
|
815 | if not req.form.has_key('cmd'): | |
921 | req.form['cmd'] = [self.t.cache['default'],] |
|
816 | req.form['cmd'] = [self.t.cache['default'],] |
General Comments 0
You need to be logged in to leave comments.
Login now