Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/hgweb.py @ 785:46a8dd3145cc
Fix undo after aborted commit bug
Commit would overwrite undo.dirstate unconditionally, so an undo after
an aborted commit would restore the dirstate from the aborted commit
and not the prior transaction.
This copies dirstate to journal.dirstate and moves it after a
successful transaction.
author | mpm@selenic.com |
---|---|
date | Wed, 27 Jul 2005 18:16:20 -0800 |
parents | 8760d0c83b9b |
children | 0108c602feb9 1fe3b14c7044 9c918287d10b |
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 | |
9 import os, cgi, time, re, difflib, 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), "") | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
73 v = callable(v) and v() or v |
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 |
142 | 227 def header(self): |
601 | 228 yield self.t("header") |
142 | 229 |
230 def footer(self): | |
601 | 231 yield self.t("footer") |
142 | 232 |
180 | 233 def changelog(self, pos): |
138 | 234 def changenav(): |
235 def seq(factor = 1): | |
236 yield 1 * factor | |
173
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
237 yield 3 * factor |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
238 #yield 5 * factor |
138 | 239 for f in seq(factor * 10): |
240 yield f | |
131 | 241 |
173
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
242 l = [] |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
243 for f in seq(): |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
244 if f < self.maxchanges / 2: continue |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
245 if f > count: break |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
246 r = "%d" % f |
351 | 247 if pos + f < count: l.append(("+" + r, pos + f)) |
248 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
|
249 |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
250 yield self.t("naventry", rev = 0, label="(0)") |
515 | 251 |
173
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
252 for label, rev in l: |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
253 yield self.t("naventry", label = label, rev = rev) |
8da1df932c16
hgweb: make navigation of changesets a bit nicer
mpm@selenic.com
parents:
172
diff
changeset
|
254 |
198
c88ef31fb5c0
hgweb: fix tip so that it doesn't need refreshing
mpm@selenic.com
parents:
197
diff
changeset
|
255 yield self.t("naventry", label="tip") |
131 | 256 |
138 | 257 def changelist(): |
142 | 258 parity = (start - end) & 1 |
138 | 259 cl = self.repo.changelog |
260 l = [] # build a list in forward order for efficiency | |
351 | 261 for i in range(start, end): |
138 | 262 n = cl.node(i) |
263 changes = cl.read(n) | |
264 hn = hex(n) | |
265 t = float(changes[2].split(' ')[0]) | |
131 | 266 |
138 | 267 l.insert(0, self.t( |
268 'changelogentry', | |
142 | 269 parity = parity, |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
270 author = changes[1], |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
271 parent = self.parents("changelogparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
272 cl.parents(n), cl.rev), |
568 | 273 changelogtag = self.showtag("changelogtag",n), |
138 | 274 manifest = hex(changes[0]), |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
275 desc = changes[4], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
276 date = t, |
138 | 277 files = self.listfilediffs(changes[3], n), |
278 rev = i, | |
279 node = hn)) | |
142 | 280 parity = 1 - parity |
138 | 281 |
282 yield l | |
131 | 283 |
168 | 284 cl = self.repo.changelog |
285 mf = cl.read(cl.tip())[0] | |
286 count = cl.count() | |
351 | 287 start = max(0, pos - self.maxchanges + 1) |
288 end = min(count, start + self.maxchanges) | |
289 pos = end - 1 | |
138 | 290 |
142 | 291 yield self.t('changelog', |
292 changenav = changenav, | |
168 | 293 manifest = hex(mf), |
142 | 294 rev = pos, changesets = count, entries = changelist) |
131 | 295 |
538 | 296 def search(self, query): |
297 | |
298 def changelist(): | |
299 cl = self.repo.changelog | |
300 count = 0 | |
301 qw = query.lower().split() | |
302 | |
303 def revgen(): | |
304 for i in range(cl.count() - 1, 0, -100): | |
305 l = [] | |
306 for j in range(max(0, i - 100), i): | |
307 n = cl.node(j) | |
308 changes = cl.read(n) | |
309 l.insert(0, (n, j, changes)) | |
310 for e in l: | |
311 yield e | |
312 | |
313 for n, i, changes in revgen(): | |
314 miss = 0 | |
315 for q in qw: | |
316 if not (q in changes[1].lower() or | |
317 q in changes[4].lower() or | |
318 q in " ".join(changes[3][:20]).lower()): | |
319 miss = 1 | |
320 break | |
321 if miss: continue | |
322 | |
323 count += 1 | |
324 hn = hex(n) | |
325 t = float(changes[2].split(' ')[0]) | |
326 | |
327 yield self.t( | |
328 'searchentry', | |
329 parity = count & 1, | |
330 author = changes[1], | |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
331 parent = self.parents("changelogparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
332 cl.parents(n), cl.rev), |
568 | 333 changelogtag = self.showtag("changelogtag",n), |
538 | 334 manifest = hex(changes[0]), |
335 desc = changes[4], | |
336 date = t, | |
337 files = self.listfilediffs(changes[3], n), | |
338 rev = i, | |
339 node = hn) | |
340 | |
341 if count >= self.maxchanges: break | |
342 | |
343 cl = self.repo.changelog | |
344 mf = cl.read(cl.tip())[0] | |
345 | |
346 yield self.t('search', | |
347 query = query, | |
348 manifest = hex(mf), | |
349 entries = changelist) | |
350 | |
138 | 351 def changeset(self, nodeid): |
352 n = bin(nodeid) | |
353 cl = self.repo.changelog | |
354 changes = cl.read(n) | |
598
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
355 p1 = cl.parents(n)[0] |
138 | 356 t = float(changes[2].split(' ')[0]) |
515 | 357 |
133
fb84d3e71042
added template support for some hgweb output, also, template files for
jake@edge2.net
parents:
132
diff
changeset
|
358 files = [] |
138 | 359 mf = self.repo.manifest.read(changes[0]) |
131 | 360 for f in changes[3]: |
138 | 361 files.append(self.t("filenodelink", |
369
09f24af48b82
hgweb: fix deleted file in changeset key error
mpm@selenic.com
parents:
366
diff
changeset
|
362 filenode = hex(mf.get(f, nullid)), file = f)) |
138 | 363 |
364 def diff(): | |
645
a55048b2ae3a
this patch permits hgweb to show the deleted files in the changeset diff
kreijack@inwind.REMOVEME.it
parents:
635
diff
changeset
|
365 yield self.diff(p1, n, None) |
131 | 366 |
138 | 367 yield self.t('changeset', |
368 diff = diff, | |
369 rev = cl.rev(n), | |
370 node = nodeid, | |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
371 parent = self.parents("changesetparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
372 cl.parents(n), cl.rev), |
568 | 373 changesettag = self.showtag("changesettag",n), |
138 | 374 manifest = hex(changes[0]), |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
375 author = changes[1], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
376 desc = changes[4], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
377 date = t, |
138 | 378 files = files) |
131 | 379 |
138 | 380 def filelog(self, f, filenode): |
381 cl = self.repo.changelog | |
382 fl = self.repo.file(f) | |
383 count = fl.count() | |
384 | |
385 def entries(): | |
386 l = [] | |
142 | 387 parity = (count - 1) & 1 |
515 | 388 |
138 | 389 for i in range(count): |
390 | |
391 n = fl.node(i) | |
392 lr = fl.linkrev(n) | |
393 cn = cl.node(lr) | |
394 cs = cl.read(cl.node(lr)) | |
395 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
|
396 |
138 | 397 l.insert(0, self.t("filelogentry", |
142 | 398 parity = parity, |
138 | 399 filenode = hex(n), |
400 filerev = i, | |
401 file = f, | |
402 node = hex(cn), | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
403 author = cs[1], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
404 date = t, |
598
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
405 parent = self.parents("filelogparent", |
f8d44a2e6928
[PATCH 4/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
582
diff
changeset
|
406 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
|
407 desc = cs[4])) |
142 | 408 parity = 1 - parity |
138 | 409 |
410 yield l | |
411 | |
412 yield self.t("filelog", | |
413 file = f, | |
414 filenode = filenode, | |
415 entries = entries) | |
131 | 416 |
138 | 417 def filerevision(self, f, node): |
418 fl = self.repo.file(f) | |
419 n = bin(node) | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
420 text = fl.read(n) |
138 | 421 changerev = fl.linkrev(n) |
422 cl = self.repo.changelog | |
423 cn = cl.node(changerev) | |
424 cs = cl.read(cn) | |
425 t = float(cs[2].split(' ')[0]) | |
426 mfn = cs[0] | |
142 | 427 |
428 def lines(): | |
429 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
|
430 yield self.t("fileline", line = t, |
142 | 431 linenumber = "% 6d" % (l + 1), |
432 parity = l & 1) | |
359 | 433 |
138 | 434 yield self.t("filerevision", file = f, |
435 filenode = node, | |
436 path = up(f), | |
142 | 437 text = lines(), |
138 | 438 rev = changerev, |
439 node = hex(cn), | |
440 manifest = hex(mfn), | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
441 author = cs[1], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
442 date = t, |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
443 parent = self.parents("filerevparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
444 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
|
445 permissions = self.repo.manifest.readflags(mfn)[f]) |
138 | 446 |
447 def fileannotate(self, f, node): | |
448 bcache = {} | |
449 ncache = {} | |
450 fl = self.repo.file(f) | |
451 n = bin(node) | |
452 changerev = fl.linkrev(n) | |
453 | |
454 cl = self.repo.changelog | |
455 cn = cl.node(changerev) | |
456 cs = cl.read(cn) | |
457 t = float(cs[2].split(' ')[0]) | |
458 mfn = cs[0] | |
131 | 459 |
138 | 460 def annotate(): |
142 | 461 parity = 1 |
462 last = None | |
138 | 463 for r, l in fl.annotate(n): |
464 try: | |
465 cnode = ncache[r] | |
466 except KeyError: | |
467 cnode = ncache[r] = self.repo.changelog.node(r) | |
515 | 468 |
138 | 469 try: |
470 name = bcache[r] | |
471 except KeyError: | |
472 cl = self.repo.changelog.read(cnode) | |
473 name = cl[1] | |
474 f = name.find('@') | |
475 if f >= 0: | |
476 name = name[:f] | |
534
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
533
diff
changeset
|
477 f = name.find('<') |
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
533
diff
changeset
|
478 if f >= 0: |
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
533
diff
changeset
|
479 name = name[f+1:] |
138 | 480 bcache[r] = name |
131 | 481 |
142 | 482 if last != cnode: |
483 parity = 1 - parity | |
484 last = cnode | |
485 | |
138 | 486 yield self.t("annotateline", |
142 | 487 parity = parity, |
138 | 488 node = hex(cnode), |
489 rev = r, | |
490 author = name, | |
491 file = f, | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
492 line = l) |
138 | 493 |
494 yield self.t("fileannotate", | |
495 file = f, | |
496 filenode = node, | |
497 annotate = annotate, | |
498 path = up(f), | |
499 rev = changerev, | |
500 node = hex(cn), | |
501 manifest = hex(mfn), | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
502 author = cs[1], |
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
503 date = t, |
570
2ee819a950aa
[PATCH 2/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
569
diff
changeset
|
504 parent = self.parents("fileannotateparent", |
569
3e347929f5f9
[PATCH 1/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
568
diff
changeset
|
505 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
|
506 permissions = self.repo.manifest.readflags(mfn)[f]) |
136 | 507 |
138 | 508 def manifest(self, mnode, path): |
509 mf = self.repo.manifest.read(bin(mnode)) | |
510 rev = self.repo.manifest.rev(bin(mnode)) | |
511 node = self.repo.changelog.node(rev) | |
359 | 512 mff=self.repo.manifest.readflags(bin(mnode)) |
138 | 513 |
514 files = {} | |
515 | 515 |
138 | 516 p = path[1:] |
517 l = len(p) | |
131 | 518 |
138 | 519 for f,n in mf.items(): |
520 if f[:l] != p: | |
521 continue | |
522 remain = f[l:] | |
523 if "/" in remain: | |
524 short = remain[:remain.find("/") + 1] # bleah | |
142 | 525 files[short] = (f, None) |
138 | 526 else: |
527 short = os.path.basename(remain) | |
528 files[short] = (f, n) | |
131 | 529 |
138 | 530 def filelist(): |
142 | 531 parity = 0 |
138 | 532 fl = files.keys() |
533 fl.sort() | |
534 for f in fl: | |
535 full, fnode = files[f] | |
142 | 536 if fnode: |
537 yield self.t("manifestfileentry", | |
538 file = full, | |
539 manifest = mnode, | |
540 filenode = hex(fnode), | |
541 parity = parity, | |
515 | 542 basename = f, |
359 | 543 permissions = mff[full]) |
142 | 544 else: |
545 yield self.t("manifestdirentry", | |
546 parity = parity, | |
547 path = os.path.join(path, f), | |
548 manifest = mnode, basename = f[:-1]) | |
549 parity = 1 - parity | |
138 | 550 |
551 yield self.t("manifest", | |
552 manifest = mnode, | |
553 rev = rev, | |
554 node = hex(node), | |
555 path = path, | |
556 up = up(path), | |
142 | 557 entries = filelist) |
131 | 558 |
168 | 559 def tags(self): |
560 cl = self.repo.changelog | |
561 mf = cl.read(cl.tip())[0] | |
562 | |
343 | 563 i = self.repo.tagslist() |
564 i.reverse() | |
168 | 565 |
566 def entries(): | |
567 parity = 0 | |
568 for k,n in i: | |
569 yield self.t("tagentry", | |
570 parity = parity, | |
571 tag = k, | |
572 node = hex(n)) | |
573 parity = 1 - parity | |
574 | |
575 yield self.t("tags", | |
576 manifest = hex(mf), | |
577 entries = entries) | |
578 | |
138 | 579 def filediff(self, file, changeset): |
580 n = bin(changeset) | |
581 cl = self.repo.changelog | |
582 p1 = cl.parents(n)[0] | |
583 cs = cl.read(n) | |
584 mf = self.repo.manifest.read(cs[0]) | |
515 | 585 |
138 | 586 def diff(): |
587 yield self.diff(p1, n, file) | |
131 | 588 |
138 | 589 yield self.t("filediff", |
590 file = file, | |
376
fadc9e126369
hgweb: fix deleted file in filediff key error
Thomas Arendsen Hein <thomas@intevation.de>
parents:
369
diff
changeset
|
591 filenode = hex(mf.get(file, nullid)), |
138 | 592 node = changeset, |
593 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
|
594 parent = self.parents("filediffparent", |
c7364b985ca2
[PATCH 3/5]: cleaning the template parent management in hgweb
mpm@selenic.com
parents:
570
diff
changeset
|
595 cl.parents(n), cl.rev), |
138 | 596 diff = diff) |
515 | 597 |
138 | 598 # add tags to things |
599 # tags -> list of changesets corresponding to tags | |
600 # find tag, changeset, file | |
131 | 601 |
132 | 602 def run(self): |
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, | |
621 "header":self.header(), | |
622 "footer":self.footer(), | |
623 }) | |
201
f918a6fa2572
hgweb: add template filters, template style maps, and raw pages
mpm@selenic.com
parents:
198
diff
changeset
|
624 |
138 | 625 if not args.has_key('cmd') or args['cmd'][0] == 'changelog': |
538 | 626 c = self.repo.changelog.count() - 1 |
627 hi = c | |
153
e8a360cd5a9f
changed pos to rev for changelog cmd, changed & to ;
jake@edge2.net
parents:
142
diff
changeset
|
628 if args.has_key('rev'): |
165 | 629 hi = args['rev'][0] |
166
39624c47060f
hgweb: don't blow up on search for unknown keys
mpm@selenic.com
parents:
165
diff
changeset
|
630 try: |
39624c47060f
hgweb: don't blow up on search for unknown keys
mpm@selenic.com
parents:
165
diff
changeset
|
631 hi = self.repo.changelog.rev(self.repo.lookup(hi)) |
688 | 632 except RepoError: |
538 | 633 write(self.search(hi)) |
634 return | |
575 | 635 |
138 | 636 write(self.changelog(hi)) |
515 | 637 |
138 | 638 elif args['cmd'][0] == 'changeset': |
639 write(self.changeset(args['node'][0])) | |
640 | |
641 elif args['cmd'][0] == 'manifest': | |
642 write(self.manifest(args['manifest'][0], args['path'][0])) | |
643 | |
168 | 644 elif args['cmd'][0] == 'tags': |
645 write(self.tags()) | |
646 | |
138 | 647 elif args['cmd'][0] == 'filediff': |
648 write(self.filediff(args['file'][0], args['node'][0])) | |
131 | 649 |
132 | 650 elif args['cmd'][0] == 'file': |
138 | 651 write(self.filerevision(args['file'][0], args['filenode'][0])) |
131 | 652 |
138 | 653 elif args['cmd'][0] == 'annotate': |
654 write(self.fileannotate(args['file'][0], args['filenode'][0])) | |
131 | 655 |
138 | 656 elif args['cmd'][0] == 'filelog': |
657 write(self.filelog(args['file'][0], args['filenode'][0])) | |
136 | 658 |
222 | 659 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
|
660 httphdr("application/mercurial-0.1") |
222 | 661 h = self.repo.heads() |
662 sys.stdout.write(" ".join(map(hex, h)) + "\n") | |
663 | |
132 | 664 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
|
665 httphdr("application/mercurial-0.1") |
132 | 666 nodes = [] |
667 if args.has_key('nodes'): | |
138 | 668 nodes = map(bin, args['nodes'][0].split(" ")) |
669 for b in self.repo.branches(nodes): | |
670 sys.stdout.write(" ".join(map(hex, b)) + "\n") | |
131 | 671 |
132 | 672 elif args['cmd'][0] == 'between': |
753 | 673 httphdr("application/mercurial-0.1") |
132 | 674 nodes = [] |
675 if args.has_key('pairs'): | |
138 | 676 pairs = [ map(bin, p.split("-")) |
132 | 677 for p in args['pairs'][0].split(" ") ] |
138 | 678 for b in self.repo.between(pairs): |
679 sys.stdout.write(" ".join(map(hex, b)) + "\n") | |
132 | 680 |
681 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
|
682 httphdr("application/mercurial-0.1") |
132 | 683 nodes = [] |
197 | 684 if self.viewonly: |
685 return | |
686 | |
132 | 687 if args.has_key('roots'): |
138 | 688 nodes = map(bin, args['roots'][0].split(" ")) |
131 | 689 |
132 | 690 z = zlib.compressobj() |
635
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
620
diff
changeset
|
691 f = self.repo.changegroup(nodes) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
620
diff
changeset
|
692 while 1: |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
620
diff
changeset
|
693 chunk = f.read(4096) |
85e2209d401c
Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents:
620
diff
changeset
|
694 if not chunk: break |
132 | 695 sys.stdout.write(z.compress(chunk)) |
696 | |
697 sys.stdout.write(z.flush()) | |
131 | 698 |
132 | 699 else: |
138 | 700 write(self.t("error")) |
131 | 701 |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
702 def create_server(path, name, templates, address, port, |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
703 accesslog = sys.stdout, errorlog = sys.stderr): |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
704 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
705 import BaseHTTPServer |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
706 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
707 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
|
708 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
|
709 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
|
710 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
|
711 format % args)) |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
712 |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
713 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
|
714 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
|
715 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
|
716 format % args)) |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
717 |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
718 def do_POST(self): |
271 | 719 try: |
720 self.do_hgweb() | |
721 except socket.error, inst: | |
722 if inst.args[0] != 32: raise | |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
723 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
724 def do_GET(self): |
271 | 725 self.do_POST() |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
726 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
727 def do_hgweb(self): |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
728 query = "" |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
729 p = self.path.find("?") |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
730 if p: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
731 query = self.path[p + 1:] |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
732 query = query.replace('+', ' ') |
515 | 733 |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
734 env = {} |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
735 env['GATEWAY_INTERFACE'] = 'CGI/1.1' |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
736 env['REQUEST_METHOD'] = self.command |
599 | 737 env['SERVER_NAME'] = self.server.server_name |
738 env['SERVER_PORT'] = str(self.server.server_port) | |
739 env['REQUEST_URI'] = "/" | |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
740 if query: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
741 env['QUERY_STRING'] = query |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
742 host = self.address_string() |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
743 if host != self.client_address[0]: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
744 env['REMOTE_HOST'] = host |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
745 env['REMOTE_ADDR'] = self.client_address[0] |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
746 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
747 if self.headers.typeheader is None: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
748 env['CONTENT_TYPE'] = self.headers.type |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
749 else: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
750 env['CONTENT_TYPE'] = self.headers.typeheader |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
751 length = self.headers.getheader('content-length') |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
752 if length: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
753 env['CONTENT_LENGTH'] = length |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
754 accept = [] |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
755 for line in self.headers.getallmatchingheaders('accept'): |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
756 if line[:1] in "\t\n\r ": |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
757 accept.append(line.strip()) |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
758 else: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
759 accept = accept + line[7:].split(',') |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
760 env['HTTP_ACCEPT'] = ','.join(accept) |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
761 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
762 os.environ.update(env) |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
763 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
764 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
|
765 try: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
766 sys.stdin = self.rfile |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
767 sys.stdout = self.wfile |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
768 sys.argv = ["hgweb.py"] |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
769 if '=' not in query: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
770 sys.argv.append(query) |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
771 self.send_response(200, "Script output follows") |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
772 hg.run() |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
773 finally: |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
774 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
|
775 |
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
776 hg = hgweb(path, name, templates) |
603
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
601
diff
changeset
|
777 return BaseHTTPServer.HTTPServer((address, port), hgwebhandler) |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
601
diff
changeset
|
778 |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
779 def server(path, name, templates, address, port, |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
780 accesslog = sys.stdout, errorlog = sys.stderr): |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
781 httpd = create_server(path, name, templates, address, port, |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
603
diff
changeset
|
782 accesslog, errorlog) |
158
be7103467d2e
Add 'hg serve' command for stand-alone server
mpm@selenic.com
parents:
157
diff
changeset
|
783 httpd.serve_forever() |