瀏覽代碼

Modify indexes.

Jelmer Vernooij 3 年之前
父節點
當前提交
c54d92e077
共有 3 個文件被更改,包括 52 次插入26 次删除
  1. 3 2
      dulwich/diff_tree.py
  2. 31 6
      dulwich/merge.py
  3. 18 18
      dulwich/tests/test_merge.py

+ 3 - 2
dulwich/diff_tree.py

@@ -248,12 +248,13 @@ def _all_same(seq, key):
 
 
 def tree_changes_for_merge(
-        store, parent_tree_ids, tree_id: bytes, rename_detector=None):
+        store, parent_tree_ids: List[bytes],
+        tree_id: bytes, rename_detector=None) -> Iterable[List[TreeChange]]:
     """Get the tree changes for a merge tree relative to all its parents.
 
     Args:
       store: An ObjectStore for looking up objects.
-      parent_tree_ids: An iterable of the SHAs of the parent trees.
+      parent_tree_ids: A list of the SHAs of the parent trees.
       tree_id: The SHA of the merge tree.
       rename_detector: RenameDetector object for detecting renames.
 

+ 31 - 6
dulwich/merge.py

@@ -21,6 +21,7 @@
 """Merge support."""
 
 from collections import namedtuple
+import stat
 from typing import Union, Iterable, List, Callable, Optional
 
 
@@ -108,7 +109,7 @@ def merge_tree(
             try:
                 this_entry = changes_this_by_this_path[other_change.new.path]
             except KeyError:
-                yield other_change.new.path
+                yield other_change.new
             else:
                 if this_entry != other_change.new:
                     # TODO(jelmer): Three way merge instead, with empty common
@@ -179,15 +180,23 @@ def merge_tree(
 
 class MergeResults(object):
 
-    def __init__(self, conflicts):
-        self.conflicts = conflicts
+    def __init__(self, conflicts=None):
+        self.conflicts = conflicts or []
+
+    def __eq__(self, other):
+        return (
+            isinstance(self, MergeResults) and
+            self.conflicts == other.conflicts)
 
 
 def merge(
         repo, commit_ids: List[bytes], rename_detector=None,
-        file_merger: Optional[FileMerger] = None) -> MergeResults:
+        file_merger: Optional[FileMerger] = None,
+        tree_encoding: str = "utf-8") -> MergeResults:
     """Perform a merge.
     """
+    from .index import index_entry_from_stat
+    import os
     conflicts = []
     [merge_base] = find_merge_base(repo, [repo.head()] + commit_ids)
     [other_id] = commit_ids
@@ -203,7 +212,23 @@ def merge(
 
         if isinstance(entry, MergeConflict):
             conflicts.append(entry)
-
-        # TODO(jelmer): apply the change to the tree
+            # TODO(jelmer): Need to still write something
+        else:
+            if stat.S_ISDIR(entry.mode):
+                continue
+            blob = repo.object_store[entry.sha]
+            fs_path = os.path.join(
+                repo.path,
+                os.fsdecode(entry.path.decode(tree_encoding)))
+            if stat.S_ISREG(entry.mode):
+                with open(fs_path, 'wb') as f:
+                    f.write(blob.as_raw_string())
+                os.chmod(fs_path, entry.mode & 0o777)
+            elif stat.S_ISLNK(entry.mode):
+                os.symlink(blob.as_raw_string(), fs_path)
+            else:
+                raise NotImplementedError("unknown file mode %s" % entry.mode)
+            index[entry.path] = index_entry_from_stat(
+                os.stat(fs_path), entry.sha, 0, entry.mode)
 
     return MergeResults(conflicts=conflicts)

+ 18 - 18
dulwich/tests/test_merge.py

@@ -29,7 +29,7 @@ import tempfile
 from dulwich.tests import TestCase
 from dulwich.tests.utils import build_commit_graph
 
-from dulwich.merge import merge, find_merge_base
+from dulwich.merge import merge, find_merge_base, MergeResults
 from dulwich.repo import Repo
 
 
@@ -42,52 +42,52 @@ class MergeTests(TestCase):
         self.repo1_path = os.path.join(self.test_dir, 'repo1')
         self.repo2_path = os.path.join(self.test_dir, 'repo2')
         self.repo1 = Repo.init(self.repo1_path, mkdir=True)
-        self.common_cid = self._add_file(self.repo1, 'a')
+        self.common_cid = self._add_file(self.repo1, 'a', 'added a\n')
         self.repo2 = self.repo1.clone(self.repo2_path, mkdir=True)
         self.addCleanup(self.repo2.close)
         self.addCleanup(self.repo1.close)
 
-    def _add_file(self, repo, name, contents='a line\n'):
+    def _add_file(self, repo, name, contents):
         with open(os.path.join(repo.path, name), 'w') as f:
-            f.write('Added in repo 1')
+            f.write(contents)
         repo.stage([name])
         return repo.do_commit(('Add file %s' % name).encode('ascii'))
 
     def test_both_adds(self):
         # Two trees both add a new file
-        cid1 = self._add_file(self.repo1, 'b')
-        cid2 = self._add_file(self.repo2, 'c')
+        cid1 = self._add_file(self.repo1, 'b', 'added in repo 1\n')
+        cid2 = self._add_file(self.repo2, 'c', 'added in repo 2\n')
         self.repo2.fetch(self.repo1)
         self.assertEqual(cid1, self.repo1.head())
-        conflicts = merge(self.repo1, [cid2])
-        self.assertEqual([], conflicts)
+        result = merge(self.repo1, [cid2])
+        self.assertEqual(MergeResults(), result)
 
     def test_fast_forward(self):
         # Other tree is ahead of us
         cid1 = self.common_cid
-        cid2 = self._add_file(self.repo2, 'c')
+        cid2 = self._add_file(self.repo2, 'c', 'added in repo 2\n')
         self.repo2.fetch(self.repo1)
         self.assertEqual(cid1, self.repo1.head())
-        conflicts = merge(self.repo1, [cid2])
-        self.assertEqual([], conflicts)
+        result = merge(self.repo1, [cid2])
+        self.assertEqual(MergeResults(), result)
 
     def test_already_ahead(self):
         # We're ahead of the other tree
-        cid1 = self._add_file(self.repo1, 'b')
+        cid1 = self._add_file(self.repo1, 'b', 'added in repo 1\n')
         cid2 = self.common_cid
         self.repo2.fetch(self.repo1)
         self.assertEqual(cid1, self.repo1.head())
-        conflicts = merge(self.repo1, [cid2])
-        self.assertEqual([], conflicts)
+        result = merge(self.repo1, [cid2])
+        self.assertEqual(MergeResults(), result)
 
     def test_changed(self):
         # Two trees both add a new file
-        cid1 = self._add_file(self.repo1, 'a', contents='a new line\n')
-        cid2 = self._add_file(self.repo2, 'c')
+        cid1 = self._add_file(self.repo1, 'a', 'a new line\n')
+        cid2 = self._add_file(self.repo2, 'c', 'added in repo 2\n')
         self.repo2.fetch(self.repo1)
         self.assertEqual(cid1, self.repo1.head())
-        conflicts = merge(self.repo1, [cid2])
-        self.assertEqual([], conflicts)
+        result = merge(self.repo1, [cid2])
+        self.assertEqual(MergeResults(), result)
 
 
 class FindMergeBaseTests(TestCase):