Update servers and compat tests to work with DictBackends.
authorDave Borowitz <dborowitz@google.com>
Sat, 3 Apr 2010 18:18:12 +0000 (20:18 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Sat, 3 Apr 2010 18:18:12 +0000 (20:18 +0200)
bin/dul-daemon
bin/dul-web
dulwich/server.py
dulwich/tests/compat/test_server.py
dulwich/tests/compat/test_web.py
dulwich/tests/test_web.py
dulwich/web.py

index 1833bbce5d7c42a2d016fbee2cd3c4ce3a8229d5..2515dc207393e3a2297a8ad745b6cdd02310eb8a 100755 (executable)
@@ -26,6 +26,6 @@ if __name__ == "__main__":
     if len(sys.argv) > 1:
         gitdir = sys.argv[1]
 
-       backend = DictBackend({"/": GitBackendRepo(Repo(gitdir))})
+    backend = DictBackend({"/": GitBackendRepo(Repo(gitdir))})
     server = TCPGitServer(backend, 'localhost')
     server.serve_forever()
index c2ad19d5f9740828d85f4aacff0462fb7d099b32..af728e964d6e1619531970a02d0266b19fe90f0a 100644 (file)
@@ -30,7 +30,7 @@ if __name__ == "__main__":
     else:
         gitdir = os.getcwd()
 
-       backend = DictBackend({"/": GitBackendRepo(Repo(gitdir))})
+    backend = DictBackend({"/": GitBackendRepo(Repo(gitdir))})
     app = HTTPGitApplication(backend)
     # TODO: allow serving on other ports via command-line flag
     server = make_server('', 8000, app)
index 971f2c75ce66940e82b5eb9c882347d510a38b4f..e289458d1957a5bb95c1355e968a2ec4d04a77db 100644 (file)
@@ -80,9 +80,10 @@ class BackendRepo(object):
 
         :param name: Name of the ref to peel
         :return: The peeled value of the ref. If the ref is known not point to
-            a tag, this will be the SHA the ref refers to. If the ref may 
-            point to a tag, but no cached information is available, None is 
-            returned.  """
+            a tag, this will be the SHA the ref refers to. If no cached
+            information about a tag is available, this method may return None,
+            but it should attempt to peel the tag if possible.
+        """
         return None
 
     def apply_pack(self, refs, read, delete_refs=True):
@@ -114,6 +115,7 @@ class GitBackendRepo(BackendRepo):
         self.object_store = self.repo.object_store
         self.fetch_objects = self.repo.fetch_objects
         self.get_refs = self.repo.get_refs
+        self.get_peeled = self.repo.get_peeled
 
     def apply_pack(self, refs, read, delete_refs=True):
         f, commit = self.repo.object_store.add_thin_pack()
index a9088854e48a6309e04bdf222c69d2e9545f7b54..86a583378e90800fa124e27c7f2e7b5f3048cd0b 100644 (file)
@@ -26,7 +26,11 @@ On *nix, you can kill the tests with Ctrl-Z, "kill %".
 
 import threading
 
-from dulwich import server
+from dulwich.server import (
+    DictBackend,
+    GitBackendRepo,
+    TCPGitServer,
+    )
 from server_utils import (
     ServerTests,
     ShutdownServerMixIn,
@@ -37,16 +41,16 @@ from utils import (
     )
 
 
-if getattr(server.TCPGitServer, 'shutdown', None):
-    TCPGitServer = server.TCPGitServer
-else:
-    class TCPGitServer(ShutdownServerMixIn, server.TCPGitServer):
+if not getattr(TCPGitServer, 'shutdown', None):
+    _TCPGitServer = TCPGitServer
+
+    class TCPGitServer(ShutdownServerMixIn, TCPGitServer):
         """Subclass of TCPGitServer that can be shut down."""
 
         def __init__(self, *args, **kwargs):
             # BaseServer is old-style so we have to call both __init__s
             ShutdownServerMixIn.__init__(self)
-            server.TCPGitServer.__init__(self, *args, **kwargs)
+            _TCPGitServer.__init__(self, *args, **kwargs)
 
         serve = ShutdownServerMixIn.serve_forever
 
@@ -65,7 +69,8 @@ class GitServerTestCase(ServerTests, CompatTestCase):
         CompatTestCase.tearDown(self)
 
     def _start_server(self, repo):
-        dul_server = TCPGitServer(server.GitBackend(repo), 'localhost', 0)
+        backend = DictBackend({'/': GitBackendRepo(repo)})
+        dul_server = TCPGitServer(backend, 'localhost', 0)
         threading.Thread(target=dul_server.serve).start()
         self._server = dul_server
         _, port = self._server.socket.getsockname()
index c30b40045e715a3ca00c0408811baf1c4ea96e19..36e1522fb8bbd8deeaafced6a74194a6c6026f8c 100644 (file)
@@ -28,7 +28,8 @@ import threading
 from wsgiref import simple_server
 
 from dulwich.server import (
-    GitBackend,
+    DictBackend,
+    GitBackendRepo,
     )
 from dulwich.web import (
     HTTPGitApplication,
@@ -68,7 +69,8 @@ class WebTests(ServerTests):
     protocol = 'http'
 
     def _start_server(self, repo):
-        app = self._make_app(GitBackend(repo))
+        backend = DictBackend({'/': GitBackendRepo(repo)})
+        app = self._make_app(backend)
         dul_server = simple_server.make_server('localhost', 0, app,
                                                server_class=WSGIServer)
         threading.Thread(target=dul_server.serve_forever).start()
index 394931612fbd014eb65e482f8d963d22df386ee9..aea558a39aa502f48df03bdd237499bd39e6a5f1 100644 (file)
@@ -114,6 +114,7 @@ class DumbHandlersTestCase(WebTestCase):
             def __init__(self, objects, peeled):
                 self._objects = dict((o.sha(), o) for o in objects)
                 self._peeled = peeled
+                self.repo = self
 
             def get_peeled(self, sha):
                 return self._peeled[sha]
@@ -121,6 +122,14 @@ class DumbHandlersTestCase(WebTestCase):
             def __getitem__(self, sha):
                 return self._objects[sha]
 
+            def get_refs(self):
+                return {
+                    'HEAD': '000',
+                    'refs/heads/master': blob1.sha(),
+                    'refs/tags/tag-tag': tag1.sha(),
+                    'refs/tags/blob-tag': blob3.sha(),
+                    }
+
         class TestBackend(object):
             def __init__(self):
                 objects = [blob1, blob2, blob3, tag1]
@@ -131,19 +140,16 @@ class DumbHandlersTestCase(WebTestCase):
                     'refs/tags/blob-tag': blob3.sha(),
                     })
 
-            def get_refs(self):
-                return {
-                    'HEAD': '000',
-                    'refs/heads/master': blob1.sha(),
-                    'refs/tags/tag-tag': tag1.sha(),
-                    'refs/tags/blob-tag': blob3.sha(),
-                    }
+            def open_repository(self, path):
+                assert path == '/'
+                return self.repo
 
+        mat = re.search('.*', '//info/refs')
         self.assertEquals(['111\trefs/heads/master\n',
                            '333\trefs/tags/blob-tag\n',
                            'aaa\trefs/tags/tag-tag\n',
                            '222\trefs/tags/tag-tag^{}\n'],
-                          list(get_info_refs(self._req, TestBackend(), None)))
+                          list(get_info_refs(self._req, TestBackend(), mat)))
 
 
 class SmartHandlersTestCase(WebTestCase):
