hgext/lfs/wireprotolfsserver.py
changeset 41446 7a11e4e55d5f
parent 41051 84d61fdcefa5
child 41447 6d7f18cd81d9
equal deleted inserted replaced
41445:2a1bb442593b 41446:7a11e4e55d5f
    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:
   226 
   226 
   227             exists = False
   227             exists = False
   228 
   228 
   229         # Items are always listed for downloads.  They are dropped for uploads
   229         # Items are always listed for downloads.  They are dropped for uploads
   230         # IFF they already exist locally.
   230         # IFF they already exist locally.
   231         if action == 'download':
   231         if action == b'download':
   232             if not exists:
   232             if not exists:
   233                 rsp['error'] = {
   233                 rsp['error'] = {
   234                     'code': 404,
   234                     'code': 404,
   235                     'message': "The object does not exist"
   235                     'message': "The object does not exist"
   236                 }
   236                 }
   257             # output.
   257             # output.
   258             hdr = {
   258             hdr = {
   259                 'Accept': 'application/vnd.git-lfs'
   259                 'Accept': 'application/vnd.git-lfs'
   260             }
   260             }
   261 
   261 
   262             auth = req.headers.get('Authorization', '')
   262             auth = req.headers.get(b'Authorization', b'')
   263             if auth.startswith('Basic '):
   263             if auth.startswith(b'Basic '):
   264                 hdr['Authorization'] = auth
   264                 hdr['Authorization'] = auth
   265 
   265 
   266             return hdr
   266             return hdr
   267 
   267 
   268         rsp['actions'] = {
   268         rsp['actions'] = {
   295     if len(req.dispatchparts) != 4:
   295     if len(req.dispatchparts) != 4:
   296         _sethttperror(res, HTTP_NOT_FOUND)
   296         _sethttperror(res, HTTP_NOT_FOUND)
   297         return True
   297         return True
   298 
   298 
   299     if method == b'PUT':
   299     if method == b'PUT':
   300         checkperm('upload')
   300         checkperm(b'upload')
   301 
   301 
   302         # TODO: verify Content-Type?
   302         # TODO: verify Content-Type?
   303 
   303 
   304         existed = localstore.has(oid)
   304         existed = localstore.has(oid)
   305 
   305 
   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: