Mercurial > hg
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 |