@@ -159,8 +165,9 @@ class SmartHandlersTestCase(WebTestCase):
                 self._handler.write('pkt-line: %s' % line)
 
     class _TestUploadPackHandler(object):
-        def __init__(self, backend, read, write, stateless_rpc=False,
+        def __init__(self, backend, args, read, write, stateless_rpc=False,
                      advertise_refs=False):
+            self.args = args
             self.read = read
             self.write = write
             self.proto = SmartHandlersTestCase.TestProtocol(self)
@@ -213,7 +220,8 @@ class SmartHandlersTestCase(WebTestCase):
         self._environ['wsgi.input'] = StringIO('foo')
         self._environ['QUERY_STRING'] = 'service=git-upload-pack'
 
-        output = ''.join(get_info_refs(self._req, 'backend', None,
+        mat = re.search('.*', '/git-upload-pack')
+        output = ''.join(get_info_refs(self._req, 'backend', mat,
                                        services=self.services()))
         self.assertEquals(('pkt-line: # service=git-upload-pack\n'
                            'flush-pkt\n'
index 1285fe2b57c865230fc2627bc91a91f5a08a93ed..06d19e9a26a745674644087578031aefe02fa372 100644 (file)
@@ -33,7 +33,7 @@ HTTP_NOT_FOUND = '404 Not Found'
 HTTP_FORBIDDEN = '403 Forbidden'
 
 
-def date_time_string(self, timestamp=None):
+def date_time_string(timestamp=None):
     # Based on BaseHTTPServer.py in python2.5
     weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
     months = [None,
@@ -46,6 +46,22 @@ def date_time_string(self, timestamp=None):
             weekdays[wd], day, months[month], year, hh, mm, ss)
 
 
+def url_prefix(mat):
+    """Extract the URL prefix from a regex match.
+
+    :param mat: A regex match object.
+    :returns: The URL prefix, defined as the text before the match in the
+        original string. Normalized to start with one leading slash and end with
+        zero.
+    """
+    return '/' + mat.string[:mat.start()].strip('/')
+
+
+def get_repo(backend, mat):
+    """Get a Repo instance for the given backend and URL regex match."""
+    return backend.open_repository(url_prefix(mat)).repo
+
+
 def send_file(req, f, content_type):
     """Send a file-like object to the request output.
 
@@ -73,13 +89,13 @@ def send_file(req, f, content_type):
 
 def get_text_file(req, backend, mat):
     req.nocache()
-    return send_file(req, backend.repo.get_named_file(mat.group()),
+    return send_file(req, get_repo(backend, mat).get_named_file(mat.group()),
                      'text/plain')
 
 
 def get_loose_object(req, backend, mat):
     sha = mat.group(1) + mat.group(2)
-    object_store = backend.object_store
+    object_store = get_repo(backend, mat).object_store
     if not object_store.contains_loose(sha):
         yield req.not_found('Object not found')
         return
@@ -94,13 +110,13 @@ def get_loose_object(req, backend, mat):
 
 def get_pack_file(req, backend, mat):
     req.cache_forever()
-    return send_file(req, backend.repo.get_named_file(mat.group()),
+    return send_file(req, get_repo(backend, mat).get_named_file(mat.group()),
                      'application/x-git-packed-objects')
 
 
 def get_idx_file(req, backend, mat):
     req.cache_forever()
-    return send_file(req, backend.repo.get_named_file(mat.group()),
+    return send_file(req, get_repo(backend, mat).get_named_file(mat.group()),
                      'application/x-git-packed-objects-toc')
 
 
@@ -120,7 +136,8 @@ def get_info_refs(req, backend, mat, services=None):
         req.respond(HTTP_OK, 'application/x-%s-advertisement' % service)
         output = StringIO()
         dummy_input = StringIO()  # GET request, handler doesn't need to read
-        handler = handler_cls(backend, dummy_input.read, output.write,
+        handler = handler_cls(backend, [url_prefix(mat)],
+                              dummy_input.read, output.write,
                               stateless_rpc=True, advertise_refs=True)
         handler.proto.write_pkt_line('# service=%s\n' % service)
         handler.proto.write_pkt_line(None)
@@ -131,18 +148,19 @@ def get_info_refs(req, backend, mat, services=None):
         # TODO: select_getanyfile() (see http-backend.c)
         req.nocache()
         req.respond(HTTP_OK, 'text/plain')
-        refs = backend.get_refs()
+        repo = get_repo(backend, mat)
+        refs = repo.get_refs()
         for name in sorted(refs.iterkeys()):
             # get_refs() includes HEAD as a special case, but we don't want to
             # advertise it
             if name == 'HEAD':
                 continue
             sha = refs[name]
-            o = backend.repo[sha]
+            o = repo[sha]
             if not o:
                 continue
             yield '%s\t%s\n' % (sha, name)
-            peeled_sha = backend.repo.get_peeled(name)
+            peeled_sha = repo.get_peeled(name)
             if peeled_sha != sha:
                 yield '%s\t%s^{}\n' % (peeled_sha, name)
 
@@ -150,7 +168,7 @@ def get_info_refs(req, backend, mat, services=None):
 def get_info_packs(req, backend, mat):
     req.nocache()
     req.respond(HTTP_OK, 'text/plain')
-    for pack in backend.object_store.packs:
+    for pack in get_repo(backend, mat).object_store.packs:
         yield 'P pack-%s.pack\n' % pack.name()
 
 
@@ -195,7 +213,8 @@ def handle_service_request(req, backend, mat, services=None):
     # content-length
     if 'CONTENT_LENGTH' in req.environ:
         input = _LengthLimitedFile(input, int(req.environ['CONTENT_LENGTH']))
-    handler = handler_cls(backend, input.read, output.write, stateless_rpc=True)
+    handler = handler_cls(backend, [url_prefix(mat)], input.read, output.write,
+                          stateless_rpc=True)
     handler.handle()
     yield output.getvalue()