Explorar o código

Add ``dulwich.porcelain._reset_file``.

Ded_Secer %!s(int64=3) %!d(string=hai) anos
pai
achega
da13fe46ff
Modificáronse 3 ficheiros con 96 adicións e 1 borrados
  1. 3 0
      NEWS
  2. 20 0
      dulwich/porcelain.py
  3. 73 1
      dulwich/tests/test_porcelain.py

+ 3 - 0
NEWS

@@ -11,6 +11,9 @@
 
  * Drop support for Python 3.5.  (Jelmer Vernooij)
 
+ * Add ``dulwich.porcelain._reset_file``.
+   (Ded_Secer)
+
 0.20.24	2021-07-18
 
  * config: disregard UTF-8 BOM when reading file.

+ 20 - 0
dulwich/porcelain.py

@@ -108,6 +108,8 @@ from dulwich.ignore import IgnoreFilterManager
 from dulwich.index import (
     blob_from_path_and_stat,
     get_unstaged_changes,
+    build_file_from_blob,
+    _fs_to_tree_path,
 )
 from dulwich.object_store import (
     tree_lookup_path,
@@ -1741,6 +1743,24 @@ def update_head(repo, target, detached=False, new_branch=None):
             r.refs.set_symbolic_ref(b"HEAD", to_set)
 
 
+def reset_file(repo, file_path: str, target: bytes = b'HEAD'):
+    """Reset the file to specific commit or branch.
+
+    Args:
+      repo: dulwich Repo object
+      file_path: file to reset, relative to the repository path
+      target: branch or commit or b'HEAD' to reset
+    """
+    tree = parse_tree(repo, treeish=target)
+    file_path = _fs_to_tree_path(file_path)
+
+    file_entry = tree.lookup_path(repo.object_store.__getitem__, file_path)
+    full_path = os.path.join(repo.path.encode(), file_path)
+    blob = repo.object_store[file_entry[1]]
+    mode = file_entry[0]
+    build_file_from_blob(blob, mode, full_path)
+
+
 def check_mailmap(repo, contact):
     """Check canonical name and email of contact.
 

+ 73 - 1
dulwich/tests/test_porcelain.py

@@ -35,7 +35,9 @@ from unittest import skipIf
 
 from dulwich import porcelain
 from dulwich.diff_tree import tree_changes
-from dulwich.errors import CommitError
+from dulwich.errors import (
+    CommitError,
+)
 from dulwich.objects import (
     Blob,
     Tag,
@@ -46,6 +48,9 @@ from dulwich.repo import (
     NoIndexPresent,
     Repo,
 )
+from dulwich.index import (
+    _fs_to_tree_path,
+)
 from dulwich.tests import (
     TestCase,
 )
@@ -1317,6 +1322,73 @@ class ResetTests(PorcelainTestCase):
         self.assertEqual([], changes)
 
 
+class ResetFileTests(PorcelainTestCase):
+
+    def test_reset_modify_file_to_commit(self):
+        file = 'foo'
+        full_path = os.path.join(self.repo.path, file)
+
+        with open(full_path, 'w') as f:
+            f.write('hello')
+        porcelain.add(self.repo, paths=[full_path])
+        sha = porcelain.commit(
+            self.repo,
+            message=b"unitest",
+            committer=b"Jane <jane@example.com>",
+            author=b"John <john@example.com>",
+        )
+        with open(full_path, 'a') as f:
+            f.write('something new')
+        porcelain.reset_file(self.repo, file, target=sha)
+
+        with open(full_path, 'r') as f:
+            self.assertEqual('hello', f.read())
+
+    def test_reset_remove_file_to_commit(self):
+        file = 'foo'
+        full_path = os.path.join(self.repo.path, file)
+
+        with open(full_path, 'w') as f:
+            f.write('hello')
+        porcelain.add(self.repo, paths=[full_path])
+        sha = porcelain.commit(
+            self.repo,
+            message=b"unitest",
+            committer=b"Jane <jane@example.com>",
+            author=b"John <john@example.com>",
+        )
+        os.remove(full_path)
+        porcelain.reset_file(self.repo, file, target=sha)
+
+        with open(full_path, 'r') as f:
+            self.assertEqual('hello', f.read())
+
+    def test_resetfile_with_dir(self):
+        os.mkdir(os.path.join(self.repo.path, 'new_dir'))
+        full_path = os.path.join(self.repo.path, 'new_dir', 'foo')
+
+        with open(full_path, 'w') as f:
+            f.write('hello')
+        porcelain.add(self.repo, paths=[full_path])
+        sha = porcelain.commit(
+            self.repo,
+            message=b"unitest",
+            committer=b"Jane <jane@example.com>",
+            author=b"John <john@example.com>",
+        )
+        with open(full_path, 'a') as f:
+            f.write('something new')
+        porcelain.commit(
+            self.repo,
+            message=b"unitest 2",
+            committer=b"Jane <jane@example.com>",
+            author=b"John <john@example.com>",
+        )
+        porcelain.reset_file(self.repo, os.path.join('new_dir', 'foo'), target=sha)
+        with open(full_path, 'r') as f:
+            self.assertEqual('hello', f.read())
+
+
 class PushTests(PorcelainTestCase):
     def test_simple(self):
         """