Преглед на файлове

Update servers and compat tests to work with DictBackends.

Dave Borowitz преди 15 години
родител
ревизия
ce5e9e9c0c
променени са 7 файла, в които са добавени 71 реда и са изтрити 35 реда
  1. 1 1
      bin/dul-daemon
  2. 1 1
      bin/dul-web
  3. 5 3
      dulwich/server.py
  4. 12 7
      dulwich/tests/compat/test_server.py
  5. 4 2
      dulwich/tests/compat/test_web.py
  6. 18 10
      dulwich/tests/test_web.py
  7. 30 11
      dulwich/web.py

+ 1 - 1
bin/dul-daemon

@@ -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()

+ 1 - 1
bin/dul-web

@@ -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)

+ 5 - 3
dulwich/server.py

@@ -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()

+ 12 - 7
dulwich/tests/compat/test_server.py

@@ -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()

+ 4 - 2
dulwich/tests/compat/test_web.py

@@ -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()

+ 18 - 10
dulwich/tests/test_web.py

@@ -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'

+ 30 - 11
dulwich/web.py

@@ -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()