changeset 37:7046d792dfcd

fix bug where it was not writing the git object names properly properly gathers list of needed shas to create packfile, updates server on send-pack next: create and send packfile
author Scott Chacon <schacon@gmail.com>
date Tue, 28 Apr 2009 12:46:51 -0700
parents c13c5f8e03fd
children f0daee676e10
files dulwich/client.py dulwich/repo.py git_handler.py
diffstat 3 files changed, 55 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/dulwich/client.py
+++ b/dulwich/client.py
@@ -105,7 +105,7 @@
             refs[ref] = sha
         return refs, server_capabilities
 
-    def send_pack(self, path, generate_pack_contents):
+    def send_pack(self, path, get_changed_refs, generate_pack_contents):
         """Upload a pack to a remote repository.
 
         :param path: Repository path
@@ -114,9 +114,7 @@
         """
         print 'SEND PACK'
         refs, server_capabilities = self.read_refs()
-        print refs
-        print server_capabilities
-        changed_refs = [] # FIXME
+        changed_refs = get_changed_refs(refs)
         if not changed_refs:
             print 'got here - nooo'
             self.proto.write_pkt_line(None)
@@ -132,8 +130,8 @@
             if changed_ref[0] != "0"*40:
                 have.append(changed_ref[0])
         self.proto.write_pkt_line(None)
-        shas = generate_pack_contents(want, have, None)
-        write_pack_data(self.write, shas, len(shas))
+        shas = generate_pack_contents(want, have)
+        #write_pack_data(self.write, shas, len(shas))
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data, progress):
         """Retrieve a pack from a git smart server.
@@ -197,13 +195,13 @@
         self.host = host
         super(TCPGitClient, self).__init__(lambda: _fileno_can_read(self._socket.fileno()), self.rfile.read, self.wfile.write, *args, **kwargs)
 
-    def send_pack(self, path, generate_pack_contents):
+    def send_pack(self, path, changed_refs, generate_pack_contents):
         """Send a pack to a remote host.
 
         :param path: Path of the repository on the remote host
         """
         self.proto.send_cmd("git-receive-pack", path, "host=%s" % self.host)
-        super(TCPGitClient, self).send_pack(path, generate_pack_contents)
+        super(TCPGitClient, self).send_pack(path, changed_refs, generate_pack_contents)
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data, progress):
         """Fetch a pack from the remote host.
@@ -238,9 +236,9 @@
             self.proc.stdin.flush()
         return GitClient(lambda: _fileno_can_read(self.proc.stdout.fileno()), read_fn, write_fn, *args, **kwargs)
 
-    def send_pack(self, path, generate_pack_contents):
+    def send_pack(self, path, changed_refs, generate_pack_contents):
         client = self._connect("git-receive-pack", path)
-        client.send_pack(path, generate_pack_contents)
+        client.send_pack(path, changed_refs, generate_pack_contents)
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data, 
         progress):
@@ -293,10 +291,10 @@
         self._args = args
         self._kwargs = kwargs
 
-    def send_pack(self, path, generate_pack_contents):
+    def send_pack(self, path, changed_refs, generate_pack_contents):
         remote = get_ssh_vendor().connect_ssh(self.host, ["git-receive-pack '%s'" % path], port=self.port)
         client = GitClient(lambda: _fileno_can_read(remote.proc.stdout.fileno()), remote.recv, remote.send, *self._args, **self._kwargs)
-        client.send_pack(path, generate_pack_contents)
+        client.send_pack(path, changed_refs, generate_pack_contents)
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data, progress):
         remote = get_ssh_vendor().connect_ssh(self.host, ["git-upload-pack '%s'" % path], port=self.port)
--- a/dulwich/repo.py
+++ b/dulwich/repo.py
@@ -361,6 +361,7 @@
         commit_data += 'committer ' + commit['committer'] + "\n"
         commit_data += "\n"
         commit_data += commit['message']
+        print commit_data
         sha = self.write_object('commit', commit_data)
         return sha
 
@@ -391,7 +392,7 @@
             object_dir = os.path.join(self.path, OBJECTDIR, git_hex_sha[0:2])
             if not os.path.exists(object_dir):
                 os.mkdir(object_dir)
-            object_path = os.path.join(object_dir, git_hex_sha[2:38])
+            object_path = os.path.join(object_dir, git_hex_sha[2:])
             data = zlib.compress(raw_data)
             open(object_path, 'w').write(data) # write the object
         return git_hex_sha
--- a/git_handler.py
+++ b/git_handler.py
@@ -154,8 +154,9 @@
             p_rev = parent.rev()
             hgsha = hex(parent.node())
             git_sha = self.map_git_get(hgsha)
-            if not git_sha:
-                self.export_hg_commit(self, p_rev)
+            if not p_rev == -1:
+                if not git_sha:
+                    self.export_hg_commit(p_rev)
         
         ctx = self.repo.changectx(rev)
         tree_sha = self.write_git_tree(ctx)
@@ -176,7 +177,8 @@
         for parent in parents:
             hgsha = hex(parent.node())
             git_sha = self.map_git_get(hgsha)
-            commit['parents'].append(git_sha)
+            if git_sha:
+                commit['parents'].append(git_sha)
             
         commit_sha = self.git.write_commit_hash(commit) # writing new blobs to git
         self.map_set(commit_sha, phgsha)
@@ -253,17 +255,49 @@
     def upload_pack(self, remote_name):
         git_url = self.remote_name_to_url(remote_name)
         client, path = self.get_transport_and_path(git_url)
+        changed = self.get_changed_refs
         genpack = self.generate_pack_contents
         try:
-            client.send_pack(path, genpack)
+            client.send_pack(path, changed, genpack)
             # TODO : self.git.set_remote_refs(refs, remote_name)
         except:
             raise
-            
-    def generate_pack_contents(self, want, have, none):
-        print "WANT: " + str(want)
-        print "HAVE: " + str(have)
-        print "NONE: " + str(none)
+
+    # TODO : for now, we'll just push all heads 
+    #        * we should have specified push, tracking branches and --all
+    # takes a dict of refs:shas from the server and returns what should be 
+    # pushed up
+    def get_changed_refs(self, refs):
+        keys = refs.keys()
+        if not keys:
+            return None
+        changed = []
+        for ref_name in keys:
+            parts = ref_name.split('/')
+            if parts[0] == 'refs': # strip off 'refs/heads'
+                if parts[1] == 'heads':
+                    head = "/".join([v for v in parts[2:]])
+                    print ref_name
+                    print head
+                    local_ref = self.git.ref(ref_name)
+                    if local_ref: 
+                        if not local_ref == refs[ref_name]:
+                            changed.append((refs[ref_name], local_ref, ref_name))
+        return changed
+        
+    # takes a list of shas the server wants and shas the server has
+    # and generates a list of commit shas we need to push up
+    def generate_pack_contents(self, want, have):
+        graph_walker = SimpleFetchGraphWalker(want, self.git.get_parents)
+        next = graph_walker.next()
+        shas = []
+        while next:
+            if next in have:
+                graph_walker.ack(next)
+            else:
+                shas.append(next)
+            next = graph_walker.next()
+        return shas
         
     def fetch_pack(self, remote_name):
         git_url = self.remote_name_to_url(remote_name)