comparison hgext/lfs/wireprotolfsserver.py @ 41425:6d7f18cd81d9

py3: raw stringify various things in the LFS server module Some of this is based on code written by Augie. I'm slightly unsure if these are the correct pycompat bytes <-> str conversion methods.
author Matt Harbison <matt_harbison@yahoo.com>
date Sun, 27 Jan 2019 00:50:39 -0500
parents 7a11e4e55d5f
children 2372284d9457
comparison
equal deleted inserted replaced
41424:7a11e4e55d5f 41425:6d7f18cd81d9
131 131
132 # XXX: specify an encoding? 132 # XXX: specify an encoding?
133 lfsreq = json.loads(req.bodyfh.read()) 133 lfsreq = json.loads(req.bodyfh.read())
134 134
135 # If no transfer handlers are explicitly requested, 'basic' is assumed. 135 # If no transfer handlers are explicitly requested, 'basic' is assumed.
136 if 'basic' not in lfsreq.get('transfers', ['basic']): 136 if r'basic' not in lfsreq.get(r'transfers', [r'basic']):
137 _sethttperror(res, HTTP_BAD_REQUEST, 137 _sethttperror(res, HTTP_BAD_REQUEST,
138 b'Only the basic LFS transfer handler is supported') 138 b'Only the basic LFS transfer handler is supported')
139 return True 139 return True
140 140
141 operation = lfsreq.get('operation') 141 operation = lfsreq.get(r'operation')
142 if operation not in ('upload', 'download'): 142 operation = pycompat.bytestr(operation)
143
144 if operation not in (b'upload', b'download'):
143 _sethttperror(res, HTTP_BAD_REQUEST, 145 _sethttperror(res, HTTP_BAD_REQUEST,
144 b'Unsupported LFS transfer operation: %s' % operation) 146 b'Unsupported LFS transfer operation: %s' % operation)
145 return True 147 return True
146 148
147 localstore = repo.svfs.lfslocalblobstore 149 localstore = repo.svfs.lfslocalblobstore
148 150
149 objects = [p for p in _batchresponseobjects(req, lfsreq.get('objects', []), 151 objects = [p for p in _batchresponseobjects(req, lfsreq.get(r'objects', []),
150 operation, localstore)] 152 operation, localstore)]
151 153
152 rsp = { 154 rsp = {
153 'transfer': 'basic', 155 r'transfer': r'basic',
154 'objects': objects, 156 r'objects': objects,
155 } 157 }
156 158
157 res.status = hgwebcommon.statusmessage(HTTP_OK) 159 res.status = hgwebcommon.statusmessage(HTTP_OK)
158 res.headers[b'Content-Type'] = b'application/vnd.git-lfs+json' 160 res.headers[b'Content-Type'] = b'application/vnd.git-lfs+json'
159 res.setbodybytes(pycompat.bytestr(json.dumps(rsp))) 161 res.setbodybytes(pycompat.bytestr(json.dumps(rsp)))
188 190
189 # TODO: Sort out the expires_at/expires_in/authenticated keys. 191 # TODO: Sort out the expires_at/expires_in/authenticated keys.
190 192
191 for obj in objects: 193 for obj in objects:
192 # Convert unicode to ASCII to create a filesystem path 194 # Convert unicode to ASCII to create a filesystem path
193 oid = obj.get('oid').encode('ascii') 195 soid = obj.get(r'oid')
196 oid = soid.encode(r'ascii')
194 rsp = { 197 rsp = {
195 'oid': oid, 198 r'oid': soid,
196 'size': obj.get('size'), # XXX: should this check the local size? 199 r'size': obj.get(r'size'), # XXX: should this check the local size?
197 #'authenticated': True, 200 #r'authenticated': True,
198 } 201 }
199 202
200 exists = True 203 exists = True
201 verifies = False 204 verifies = False
202 205
215 store.linkfromusercache(oid) 218 store.linkfromusercache(oid)
216 except IOError as inst: 219 except IOError as inst:
217 if inst.errno != errno.ENOENT: 220 if inst.errno != errno.ENOENT:
218 _logexception(req) 221 _logexception(req)
219 222
220 rsp['error'] = { 223 rsp[r'error'] = {
221 'code': 500, 224 r'code': 500,
222 'message': inst.strerror or 'Internal Server Server' 225 r'message': inst.strerror or r'Internal Server Server'
223 } 226 }
224 yield rsp 227 yield rsp
225 continue 228 continue
226 229
227 exists = False 230 exists = False
228 231
229 # Items are always listed for downloads. They are dropped for uploads 232 # Items are always listed for downloads. They are dropped for uploads
230 # IFF they already exist locally. 233 # IFF they already exist locally.
231 if action == b'download': 234 if action == b'download':
232 if not exists: 235 if not exists:
233 rsp['error'] = { 236 rsp[r'error'] = {
234 'code': 404, 237 r'code': 404,
235 'message': "The object does not exist" 238 r'message': r"The object does not exist"
236 } 239 }
237 yield rsp 240 yield rsp
238 continue 241 continue
239 242
240 elif not verifies: 243 elif not verifies:
241 rsp['error'] = { 244 rsp[r'error'] = {
242 'code': 422, # XXX: is this the right code? 245 r'code': 422, # XXX: is this the right code?
243 'message': "The object is corrupt" 246 r'message': r"The object is corrupt"
244 } 247 }
245 yield rsp 248 yield rsp
246 continue 249 continue
247 250
248 elif verifies: 251 elif verifies:
254 def _buildheader(): 257 def _buildheader():
255 # The spec doesn't mention the Accept header here, but avoid 258 # The spec doesn't mention the Accept header here, but avoid
256 # a gratuitous deviation from lfs-test-server in the test 259 # a gratuitous deviation from lfs-test-server in the test
257 # output. 260 # output.
258 hdr = { 261 hdr = {
259 'Accept': 'application/vnd.git-lfs' 262 r'Accept': r'application/vnd.git-lfs'
260 } 263 }
261 264
262 auth = req.headers.get(b'Authorization', b'') 265 auth = req.headers.get(b'Authorization', b'')
263 if auth.startswith(b'Basic '): 266 if auth.startswith(b'Basic '):
264 hdr['Authorization'] = auth 267 hdr[r'Authorization'] = pycompat.strurl(auth)
265 268
266 return hdr 269 return hdr
267 270
268 rsp['actions'] = { 271 rsp[r'actions'] = {
269 '%s' % action: { 272 r'%s' % pycompat.strurl(action): {
270 'href': '%s%s/.hg/lfs/objects/%s' 273 r'href': pycompat.strurl(b'%s%s/.hg/lfs/objects/%s'
271 % (req.baseurl, req.apppath, oid), 274 % (req.baseurl, req.apppath, oid)),
272 # datetime.isoformat() doesn't include the 'Z' suffix 275 # datetime.isoformat() doesn't include the 'Z' suffix
273 "expires_at": expiresat.strftime('%Y-%m-%dT%H:%M:%SZ'), 276 r"expires_at": expiresat.strftime(r'%Y-%m-%dT%H:%M:%SZ'),
274 'header': _buildheader(), 277 r'header': _buildheader(),
275 } 278 }
276 } 279 }
277 280
278 yield rsp 281 yield rsp
279 282