Przeglądaj źródła

Fix support for short commit hashes in porcelain.reset() (#1610)

Modified parse_tree() to handle short commit hashes by falling back to
parse_commit() when direct repository lookup fails. This resolves issue

Fixes #1154
Jelmer Vernooij 1 miesiąc temu
rodzic
commit
77af7c5f34
3 zmienionych plików z 49 dodań i 1 usunięć
  1. 3 0
      NEWS
  2. 9 1
      dulwich/objectspec.py
  3. 37 0
      tests/test_porcelain.py

+ 3 - 0
NEWS

@@ -1,5 +1,8 @@
 0.23.1	UNRELEASED
 
+ * Support short commit hashes in ``porcelain.reset()``.
+   (Jelmer Vernooij, #1154)
+
  * Support dumb repository access.
    (Jelmer Vernooij, #1097)
 

+ 9 - 1
dulwich/objectspec.py

@@ -66,7 +66,15 @@ def parse_tree(repo: "Repo", treeish: Union[bytes, str]) -> "Tree":
         treeish = parse_ref(repo, treeish)
     except KeyError:  # treeish is commit sha
         pass
-    o = repo[treeish]
+    try:
+        o = repo[treeish]
+    except KeyError:
+        # Try parsing as commit (handles short hashes)
+        try:
+            commit = parse_commit(repo, treeish)
+            return repo[commit.tree]
+        except KeyError:
+            raise KeyError(treeish)
     if o.type_name == b"commit":
         return repo[o.tree]
     return o

+ 37 - 0
tests/test_porcelain.py

@@ -2118,6 +2118,43 @@ class ResetTests(PorcelainTestCase):
 
         self.assertEqual([], changes)
 
+    def test_hard_commit_short_hash(self) -> None:
+        fullpath = os.path.join(self.repo.path, "foo")
+        with open(fullpath, "w") as f:
+            f.write("BAR")
+        porcelain.add(self.repo.path, paths=[fullpath])
+        sha = porcelain.commit(
+            self.repo.path,
+            message=b"Some message",
+            committer=b"Jane <jane@example.com>",
+            author=b"John <john@example.com>",
+        )
+
+        with open(fullpath, "wb") as f:
+            f.write(b"BAZ")
+        porcelain.add(self.repo.path, paths=[fullpath])
+        porcelain.commit(
+            self.repo.path,
+            message=b"Some other message",
+            committer=b"Jane <jane@example.com>",
+            author=b"John <john@example.com>",
+        )
+
+        # Test with short hash (7 characters)
+        short_sha = sha[:7].decode("ascii")
+        porcelain.reset(self.repo, "hard", short_sha)
+
+        index = self.repo.open_index()
+        changes = list(
+            tree_changes(
+                self.repo,
+                index.commit(self.repo.object_store),
+                self.repo[sha].tree,
+            )
+        )
+
+        self.assertEqual([], changes)
+
 
 class ResetFileTests(PorcelainTestCase):
     def test_reset_modify_file_to_commit(self) -> None: