Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/hgweb.py @ 862:d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
The dirstate has to match what is in the repository (what would be
checked out with 'hg update -C'), because the resulting file may be
identical to the new parent, or it may be completely different.
Previously the dirstate wasn't updated, so if you changed the file to
look like the original parent, it might be considered unmodified
relative to the new parent.
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Wed, 10 Aug 2005 06:47:46 +0100 |
parents | c333dfa8fa1a |
children | c2e77581bc84 d4cb383e7de7 16ce690c411d 62ec665759f2 01215ad04283 |
rev | line source |
---|---|
238
3b92f8fe47ae
hgweb.py: kill #! line, clean up copyright notice
mpm@selenic.com
parents:
222
diff
changeset
|
1 # hgweb.py - web interface to a mercurial repository |
131 | 2 # |
238
3b92f8fe47ae
hgweb.py: kill #! line, clean up copyright notice
mpm@selenic.com
parents:
222
diff
changeset
|
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> |
575 | 4 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
131 | 5 # |
6 # This software may be used and distributed according to the terms | |
7 # of the GNU General Public License, incorporated herein by reference. | |
8 | |
825
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
9 import os, cgi, time, re, difflib, socket, sys, zlib |
138 | 10 from mercurial.hg import * |
215 | 11 from mercurial.ui import * |
138 | 12 |
157
2653740d8118
Install the templates where they can be found by hgweb.py
mpm@selenic.com
parents:
156
diff
changeset
|
13 def templatepath(): |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
14 for f in "templates", "../templates": |
157
2653740d8118
Install the templates where they can be found by hgweb.py
mpm@selenic.com
parents:
156
diff
changeset
|
15 p = os.path.join(os.path.dirname(__file__), f) |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
16 if os.path.isdir(p): return p |
157
2653740d8118
Install the templates where they can be found by hgweb.py
mpm@selenic.com
parents:
156
diff
changeset
|
17 |
138 | 18 def age(t): |
19 def plural(t, c): | |
20 if c == 1: return t | |
21 return t + "s" | |
22 def fmt(t, c): | |
23 return "%d %s" % (c, plural(t, c)) | |
24 | |
25 now = time.time() | |
26 delta = max(1, int(now - t)) | |
27 | |
28 scales = [["second", 1], | |
29 ["minute", 60], | |
30 ["hour", 3600], | |
31 ["day", 3600 * 24], | |
32 ["week", 3600 * 24 * 7], | |
33 ["month", 3600 * 24 * 30], | |
34 ["year", 3600 * 24 * 365]] | |
35 | |
36 scales.reverse() | |
37 | |
38 for t, s in scales: | |
39 n = delta / s | |
195 | 40 if n >= 2 or s == 1: return fmt(t, n) |
131 | 41 |
42 def nl2br(text): | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
43 return text.replace('\n', '<br/>\n') |
131 | 44 |
45 def obfuscate(text): | |
533
b8404005d6d5
[PATCH] Generate correctly XML entities for obfuscated user
mpm@selenic.com
parents:
515
diff
changeset
|
46 return ''.join([ '&#%d;' % ord(c) for c in text ]) |
138 | 47 |
48 def up(p): | |
49 if p[0] != "/": p = "/" + p | |
50 if p[-1] == "/": p = p[:-1] | |
51 up = os.path.dirname(p) | |
52 if up == "/": | |
53 return "/" | |
54 return up + "/" | |
131 | 55 |
56 def httphdr(type): | |
582 | 57 sys.stdout.write('Content-type: %s\n\n' % type) |
131 | 58 |
135 | 59 def write(*things): |
60 for thing in things: | |
61 if hasattr(thing, "__iter__"): | |
62 for part in thing: | |
63 write(part) | |
64 else: | |
65 sys.stdout.write(str(thing)) | |
66 | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
67 def template(tmpl, filters = {}, **map): |
138 | 68 while tmpl: |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
69 m = re.search(r"#([a-zA-Z0-9]+)((\|[a-zA-Z0-9]+)*)#", tmpl) |
138 | 70 if m: |
71 yield tmpl[:m.start(0)] | |
72 v = map.get(m.group(1), "") | |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
73 v = callable(v) and v(**map) or v |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
74 |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
75 fl = m.group(2) |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
76 if fl: |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
77 for f in fl.split("|")[1:]: |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
78 v = filters[f](v) |
515 | 79 |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
80 yield v |
138 | 81 tmpl = tmpl[m.end(0):] |
82 else: | |
83 yield tmpl | |
84 return | |
85 | |
86 class templater: | |
601 | 87 def __init__(self, mapfile, filters = {}, defaults = {}): |
138 | 88 self.cache = {} |
89 self.map = {} | |
90 self.base = os.path.dirname(mapfile) | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
91 self.filters = filters |
601 | 92 self.defaults = defaults |
515 | 93 |
138 | 94 for l in file(mapfile): |
95 m = re.match(r'(\S+)\s*=\s*"(.*)"$', l) | |
133
fb84d3e71042
added template support for some hgweb output, also, template files for
jake@edge2.net
parents:
132
diff
changeset
|
96 if m: |
138 | 97 self.cache[m.group(1)] = m.group(2) |
98 else: | |
99 m = re.match(r'(\S+)\s*=\s*(\S+)', l) | |
100 if m: | |
101 self.map[m.group(1)] = os.path.join(self.base, m.group(2)) | |
133
fb84d3e71042
added template support for some hgweb output, also, template files for
jake@edge2.net
parents:
132
diff
changeset
|
102 else: |
138 | 103 raise "unknown map entry '%s'" % l |
133
fb84d3e71042
added template support for some hgweb output, also, template files for
jake@edge2.net
parents:
132
diff
changeset
|
104 |
138 | 105 def __call__(self, t, **map): |
601 | 106 m = self.defaults.copy() |
107 m.update(map) | |
138 | 108 try: |
109 tmpl = self.cache[t] | |
110 except KeyError: | |
111 tmpl = self.cache[t] = file(self.map[t]).read() | |
601 | 112 return template(tmpl, self.filters, **m) |
515 | 113 |
599 | 114 def rfc822date(x): |
601 | 115 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(x)) |
599 | 116 |
138 | 117 class hgweb: |
269
24e9e140485f
hgweb: shrink the default changelog list to 10
mpm@selenic.com
parents:
265
diff
changeset
|
118 maxchanges = 10 |
138 | 119 maxfiles = 10 |
133
fb84d3e71042
added template support for some hgweb output, also, template files for
jake@edge2.net
parents:
132
diff
changeset
|
120 |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
121 def __init__(self, path, name, templates = ""): |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
122 self.templates = templates or templatepath() |
138 | 123 self.reponame = name |
258 | 124 self.path = path |
125 self.mtime = -1 | |
197 | 126 self.viewonly = 0 |
131 | 127 |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
128 self.filters = { |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
129 "escape": cgi.escape, |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
130 "age": age, |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
131 "date": (lambda x: time.asctime(time.gmtime(x))), |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
132 "addbreaks": nl2br, |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
133 "obfuscate": obfuscate, |
375 | 134 "short": (lambda x: x[:12]), |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
135 "firstline": (lambda x: x.splitlines(1)[0]), |
599 | 136 "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"), |
137 "rfc822date": rfc822date, | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
138 } |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
139 |
258 | 140 def refresh(self): |
141 s = os.stat(os.path.join(self.path, ".hg", "00changelog.i")) | |
142 if s.st_mtime != self.mtime: | |
322 | 143 self.mtime = s.st_mtime |
258 | 144 self.repo = repository(ui(), self.path) |
145 | |
138 | 146 def date(self, cs): |
147 return time.asctime(time.gmtime(float(cs[2].split(' ')[0]))) | |
148 | |
149 def listfiles(self, files, mf): | |
150 for f in files[:self.maxfiles]: | |
151 yield self.t("filenodelink", node = hex(mf[f]), file = f) | |
152 if len(files) > self.maxfiles: | |
153 yield self.t("fileellipses") | |
154 | |
155 def listfilediffs(self, files, changeset): | |
156 for f in files[:self.maxfiles]: | |
157 yield self.t("filedifflink", node = hex(changeset), file = f) | |
158 if len(files) > self.maxfiles: | |
159 yield self.t("fileellipses") | |
160 | |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
161 def parents(self, t1, nodes=[], rev=None,**args): |
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
162 if not rev: rev = lambda x: "" |
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
163 for node in nodes: |
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
164 if node != nullid: |
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
165 yield self.t(t1, node = hex(node), rev = rev(node), **args) |
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
166 |
568 | 167 def showtag(self, t1, node=nullid, **args): |
168 for t in self.repo.nodetags(node): | |
169 yield self.t(t1, tag = t, **args) | |
170 | |
138 | 171 def diff(self, node1, node2, files): |
172 def filterfiles(list, files): | |
173 l = [ x for x in list if x in files ] | |
515 | 174 |
138 | 175 for f in files: |
176 if f[-1] != os.sep: f += os.sep | |
177 l += [ x for x in list if x.startswith(f) ] | |
178 return l | |
131 | 179 |
172
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
180 parity = [0] |
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
181 def diffblock(diff, f, fn): |
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
182 yield self.t("diffblock", |
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
183 lines = prettyprintlines(diff), |
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
184 parity = parity[0], |
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
185 file = f, |
369
09f24af48b82
hgweb: fix deleted file in changeset key error
mpm@selenic.com
parents:
366
diff
changeset
|
186 filenode = hex(fn or nullid)) |
172
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
187 parity[0] = 1 - parity[0] |
515 | 188 |
172
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
189 def prettyprintlines(diff): |
138 | 190 for l in diff.splitlines(1): |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
191 if l.startswith('+'): |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
192 yield self.t("difflineplus", line = l) |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
193 elif l.startswith('-'): |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
194 yield self.t("difflineminus", line = l) |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
195 elif l.startswith('@'): |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
196 yield self.t("difflineat", line = l) |
138 | 197 else: |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
198 yield self.t("diffline", line = l) |
131 | 199 |
138 | 200 r = self.repo |
201 cl = r.changelog | |
202 mf = r.manifest | |
203 change1 = cl.read(node1) | |
204 change2 = cl.read(node2) | |
205 mmap1 = mf.read(change1[0]) | |
206 mmap2 = mf.read(change2[0]) | |
207 date1 = self.date(change1) | |
208 date2 = self.date(change2) | |
131 | 209 |
539 | 210 c, a, d, u = r.changes(node1, node2) |
645
a55048b2ae3a
this patch permits hgweb to show the deleted files in the changeset diff
kreijack@inwind.REMOVEME.it
parents:
635
diff
changeset
|
211 if files: |
a55048b2ae3a
this patch permits hgweb to show the deleted files in the changeset diff
kreijack@inwind.REMOVEME.it
parents:
635
diff
changeset
|
212 c, a, d = map(lambda x: filterfiles(x, files), (c, a, d)) |
131 | 213 |
138 | 214 for f in c: |
215 to = r.file(f).read(mmap1[f]) | |
216 tn = r.file(f).read(mmap2[f]) | |
172
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
217 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f), f, tn) |
138 | 218 for f in a: |
265
7ca05593bd30
hgweb: fix non-existent source or destination for diff
mpm@selenic.com
parents:
258
diff
changeset
|
219 to = None |
138 | 220 tn = r.file(f).read(mmap2[f]) |
172
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
221 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f), f, tn) |
138 | 222 for f in d: |
223 to = r.file(f).read(mmap1[f]) | |
265
7ca05593bd30
hgweb: fix non-existent source or destination for diff
mpm@selenic.com
parents:
258
diff
changeset
|
224 tn = None |
172
e9b1147db448
hgweb: alternating colors for multifile diffs
mpm@selenic.com
parents:
168
diff
changeset
|
225 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f), f, tn) |
131 | 226 |
180 | 227 def changelog(self, pos): |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
228 def changenav(**map): |
138 | 229 def seq(factor = 1): |
230 yield 1 * factor | |
173
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
231 yield 3 * factor |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
232 #yield 5 * factor |
138 | 233 for f in seq(factor * 10): |
234 yield f | |
131 | 235 |
173
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
236 l = [] |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
237 for f in seq(): |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
238 if f < self.maxchanges / 2: continue |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
239 if f > count: break |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
240 r = "%d" % f |
351 | 241 if pos + f < count: l.append(("+" + r, pos + f)) |
242 if pos - f >= 0: l.insert(0, ("-" + r, pos - f)) | |
173
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
243 |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
244 yield self.t("naventry", rev = 0, label="(0)") |
515 | 245 |
173
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
246 for label, rev in l: |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
247 yield self.t("naventry", label = label, rev = rev) |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
248 |
198
c88ef31fb5c0
hgweb: fix tip so that it doesn't need refreshing
mpm@selenic.com
parents:
197
diff
changeset
|
249 yield self.t("naventry", label="tip") |
131 | 250 |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
251 def changelist(**map): |
142 | 252 parity = (start - end) & 1 |
138 | 253 cl = self.repo.changelog |
254 l = [] # build a list in forward order for efficiency | |
351 | 255 for i in range(start, end): |
138 | 256 n = cl.node(i) |
257 changes = cl.read(n) | |
258 hn = hex(n) | |
259 t = float(changes[2].split(' ')[0]) | |
131 | 260 |
138 | 261 l.insert(0, self.t( |
262 'changelogentry', | |
142 | 263 parity = parity, |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
264 author = changes[1], |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
265 parent = self.parents("changelogparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
266 cl.parents(n), cl.rev), |
568 | 267 changelogtag = self.showtag("changelogtag",n), |
138 | 268 manifest = hex(changes[0]), |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
269 desc = changes[4], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
270 date = t, |
138 | 271 files = self.listfilediffs(changes[3], n), |
272 rev = i, | |
273 node = hn)) | |
142 | 274 parity = 1 - parity |
138 | 275 |
276 yield l | |
131 | 277 |
168 | 278 cl = self.repo.changelog |
279 mf = cl.read(cl.tip())[0] | |
280 count = cl.count() | |
351 | 281 start = max(0, pos - self.maxchanges + 1) |
282 end = min(count, start + self.maxchanges) | |
283 pos = end - 1 | |
138 | 284 |
142 | 285 yield self.t('changelog', |
286 changenav = changenav, | |
168 | 287 manifest = hex(mf), |
142 | 288 rev = pos, changesets = count, entries = changelist) |
131 | 289 |
538 | 290 def search(self, query): |
291 | |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
292 def changelist(**map): |
538 | 293 cl = self.repo.changelog |
294 count = 0 | |
295 qw = query.lower().split() | |
296 | |
297 def revgen(): | |
298 for i in range(cl.count() - 1, 0, -100): | |
299 l = [] | |
300 for j in range(max(0, i - 100), i): | |
301 n = cl.node(j) | |
302 changes = cl.read(n) | |
303 l.insert(0, (n, j, changes)) | |
304 for e in l: | |
305 yield e | |
306 | |
307 for n, i, changes in revgen(): | |
308 miss = 0 | |
309 for q in qw: | |
310 if not (q in changes[1].lower() or | |
311 q in changes[4].lower() or | |
312 q in " ".join(changes[3][:20]).lower()): | |
313 miss = 1 | |
314 break | |
315 if miss: continue | |
316 | |
317 count += 1 | |
318 hn = hex(n) | |
319 t = float(changes[2].split(' ')[0]) | |
320 | |
321 yield self.t( | |
322 'searchentry', | |
323 parity = count & 1, | |
324 author = changes[1], | |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
325 parent = self.parents("changelogparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
326 cl.parents(n), cl.rev), |
568 | 327 changelogtag = self.showtag("changelogtag",n), |
538 | 328 manifest = hex(changes[0]), |
329 desc = changes[4], | |
330 date = t, | |
331 files = self.listfilediffs(changes[3], n), | |
332 rev = i, | |
333 node = hn) | |
334 | |
335 if count >= self.maxchanges: break | |
336 | |
337 cl = self.repo.changelog | |
338 mf = cl.read(cl.tip())[0] | |
339 | |
340 yield self.t('search', | |
341 query = query, | |
342 manifest = hex(mf), | |
343 entries = changelist) | |
344 | |
138 | 345 def changeset(self, nodeid): |
346 n = bin(nodeid) | |
347 cl = self.repo.changelog | |
348 changes = cl.read(n) | |
598
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
349 p1 = cl.parents(n)[0] |
138 | 350 t = float(changes[2].split(' ')[0]) |
515 | 351 |
133
fb84d3e71042
added template support for some hgweb output, also, template files for
jake@edge2.net
parents:
132
diff
changeset
|
352 files = [] |
138 | 353 mf = self.repo.manifest.read(changes[0]) |
131 | 354 for f in changes[3]: |
138 | 355 files.append(self.t("filenodelink", |
369
09f24af48b82
hgweb: fix deleted file in changeset key error
mpm@selenic.com
parents:
366
diff
changeset
|
356 filenode = hex(mf.get(f, nullid)), file = f)) |
138 | 357 |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
358 def diff(**map): |
645
a55048b2ae3a
this patch permits hgweb to show the deleted files in the changeset diff
kreijack@inwind.REMOVEME.it
parents:
635
diff
changeset
|
359 yield self.diff(p1, n, None) |
131 | 360 |
138 | 361 yield self.t('changeset', |
362 diff = diff, | |
363 rev = cl.rev(n), | |
364 node = nodeid, | |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
365 parent = self.parents("changesetparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
366 cl.parents(n), cl.rev), |
568 | 367 changesettag = self.showtag("changesettag",n), |
138 | 368 manifest = hex(changes[0]), |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
369 author = changes[1], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
370 desc = changes[4], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
371 date = t, |
138 | 372 files = files) |
131 | 373 |
138 | 374 def filelog(self, f, filenode): |
375 cl = self.repo.changelog | |
376 fl = self.repo.file(f) | |
377 count = fl.count() | |
378 | |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
379 def entries(**map): |
138 | 380 l = [] |
142 | 381 parity = (count - 1) & 1 |
515 | 382 |
138 | 383 for i in range(count): |
384 | |
385 n = fl.node(i) | |
386 lr = fl.linkrev(n) | |
387 cn = cl.node(lr) | |
388 cs = cl.read(cl.node(lr)) | |
389 t = float(cs[2].split(' ')[0]) | |
133
fb84d3e71042
added template support for some hgweb output, also, template files for
jake@edge2.net
parents:
132
diff
changeset
|
390 |
138 | 391 l.insert(0, self.t("filelogentry", |
142 | 392 parity = parity, |
138 | 393 filenode = hex(n), |
394 filerev = i, | |
395 file = f, | |
396 node = hex(cn), | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
397 author = cs[1], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
398 date = t, |
598
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
399 parent = self.parents("filelogparent", |
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
400 fl.parents(n), fl.rev, file=f), |
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
401 desc = cs[4])) |
142 | 402 parity = 1 - parity |
138 | 403 |
404 yield l | |
405 | |
406 yield self.t("filelog", | |
407 file = f, | |
408 filenode = filenode, | |
409 entries = entries) | |
131 | 410 |
138 | 411 def filerevision(self, f, node): |
412 fl = self.repo.file(f) | |
413 n = bin(node) | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
414 text = fl.read(n) |
138 | 415 changerev = fl.linkrev(n) |
416 cl = self.repo.changelog | |
417 cn = cl.node(changerev) | |
418 cs = cl.read(cn) | |
419 t = float(cs[2].split(' ')[0]) | |
420 mfn = cs[0] | |
142 | 421 |
422 def lines(): | |
423 for l, t in enumerate(text.splitlines(1)): | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
424 yield self.t("fileline", line = t, |
142 | 425 linenumber = "% 6d" % (l + 1), |
426 parity = l & 1) | |
359 | 427 |
138 | 428 yield self.t("filerevision", file = f, |
429 filenode = node, | |
430 path = up(f), | |
142 | 431 text = lines(), |
138 | 432 rev = changerev, |
433 node = hex(cn), | |
434 manifest = hex(mfn), | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
435 author = cs[1], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
436 date = t, |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
437 parent = self.parents("filerevparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
438 fl.parents(n), fl.rev, file=f), |
598
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
439 permissions = self.repo.manifest.readflags(mfn)[f]) |
138 | 440 |
441 def fileannotate(self, f, node): | |
442 bcache = {} | |
443 ncache = {} | |
444 fl = self.repo.file(f) | |
445 n = bin(node) | |
446 changerev = fl.linkrev(n) | |
447 | |
448 cl = self.repo.changelog | |
449 cn = cl.node(changerev) | |
450 cs = cl.read(cn) | |
451 t = float(cs[2].split(' ')[0]) | |
452 mfn = cs[0] | |
131 | 453 |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
454 def annotate(**map): |
142 | 455 parity = 1 |
456 last = None | |
138 | 457 for r, l in fl.annotate(n): |
458 try: | |
459 cnode = ncache[r] | |
460 except KeyError: | |
461 cnode = ncache[r] = self.repo.changelog.node(r) | |
515 | 462 |
138 | 463 try: |
464 name = bcache[r] | |
465 except KeyError: | |
466 cl = self.repo.changelog.read(cnode) | |
467 name = cl[1] | |
468 f = name.find('@') | |
469 if f >= 0: | |
470 name = name[:f] | |
534
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
533
diff
changeset
|
471 f = name.find('<') |
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
533
diff
changeset
|
472 if f >= 0: |
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
533
diff
changeset
|
473 name = name[f+1:] |
138 | 474 bcache[r] = name |
131 | 475 |
142 | 476 if last != cnode: |
477 parity = 1 - parity | |
478 last = cnode | |
479 | |
138 | 480 yield self.t("annotateline", |
142 | 481 parity = parity, |
138 | 482 node = hex(cnode), |
483 rev = r, | |
484 author = name, | |
485 file = f, | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
486 line = l) |
138 | 487 |
488 yield self.t("fileannotate", | |
489 file = f, | |
490 filenode = node, | |
491 annotate = annotate, | |
492 path = up(f), | |
493 rev = changerev, | |
494 node = hex(cn), | |
495 manifest = hex(mfn), | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
496 author = cs[1], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
497 date = t, |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
498 parent = self.parents("fileannotateparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
499 fl.parents(n), fl.rev, file=f), |
598
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
500 permissions = self.repo.manifest.readflags(mfn)[f]) |
136 | 501 |
138 | 502 def manifest(self, mnode, path): |
503 mf = self.repo.manifest.read(bin(mnode)) | |
504 rev = self.repo.manifest.rev(bin(mnode)) | |
505 node = self.repo.changelog.node(rev) | |
359 | 506 mff=self.repo.manifest.readflags(bin(mnode)) |
138 | 507 |
508 files = {} | |
515 | 509 |
138 | 510 p = path[1:] |
511 l = len(p) | |
131 | 512 |
138 | 513 for f,n in mf.items(): |
514 if f[:l] != p: | |
515 continue | |
516 remain = f[l:] | |
517 if "/" in remain: | |
518 short = remain[:remain.find("/") + 1] # bleah | |
142 | 519 files[short] = (f, None) |
138 | 520 else: |
521 short = os.path.basename(remain) | |
522 files[short] = (f, n) | |
131 | 523 |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
524 def filelist(**map): |
142 | 525 parity = 0 |
138 | 526 fl = files.keys() |
527 fl.sort() | |
528 for f in fl: | |
529 full, fnode = files[f] | |
142 | 530 if fnode: |
531 yield self.t("manifestfileentry", | |
532 file = full, | |
533 manifest = mnode, | |
534 filenode = hex(fnode), | |
535 parity = parity, | |
515 | 536 basename = f, |
359 | 537 permissions = mff[full]) |
142 | 538 else: |
539 yield self.t("manifestdirentry", | |
540 parity = parity, | |
541 path = os.path.join(path, f), | |
542 manifest = mnode, basename = f[:-1]) | |
543 parity = 1 - parity | |
138 | 544 |
545 yield self.t("manifest", | |
546 manifest = mnode, | |
547 rev = rev, | |
548 node = hex(node), | |
549 path = path, | |
550 up = up(path), | |
142 | 551 entries = filelist) |
131 | 552 |
168 | 553 def tags(self): |
554 cl = self.repo.changelog | |
555 mf = cl.read(cl.tip())[0] | |
556 | |
343 | 557 i = self.repo.tagslist() |
558 i.reverse() | |
168 | 559 |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
560 def entries(**map): |
168 | 561 parity = 0 |
562 for k,n in i: | |
563 yield self.t("tagentry", | |
564 parity = parity, | |
565 tag = k, | |
566 node = hex(n)) | |
567 parity = 1 - parity | |
568 | |
569 yield self.t("tags", | |
570 manifest = hex(mf), | |
571 entries = entries) | |
572 | |
138 | 573 def filediff(self, file, changeset): |
574 n = bin(changeset) | |
575 cl = self.repo.changelog | |
576 p1 = cl.parents(n)[0] | |
577 cs = cl.read(n) | |
578 mf = self.repo.manifest.read(cs[0]) | |
515 | 579 |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
580 def diff(**map): |
138 | 581 yield self.diff(p1, n, file) |
131 | 582 |
138 | 583 yield self.t("filediff", |
584 file = file, | |
376
fadc9e126369
hgweb: fix deleted file in filediff key error
Thomas Arendsen Hein <thomas@intevation.de>
parents:
369
diff
changeset
|
585 filenode = hex(mf.get(file, nullid)), |
138 | 586 node = changeset, |
587 rev = self.repo.changelog.rev(n), | |
571
c7364b985ca2
[PATCH 3/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
570
diff
changeset
|
588 parent = self.parents("filediffparent", |
c7364b985ca2
[PATCH 3/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
570
diff
changeset
|
589 cl.parents(n), cl.rev), |
138 | 590 diff = diff) |
515 | 591 |
138 | 592 # add tags to things |
593 # tags -> list of changesets corresponding to tags | |
594 # find tag, changeset, file | |
131 | 595 |
132 | 596 def run(self): |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
597 def header(**map): |
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
598 yield self.t("header", **map) |
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
599 |
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
600 def footer(**map): |
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
601 yield self.t("footer", **map) |
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
602 |
258 | 603 self.refresh() |
132 | 604 args = cgi.parse() |
605 | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
606 m = os.path.join(self.templates, "map") |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
607 if args.has_key('style'): |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
608 b = os.path.basename("map-" + args['style'][0]) |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
609 p = os.path.join(self.templates, b) |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
610 if os.path.isfile(p): m = p |
515 | 611 |
601 | 612 port = os.environ["SERVER_PORT"] |
613 port = port != "80" and (":" + port) or "" | |
620
7369ec5d93f2
Attempt to handle RSS URIs properly
Matt Mackall <mpm@selenic.com>
parents:
605
diff
changeset
|
614 uri = os.environ["REQUEST_URI"] |
7369ec5d93f2
Attempt to handle RSS URIs properly
Matt Mackall <mpm@selenic.com>
parents:
605
diff
changeset
|
615 if "?" in uri: uri = uri.split("?")[0] |
7369ec5d93f2
Attempt to handle RSS URIs properly
Matt Mackall <mpm@selenic.com>
parents:
605
diff
changeset
|
616 url = "http://%s%s%s" % (os.environ["SERVER_NAME"], port, uri) |
601 | 617 |
618 self.t = templater(m, self.filters, | |
619 {"url":url, | |
620 "repo":self.reponame, | |
857
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
621 "header":header, |
41b344235bb7
[PATCH] Propagate the template map though recursively
Jeff Sipek <jeffpc@optonline.net>
parents:
839
diff
changeset
|
622 "footer":footer, |
601 | 623 }) |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
624 |
858
c333dfa8fa1a
[PATCH] Move default page name into map file
Jeff Sipek <jeffpc@optonline.net>
parents:
857
diff
changeset
|
625 if not args.has_key('cmd'): |
c333dfa8fa1a
[PATCH] Move default page name into map file
Jeff Sipek <jeffpc@optonline.net>
parents:
857
diff
changeset
|
626 args['cmd'] = [self.t.cache['default'],] |
c333dfa8fa1a
[PATCH] Move default page name into map file
Jeff Sipek <jeffpc@optonline.net>
parents:
857
diff
changeset
|
627 |
c333dfa8fa1a
[PATCH] Move default page name into map file
Jeff Sipek <jeffpc@optonline.net>
parents:
857
diff
changeset
|
628 if args['cmd'][0] == 'changelog': |
538 | 629 c = self.repo.changelog.count() - 1 |
630 hi = c | |
153
e8a360cd5a9f
changed pos to rev for changelog cmd, changed & to ;
jake@edge2.net
parents:
142
diff
changeset
|
631 if args.has_key('rev'): |
165 | 632 hi = args['rev'][0] |
166
39624c47060f
hgweb: don't blow up on search for unknown keys
mpm@selenic.com
parents:
165
diff
changeset
|
633 try: |
39624c47060f
hgweb: don't blow up on search for unknown keys
mpm@selenic.com
parents:
165
diff
changeset
|
634 hi = self.repo.changelog.rev(self.repo.lookup(hi)) |
688 | 635 except RepoError: |
538 | 636 write(self.search(hi)) |
637 return | |
575 | 638 |
138 | 639 write(self.changelog(hi)) |
515 | 640 |
138 | 641 elif args['cmd'][0] == 'changeset': |
642 write(self.changeset(args['node'][0])) | |
643 | |
644 elif args['cmd'][0] == 'manifest': | |
645 write(self.manifest(args['manifest'][0], args['path'][0])) | |
646 | |
168 | 647 elif args['cmd'][0] == 'tags': |
648 write(self.tags()) | |
649 | |
138 | 650 elif args['cmd'][0] == 'filediff': |
651 write(self.filediff(args['file'][0], args['node'][0])) | |
131 | 652 |
132 | 653 elif args['cmd'][0] == 'file': |
138 | 654 write(self.filerevision(args['file'][0], args['filenode'][0])) |
131 | 655 |
138 | 656 elif args['cmd'][0] == 'annotate': |
657 write(self.fileannotate(args['file'][0], args['filenode'][0])) | |
131 | 658 |
138 | 659 elif args['cmd'][0] == 'filelog': |
660 write(self.filelog(args['file'][0], args['filenode'][0])) | |
136 | 661 |
222 | 662 elif args['cmd'][0] == 'heads': |
751
0b245edec124
When pulling from a non hg repository URL (e.g. http://www.kernel.org/hg)
Muli Ben-Yehuda <mulix@mulix.org>
parents:
688
diff
changeset
|
663 httphdr("application/mercurial-0.1") |
222 | 664 h = self.repo.heads() |
665 sys.stdout.write(" ".join(map(hex, h)) + "\n") | |
666 | |
132 | 667 elif args['cmd'][0] == 'branches': |
751
0b245edec124
When pulling from a non hg repository URL (e.g. http://www.kernel.org/hg)
Muli Ben-Yehuda <mulix@mulix.org>
parents:
688
diff
changeset
|
668 httphdr("application/mercurial-0.1") |
132 | 669 nodes = [] |
670 if args.has_key('nodes'): | |
138 | 671 nodes = map(bin, args['nodes'][0].split(" ")) |
672 for b in self.repo.branches(nodes): | |
673 sys.stdout.write(" ".join(map(hex, b)) + "\n") | |
131 | 674 |
132 | 675 elif args['cmd'][0] == 'between': |
753 | 676 httphdr("application/mercurial-0.1") |
132 | 677 nodes = [] |
678 if args.has_key('pairs'): | |
138 | 679 pairs = [ map(bin, p.split("-")) |
132 | 680 for p in args['pairs'][0].split(" ") ] |
138 | 681 for b in self.repo.between(pairs): |
682 sys.stdout.write(" ".join(map(hex, b)) + "\n") | |
132 | 683 |
684 elif args['cmd'][0] == 'changegroup': | |
751
0b245edec124
When pulling from a non hg repository URL (e.g. http://www.kernel.org/hg)
Muli Ben-Yehuda <mulix@mulix.org>
parents:
688
diff
changeset
|
685 httphdr("application/mercurial-0.1") |
132 | 686 nodes = [] |
197 | 687 if self.viewonly: |
688 return | |
689 | |
132 | 690 if args.has_key('roots'): |
138 | 691 nodes = map(bin, args['roots'][0].split(" ")) |
131 | 692 |
132 | 693 z = zlib.compressobj() |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
620
diff
changeset
|
694 f = self.repo.changegroup(nodes) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
620
diff
changeset
|
695 while 1: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
620
diff
changeset
|
696 chunk = f.read(4096) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
620
diff
changeset
|
697 if not chunk: break |
132 | 698 sys.stdout.write(z.compress(chunk)) |
699 | |
700 sys.stdout.write(z.flush()) | |
131 | 701 |
132 | 702 else: |
138 | 703 write(self.t("error")) |
131 | 704 |
825
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
705 def create_server(path, name, templates, address, port, use_ipv6 = False, |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
706 accesslog = sys.stdout, errorlog = sys.stderr): |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
707 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
708 import BaseHTTPServer |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
709 |
825
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
710 class IPv6HTTPServer(BaseHTTPServer.HTTPServer): |
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
711 address_family = socket.AF_INET6 |
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
712 |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
713 class hgwebhandler(BaseHTTPServer.BaseHTTPRequestHandler): |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
714 def log_error(self, format, *args): |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
715 errorlog.write("%s - - [%s] %s\n" % (self.address_string(), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
716 self.log_date_time_string(), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
717 format % args)) |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
718 |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
719 def log_message(self, format, *args): |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
720 accesslog.write("%s - - [%s] %s\n" % (self.address_string(), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
721 self.log_date_time_string(), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
722 format % args)) |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
723 |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
724 def do_POST(self): |
271 | 725 try: |
726 self.do_hgweb() | |
727 except socket.error, inst: | |
728 if inst.args[0] != 32: raise | |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
729 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
730 def do_GET(self): |
271 | 731 self.do_POST() |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
732 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
733 def do_hgweb(self): |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
734 query = "" |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
735 p = self.path.find("?") |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
736 if p: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
737 query = self.path[p + 1:] |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
738 query = query.replace('+', ' ') |
515 | 739 |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
740 env = {} |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
741 env['GATEWAY_INTERFACE'] = 'CGI/1.1' |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
742 env['REQUEST_METHOD'] = self.command |
599 | 743 env['SERVER_NAME'] = self.server.server_name |
744 env['SERVER_PORT'] = str(self.server.server_port) | |
745 env['REQUEST_URI'] = "/" | |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
746 if query: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
747 env['QUERY_STRING'] = query |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
748 host = self.address_string() |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
749 if host != self.client_address[0]: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
750 env['REMOTE_HOST'] = host |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
751 env['REMOTE_ADDR'] = self.client_address[0] |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
752 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
753 if self.headers.typeheader is None: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
754 env['CONTENT_TYPE'] = self.headers.type |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
755 else: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
756 env['CONTENT_TYPE'] = self.headers.typeheader |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
757 length = self.headers.getheader('content-length') |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
758 if length: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
759 env['CONTENT_LENGTH'] = length |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
760 accept = [] |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
761 for line in self.headers.getallmatchingheaders('accept'): |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
762 if line[:1] in "\t\n\r ": |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
763 accept.append(line.strip()) |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
764 else: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
765 accept = accept + line[7:].split(',') |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
766 env['HTTP_ACCEPT'] = ','.join(accept) |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
767 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
768 os.environ.update(env) |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
769 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
770 save = sys.argv, sys.stdin, sys.stdout, sys.stderr |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
771 try: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
772 sys.stdin = self.rfile |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
773 sys.stdout = self.wfile |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
774 sys.argv = ["hgweb.py"] |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
775 if '=' not in query: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
776 sys.argv.append(query) |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
777 self.send_response(200, "Script output follows") |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
778 hg.run() |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
779 finally: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
780 sys.argv, sys.stdin, sys.stdout, sys.stderr = save |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
781 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
782 hg = hgweb(path, name, templates) |
825
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
783 if use_ipv6: |
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
784 return IPv6HTTPServer((address, port), hgwebhandler) |
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
785 else: |
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
786 return BaseHTTPServer.HTTPServer((address, port), hgwebhandler) |
603
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
601
diff
changeset
|
787 |
825
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
788 def server(path, name, templates, address, port, use_ipv6 = False, |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
789 accesslog = sys.stdout, errorlog = sys.stderr): |
825
0108c602feb9
Add an option to hg serve to serve file using IPv6
Samuel Tardieu <sam@rfc1149.net>
parents:
753
diff
changeset
|
790 httpd = create_server(path, name, templates, address, port, use_ipv6, |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
791 accesslog, errorlog) |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
792 httpd.serve_forever() |