Commit Diff


commit - ba0fa0cc9c7e490dc4fdf07837716b4f9fde8404
commit + 4af5055095e5a61e781fe44c8d2efb497b3cc130
blob - 34e8dda184436f34544f1badd646cde24bcf7851
blob + 6ebc4e09cda23a9ac99061c5d8793eb08c9a645a
--- dulwich/porcelain.py
+++ dulwich/porcelain.py
@@ -1139,13 +1139,14 @@ def pull(
             path, r, progress=errstream.write, determine_wants=determine_wants
         )
         for (lh, rh, force_ref) in selected_refs:
-            try:
-                check_diverged(r, r.refs[rh], fetch_result.refs[lh])
-            except DivergedBranches:
-                if fast_forward:
-                    raise
-                else:
-                    raise NotImplementedError("merge is not yet supported")
+            if not force_ref and rh in r.refs:
+                try:
+                    check_diverged(r, r.refs.get(rh), fetch_result.refs[lh])
+                except DivergedBranches:
+                    if fast_forward:
+                        raise
+                    else:
+                        raise NotImplementedError("merge is not yet supported")
             r.refs[rh] = fetch_result.refs[lh]
         if selected_refs:
             r[b"HEAD"] = fetch_result.refs[selected_refs[0][1]]
blob - 201669ebff9d296ddd2ea89404ca02dfa5debb6e
blob + bb294223e62ffeb4c3b83ba0ea35a4e8df522ebb
--- dulwich/tests/test_porcelain.py
+++ dulwich/tests/test_porcelain.py
@@ -20,6 +20,7 @@
 
 """Tests for dulwich.porcelain."""
 
+import contextlib
 from io import BytesIO, StringIO
 import os
 import platform
@@ -30,6 +31,7 @@ import subprocess
 import sys
 import tarfile
 import tempfile
+import threading
 import time
 from unittest import skipIf
 
@@ -48,6 +50,7 @@ from dulwich.repo import (
     NoIndexPresent,
     Repo,
 )
+from dulwich import server
 from dulwich.tests import (
     TestCase,
 )
@@ -56,6 +59,10 @@ from dulwich.tests.utils import (
     make_commit,
     make_object,
 )
+from dulwich.web import (
+    make_server,
+    make_wsgi_chain,
+)
 
 
 def flat_walk_dir(dir_to_walk):
@@ -2867,3 +2874,35 @@ class FindUniqueAbbrevTests(PorcelainTestCase):
         self.assertEqual(
             c1.id.decode('ascii')[:7],
             porcelain.find_unique_abbrev(self.repo.object_store, c1.id))
+
+
+class ServerTests(PorcelainTestCase):
+    @contextlib.contextmanager
+    def _serving(self):
+        with make_server('localhost', 0, self.app) as server:
+            thread = threading.Thread(target=server.serve_forever, daemon=True)
+            thread.start()
+
+            try:
+                yield f"http://localhost:{server.server_port}"
+
+            finally:
+                server.shutdown()
+                thread.join(10)
+
+    def setUp(self):
+        super().setUp()
+
+        self.served_repo_path = os.path.join(self.test_dir, "served_repo.git")
+        self.served_repo = Repo.init_bare(self.served_repo_path, mkdir=True)
+        self.addCleanup(self.served_repo.close)
+
+        backend = DictBackend({"/": self.served_repo})
+        self.app = make_wsgi_chain(backend)
+
+    def test_pull(self):
+        c1, = build_commit_graph(self.served_repo.object_store, [[1]])
+        self.served_repo.refs[b"refs/heads/master"] = c1.id
+
+        with self._serving() as url:
+            porcelain.pull(self.repo, url, "master")