wireprotolfsserver.py
75 lines
| 2.5 KiB
| text/x-python
|
PythonLexer
Matt Harbison
|
r37165 | # wireprotolfsserver.py - lfs protocol server side implementation | ||
# | ||||
# Copyright 2018 Matt Harbison <matt_harbison@yahoo.com> | ||||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | ||||
from __future__ import absolute_import | ||||
from mercurial.hgweb import ( | ||||
common as hgwebcommon, | ||||
) | ||||
from mercurial import ( | ||||
pycompat, | ||||
) | ||||
def handlewsgirequest(orig, rctx, req, res, checkperm): | ||||
"""Wrap wireprotoserver.handlewsgirequest() to possibly process an LFS | ||||
request if it is left unprocessed by the wrapped method. | ||||
""" | ||||
if orig(rctx, req, res, checkperm): | ||||
return True | ||||
if not req.dispatchpath: | ||||
return False | ||||
try: | ||||
if req.dispatchpath == b'.git/info/lfs/objects/batch': | ||||
checkperm(rctx, req, 'pull') | ||||
return _processbatchrequest(rctx.repo, req, res) | ||||
# TODO: reserve and use a path in the proposed http wireprotocol /api/ | ||||
# namespace? | ||||
elif req.dispatchpath.startswith(b'.hg/lfs/objects'): | ||||
return _processbasictransfer(rctx.repo, req, res, | ||||
lambda perm: | ||||
checkperm(rctx, req, perm)) | ||||
return False | ||||
except hgwebcommon.ErrorResponse as e: | ||||
# XXX: copied from the handler surrounding wireprotoserver._callhttp() | ||||
# in the wrapped function. Should this be moved back to hgweb to | ||||
# be a common handler? | ||||
for k, v in e.headers: | ||||
res.headers[k] = v | ||||
res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e)) | ||||
res.setbodybytes(b'0\n%s\n' % pycompat.bytestr(e)) | ||||
return True | ||||
def _processbatchrequest(repo, req, res): | ||||
"""Handle a request for the Batch API, which is the gateway to granting file | ||||
access. | ||||
https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md | ||||
""" | ||||
return False | ||||
def _processbasictransfer(repo, req, res, checkperm): | ||||
"""Handle a single file upload (PUT) or download (GET) action for the Basic | ||||
Transfer Adapter. | ||||
After determining if the request is for an upload or download, the access | ||||
must be checked by calling ``checkperm()`` with either 'pull' or 'upload' | ||||
before accessing the files. | ||||
https://github.com/git-lfs/git-lfs/blob/master/docs/api/basic-transfers.md | ||||
""" | ||||
method = req.method | ||||
if method == b'PUT': | ||||
checkperm('upload') | ||||
elif method == b'GET': | ||||
checkperm('pull') | ||||
return False | ||||