##// END OF EJS Templates
hgweb: use string join instead of slower cStringIO
Sune Foldager -
r10531:e3eff765 stable
parent child Browse files
Show More
@@ -1,207 +1,204 b''
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 resp = cStringIO.StringIO()
68 for b in repo.between(pairs):
69 resp.write(" ".join(map(hex, b)) + "\n")
70 resp = resp.getvalue()
67 resp = ''.join(" ".join(map(hex, b)) + "\n" for b in repo.between(pairs))
71 68 req.respond(HTTP_OK, HGTYPE, length=len(resp))
72 69 yield resp
73 70
74 71 def changegroup(repo, req):
75 72 req.respond(HTTP_OK, HGTYPE)
76 73 nodes = []
77 74
78 75 if 'roots' in req.form:
79 76 nodes = map(bin, req.form['roots'][0].split(" "))
80 77
81 78 z = zlib.compressobj()
82 79 f = repo.changegroup(nodes, 'serve')
83 80 while 1:
84 81 chunk = f.read(4096)
85 82 if not chunk:
86 83 break
87 84 yield z.compress(chunk)
88 85
89 86 yield z.flush()
90 87
91 88 def changegroupsubset(repo, req):
92 89 req.respond(HTTP_OK, HGTYPE)
93 90 bases = []
94 91 heads = []
95 92
96 93 if 'bases' in req.form:
97 94 bases = [bin(x) for x in req.form['bases'][0].split(' ')]
98 95 if 'heads' in req.form:
99 96 heads = [bin(x) for x in req.form['heads'][0].split(' ')]
100 97
101 98 z = zlib.compressobj()
102 99 f = repo.changegroupsubset(bases, heads, 'serve')
103 100 while 1:
104 101 chunk = f.read(4096)
105 102 if not chunk:
106 103 break
107 104 yield z.compress(chunk)
108 105
109 106 yield z.flush()
110 107
111 108 def capabilities(repo, req):
112 109 caps = copy.copy(basecaps)
113 110 if streamclone.allowed(repo.ui):
114 111 caps.append('stream=%d' % repo.changelog.version)
115 112 if changegroupmod.bundlepriority:
116 113 caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
117 114 rsp = ' '.join(caps)
118 115 req.respond(HTTP_OK, HGTYPE, length=len(rsp))
119 116 yield rsp
120 117
121 118 def unbundle(repo, req):
122 119
123 120 proto = req.env.get('wsgi.url_scheme') or 'http'
124 121 their_heads = req.form['heads'][0].split(' ')
125 122
126 123 def check_heads():
127 124 heads = map(hex, repo.heads())
128 125 return their_heads == [hex('force')] or their_heads == heads
129 126
130 127 # fail early if possible
131 128 if not check_heads():
132 129 req.drain()
133 130 raise ErrorResponse(HTTP_OK, 'unsynced changes')
134 131
135 132 # do not lock repo until all changegroup data is
136 133 # streamed. save to temporary file.
137 134
138 135 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
139 136 fp = os.fdopen(fd, 'wb+')
140 137 try:
141 138 length = int(req.env['CONTENT_LENGTH'])
142 139 for s in util.filechunkiter(req, limit=length):
143 140 fp.write(s)
144 141
145 142 try:
146 143 lock = repo.lock()
147 144 try:
148 145 if not check_heads():
149 146 raise ErrorResponse(HTTP_OK, 'unsynced changes')
150 147
151 148 fp.seek(0)
152 149 header = fp.read(6)
153 150 if header.startswith('HG') and not header.startswith('HG10'):
154 151 raise ValueError('unknown bundle version')
155 152 elif header not in changegroupmod.bundletypes:
156 153 raise ValueError('unknown bundle compression type')
157 154 gen = changegroupmod.unbundle(header, fp)
158 155
159 156 # send addchangegroup output to client
160 157
161 158 oldio = sys.stdout, sys.stderr
162 159 sys.stderr = sys.stdout = cStringIO.StringIO()
163 160
164 161 try:
165 162 url = 'remote:%s:%s:%s' % (
166 163 proto,
167 164 urllib.quote(req.env.get('REMOTE_HOST', '')),
168 165 urllib.quote(req.env.get('REMOTE_USER', '')))
169 166 try:
170 167 ret = repo.addchangegroup(gen, 'serve', url)
171 168 except util.Abort, inst:
172 169 sys.stdout.write("abort: %s\n" % inst)
173 170 ret = 0
174 171 finally:
175 172 val = sys.stdout.getvalue()
176 173 sys.stdout, sys.stderr = oldio
177 174 req.respond(HTTP_OK, HGTYPE)
178 175 return '%d\n%s' % (ret, val),
179 176 finally:
180 177 lock.release()
181 178 except ValueError, inst:
182 179 raise ErrorResponse(HTTP_OK, inst)
183 180 except (OSError, IOError), inst:
184 181 error = getattr(inst, 'strerror', 'Unknown error')
185 182 if inst.errno == errno.ENOENT:
186 183 code = HTTP_NOT_FOUND
187 184 else:
188 185 code = HTTP_SERVER_ERROR
189 186 filename = getattr(inst, 'filename', '')
190 187 # Don't send our filesystem layout to the client
191 188 if filename and filename.startswith(repo.root):
192 189 filename = filename[len(repo.root)+1:]
193 190 text = '%s: %s' % (error, filename)
194 191 else:
195 192 text = error.replace(repo.root + os.path.sep, '')
196 193 raise ErrorResponse(code, text)
197 194 finally:
198 195 fp.close()
199 196 os.unlink(tempname)
200 197
201 198 def stream_out(repo, req):
202 199 req.respond(HTTP_OK, HGTYPE)
203 200 try:
204 201 for chunk in streamclone.stream_out(repo):
205 202 yield chunk
206 203 except streamclone.StreamException, inst:
207 204 yield str(inst)
General Comments 0
You need to be logged in to leave comments. Login now