comparison mercurial/hgweb/protocol.py @ 6781:b4b7261164d5

hgweb: protocol functions take repo instead of web This makes it much easier for implementers of hgweb alternatives to simply call into protocol functions after setting up a repo and a request.
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Sun, 29 Jun 2008 11:34:36 +0200
parents 4c1d67e0fa8c
children b9d6ab187523
comparison
equal deleted inserted replaced
6780:4c1d67e0fa8c 6781:b4b7261164d5
19 'changegroupsubset', 'capabilities', 'unbundle', 'stream_out', 19 'changegroupsubset', 'capabilities', 'unbundle', 'stream_out',
20 ] 20 ]
21 21
22 HGTYPE = 'application/mercurial-0.1' 22 HGTYPE = 'application/mercurial-0.1'
23 23
24 def lookup(web, req): 24 def lookup(repo, req):
25 try: 25 try:
26 r = hex(web.repo.lookup(req.form['key'][0])) 26 r = hex(repo.lookup(req.form['key'][0]))
27 success = 1 27 success = 1
28 except Exception,inst: 28 except Exception,inst:
29 r = str(inst) 29 r = str(inst)
30 success = 0 30 success = 0
31 resp = "%s %s\n" % (success, r) 31 resp = "%s %s\n" % (success, r)
32 req.respond(HTTP_OK, HGTYPE, length=len(resp)) 32 req.respond(HTTP_OK, HGTYPE, length=len(resp))
33 req.write(resp) 33 req.write(resp)
34 34
35 def heads(web, req): 35 def heads(repo, req):
36 resp = " ".join(map(hex, web.repo.heads())) + "\n" 36 resp = " ".join(map(hex, repo.heads())) + "\n"
37 req.respond(HTTP_OK, HGTYPE, length=len(resp)) 37 req.respond(HTTP_OK, HGTYPE, length=len(resp))
38 req.write(resp) 38 req.write(resp)
39 39
40 def branches(web, req): 40 def branches(repo, req):
41 nodes = [] 41 nodes = []
42 if 'nodes' in req.form: 42 if 'nodes' in req.form:
43 nodes = map(bin, req.form['nodes'][0].split(" ")) 43 nodes = map(bin, req.form['nodes'][0].split(" "))
44 resp = cStringIO.StringIO() 44 resp = cStringIO.StringIO()
45 for b in web.repo.branches(nodes): 45 for b in repo.branches(nodes):
46 resp.write(" ".join(map(hex, b)) + "\n") 46 resp.write(" ".join(map(hex, b)) + "\n")
47 resp = resp.getvalue() 47 resp = resp.getvalue()
48 req.respond(HTTP_OK, HGTYPE, length=len(resp)) 48 req.respond(HTTP_OK, HGTYPE, length=len(resp))
49 req.write(resp) 49 req.write(resp)
50 50
51 def between(web, req): 51 def between(repo, req):
52 if 'pairs' in req.form: 52 if 'pairs' in req.form:
53 pairs = [map(bin, p.split("-")) 53 pairs = [map(bin, p.split("-"))
54 for p in req.form['pairs'][0].split(" ")] 54 for p in req.form['pairs'][0].split(" ")]
55 resp = cStringIO.StringIO() 55 resp = cStringIO.StringIO()
56 for b in web.repo.between(pairs): 56 for b in repo.between(pairs):
57 resp.write(" ".join(map(hex, b)) + "\n") 57 resp.write(" ".join(map(hex, b)) + "\n")
58 resp = resp.getvalue() 58 resp = resp.getvalue()
59 req.respond(HTTP_OK, HGTYPE, length=len(resp)) 59 req.respond(HTTP_OK, HGTYPE, length=len(resp))
60 req.write(resp) 60 req.write(resp)
61 61
62 def changegroup(web, req): 62 def changegroup(repo, req):
63 req.respond(HTTP_OK, HGTYPE) 63 req.respond(HTTP_OK, HGTYPE)
64 nodes = [] 64 nodes = []
65 65
66 if 'roots' in req.form: 66 if 'roots' in req.form:
67 nodes = map(bin, req.form['roots'][0].split(" ")) 67 nodes = map(bin, req.form['roots'][0].split(" "))
68 68
69 z = zlib.compressobj() 69 z = zlib.compressobj()
70 f = web.repo.changegroup(nodes, 'serve') 70 f = repo.changegroup(nodes, 'serve')
71 while 1: 71 while 1:
72 chunk = f.read(4096) 72 chunk = f.read(4096)
73 if not chunk: 73 if not chunk:
74 break 74 break
75 req.write(z.compress(chunk)) 75 req.write(z.compress(chunk))
76 76
77 req.write(z.flush()) 77 req.write(z.flush())
78 78
79 def changegroupsubset(web, req): 79 def changegroupsubset(repo, req):
80 req.respond(HTTP_OK, HGTYPE) 80 req.respond(HTTP_OK, HGTYPE)
81 bases = [] 81 bases = []
82 heads = [] 82 heads = []
83 83
84 if 'bases' in req.form: 84 if 'bases' in req.form:
85 bases = [bin(x) for x in req.form['bases'][0].split(' ')] 85 bases = [bin(x) for x in req.form['bases'][0].split(' ')]
86 if 'heads' in req.form: 86 if 'heads' in req.form:
87 heads = [bin(x) for x in req.form['heads'][0].split(' ')] 87 heads = [bin(x) for x in req.form['heads'][0].split(' ')]
88 88
89 z = zlib.compressobj() 89 z = zlib.compressobj()
90 f = web.repo.changegroupsubset(bases, heads, 'serve') 90 f = repo.changegroupsubset(bases, heads, 'serve')
91 while 1: 91 while 1:
92 chunk = f.read(4096) 92 chunk = f.read(4096)
93 if not chunk: 93 if not chunk:
94 break 94 break
95 req.write(z.compress(chunk)) 95 req.write(z.compress(chunk))
96 96
97 req.write(z.flush()) 97 req.write(z.flush())
98 98
99 def capabilities(web, req): 99 def capabilities(repo, req):
100 caps = ['lookup', 'changegroupsubset'] 100 caps = ['lookup', 'changegroupsubset']
101 if web.repo.ui.configbool('server', 'uncompressed', untrusted=True): 101 if repo.ui.configbool('server', 'uncompressed', untrusted=True):
102 caps.append('stream=%d' % web.repo.changelog.version) 102 caps.append('stream=%d' % repo.changelog.version)
103 if changegroupmod.bundlepriority: 103 if changegroupmod.bundlepriority:
104 caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority)) 104 caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
105 rsp = ' '.join(caps) 105 rsp = ' '.join(caps)
106 req.respond(HTTP_OK, HGTYPE, length=len(rsp)) 106 req.respond(HTTP_OK, HGTYPE, length=len(rsp))
107 req.write(rsp) 107 req.write(rsp)
108 108
109 def unbundle(web, req): 109 def unbundle(repo, req):
110 110
111 def bail(response, headers={}): 111 def bail(response, headers={}):
112 length = int(req.env.get('CONTENT_LENGTH', 0)) 112 length = int(req.env.get('CONTENT_LENGTH', 0))
113 for s in util.filechunkiter(req, limit=length): 113 for s in util.filechunkiter(req, limit=length):
114 # drain incoming bundle, else client will not see 114 # drain incoming bundle, else client will not see
123 123
124 proto = req.env.get('wsgi.url_scheme') or 'http' 124 proto = req.env.get('wsgi.url_scheme') or 'http'
125 their_heads = req.form['heads'][0].split(' ') 125 their_heads = req.form['heads'][0].split(' ')
126 126
127 def check_heads(): 127 def check_heads():
128 heads = map(hex, web.repo.heads()) 128 heads = map(hex, repo.heads())
129 return their_heads == [hex('force')] or their_heads == heads 129 return their_heads == [hex('force')] or their_heads == heads
130 130
131 # fail early if possible 131 # fail early if possible
132 if not check_heads(): 132 if not check_heads():
133 bail('unsynced changes\n') 133 bail('unsynced changes\n')
144 length = int(req.env['CONTENT_LENGTH']) 144 length = int(req.env['CONTENT_LENGTH'])
145 for s in util.filechunkiter(req, limit=length): 145 for s in util.filechunkiter(req, limit=length):
146 fp.write(s) 146 fp.write(s)
147 147
148 try: 148 try:
149 lock = web.repo.lock() 149 lock = repo.lock()
150 try: 150 try:
151 if not check_heads(): 151 if not check_heads():
152 req.write('0\n') 152 req.write('0\n')
153 req.write('unsynced changes\n') 153 req.write('unsynced changes\n')
154 return 154 return
168 168
169 try: 169 try:
170 url = 'remote:%s:%s' % (proto, 170 url = 'remote:%s:%s' % (proto,
171 req.env.get('REMOTE_HOST', '')) 171 req.env.get('REMOTE_HOST', ''))
172 try: 172 try:
173 ret = web.repo.addchangegroup(gen, 'serve', url) 173 ret = repo.addchangegroup(gen, 'serve', url)
174 except util.Abort, inst: 174 except util.Abort, inst:
175 sys.stdout.write("abort: %s\n" % inst) 175 sys.stdout.write("abort: %s\n" % inst)
176 ret = 0 176 ret = 0
177 finally: 177 finally:
178 val = sys.stdout.getvalue() 178 val = sys.stdout.getvalue()
186 req.write(str(inst) + '\n') 186 req.write(str(inst) + '\n')
187 except (OSError, IOError), inst: 187 except (OSError, IOError), inst:
188 req.write('0\n') 188 req.write('0\n')
189 filename = getattr(inst, 'filename', '') 189 filename = getattr(inst, 'filename', '')
190 # Don't send our filesystem layout to the client 190 # Don't send our filesystem layout to the client
191 if filename.startswith(web.repo.root): 191 if filename.startswith(repo.root):
192 filename = filename[len(web.repo.root)+1:] 192 filename = filename[len(repo.root)+1:]
193 else: 193 else:
194 filename = '' 194 filename = ''
195 error = getattr(inst, 'strerror', 'Unknown error') 195 error = getattr(inst, 'strerror', 'Unknown error')
196 if inst.errno == errno.ENOENT: 196 if inst.errno == errno.ENOENT:
197 code = HTTP_NOT_FOUND 197 code = HTTP_NOT_FOUND
201 req.write('%s: %s\n' % (error, filename)) 201 req.write('%s: %s\n' % (error, filename))
202 finally: 202 finally:
203 fp.close() 203 fp.close()
204 os.unlink(tempname) 204 os.unlink(tempname)
205 205
206 def stream_out(web, req): 206 def stream_out(repo, req):
207 req.respond(HTTP_OK, HGTYPE) 207 req.respond(HTTP_OK, HGTYPE)
208 streamclone.stream_out(web.repo, req, untrusted=True) 208 streamclone.stream_out(repo, req, untrusted=True)