##// END OF EJS Templates
hgweb: fix attribute error in error response (issue2060)
Mark Determann -
r10951:5dc09507 stable
parent child Browse files
Show More
@@ -1,204 +1,206
1 1 #
2 2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 import cStringIO, zlib, tempfile, errno, os, sys, urllib, copy
9 9 from mercurial import util, streamclone
10 10 from mercurial.node import bin, hex
11 11 from mercurial import changegroup as changegroupmod
12 12 from common import ErrorResponse, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
13 13
14 14 # __all__ is populated with the allowed commands. Be sure to add to it if
15 15 # you're adding a new command, or the new command won't work.
16 16
17 17 __all__ = [
18 18 'lookup', 'heads', 'branches', 'between', 'changegroup',
19 19 'changegroupsubset', 'capabilities', 'unbundle', 'stream_out',
20 20 'branchmap',
21 21 ]
22 22
23 23 HGTYPE = 'application/mercurial-0.1'
24 24 basecaps = 'lookup changegroupsubset branchmap'.split()
25 25
26 26 def lookup(repo, req):
27 27 try:
28 28 r = hex(repo.lookup(req.form['key'][0]))
29 29 success = 1
30 30 except Exception, inst:
31 31 r = str(inst)
32 32 success = 0
33 33 resp = "%s %s\n" % (success, r)
34 34 req.respond(HTTP_OK, HGTYPE, length=len(resp))
35 35 yield resp
36 36
37 37 def heads(repo, req):
38 38 resp = " ".join(map(hex, repo.heads())) + "\n"
39 39 req.respond(HTTP_OK, HGTYPE, length=len(resp))
40 40 yield resp
41 41
42 42 def branchmap(repo, req):
43 43 branches = repo.branchmap()
44 44 heads = []
45 45 for branch, nodes in branches.iteritems():
46 46 branchname = urllib.quote(branch)
47 47 branchnodes = [hex(node) for node in nodes]
48 48 heads.append('%s %s' % (branchname, ' '.join(branchnodes)))
49 49 resp = '\n'.join(heads)
50 50 req.respond(HTTP_OK, HGTYPE, length=len(resp))
51 51 yield resp
52 52
53 53 def branches(repo, req):
54 54 nodes = []
55 55 if 'nodes' in req.form:
56 56 nodes = map(bin, req.form['nodes'][0].split(" "))
57 57 resp = cStringIO.StringIO()
58 58 for b in repo.branches(nodes):
59 59 resp.write(" ".join(map(hex, b)) + "\n")
60 60 resp = resp.getvalue()
61 61 req.respond(HTTP_OK, HGTYPE, length=len(resp))
62 62 yield resp
63 63
64 64 def between(repo, req):
65 65 pairs = [map(bin, p.split("-"))
66 66 for p in req.form['pairs'][0].split(" ")]
67 67 resp = ''.join(" ".join(map(hex, b)) + "\n" for b in repo.between(pairs))
68 68 req.respond(HTTP_OK, HGTYPE, length=len(resp))
69 69 yield resp
70 70
71 71 def changegroup(repo, req):
72 72 req.respond(HTTP_OK, HGTYPE)
73 73 nodes = []
74 74
75 75 if 'roots' in req.form:
76 76 nodes = map(bin, req.form['roots'][0].split(" "))
77 77
78 78 z = zlib.compressobj()
79 79 f = repo.changegroup(nodes, 'serve')
80 80 while 1:
81 81 chunk = f.read(4096)
82 82 if not chunk:
83 83 break
84 84 yield z.compress(chunk)
85 85
86 86 yield z.flush()
87 87
88 88 def changegroupsubset(repo, req):
89 89 req.respond(HTTP_OK, HGTYPE)
90 90 bases = []
91 91 heads = []
92 92
93 93 if 'bases' in req.form:
94 94 bases = [bin(x) for x in req.form['bases'][0].split(' ')]
95 95 if 'heads' in req.form:
96 96 heads = [bin(x) for x in req.form['heads'][0].split(' ')]
97 97
98 98 z = zlib.compressobj()
99 99 f = repo.changegroupsubset(bases, heads, 'serve')
100 100 while 1:
101 101 chunk = f.read(4096)
102 102 if not chunk:
103 103 break
104 104 yield z.compress(chunk)
105 105
106 106 yield z.flush()
107 107
108 108 def capabilities(repo, req):
109 109 caps = copy.copy(basecaps)
110 110 if streamclone.allowed(repo.ui):
111 111 caps.append('stream=%d' % repo.changelog.version)
112 112 if changegroupmod.bundlepriority:
113 113 caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
114 114 rsp = ' '.join(caps)
115 115 req.respond(HTTP_OK, HGTYPE, length=len(rsp))
116 116 yield rsp
117 117
118 118 def unbundle(repo, req):
119 119
120 120 proto = req.env.get('wsgi.url_scheme') or 'http'
121 121 their_heads = req.form['heads'][0].split(' ')
122 122
123 123 def check_heads():
124 124 heads = map(hex, repo.heads())
125 125 return their_heads == [hex('force')] or their_heads == heads
126 126
127 127 # fail early if possible
128 128 if not check_heads():
129 129 req.drain()
130 130 raise ErrorResponse(HTTP_OK, 'unsynced changes')
131 131
132 132 # do not lock repo until all changegroup data is
133 133 # streamed. save to temporary file.
134 134
135 135 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
136 136 fp = os.fdopen(fd, 'wb+')
137 137 try:
138 138 length = int(req.env['CONTENT_LENGTH'])
139 139 for s in util.filechunkiter(req, limit=length):
140 140 fp.write(s)
141 141
142 142 try:
143 143 lock = repo.lock()
144 144 try:
145 145 if not check_heads():
146 146 raise ErrorResponse(HTTP_OK, 'unsynced changes')
147 147
148 148 fp.seek(0)
149 149 header = fp.read(6)
150 150 if header.startswith('HG') and not header.startswith('HG10'):
151 151 raise ValueError('unknown bundle version')
152 152 elif header not in changegroupmod.bundletypes:
153 153 raise ValueError('unknown bundle compression type')
154 154 gen = changegroupmod.unbundle(header, fp)
155 155
156 156 # send addchangegroup output to client
157 157
158 158 oldio = sys.stdout, sys.stderr
159 159 sys.stderr = sys.stdout = cStringIO.StringIO()
160 160
161 161 try:
162 162 url = 'remote:%s:%s:%s' % (
163 163 proto,
164 164 urllib.quote(req.env.get('REMOTE_HOST', '')),
165 165 urllib.quote(req.env.get('REMOTE_USER', '')))
166 166 try:
167 167 ret = repo.addchangegroup(gen, 'serve', url)
168 168 except util.Abort, inst:
169 169 sys.stdout.write("abort: %s\n" % inst)
170 170 ret = 0
171 171 finally:
172 172 val = sys.stdout.getvalue()
173 173 sys.stdout, sys.stderr = oldio
174 174 req.respond(HTTP_OK, HGTYPE)
175 175 return '%d\n%s' % (ret, val),
176 176 finally:
177 177 lock.release()
178 178 except ValueError, inst:
179 179 raise ErrorResponse(HTTP_OK, inst)
180 180 except (OSError, IOError), inst:
181 181 error = getattr(inst, 'strerror', 'Unknown error')
182 if not isinstance(error, str):
183 error = 'Error: %s' % str(error)
182 184 if inst.errno == errno.ENOENT:
183 185 code = HTTP_NOT_FOUND
184 186 else:
185 187 code = HTTP_SERVER_ERROR
186 188 filename = getattr(inst, 'filename', '')
187 189 # Don't send our filesystem layout to the client
188 190 if filename and filename.startswith(repo.root):
189 191 filename = filename[len(repo.root)+1:]
190 192 text = '%s: %s' % (error, filename)
191 193 else:
192 194 text = error.replace(repo.root + os.path.sep, '')
193 195 raise ErrorResponse(code, text)
194 196 finally:
195 197 fp.close()
196 198 os.unlink(tempname)
197 199
198 200 def stream_out(repo, req):
199 201 req.respond(HTTP_OK, HGTYPE)
200 202 try:
201 203 for chunk in streamclone.stream_out(repo):
202 204 yield chunk
203 205 except streamclone.StreamException, inst:
204 206 yield str(inst)
General Comments 0
You need to be logged in to leave comments. Login now