47
57
def open_repository(self, path):
48
58
# FIXME: More secure path sanitization
49
return BzrBackendRepo(self.transport.clone(path.lstrip("/")),
59
transport = self.transport.clone(path.lstrip("/"))
60
trace.mutter('client opens %r: %r', path, transport)
61
return BzrBackendRepo(transport, self.mapping)
53
64
class BzrBackendRepo(BackendRepo):
55
66
def __init__(self, transport, mapping):
56
self.transport = transport
57
67
self.mapping = mapping
58
self.repo_dir = BzrDir.open_from_transport(self.transport)
68
self.repo_dir = BzrDir.open_from_transport(transport)
59
69
self.repo = self.repo_dir.find_repository()
60
70
self.object_store = get_object_store(self.repo)
61
self.refs = BazaarRefsContainer(self.repo_dir, self.object_store)
62
self._refs = self.refs.as_dict() # Much faster for now..
71
self.refs = get_refs_container(self.repo_dir, self.object_store)
64
73
def get_refs(self):
74
self.object_store.lock_read()
76
return self.refs.as_dict()
78
self.object_store.unlock()
67
80
def get_peeled(self, name):
68
return self.get_refs()[name]
81
cached = self.refs.get_peeled(name)
82
if cached is not None:
84
return self.object_store.peel_sha(self.refs[name]).id
70
86
def fetch_objects(self, determine_wants, graph_walker, progress,
72
""" yield git objects to send to client """
74
wants = determine_wants(self.get_refs())
88
"""Yield git objects to send to client """
89
self.object_store.lock_read()
91
wants = determine_wants(self.get_refs())
77
92
have = self.object_store.find_common_revisions(graph_walker)
78
95
return self.object_store.generate_pack_contents(have, wants, progress,
96
get_tagged, lossy=(not self.mapping.roundtripping))
98
self.object_store.unlock()
101
class BzrTCPGitServer(TCPGitServer):
103
def handle_error(self, request, client_address):
104
trace.log_exception_quietly()
105
trace.warning('Exception happened during processing of request '
106
'from %s', client_address)
84
109
def serve_git(transport, host=None, port=None, inet=False):
88
113
host = 'localhost'
90
server = TCPGitServer(backend, host, port)
115
server = BzrTCPGitServer(backend, host, port)
92
server = TCPGitServer(backend, host)
117
server = BzrTCPGitServer(backend, host)
93
118
server.serve_forever()
121
def git_http_hook(branch, method, path):
122
from dulwich.web import HTTPGitApplication, HTTPGitRequest, DEFAULT_HANDLERS
124
for (smethod, spath) in HTTPGitApplication.services:
125
if smethod != method:
127
mat = spath.search(path)
129
handler = HTTPGitApplication.services[smethod, spath]
133
backend = BzrBackend(branch.user_transport)
134
def git_call(environ, start_response):
135
req = HTTPGitRequest(environ, start_response, dumb=False,
136
handlers=DEFAULT_HANDLERS)
137
return handler(req, backend, mat)
141
def serve_command(handler_cls, backend, inf=sys.stdin, outf=sys.stdout):
142
"""Serve a single command.
144
This is mostly useful for the implementation of commands used by e.g. git+ssh.
146
:param handler_cls: `Handler` class to use for the request
147
:param argv: execv-style command-line arguments. Defaults to sys.argv.
148
:param backend: `Backend` to use
149
:param inf: File-like object to read from, defaults to standard input.
150
:param outf: File-like object to write to, defaults to standard output.
151
:return: Exit code for use with sys.exit. 0 on success, 1 on failure.
156
proto = Protocol(inf.read, send_fn)
157
handler = handler_cls(backend, ["/"], proto)
158
# FIXME: Catch exceptions and write a single-line summary to outf.
163
def serve_git_receive_pack(transport, host=None, port=None, inet=False):
165
raise errors.BzrCommandError(
166
"git-receive-pack only works in inetd mode")
167
backend = BzrBackend(transport)
168
sys.exit(serve_command(ReceivePackHandler, backend=backend))
171
def serve_git_upload_pack(transport, host=None, port=None, inet=False):
173
raise errors.BzrCommandError(
174
"git-receive-pack only works in inetd mode")
175
backend = BzrBackend(transport)
176
sys.exit(serve_command(UploadPackHandler, backend=backend))