def handle(self): proto = ReceivableProtocol(self.connection.recv, self.wfile.write) command, args = proto.read_cmd() logger.info('Handling %s request, args=%s', command, args) cls = self.handlers.get(command, None) if not callable(cls): raise GitProtocolError('Invalid service %s' % command) h = cls(self.server.backend, args, proto) h.handle()
def run(self, flavor, repo_path, data): backend = load_backend(flavor, repo_path, cache=False) out = StringIO() proto = ReceivableProtocol(StringIO(data).read, out.write) handler = _ReceivePackHandler(WebBackend(), [backend], proto, stateless_rpc=True) handler.handle() sync_tasks = [] for oldrev, newrev, name in handler._good_refs: if name.startswith('refs/heads/'): branch = name[11:] sync_tasks.append( subtask(SyncTask, args=[ backend.flavor, backend.path, oldrev, newrev, branch ])) if sync_tasks: taskset = TaskSet(tasks=sync_tasks) taskset.apply_async().join() return out.getvalue(), handler._good_refs
def get_info_refs(req, backend, mat): params = parse_qs(req.environ["QUERY_STRING"]) service = params.get("service", [None])[0] try: repo = get_repo(backend, mat) except NotGitRepository as e: yield req.not_found(str(e)) return if service and not req.dumb: handler_cls = req.handlers.get(service.encode("ascii"), None) if handler_cls is None: yield req.forbidden("Unsupported service") return req.nocache() write = req.respond(HTTP_OK, "application/x-%s-advertisement" % service) proto = ReceivableProtocol(BytesIO().read, write) handler = handler_cls( backend, [url_prefix(mat)], proto, stateless_rpc=req, advertise_refs=True, ) handler.proto.write_pkt_line(b"# service=" + service.encode("ascii") + b"\n") handler.proto.write_pkt_line(None) handler.handle() else: # non-smart fallback # TODO: select_getanyfile() (see http-backend.c) req.nocache() req.respond(HTTP_OK, "text/plain") logger.info("Emulating dumb info/refs") for text in generate_info_refs(repo): yield text
def get_info_refs(req, backend, mat): params = parse_qs(req.environ['QUERY_STRING']) service = params.get('service', [None])[0] try: repo = get_repo(backend, mat) except NotGitRepository as e: yield req.not_found(str(e)) return if service and not req.dumb: handler_cls = req.handlers.get(service.encode('ascii'), None) if handler_cls is None: yield req.forbidden('Unsupported service') return req.nocache() write = req.respond( HTTP_OK, 'application/x-%s-advertisement' % service) proto = ReceivableProtocol(BytesIO().read, write) handler = handler_cls(backend, [url_prefix(mat)], proto, http_req=req, advertise_refs=True) handler.proto.write_pkt_line( b'# service=' + service.encode('ascii') + b'\n') handler.proto.write_pkt_line(None) handler.handle() else: # non-smart fallback # TODO: select_getanyfile() (see http-backend.c) req.nocache() req.respond(HTTP_OK, 'text/plain') logger.info('Emulating dumb info/refs') for text in generate_info_refs(repo): yield text
def handle(): r = repo._git proto = ReceivableProtocol(inf.read, outf.write) handler = handler_cls(DictBackend({".": r}), ["."], proto, stateless_rpc=True) handler.handle()
def handle_service_request(req, backend, mat): service = mat.group().lstrip('/') logger.info('Handling service request for %s', service) handler_cls = req.handlers.get(service, None) if handler_cls is None: yield req.forbidden('Unsupported service %s' % service) return req.nocache() write = req.respond(HTTP_OK, 'application/x-%s-result' % service) proto = ReceivableProtocol(req.environ['wsgi.input'].read, write) handler = handler_cls(backend, [url_prefix(mat)], proto, http_req=req) handler.handle()
def setUp(self): TestCase.setUp(self) self.rout = BytesIO() self.rin = ReceivableBytesIO() def _closeit(): self.rout.close() self.rin.close() self.proto = ReceivableProtocol(self.rin.recv, self.rout.write, _closeit) self.proto._rbufsize = 8 self.addCleanup(self.proto.close)
async def dulwich_refs(request): package = request.match_info["package"] allow_writes = await is_worker(request.app.db, request) span = aiozipkin.request_span(request) with span.new_child('open-repo'): repo = await _git_open_repo(request.app.vcs_manager, request.app.db, package) r = repo._git service = request.query.get("service") _git_check_service(service, allow_writes) headers = { "Expires": "Fri, 01 Jan 1980 00:00:00 GMT", "Pragma": "no-cache", "Cache-Control": "no-cache, max-age=0, must-revalidate", } handler_cls = DULWICH_SERVICE_HANDLERS[service.encode("ascii")] response = web.StreamResponse(status=200, headers=headers) response.content_type = "application/x-%s-advertisement" % service await response.prepare(request) out = BytesIO() proto = ReceivableProtocol(BytesIO().read, out.write) handler = handler_cls(DictBackend({".": r}), ["."], proto, stateless_rpc=True, advertise_refs=True) handler.proto.write_pkt_line(b"# service=" + service.encode("ascii") + b"\n") handler.proto.write_pkt_line(None) await asyncio.to_thread(handler.handle) await response.write(out.getvalue()) await response.write_eof() return response
def handle_service_request(req, backend, mat): service = mat.group().lstrip("/") logger.info("Handling service request for %s", service) handler_cls = req.handlers.get(service.encode("ascii"), None) if handler_cls is None: yield req.forbidden("Unsupported service") return try: get_repo(backend, mat) except NotGitRepository as e: yield req.not_found(str(e)) return req.nocache() write = req.respond(HTTP_OK, "application/x-%s-result" % service) proto = ReceivableProtocol(req.environ["wsgi.input"].read, write) # TODO(user): Find a way to pass in repo, rather than having handler_cls # reopen. handler = handler_cls(backend, [url_prefix(mat)], proto, stateless_rpc=req) handler.handle()
def handle_service_request(req, backend, mat): service = mat.group().lstrip('/') logger.info('Handling service request for %s', service) handler_cls = req.handlers.get(service.encode('ascii'), None) if handler_cls is None: yield req.forbidden('Unsupported service') return try: get_repo(backend, mat) except NotGitRepository as e: yield req.not_found(str(e)) return req.nocache() write = req.respond(HTTP_OK, 'application/x-%s-result' % service) proto = ReceivableProtocol(req.environ['wsgi.input'].read, write) # TODO(jelmer): Find a way to pass in repo, rather than having handler_cls # reopen. handler = handler_cls(backend, [url_prefix(mat)], proto, http_req=req) handler.handle()
def handle_service_request(req, backend, mat): service = mat.group().lstrip('/') logger.info('Handling service request for %s', service) handler_cls = req.handlers.get(service, None) if handler_cls is None: yield req.forbidden('Unsupported service %s' % service) return req.nocache() write = req.respond(HTTP_OK, 'application/x-%s-result' % service) input = req.environ['wsgi.input'] # This is not necessary if this app is run from a conforming WSGI server. # Unfortunately, there's no way to tell that at this point. # TODO: git may used HTTP/1.1 chunked encoding instead of specifying # content-length content_length = req.environ.get('CONTENT_LENGTH', '') if content_length: input = _LengthLimitedFile(input, int(content_length)) proto = ReceivableProtocol(input.read, write) handler = handler_cls(backend, [url_prefix(mat)], proto, http_req=req) handler.handle()
class ReceivableProtocolTests(BaseProtocolTests, TestCase): def setUp(self): TestCase.setUp(self) self.rout = BytesIO() self.rin = ReceivableBytesIO() def _closeit(): self.rout.close() self.rin.close() self.proto = ReceivableProtocol(self.rin.recv, self.rout.write, _closeit) self.proto._rbufsize = 8 self.addCleanup(self.proto.close) def test_eof(self): # Allow blocking reads past EOF just for this test. The only parts of # the protocol that might check for EOF do not depend on the recv() # semantics anyway. self.rin.allow_read_past_eof = True BaseProtocolTests.test_eof(self) def test_recv(self): all_data = b'1234567' * 10 # not a multiple of bufsize self.rin.write(all_data) self.rin.seek(0) data = b'' # We ask for 8 bytes each time and actually read 7, so it should take # exactly 10 iterations. for _ in range(10): data += self.proto.recv(10) # any more reads would block self.assertRaises(AssertionError, self.proto.recv, 10) self.assertEqual(all_data, data) def test_recv_read(self): all_data = b'1234567' # recv exactly in one call self.rin.write(all_data) self.rin.seek(0) self.assertEqual(b'1234', self.proto.recv(4)) self.assertEqual(b'567', self.proto.read(3)) self.assertRaises(AssertionError, self.proto.recv, 10) def test_read_recv(self): all_data = b'12345678abcdefg' self.rin.write(all_data) self.rin.seek(0) self.assertEqual(b'1234', self.proto.read(4)) self.assertEqual(b'5678abc', self.proto.recv(8)) self.assertEqual(b'defg', self.proto.read(4)) self.assertRaises(AssertionError, self.proto.recv, 10) def test_mixed(self): # arbitrary non-repeating string all_data = ','.join(str(i) for i in range(100)).encode('utf-8') self.rin.write(all_data) self.rin.seek(0) data = b'' for i in range(1, 100): data += self.proto.recv(i) # if we get to the end, do a non-blocking read instead of blocking if len(data) + i > len(all_data): data += self.proto.recv(i) # ReceivableBytesIO leaves off the last byte unless we ask # nicely data += self.proto.recv(1) break else: data += self.proto.read(i) else: # didn't break, something must have gone wrong self.fail() self.assertEqual(all_data, data)
def setUp(self): TestCase.setUp(self) self.rout = StringIO() self.rin = ReceivableStringIO() self.proto = ReceivableProtocol(self.rin.recv, self.rout.write) self.proto._rbufsize = 8
class ReceivableProtocolTests(BaseProtocolTests, TestCase): def setUp(self): TestCase.setUp(self) self.rout = StringIO() self.rin = ReceivableStringIO() self.proto = ReceivableProtocol(self.rin.recv, self.rout.write) self.proto._rbufsize = 8 def test_recv(self): all_data = "1234567" * 10 # not a multiple of bufsize self.rin.write(all_data) self.rin.seek(0) data = "" # We ask for 8 bytes each time and actually read 7, so it should take # exactly 10 iterations. for _ in xrange(10): data += self.proto.recv(10) # any more reads would block self.assertRaises(AssertionError, self.proto.recv, 10) self.assertEquals(all_data, data) def test_recv_read(self): all_data = "1234567" # recv exactly in one call self.rin.write(all_data) self.rin.seek(0) self.assertEquals("1234", self.proto.recv(4)) self.assertEquals("567", self.proto.read(3)) self.assertRaises(AssertionError, self.proto.recv, 10) def test_read_recv(self): all_data = "12345678abcdefg" self.rin.write(all_data) self.rin.seek(0) self.assertEquals("1234", self.proto.read(4)) self.assertEquals("5678abc", self.proto.recv(8)) self.assertEquals("defg", self.proto.read(4)) self.assertRaises(AssertionError, self.proto.recv, 10) def test_mixed(self): # arbitrary non-repeating string all_data = ",".join(str(i) for i in xrange(100)) self.rin.write(all_data) self.rin.seek(0) data = "" for i in xrange(1, 100): data += self.proto.recv(i) # if we get to the end, do a non-blocking read instead of blocking if len(data) + i > len(all_data): data += self.proto.recv(i) # ReceivableStringIO leaves off the last byte unless we ask # nicely data += self.proto.recv(1) break else: data += self.proto.read(i) else: # didn't break, something must have gone wrong self.fail() self.assertEquals(all_data, data)
class ReceivableProtocolTests(BaseProtocolTests, TestCase): def setUp(self): TestCase.setUp(self) self.rout = StringIO() self.rin = ReceivableStringIO() self.proto = ReceivableProtocol(self.rin.recv, self.rout.write) self.proto._rbufsize = 8 def test_eof(self): # Allow blocking reads past EOF just for this test. The only parts of # the protocol that might check for EOF do not depend on the recv() # semantics anyway. self.rin.allow_read_past_eof = True BaseProtocolTests.test_eof(self) def test_recv(self): all_data = '1234567' * 10 # not a multiple of bufsize self.rin.write(all_data) self.rin.seek(0) data = '' # We ask for 8 bytes each time and actually read 7, so it should take # exactly 10 iterations. for _ in xrange(10): data += self.proto.recv(10) # any more reads would block self.assertRaises(AssertionError, self.proto.recv, 10) self.assertEquals(all_data, data) def test_recv_read(self): all_data = '1234567' # recv exactly in one call self.rin.write(all_data) self.rin.seek(0) self.assertEquals('1234', self.proto.recv(4)) self.assertEquals('567', self.proto.read(3)) self.assertRaises(AssertionError, self.proto.recv, 10) def test_read_recv(self): all_data = '12345678abcdefg' self.rin.write(all_data) self.rin.seek(0) self.assertEquals('1234', self.proto.read(4)) self.assertEquals('5678abc', self.proto.recv(8)) self.assertEquals('defg', self.proto.read(4)) self.assertRaises(AssertionError, self.proto.recv, 10) def test_mixed(self): # arbitrary non-repeating string all_data = ','.join(str(i) for i in xrange(100)) self.rin.write(all_data) self.rin.seek(0) data = '' for i in xrange(1, 100): data += self.proto.recv(i) # if we get to the end, do a non-blocking read instead of blocking if len(data) + i > len(all_data): data += self.proto.recv(i) # ReceivableStringIO leaves off the last byte unless we ask # nicely data += self.proto.recv(1) break else: data += self.proto.read(i) else: # didn't break, something must have gone wrong self.fail() self.assertEquals(all_data, data)