Dulwich.io dulwich / 88d5e09
Support opening git repositories by path. Jelmer Vernooij 9 years ago
4 changed file(s) with 51 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
1818
1919 import sys
2020 from dulwich.repo import Repo
21 from dulwich.server import GitBackend, TCPGitServer
21 from dulwich.server import DictBackend, GitBackendRepo, TCPGitServer
2222
2323 if __name__ == "__main__":
2424 gitdir = None
2525 if len(sys.argv) > 1:
2626 gitdir = sys.argv[1]
2727
28 backend = GitBackend(Repo(gitdir))
28 backend = DictBackend({"/": GitBackendRepo(Repo(gitdir))})
2929 server = TCPGitServer(backend, 'localhost')
3030 server.serve_forever()
1919 import os
2020 import sys
2121 from dulwich.repo import Repo
22 from dulwich.server import GitBackend
22 from dulwich.server import GitBackendRepo, DictBackend
2323 from dulwich.web import HTTPGitApplication
2424 from wsgiref.simple_server import make_server
2525
2929 else:
3030 gitdir = os.getcwd()
3131
32 backend = GitBackend(Repo(gitdir))
32 backend = DictBackend({"/": GitBackendRepo(Repo(gitdir))})
3333 app = HTTPGitApplication(backend)
3434 # TODO: allow serving on other ports via command-line flag
3535 server = make_server('', 8000, app)
5555 class Backend(object):
5656 """A backend for the Git smart server implementation."""
5757
58 def open_repository(self, path):
59 """Open the repository at a path."""
60 raise NotImplementedError(self.open_repository)
61
62
63 class BackendRepo(object):
64 """Repository abstraction used by the Git server.
65
66 Eventually this should become just a subset of Repo.
67 """
68
5869 def get_refs(self):
5970 """
6071 Get all the refs in the repository
8495 raise NotImplementedError
8596
8697
87 class GitBackend(Backend):
98 class GitBackendRepo(BackendRepo):
8899
89100 def __init__(self, repo):
90101 self.repo = repo
148159 return status
149160
150161
162 class DictBackend(Backend):
163 """Trivial backend that looks up Git repositories in a dictionary."""
164
165 def __init__(self, repos):
166 self.repos = repos
167
168 def open_repository(self, path):
169 # FIXME: What to do in case there is no repo ?
170 return self.repos[path]
171
172
151173 class Handler(object):
152174 """Smart protocol command handler base class."""
153175
195217 def __init__(self, backend, args, read, write,
196218 stateless_rpc=False, advertise_refs=False):
197219 Handler.__init__(self, backend, read, write)
220 self.repo = backend.open_repository(args[0])
198221 self._graph_walker = None
199222 self.stateless_rpc = stateless_rpc
200223 self.advertise_refs = advertise_refs
224247 if not self.has_capability("include-tag"):
225248 return {}
226249 if refs is None:
227 refs = self.backend.get_refs()
250 refs = self.repo.get_refs()
228251 if repo is None:
229 repo = getattr(self.backend, "repo", None)
252 repo = getattr(self.repo, "repo", None)
230253 if repo is None:
231254 # Bail if we don't have a Repo available; this is ok since
232255 # clients must be able to handle if the server doesn't include
233256 # all relevant tags.
234 # TODO: either guarantee a Repo, or fix behavior when missing
257 # TODO: fix behavior when missing
235258 return {}
236259 tagged = {}
237260 for name, sha in refs.iteritems():
243266 def handle(self):
244267 write = lambda x: self.proto.write_sideband(1, x)
245268
246 graph_walker = ProtocolGraphWalker(self)
247 objects_iter = self.backend.fetch_objects(
269 graph_walker = ProtocolGraphWalker(self, self.repo.object_store)
270 objects_iter = self.repo.fetch_objects(
248271 graph_walker.determine_wants, graph_walker, self.progress,
249272 get_tagged=self.get_tagged)
250273
274297 call to set_ack_level() is required to set up the implementation, before any
275298 calls to next() or ack() are made.
276299 """
277 def __init__(self, handler):
300 def __init__(self, handler, object_store):
278301 self.handler = handler
279 self.store = handler.backend.object_store
302 self.store = object_store
280303 self.proto = handler.proto
281304 self.stateless_rpc = handler.stateless_rpc
282305 self.advertise_refs = handler.advertise_refs
556579 def __init__(self, backend, args, read, write,
557580 stateless_rpc=False, advertise_refs=False):
558581 Handler.__init__(self, backend, read, write)
582 self.repo = backend.open_repository(args[0])
559583 self.stateless_rpc = stateless_rpc
560584 self.advertise_refs = advertise_refs
561585
563587 return ("report-status", "delete-refs")
564588
565589 def handle(self):
566 refs = self.backend.get_refs().items()
590 refs = self.repo.get_refs().items()
567591
568592 if self.advertise_refs or not self.stateless_rpc:
569593 if refs:
597621 ref = self.proto.read_pkt_line()
598622
599623 # backend can now deal with this refs and read a pack using self.read
600 status = self.backend.apply_pack(client_refs, self.proto.read,
601 self.has_capability('delete-refs'))
624 status = self.repo.apply_pack(client_refs, self.proto.read,
625 self.has_capability('delete-refs'))
602626
603627 # when we have read all the pack from the client, send a status report
604628 # if the client asked for it
2525 GitProtocolError,
2626 )
2727 from dulwich.server import (
28 UploadPackHandler,
28 Backend,
29 DictBackend,
30 BackendRepo,
2931 Handler,
32 MultiAckGraphWalkerImpl,
33 MultiAckDetailedGraphWalkerImpl,
3034 ProtocolGraphWalker,
3135 SingleAckGraphWalkerImpl,
32 MultiAckGraphWalkerImpl,
33 MultiAckDetailedGraphWalkerImpl,
36 UploadPackHandler,
3437 )
3538
3639
7578 class HandlerTestCase(TestCase):
7679
7780 def setUp(self):
78 self._handler = Handler(None, None, None)
81 self._handler = Handler(Backend(), None, None)
7982 self._handler.capabilities = lambda: ('cap1', 'cap2', 'cap3')
8083 self._handler.required_capabilities = lambda: ('cap2',)
8184
118121 class UploadPackHandlerTestCase(TestCase):
119122
120123 def setUp(self):
121 self._handler = UploadPackHandler(None, ["/", "host=lolcathost"],
122 None, None)
124 self._backend = DictBackend({"/": BackendRepo()})
125 self._handler = UploadPackHandler(self._backend,
126 ["/", "host=lolcathost"], None, None)
123127 self._handler.proto = TestProto()
124128
125129 def test_progress(self):
223227 }
224228
225229 self._walker = ProtocolGraphWalker(
226 TestUploadPackHandler(self._objects, TestProto()))
230 TestUploadPackHandler(self._objects, TestProto()),
231 self._objects)
227232
228233 def test_is_satisfied_no_haves(self):
229234 self.assertFalse(self._walker._is_satisfied([], ONE, 0))