# HG changeset patch # User Matt Harbison <matt_harbison@yahoo.com> # Date 1521266024 14400 # Sat Mar 17 01:53:44 2018 -0400 # Node ID cc0a6ea95d981ea916d660f32f80eacf8027d926 # Parent ea6fc58524d71ef1ced27c658888655c4dcac7bc lfs: add support for serving blob files diff --git a/hgext/lfs/wireprotolfsserver.py b/hgext/lfs/wireprotolfsserver.py --- a/hgext/lfs/wireprotolfsserver.py +++ b/hgext/lfs/wireprotolfsserver.py @@ -10,6 +10,7 @@ import datetime import errno import json +import os from mercurial.hgweb import ( common as hgwebcommon, @@ -20,6 +21,7 @@ ) HTTP_OK = hgwebcommon.HTTP_OK +HTTP_CREATED = hgwebcommon.HTTP_CREATED HTTP_BAD_REQUEST = hgwebcommon.HTTP_BAD_REQUEST def handlewsgirequest(orig, rctx, req, res, checkperm): @@ -237,10 +239,46 @@ """ method = req.method + oid = os.path.basename(req.dispatchpath) + localstore = repo.svfs.lfslocalblobstore if method == b'PUT': checkperm('upload') + + # TODO: verify Content-Type? + + existed = localstore.has(oid) + + # TODO: how to handle timeouts? The body proxy handles limiting to + # Content-Length, but what happens if a client sends less than it + # says it will? + + # TODO: download() will abort if the checksum fails. It should raise + # something checksum specific that can be caught here, and turned + # into an http code. + localstore.download(oid, req.bodyfh) + + statusmessage = hgwebcommon.statusmessage + res.status = statusmessage(HTTP_OK if existed else HTTP_CREATED) + + # There's no payload here, but this is the header that lfs-test-server + # sends back. This eliminates some gratuitous test output conditionals. + res.headers[b'Content-Type'] = b'text/plain; charset=utf-8' + res.setbodybytes(b'') + + return True elif method == b'GET': checkperm('pull') - return False + res.status = hgwebcommon.statusmessage(HTTP_OK) + res.headers[b'Content-Type'] = b'application/octet-stream' + + # TODO: figure out how to send back the file in chunks, instead of + # reading the whole thing. + res.setbodybytes(localstore.read(oid)) + + return True + else: + _sethttperror(res, HTTP_BAD_REQUEST, + message=b'Unsupported LFS transfer method: %s' % method) + return True diff --git a/mercurial/hgweb/common.py b/mercurial/hgweb/common.py --- a/mercurial/hgweb/common.py +++ b/mercurial/hgweb/common.py @@ -23,6 +23,7 @@ httpserver = util.httpserver HTTP_OK = 200 +HTTP_CREATED = 201 HTTP_NOT_MODIFIED = 304 HTTP_BAD_REQUEST = 400 HTTP_UNAUTHORIZED = 401