hgext/lfs/wireprotolfsserver.py
changeset 37147 a2566597acb5
child 37148 ea6fc58524d7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/lfs/wireprotolfsserver.py	Sat Mar 17 01:23:01 2018 -0400
@@ -0,0 +1,75 @@
+# 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