Browse Source

Add basic function for finding merge base, currently a wrapper around C Git.

Jelmer Vernooij 5 years ago
parent
commit
944bc7f356
3 changed files with 62 additions and 0 deletions
  1. 35 0
      dulwich/merge.py
  2. 17 0
      dulwich/porcelain.py
  3. 10 0
      dulwich/tests/test_porcelain.py

+ 35 - 0
dulwich/merge.py

@@ -0,0 +1,35 @@
+# merge.py -- Merge support in Dulwich
+# Copyright (C) 2020 Jelmer Vernooij <jelmer@jelmer.uk>
+#
+# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
+# General Public License as public by the Free Software Foundation; version 2.0
+# or (at your option) any later version. You can redistribute it and/or
+# modify it under the terms of either of these two licenses.
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# You should have received a copy of the licenses; if not, see
+# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
+# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
+# License, Version 2.0.
+#
+
+"""Merge support."""
+
+
+def find_merge_base(repo, commit_ids):
+    """Find a reasonable merge base.
+
+    Args:
+      repo: Repository object
+      commit_ids: List of commit ids
+    """
+    import subprocess
+    return subprocess.check_output(
+        ['git', 'merge-base'] +
+        [x.decode('ascii') for x in commit_ids],
+        cwd=repo.path).rstrip(b'\n')

+ 17 - 0
dulwich/porcelain.py

@@ -37,6 +37,7 @@ Currently implemented:
  * ls-files
  * ls-remote
  * ls-tree
+ * merge-base
  * pull
  * push
  * rm
@@ -1887,3 +1888,19 @@ def write_tree(repo):
     """
     with open_repo_closing(repo) as r:
         return r.open_index().commit(r.object_store)
+
+
+def merge_base(repo, committishs):
+    """Find the merge base to use for a set of commits.
+
+    Args:
+      repo: Repository in which the commits live
+      committishs: List of committish entries
+    Returns:
+      common merge commit
+    """
+    from .merge import find_merge_base
+    with open_repo_closing(repo) as r:
+        commits = [parse_commit(r, committish).id
+                   for committish in committishs]
+        return find_merge_base(repo, commits)

+ 10 - 0
dulwich/tests/test_porcelain.py

@@ -2825,3 +2825,13 @@ class FindUniqueAbbrevTests(PorcelainTestCase):
         self.assertEqual(
             c1.id.decode('ascii')[:7],
             porcelain.find_unique_abbrev(self.repo.object_store, c1.id))
+        self.assertEqual(b'master', porcelain.active_branch(self.repo))
+
+
+class MergeBaseTests(PorcelainTestCase):
+
+    def test_simple(self):
+        c1, c2, c3, c4 = build_commit_graph(
+                self.repo.object_store, [[1], [2, 1], [3, 1, 2], [4, 1]])
+        self.assertEqual(
+            c1.id, porcelain.merge_base(self.repo, [c3.id, c4.id]))