Browse Source

Merge john.

Jelmer Vernooij 16 years ago
parent
commit
073976c9d1
4 changed files with 104 additions and 29 deletions
  1. 36 5
      bin/dul-daemon
  2. 2 2
      dulwich/pack.py
  3. 6 4
      dulwich/repo.py
  4. 60 18
      dulwich/server.py

+ 36 - 5
bin/dul-daemon

@@ -17,28 +17,59 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.
 
-import sys
+import os, sys, tempfile
 from dulwich.server import Backend, TCPGitServer
+from dulwich.repo import Repo
+from dulwich.pack import PackData, Pack
 
 class GitBackend(Backend):
 
-    def __init__(self, gitdir):
+    def __init__(self, gitdir=None):
         self.gitdir = gitdir
 
+        if not self.gitdir:
+            self.gitdir = tempfile.mkdtemp()
+            Repo.create(self.gitdir)
+
+        self.repo = Repo(self.gitdir)
+
     def get_refs(self):
-        return [['refs/heads/foo', '768fbb786f3a0a2a97ed980f3ce730e9e984f436']]
+        refs = []
+        if self.repo.head():
+            refs.append(('HEAD', self.repo.head()))
+        for refsha in self.repo.heads().items():
+            refs.append(refsha)
+        return refs
 
     def has_revision(self, sha):
         return False
 
     def apply_pack(self, refs, read):
-        read()
+        # store the incoming pack in the repository
+        fd, name = tempfile.mkstemp(suffix='pack', prefix='', dir=self.repo.pack_dir())
+        os.write(fd, read())
+        os.close(fd)
+
+        # strip '.pack' off our filename
+        basename = name[:-5]
+
+        # generate an index for it
+        pd = PackData(name)
+        pd.create_index_v2(basename+".idx")
+
+        # FIXME: Update heads
+
+        print "pack applied"
 
     def generate_pack(self, want, have, write, progress):
         pass
 
 
 if __name__ == "__main__":
-    backend = GitBackend(sys.argv[1])
+    gitdir = None
+    if len(sys.argv) > 1:
+        gitdir = sys.argv[1]
+
+    backend = GitBackend(gitdir)
     server = TCPGitServer(backend, ('localhost', 9418))
     server.serve_forever()

+ 2 - 2
dulwich/pack.py

@@ -390,7 +390,7 @@ class PackData(object):
     found = {}
     postponed = list(self.iterobjects())
     while postponed:
-      (offset, type, obj) = postponed.pop()
+      (offset, type, obj) = postponed.pop(0)
       assert isinstance(offset, int)
       assert isinstance(type, int)
       assert isinstance(obj, tuple) or isinstance(obj, str)
@@ -462,7 +462,7 @@ class PackData(object):
         basename = map[raw_base:raw_base+20]
         uncomp, comp_len = read_zlib(map, raw_base+20, size)
         assert size == len(uncomp)
-        return type, (basename, uncomp), comp_len+raw_base
+        return type, (basename, uncomp), comp_len+raw_base+20
     else:
         uncomp, comp_len = read_zlib(map, raw_base, size)
         assert len(uncomp) == size

+ 6 - 4
dulwich/repo.py

@@ -92,14 +92,16 @@ class Repo(object):
 
   def get_tags(self):
     ret = {}
-    for name in os.listdir(os.path.join(self.basedir(), 'refs', 'tags')):
-      ret[name] = self._get_ref(os.path.join(self.basedir(), 'refs', 'tags', name))
+    for root, dirs, files in os.walk(os.path.join(self.basedir(), 'refs', 'tags')):
+      for name in files:
+        ret[name] = self._get_ref(os.path.join(root, name))
     return ret
 
   def heads(self):
     ret = {}
-    for name in os.listdir(os.path.join(self.basedir(), 'refs', 'heads')):
-      ret[name] = self._get_ref(os.path.join(self.basedir(), 'refs', 'heads', name))
+    for root, dirs, files in os.walk(os.path.join(self.basedir(), 'refs', 'heads')):
+      for name in files:
+        ret[name] = self._get_ref(os.path.join(root, name))
     return ret
 
   def head(self):

+ 60 - 18
dulwich/server.py

@@ -17,24 +17,42 @@
 # MA  02110-1301, USA.
 
 import SocketServer
-# import dulwich as git
-
 
 class Backend(object):
 
-    def __init__(self):
-        pass
-
     def get_refs(self):
+        """
+        Get all the refs in the repository
+
+        :return: list of tuple(name, sha)
+        """
         raise NotImplementedError
 
-    def has_revision(self):
+    def has_revision(self, sha):
+        """
+        Is a given sha in this repository?
+
+        :return: True or False
+        """
         raise NotImplementedError
 
     def apply_pack(self, refs, read):
