comparison hgext/lfs/blobstore.py @ 37242:67db84842356

lfs: improve the client message when the server signals an object error Two things here. First, the previous message included a snippet of JSON, which tends to be long (and in the case of lfs-test-server, has no error message). Instead, give a concise message where possible, and leave the JSON to a debug output. Second, the server can signal issues other than a missing individual file. This change shows a corrupt file, but I'm debating letting the corrupt file get downloaded, because 1) the error code doesn't really fit, and 2) having it locally makes forensics easier. Maybe need a config knob for that.
author Matt Harbison <matt_harbison@yahoo.com>
date Sun, 25 Feb 2018 23:44:02 -0500
parents b00bd974eef5
children 3e293808e835
comparison
equal deleted inserted replaced
37241:79af9ae46a78 37242:67db84842356
261 for response in responses: 261 for response in responses:
262 # The server should return 404 when objects cannot be found. Some 262 # The server should return 404 when objects cannot be found. Some
263 # server implementation (ex. lfs-test-server) does not set "error" 263 # server implementation (ex. lfs-test-server) does not set "error"
264 # but just removes "download" from "actions". Treat that case 264 # but just removes "download" from "actions". Treat that case
265 # as the same as 404 error. 265 # as the same as 404 error.
266 notfound = (response.get('error', {}).get('code') == 404 266 if 'error' not in response:
267 or (action == 'download' 267 if (action == 'download'
268 and action not in response.get('actions', []))) 268 and action not in response.get('actions', [])):
269 if notfound: 269 code = 404
270 ptrmap = {p.oid(): p for p in pointers}
271 p = ptrmap.get(response['oid'], None)
272 if p:
273 filename = getattr(p, 'filename', 'unknown')
274 raise LfsRemoteError(
275 _(('LFS server error. Remote object '
276 'for "%s" not found: %r')) % (filename, response))
277 else: 270 else:
278 raise LfsRemoteError( 271 continue
279 _('LFS server error. Unsolicited response for oid %s') 272 else:
280 % response['oid']) 273 # An error dict without a code doesn't make much sense, so
281 if 'error' in response: 274 # treat as a server error.
282 raise LfsRemoteError(_('LFS server error: %r') % response) 275 code = response.get('error').get('code', 500)
276
277 ptrmap = {p.oid(): p for p in pointers}
278 p = ptrmap.get(response['oid'], None)
279 if p:
280 filename = getattr(p, 'filename', 'unknown')
281 errors = {
282 404: 'The object does not exist',
283 410: 'The object was removed by the owner',
284 422: 'Validation error',
285 500: 'Internal server error',
286 }
287 msg = errors.get(code, 'status code %d' % code)
288 raise LfsRemoteError(_('LFS server error for "%s": %s')
289 % (filename, msg))
290 else:
291 raise LfsRemoteError(
292 _('LFS server error. Unsolicited response for oid %s')
293 % response['oid'])
283 294
284 def _extractobjects(self, response, pointers, action): 295 def _extractobjects(self, response, pointers, action):
285 """extract objects from response of the batch API 296 """extract objects from response of the batch API
286 297
287 response: parsed JSON object returned by batch API 298 response: parsed JSON object returned by batch API