فهرست منبع

Smart protocol clients can now change refs even if they are not uploading new data.

Jelmer Vernooij 13 سال پیش
والد
کامیت
ea94de72ff
3فایلهای تغییر یافته به همراه37 افزوده شده و 14 حذف شده
  1. 3 0
      NEWS
  2. 10 8
      dulwich/client.py
  3. 24 6
      dulwich/tests/compat/test_client.py

+ 3 - 0
NEWS

@@ -27,6 +27,9 @@
 
   * Special case 'refs/stash' as a valid ref. (Jelmer Vernooij, #695577)
 
+  * Smart protocol clients can now change refs even if they are
+    not uploading new data. (Jelmer Vernooij, #855993)
+
 0.8.0	2011-08-07
 
  FEATURES

+ 10 - 8
dulwich/client.py

@@ -416,15 +416,16 @@ class TraditionalGitClient(GitClient):
         if 'report-status' not in server_capabilities:
             negotiated_capabilities.remove('report-status')
         new_refs = determine_wants(old_refs)
-        if not new_refs:
+        if new_refs is None:
             proto.write_pkt_line(None)
-            return {}
+            return old_refs
         (have, want) = self._handle_receive_pack_head(proto,
             negotiated_capabilities, old_refs, new_refs)
-        if not want:
+        if not want and old_refs == new_refs:
             return new_refs
         objects = generate_pack_contents(have, want)
-        entries, sha = write_pack_objects(proto.write_file(), objects)
+        if len(objects) > 0:
+            entries, sha = write_pack_objects(proto.write_file(), objects)
         self._handle_receive_pack_tail(proto, negotiated_capabilities,
             progress)
         return new_refs
@@ -650,18 +651,19 @@ class HttpGitClient(GitClient):
             "git-receive-pack", url)
         negotiated_capabilities = list(self._send_capabilities)
         new_refs = determine_wants(old_refs)
-        if not new_refs:
-            return {}
+        if new_refs is None:
+            return old_refs
         if self.dumb:
             raise NotImplementedError(self.fetch_pack)
         req_data = StringIO()
         req_proto = Protocol(None, req_data.write)
         (have, want) = self._handle_receive_pack_head(
             req_proto, negotiated_capabilities, old_refs, new_refs)
-        if not want:
+        if not want and old_refs == new_refs:
             return new_refs
         objects = generate_pack_contents(have, want)
-        entries, sha = write_pack_objects(req_proto.write_file(), objects)
+        if len(objects) > 0:
+            entries, sha = write_pack_objects(req_proto.write_file(), objects)
         resp = self._smart_request("git-receive-pack", url,
             data=req_data.getvalue())
         resp_proto = Protocol(resp.read, None)

+ 24 - 6
dulwich/tests/compat/test_client.py

@@ -108,11 +108,7 @@ class DulwichClientTestBase(object):
                     src.object_store.generate_pack_contents)
         self.assertDestEqualsSrc()
 
-    def disable_ff_and_make_dummy_commit(self):
-        # disable non-fast-forward pushes to the server
-        dest = repo.Repo(os.path.join(self.gitroot, 'dest'))
-        run_git_or_fail(['config', 'receive.denyNonFastForwards', 'true'],
-                        cwd=dest.path)
+    def make_dummy_commit(self, dest):
         b = objects.Blob.from_string('hi')
         dest.object_store.add_object(b)
         t = index.commit_tree(dest.object_store, [('hi', b.id, 0100644)])
@@ -123,7 +119,15 @@ class DulwichClientTestBase(object):
         c.message = 'hi'
         c.tree = t
         dest.object_store.add_object(c)
-        return dest, c.id
+        return c.id
+
+    def disable_ff_and_make_dummy_commit(self):
+        # disable non-fast-forward pushes to the server
+        dest = repo.Repo(os.path.join(self.gitroot, 'dest'))
+        run_git_or_fail(['config', 'receive.denyNonFastForwards', 'true'],
+                        cwd=dest.path)
+        commit_id = self.make_dummy_commit(dest)
+        return dest, commit_id
 
     def compute_send(self):
         srcpath = os.path.join(self.gitroot, 'server_new.export')
@@ -177,6 +181,20 @@ class DulwichClientTestBase(object):
         map(lambda r: dest.refs.set_if_equals(r[0], None, r[1]), refs.items())
         self.assertDestEqualsSrc()
 
+    def test_send_remove_branch(self):
+        dest = repo.Repo(os.path.join(self.gitroot, 'dest'))
+        dummy_commit = self.make_dummy_commit(dest)
+        dest.refs['refs/heads/master'] = dummy_commit
+        dest.refs['refs/heads/abranch'] = dummy_commit
+        sendrefs = dict(dest.refs)
+        sendrefs['refs/heads/abranch'] = "00" * 20
+        del sendrefs['HEAD']
+        gen_pack = lambda have, want: []
+        c = self._client()
+        self.assertEquals(dest.refs["refs/heads/abranch"], dummy_commit)
+        c.send_pack(self._build_path('/dest'), lambda _: sendrefs, gen_pack)
+        self.assertFalse("refs/heads/abranch" in dest.refs)
+
 
 class DulwichTCPClientTest(CompatTestCase, DulwichClientTestBase):