+        """ Import a set of changes into a repository and update the refs
+
+        :param refs: list of tuple(name, sha)
+        :param read: callback to read from the incoming pack
+        """
         raise NotImplementedError
 
     def generate_pack(self, want, have, write, progress):
+        """
+        Generate a pack containing all commits a client is missing
+
+        :param want: is a list of sha's the client desires
+        :param have: is a list of sha's the client has (allowing us to send the minimal pack)
+        :param write: is a callback to write pack data to the client
+        :param progress: is a callback to send progress messages to the client
+        """
         raise NotImplementedError
 
 
@@ -47,17 +65,33 @@ class Handler(object):
 
     def read_pkt_line(self):
         """
-        reads a 'git line' of info from the stream
+        Reads a 'pkt line' from the remote git process
+
+        :return: The next string from the stream
         """
-        size = int(self.read(4), 16)
+        sizestr = self.read(4)
+        if not sizestr:
+            return None
+        size = int(sizestr, 16)
         if size == 0:
             return None
         return self.read(size-4)
 
     def write_pkt_line(self, line):
+        """
+        Sends a 'pkt line' to the remote git process
+
+        :param line: A string containing the data to send
+        """
         self.write("%04x%s" % (len(line)+4, line))
 
     def write_sideband(self, channel, blob):
+        """
+        Write data to the sideband (a git multiplexing method)
+
+        :param channel: int specifying which channel to write to
+        :param blob: a blob of data (as a string) to send on this channel
+        """
         # a pktline can be a max of 65535. a sideband line can therefore be
         # 65535-5 = 65530
         # WTF: Why have the len in ASCII, but the channel in binary.
@@ -66,6 +100,9 @@ class Handler(object):
             blob = blob[65530:]
 
     def handle(self):
+        """
+        Deal with the request
+        """
         raise NotImplementedError
 
 
@@ -74,10 +111,11 @@ class UploadPackHandler(Handler):
     def handle(self):
         refs = self.backend.get_refs()
 
-        self.write_pkt_line("%s %s\x00multi_ack side-band-64k thin-pack ofs-delta\0x0a" % (refs[0][1], refs[0][0]))
-        for i in range(1, len(refs)-1):
-            ref = refs[i]
-            self.write_pkt_line("%s %s\0x0a" % (ref[1], ref[0]))
+        if refs:
+            self.write_pkt_line("%s %s\x00multi_ack side-band-64k thin-pack ofs-delta\n" % (refs[0][1], refs[0][0]))
+            for i in range(1, len(refs)):
+                ref = refs[i]
+                self.write_pkt_line("%s %s\n" % (ref[1], ref[0]))
 
         # i'm done...
         self.write("0000")
@@ -91,7 +129,7 @@ class UploadPackHandler(Handler):
         # Keep reading the list of demands until we hit another "0000" 
         want_revs = []
         while want and want[:4] == 'want':
-            want_rev = want[5:]
+            want_rev = want[5:40]
             # FIXME: This check probably isnt needed?
             if self.backend.has_revision(want_rev):
                want_revs.append(want_rev)
@@ -123,7 +161,7 @@ class UploadPackHandler(Handler):
         #if True: # False: #self.no_progress == False:
         #    self.write_sideband(2, "Bazaar is preparing your pack, plz hold.\n")
 
-        #    for x in range(1,200):
+        #    for x in range(1,200)
         #        self.write_sideband(2, "Counting objects: %d\x0d" % x*2)
         #    self.write_sideband(2, "Counting objects: 200, done.\n")
 
@@ -139,10 +177,11 @@ class ReceivePackHandler(Handler):
     def handle(self):
         refs = self.backend.get_refs()
 
-        self.write_pkt_line("%s %s\x00multi_ack side-band-64k thin-pack ofs-delta\0x0a" % (refs[0][1], refs[0][0]))
-        for i in range(1, len(refs)-1):
-            ref = refs[i]
-            self.write_pkt_line("%s %s\0x0a" % (ref[1], ref[0]))
+        if refs:
+            self.write_pkt_line("%s %s\x00multi_ack side-band-64k thin-pack ofs-delta\n" % (refs[0][1], refs[0][0]))
+            for i in range(1, len(refs)):
+                ref = refs[i]
+                self.write_pkt_line("%s %s\n" % (ref[1], ref[0]))
 
         self.write("0000")
 
@@ -152,6 +191,9 @@ class ReceivePackHandler(Handler):
             client_refs.append(ref.split())
             ref = self.read_pkt_line()
 
+        if len(client_refs) == 0:
+            return None
+
         self.backend.apply_pack(client_refs, self.read)