41 request if it is left unprocessed by the wrapped method. |
41 request if it is left unprocessed by the wrapped method. |
42 """ |
42 """ |
43 if orig(rctx, req, res, checkperm): |
43 if orig(rctx, req, res, checkperm): |
44 return True |
44 return True |
45 |
45 |
46 if not rctx.repo.ui.configbool('experimental', 'lfs.serve'): |
46 if not rctx.repo.ui.configbool(b'experimental', b'lfs.serve'): |
47 return False |
47 return False |
48 |
48 |
49 if not util.safehasattr(rctx.repo.svfs, 'lfslocalblobstore'): |
49 if not util.safehasattr(rctx.repo.svfs, 'lfslocalblobstore'): |
50 return False |
50 return False |
51 |
51 |
52 if not req.dispatchpath: |
52 if not req.dispatchpath: |
53 return False |
53 return False |
54 |
54 |
55 try: |
55 try: |
56 if req.dispatchpath == b'.git/info/lfs/objects/batch': |
56 if req.dispatchpath == b'.git/info/lfs/objects/batch': |
57 checkperm(rctx, req, 'pull') |
57 checkperm(rctx, req, b'pull') |
58 return _processbatchrequest(rctx.repo, req, res) |
58 return _processbatchrequest(rctx.repo, req, res) |
59 # TODO: reserve and use a path in the proposed http wireprotocol /api/ |
59 # TODO: reserve and use a path in the proposed http wireprotocol /api/ |
60 # namespace? |
60 # namespace? |
61 elif req.dispatchpath.startswith(b'.hg/lfs/objects'): |
61 elif req.dispatchpath.startswith(b'.hg/lfs/objects'): |
62 return _processbasictransfer(rctx.repo, req, res, |
62 return _processbasictransfer(rctx.repo, req, res, |
79 res.setbodybytes(b'') |
79 res.setbodybytes(b'') |
80 |
80 |
81 def _logexception(req): |
81 def _logexception(req): |
82 """Write information about the current exception to wsgi.errors.""" |
82 """Write information about the current exception to wsgi.errors.""" |
83 tb = pycompat.sysbytes(traceback.format_exc()) |
83 tb = pycompat.sysbytes(traceback.format_exc()) |
84 errorlog = req.rawenv[r'wsgi.errors'] |
84 errorlog = req.rawenv[b'wsgi.errors'] |
85 |
85 |
86 uri = b'' |
86 uri = b'' |
87 if req.apppath: |
87 if req.apppath: |
88 uri += req.apppath |
88 uri += req.apppath |
89 uri += b'/' + req.dispatchpath |
89 uri += b'/' + req.dispatchpath |
207 # IFF the client can assert that the remote end is an hg server.) |
207 # IFF the client can assert that the remote end is an hg server.) |
208 # Otherwise, it's potentially overkill on download, since it is also |
208 # Otherwise, it's potentially overkill on download, since it is also |
209 # verified as the file is streamed to the caller. |
209 # verified as the file is streamed to the caller. |
210 try: |
210 try: |
211 verifies = store.verify(oid) |
211 verifies = store.verify(oid) |
212 if verifies and action == 'upload': |
212 if verifies and action == b'upload': |
213 # The client will skip this upload, but make sure it remains |
213 # The client will skip this upload, but make sure it remains |
214 # available locally. |
214 # available locally. |
215 store.linkfromusercache(oid) |
215 store.linkfromusercache(oid) |
216 except IOError as inst: |
216 except IOError as inst: |
217 if inst.errno != errno.ENOENT: |
217 if inst.errno != errno.ENOENT: |
322 res.headers[b'Content-Type'] = b'text/plain; charset=utf-8' |
322 res.headers[b'Content-Type'] = b'text/plain; charset=utf-8' |
323 res.setbodybytes(b'') |
323 res.setbodybytes(b'') |
324 |
324 |
325 return True |
325 return True |
326 elif method == b'GET': |
326 elif method == b'GET': |
327 checkperm('pull') |
327 checkperm(b'pull') |
328 |
328 |
329 res.status = hgwebcommon.statusmessage(HTTP_OK) |
329 res.status = hgwebcommon.statusmessage(HTTP_OK) |
330 res.headers[b'Content-Type'] = b'application/octet-stream' |
330 res.headers[b'Content-Type'] = b'application/octet-stream' |
331 |
331 |
332 try: |
332 try: |