Browse Source

Fix deprecation warnings

Jelmer Vernooij 1 week ago
parent
commit
93b2be96d6

+ 1 - 1
docs/tutorial/remote.txt

@@ -6,7 +6,7 @@ Most of the tests in this file require a Dulwich server, so let's start one:
     >>> from dulwich.server import DictBackend, TCPGitServer
     >>> from dulwich.server import DictBackend, TCPGitServer
     >>> import threading
     >>> import threading
     >>> repo = Repo.init("remote", mkdir=True)
     >>> repo = Repo.init("remote", mkdir=True)
-    >>> cid = repo.do_commit(b"message", committer=b"Jelmer <jelmer@samba.org>")
+    >>> cid = repo.get_worktree().commit(b"message", committer=b"Jelmer <jelmer@samba.org>")
     >>> backend = DictBackend({b'/': repo})
     >>> backend = DictBackend({b'/': repo})
     >>> dul_server = TCPGitServer(backend, b'localhost', 0)
     >>> dul_server = TCPGitServer(backend, b'localhost', 0)
     >>> server_thread = threading.Thread(target=dul_server.serve)
     >>> server_thread = threading.Thread(target=dul_server.serve)

+ 4 - 4
docs/tutorial/repo.txt

@@ -71,7 +71,7 @@ aren't tracked explicitly by git. Let's create a simple text file and stage it::
     >>> _ = f.write(b"monty")
     >>> _ = f.write(b"monty")
     >>> f.close()
     >>> f.close()
 
 
-    >>> repo.stage([b"foo"])
+    >>> repo.get_worktree().stage([b"foo"])
 
 
 It will now show up in the index::
 It will now show up in the index::
 
 
@@ -83,7 +83,7 @@ Creating new commits
 --------------------
 --------------------
 
 
 Now that we have staged a change, we can commit it. The easiest way to
 Now that we have staged a change, we can commit it. The easiest way to
-do this is by using ``Repo.do_commit``. It is also possible to manipulate
+do this is by using ``WorkTree.commit``. It is also possible to manipulate
 the lower-level objects involved in this, but we'll leave that for a
 the lower-level objects involved in this, but we'll leave that for a
 separate chapter of the tutorial.
 separate chapter of the tutorial.
 
 
@@ -91,10 +91,10 @@ To create a simple commit on the current branch, it is only necessary
 to specify the message. The committer and author will be retrieved from the
 to specify the message. The committer and author will be retrieved from the
 repository configuration or global configuration if they are not specified::
 repository configuration or global configuration if they are not specified::
 
 
-    >>> commit_id = repo.do_commit(
+    >>> commit_id = repo.get_worktree().commit(
     ...     b"The first commit", committer=b"Jelmer Vernooij <jelmer@samba.org>")
     ...     b"The first commit", committer=b"Jelmer Vernooij <jelmer@samba.org>")
 
 
-``do_commit`` returns the SHA1 of the commit. Since the commit was to the 
+``commit`` returns the SHA1 of the commit. Since the commit was to the 
 default branch, the repository's head will now be set to that commit::
 default branch, the repository's head will now be set to that commit::
 
 
     >>> repo.head() == commit_id
     >>> repo.head() == commit_id

+ 1 - 1
dulwich/client.py

@@ -901,7 +901,7 @@ class GitClient:
                     head = None
                     head = None
 
 
             if checkout and head is not None:
             if checkout and head is not None:
-                target.reset_index()
+                target.get_worktree().reset_index()
         except BaseException:
         except BaseException:
             if target is not None:
             if target is not None:
                 target.close()
                 target.close()

+ 70 - 83
dulwich/porcelain.py

@@ -133,7 +133,6 @@ from .objects import (
     Tag,
     Tag,
     Tree,
     Tree,
     format_timezone,
     format_timezone,
-    hex_to_filename,
     parse_timezone,
     parse_timezone,
     pretty_format_tree_entry,
     pretty_format_tree_entry,
 )
 )
@@ -180,6 +179,9 @@ GitStatus = namedtuple("GitStatus", "staged unstaged untracked")
 # TypeVar for preserving BaseRepo subclass types
 # TypeVar for preserving BaseRepo subclass types
 T = TypeVar("T", bound="BaseRepo")
 T = TypeVar("T", bound="BaseRepo")
 
 
+# Type alias for common repository parameter pattern
+RepoPath = Union[str, os.PathLike, Repo]
+
 
 
 @dataclass
 @dataclass
 class CountObjectsResult:
 class CountObjectsResult:
@@ -454,7 +456,7 @@ def archive(
             outstream.write(chunk)
             outstream.write(chunk)
 
 
 
 
-def update_server_info(repo: Union[str, os.PathLike, BaseRepo] = ".") -> None:
+def update_server_info(repo: RepoPath = ".") -> None:
     """Update server info files for a repository.
     """Update server info files for a repository.
 
 
     Args:
     Args:
@@ -464,9 +466,7 @@ def update_server_info(repo: Union[str, os.PathLike, BaseRepo] = ".") -> None:
         server_update_server_info(r)
         server_update_server_info(r)
 
 
 
 
-def write_commit_graph(
-    repo: Union[str, os.PathLike, BaseRepo] = ".", reachable=True
-) -> None:
+def write_commit_graph(repo: RepoPath = ".", reachable=True) -> None:
     """Write a commit graph file for a repository.
     """Write a commit graph file for a repository.
 
 
     Args:
     Args:
@@ -481,9 +481,7 @@ def write_commit_graph(
             r.object_store.write_commit_graph(refs, reachable=reachable)
             r.object_store.write_commit_graph(refs, reachable=reachable)
 
 
 
 
-def symbolic_ref(
-    repo: Union[str, os.PathLike, BaseRepo], ref_name, force=False
-) -> None:
+def symbolic_ref(repo: RepoPath, ref_name, force=False) -> None:
     """Set git symbolic ref into HEAD.
     """Set git symbolic ref into HEAD.
 
 
     Args:
     Args:
@@ -498,7 +496,7 @@ def symbolic_ref(
         repo_obj.refs.set_symbolic_ref(b"HEAD", ref_path)
         repo_obj.refs.set_symbolic_ref(b"HEAD", ref_path)
 
 
 
 
-def pack_refs(repo: Union[str, os.PathLike, BaseRepo], all=False) -> None:
+def pack_refs(repo: RepoPath, all=False) -> None:
     with open_repo_closing(repo) as repo_obj:
     with open_repo_closing(repo) as repo_obj:
         repo_obj.refs.pack_refs(all=all)
         repo_obj.refs.pack_refs(all=all)
 
 
@@ -609,7 +607,7 @@ def commit(
 
 
 
 
 def commit_tree(
 def commit_tree(
-    repo: Union[str, os.PathLike, BaseRepo],
+    repo: RepoPath,
     tree,
     tree,
     message=None,
     message=None,
     author=None,
     author=None,
@@ -927,9 +925,7 @@ def clean(repo: Union[str, os.PathLike, Repo] = ".", target_dir=None) -> None:
                     os.remove(ap)
                     os.remove(ap)
 
 
 
 
-def remove(
-    repo: Union[str, os.PathLike, Repo] = ".", paths=None, cached=False
-) -> None:
+def remove(repo: Union[str, os.PathLike, Repo] = ".", paths=None, cached=False) -> None:
     """Remove files from the staging area.
     """Remove files from the staging area.
 
 
     Args:
     Args:
@@ -1160,9 +1156,7 @@ def print_tag(tag, decode, outstream=sys.stdout) -> None:
     outstream.write("\n")
     outstream.write("\n")
 
 
 
 
-def show_blob(
-    repo: Union[str, os.PathLike, BaseRepo], blob, decode, outstream=sys.stdout
-) -> None:
+def show_blob(repo: RepoPath, blob, decode, outstream=sys.stdout) -> None:
     """Write a blob to a stream.
     """Write a blob to a stream.
 
 
     Args:
     Args:
@@ -1174,9 +1168,7 @@ def show_blob(
     outstream.write(decode(blob.data))
     outstream.write(decode(blob.data))
 
 
 
 
-def show_commit(
-    repo: Union[str, os.PathLike, BaseRepo], commit, decode, outstream=sys.stdout
-) -> None:
+def show_commit(repo: RepoPath, commit, decode, outstream=sys.stdout) -> None:
     """Show a commit to a stream.
     """Show a commit to a stream.
 
 
     Args:
     Args:
@@ -1198,9 +1190,7 @@ def show_commit(
     outstream.write(commit_decode(commit, diffstream.getvalue()))
     outstream.write(commit_decode(commit, diffstream.getvalue()))
 
 
 
 
-def show_tree(
-    repo: Union[str, os.PathLike, BaseRepo], tree, decode, outstream=sys.stdout
-) -> None:
+def show_tree(repo: RepoPath, tree, decode, outstream=sys.stdout) -> None:
     """Print a tree to a stream.
     """Print a tree to a stream.
 
 
     Args:
     Args:
@@ -1213,9 +1203,7 @@ def show_tree(
         outstream.write(decode(n) + "\n")
         outstream.write(decode(n) + "\n")
 
 
 
 
-def show_tag(
-    repo: Union[str, os.PathLike, BaseRepo], tag, decode, outstream=sys.stdout
-) -> None:
+def show_tag(repo: RepoPath, tag, decode, outstream=sys.stdout) -> None:
     """Print a tag to a stream.
     """Print a tag to a stream.
 
 
     Args:
     Args:
@@ -1229,7 +1217,7 @@ def show_tag(
         show_object(repo, r[tag.object[1]], decode, outstream)
         show_object(repo, r[tag.object[1]], decode, outstream)
 
 
 
 
-def show_object(repo: Union[str, os.PathLike, BaseRepo], obj, decode, outstream):
+def show_object(repo: RepoPath, obj, decode, outstream):
     return {
     return {
         b"tree": show_tree,
         b"tree": show_tree,
         b"blob": show_blob,
         b"blob": show_blob,
@@ -1342,7 +1330,7 @@ def show(
 
 
 
 
 def diff_tree(
 def diff_tree(
-    repo: Union[str, os.PathLike, BaseRepo],
+    repo: RepoPath,
     old_tree,
     old_tree,
     new_tree,
     new_tree,
     outstream=default_bytes_out_stream,
     outstream=default_bytes_out_stream,
@@ -1455,9 +1443,7 @@ def diff(
             diff_module.diff_working_tree_to_index(r, outstream, paths)
             diff_module.diff_working_tree_to_index(r, outstream, paths)
 
 
 
 
-def rev_list(
-    repo: Union[str, os.PathLike, BaseRepo], commits, outstream=sys.stdout
-) -> None:
+def rev_list(repo: RepoPath, commits, outstream=sys.stdout) -> None:
     """Lists commit objects in reverse chronological order.
     """Lists commit objects in reverse chronological order.
 
 
     Args:
     Args:
@@ -1521,7 +1507,7 @@ def submodule_init(repo: Union[str, os.PathLike, Repo]) -> None:
         config.write_to_path()
         config.write_to_path()
 
 
 
 
-def submodule_list(repo: Union[str, os.PathLike, BaseRepo]):
+def submodule_list(repo: RepoPath):
     """List submodules.
     """List submodules.
 
 
     Args:
     Args:
@@ -1754,7 +1740,7 @@ def tag_create(
         r.refs[_make_tag_ref(tag)] = tag_id
         r.refs[_make_tag_ref(tag)] = tag_id
 
 
 
 
-def tag_list(repo: Union[str, os.PathLike, BaseRepo], outstream=sys.stdout):
+def tag_list(repo: RepoPath, outstream=sys.stdout):
     """List all tags.
     """List all tags.
 
 
     Args:
     Args:
@@ -1766,7 +1752,7 @@ def tag_list(repo: Union[str, os.PathLike, BaseRepo], outstream=sys.stdout):
         return tags
         return tags
 
 
 
 
-def tag_delete(repo: Union[str, os.PathLike, BaseRepo], name) -> None:
+def tag_delete(repo: RepoPath, name) -> None:
     """Remove a tag.
     """Remove a tag.
 
 
     Args:
     Args:
@@ -1869,7 +1855,7 @@ def notes_remove(
         )
         )
 
 
 
 
-def notes_show(repo: Union[str, os.PathLike, BaseRepo], object_sha, ref=b"commits"):
+def notes_show(repo: Union[str, os.PathLike, Repo], object_sha, ref=b"commits"):
     """Show the note for an object.
     """Show the note for an object.
 
 
     Args:
     Args:
@@ -1894,7 +1880,7 @@ def notes_show(repo: Union[str, os.PathLike, BaseRepo], object_sha, ref=b"commit
         return r.notes.get_note(object_sha, notes_ref, config=config)
         return r.notes.get_note(object_sha, notes_ref, config=config)
 
 
 
 
-def notes_list(repo: Union[str, os.PathLike, BaseRepo], ref=b"commits"):
+def notes_list(repo: RepoPath, ref=b"commits"):
     """List all notes in a notes ref.
     """List all notes in a notes ref.
 
 
     Args:
     Args:
@@ -2507,7 +2493,7 @@ def get_untracked_paths(
     yield from ignored_dirs
     yield from ignored_dirs
 
 
 
 
-def get_tree_changes(repo: Union[str, os.PathLike, BaseRepo]):
+def get_tree_changes(repo: RepoPath):
     """Return add/delete/modify changes to tree by comparing index to HEAD.
     """Return add/delete/modify changes to tree by comparing index to HEAD.
 
 
     Args:
     Args:
@@ -2650,7 +2636,7 @@ def _make_tag_ref(name: Union[str, bytes]) -> Ref:
     return LOCAL_TAG_PREFIX + name
     return LOCAL_TAG_PREFIX + name
 
 
 
 
-def branch_delete(repo: Union[str, os.PathLike, BaseRepo], name) -> None:
+def branch_delete(repo: RepoPath, name) -> None:
     """Delete a branch.
     """Delete a branch.
 
 
     Args:
     Args:
@@ -2667,7 +2653,7 @@ def branch_delete(repo: Union[str, os.PathLike, BaseRepo], name) -> None:
 
 
 
 
 def branch_create(
 def branch_create(
-    repo: Union[str, os.PathLike, BaseRepo], name, objectish=None, force=False
+    repo: Union[str, os.PathLike, Repo], name, objectish=None, force=False
 ) -> None:
 ) -> None:
     """Create a branch.
     """Create a branch.
 
 
@@ -2754,12 +2740,16 @@ def branch_create(
                     branch_name_bytes = (
                     branch_name_bytes = (
                         name.encode(DEFAULT_ENCODING) if isinstance(name, str) else name
                         name.encode(DEFAULT_ENCODING) if isinstance(name, str) else name
                     )
                     )
-                    repo_config.set((b"branch", branch_name_bytes), b"remote", remote_name)
-                    repo_config.set((b"branch", branch_name_bytes), b"merge", remote_branch)
+                    repo_config.set(
+                        (b"branch", branch_name_bytes), b"remote", remote_name
+                    )
+                    repo_config.set(
+                        (b"branch", branch_name_bytes), b"merge", remote_branch
+                    )
                     repo_config.write_to_path()
                     repo_config.write_to_path()
 
 
 
 
-def branch_list(repo: Union[str, os.PathLike, BaseRepo]):
+def branch_list(repo: RepoPath):
     """List all branches.
     """List all branches.
 
 
     Args:
     Args:
@@ -2815,7 +2805,7 @@ def branch_list(repo: Union[str, os.PathLike, BaseRepo]):
         return branches
         return branches
 
 
 
 
-def active_branch(repo: Union[str, os.PathLike, BaseRepo]):
+def active_branch(repo: RepoPath):
     """Return the active branch in the repository, if any.
     """Return the active branch in the repository, if any.
 
 
     Args:
     Args:
@@ -2853,7 +2843,7 @@ def get_branch_remote(repo: Union[str, os.PathLike, Repo]):
     return remote_name
     return remote_name
 
 
 
 
-def get_branch_merge(repo: Union[str, os.PathLike, BaseRepo], branch_name=None):
+def get_branch_merge(repo: RepoPath, branch_name=None):
     """Return the branch's merge reference (upstream branch), if any.
     """Return the branch's merge reference (upstream branch), if any.
 
 
     Args:
     Args:
@@ -3012,7 +3002,7 @@ def ls_remote(remote, config: Optional[Config] = None, **kwargs):
     return client.get_refs(host_path)
     return client.get_refs(host_path)
 
 
 
 
-def repack(repo: Union[str, os.PathLike, BaseRepo]) -> None:
+def repack(repo: RepoPath) -> None:
     """Repack loose files in a repository.
     """Repack loose files in a repository.
 
 
     Currently this only packs loose objects.
     Currently this only packs loose objects.
@@ -3095,7 +3085,7 @@ def ls_tree(
 
 
 
 
 def remote_add(
 def remote_add(
-    repo: Union[str, os.PathLike, BaseRepo],
+    repo: RepoPath,
     name: Union[bytes, str],
     name: Union[bytes, str],
     url: Union[bytes, str],
     url: Union[bytes, str],
 ) -> None:
 ) -> None:
@@ -3172,9 +3162,7 @@ def _quote_path(path: str) -> str:
     return quoted
     return quoted
 
 
 
 
-def check_ignore(
-    repo: Union[str, os.PathLike, BaseRepo], paths, no_index=False, quote_path=True
-):
+def check_ignore(repo: RepoPath, paths, no_index=False, quote_path=True):
     r"""Debug gitignore files.
     r"""Debug gitignore files.
 
 
     Args:
     Args:
@@ -3226,9 +3214,7 @@ def check_ignore(
                 yield _quote_path(output_path) if quote_path else output_path
                 yield _quote_path(output_path) if quote_path else output_path
 
 
 
 
-def update_head(
-    repo: Union[str, os.PathLike, BaseRepo], target, detached=False, new_branch=None
-) -> None:
+def update_head(repo: RepoPath, target, detached=False, new_branch=None) -> None:
     """Update HEAD to point at a new branch/commit.
     """Update HEAD to point at a new branch/commit.
 
 
     Note that this does not actually update the working tree.
     Note that this does not actually update the working tree.
@@ -3581,16 +3567,16 @@ def sparse_checkout(
     with open_repo_closing(repo) as repo_obj:
     with open_repo_closing(repo) as repo_obj:
         # --- 0) Possibly infer 'cone' from config ---
         # --- 0) Possibly infer 'cone' from config ---
         if cone is None:
         if cone is None:
-            cone = repo_obj.infer_cone_mode()
+            cone = repo_obj.get_worktree().infer_cone_mode()
 
 
         # --- 1) Read or write patterns ---
         # --- 1) Read or write patterns ---
         if patterns is None:
         if patterns is None:
-            lines = repo_obj.get_sparse_checkout_patterns()
+            lines = repo_obj.get_worktree().get_sparse_checkout_patterns()
             if lines is None:
             if lines is None:
                 raise Error("No sparse checkout patterns found.")
                 raise Error("No sparse checkout patterns found.")
         else:
         else:
             lines = patterns
             lines = patterns
-            repo_obj.set_sparse_checkout_patterns(patterns)
+            repo_obj.get_worktree().set_sparse_checkout_patterns(patterns)
 
 
         # --- 2) Determine the set of included paths ---
         # --- 2) Determine the set of included paths ---
         index = repo_obj.open_index()
         index = repo_obj.open_index()
@@ -3621,7 +3607,7 @@ def cone_mode_init(repo: Union[str, os.PathLike, Repo]):
       None
       None
     """
     """
     with open_repo_closing(repo) as repo_obj:
     with open_repo_closing(repo) as repo_obj:
-        repo_obj.configure_for_cone_mode()
+        repo_obj.get_worktree().configure_for_cone_mode()
         patterns = ["/*", "!/*/"]  # root-level files only
         patterns = ["/*", "!/*/"]  # root-level files only
         sparse_checkout(repo_obj, patterns, force=True, cone=True)
         sparse_checkout(repo_obj, patterns, force=True, cone=True)
 
 
@@ -3642,9 +3628,9 @@ def cone_mode_set(repo: Union[str, os.PathLike, Repo], dirs, force=False):
       None
       None
     """
     """
     with open_repo_closing(repo) as repo_obj:
     with open_repo_closing(repo) as repo_obj:
-        repo_obj.configure_for_cone_mode()
-        repo_obj.set_cone_mode_patterns(dirs=dirs)
-        new_patterns = repo_obj.get_sparse_checkout_patterns()
+        repo_obj.get_worktree().configure_for_cone_mode()
+        repo_obj.get_worktree().set_cone_mode_patterns(dirs=dirs)
+        new_patterns = repo_obj.get_worktree().get_sparse_checkout_patterns()
         # Finally, apply the patterns and update the working tree
         # Finally, apply the patterns and update the working tree
         sparse_checkout(repo_obj, new_patterns, force=force, cone=True)
         sparse_checkout(repo_obj, new_patterns, force=force, cone=True)
 
 
@@ -3665,21 +3651,21 @@ def cone_mode_add(repo: Union[str, os.PathLike, Repo], dirs, force=False):
       None
       None
     """
     """
     with open_repo_closing(repo) as repo_obj:
     with open_repo_closing(repo) as repo_obj:
-        repo_obj.configure_for_cone_mode()
+        repo_obj.get_worktree().configure_for_cone_mode()
         # Do not pass base patterns as dirs
         # Do not pass base patterns as dirs
         base_patterns = ["/*", "!/*/"]
         base_patterns = ["/*", "!/*/"]
         existing_dirs = [
         existing_dirs = [
             pat.strip("/")
             pat.strip("/")
-            for pat in repo_obj.get_sparse_checkout_patterns()
+            for pat in repo_obj.get_worktree().get_sparse_checkout_patterns()
             if pat not in base_patterns
             if pat not in base_patterns
         ]
         ]
         added_dirs = existing_dirs + (dirs or [])
         added_dirs = existing_dirs + (dirs or [])
-        repo_obj.set_cone_mode_patterns(dirs=added_dirs)
-        new_patterns = repo_obj.get_sparse_checkout_patterns()
+        repo_obj.get_worktree().set_cone_mode_patterns(dirs=added_dirs)
+        new_patterns = repo_obj.get_worktree().get_sparse_checkout_patterns()
         sparse_checkout(repo_obj, patterns=new_patterns, force=force, cone=True)
         sparse_checkout(repo_obj, patterns=new_patterns, force=force, cone=True)
 
 
 
 
-def check_mailmap(repo: Union[str, os.PathLike, BaseRepo], contact):
+def check_mailmap(repo: RepoPath, contact):
     """Check canonical name and email of contact.
     """Check canonical name and email of contact.
 
 
     Args:
     Args:
@@ -3697,7 +3683,7 @@ def check_mailmap(repo: Union[str, os.PathLike, BaseRepo], contact):
         return mailmap.lookup(contact)
         return mailmap.lookup(contact)
 
 
 
 
-def fsck(repo: Union[str, os.PathLike, BaseRepo]):
+def fsck(repo: RepoPath):
     """Check a repository.
     """Check a repository.
 
 
     Args:
     Args:
@@ -3752,7 +3738,7 @@ def stash_drop(repo: Union[str, os.PathLike, Repo], index) -> None:
         stash.drop(index)
         stash.drop(index)
 
 
 
 
-def ls_files(repo: Union[str, os.PathLike, BaseRepo]):
+def ls_files(repo: RepoPath):
     """List all files in an index."""
     """List all files in an index."""
     with open_repo_closing(repo) as r:
     with open_repo_closing(repo) as r:
         return sorted(r.open_index())
         return sorted(r.open_index())
@@ -3825,10 +3811,12 @@ def describe(repo: Union[str, os.PathLike, Repo], abbrev=None):
             else:
             else:
                 # Lightweight tag case - obj is already the commit
                 # Lightweight tag case - obj is already the commit
                 commit = obj
                 commit = obj
-            
+
             if not isinstance(commit, Commit):
             if not isinstance(commit, Commit):
-                raise AssertionError(f"Expected Commit object, got {type(commit).__name__}")
-            
+                raise AssertionError(
+                    f"Expected Commit object, got {type(commit).__name__}"
+                )
+
             tags[tag] = [
             tags[tag] = [
                 datetime.datetime(*time.gmtime(commit.commit_time)[:6]),
                 datetime.datetime(*time.gmtime(commit.commit_time)[:6]),
                 commit.id.decode("ascii"),
                 commit.id.decode("ascii"),
@@ -3899,7 +3887,7 @@ def get_object_by_path(
         return r[sha]
         return r[sha]
 
 
 
 
-def write_tree(repo: Union[str, os.PathLike, BaseRepo]):
+def write_tree(repo: RepoPath):
     """Write a tree object from the index.
     """Write a tree object from the index.
 
 
     Args:
     Args:
@@ -4187,7 +4175,7 @@ def cherry_pick(
             except FileNotFoundError:
             except FileNotFoundError:
                 pass
                 pass
             # Reset index to HEAD
             # Reset index to HEAD
-            r.reset_index(r[b"HEAD"].tree)
+            r.get_worktree().reset_index(r[b"HEAD"].tree)
             return None
             return None
 
 
         # Handle continue
         # Handle continue
@@ -4270,7 +4258,7 @@ def cherry_pick(
 
 
         # Update working tree and index
         # Update working tree and index
         # Reset index to match merged tree
         # Reset index to match merged tree
-        r.reset_index(merged_tree.id)
+        r.get_worktree().reset_index(merged_tree.id)
 
 
         # Update working tree from the new index
         # Update working tree from the new index
         # Allow overwriting because we're applying the merge result
         # Allow overwriting because we're applying the merge result
@@ -4520,9 +4508,7 @@ def prune(
             r.object_store.prune(grace_period=grace_period)
             r.object_store.prune(grace_period=grace_period)
 
 
 
 
-def count_objects(
-    repo: Union[str, os.PathLike, BaseRepo] = ".", verbose=False
-) -> CountObjectsResult:
+def count_objects(repo: RepoPath = ".", verbose=False) -> CountObjectsResult:
     """Count unpacked objects and their disk usage.
     """Count unpacked objects and their disk usage.
 
 
     Args:
     Args:
@@ -4541,6 +4527,7 @@ def count_objects(
         for sha in object_store._iter_loose_objects():
         for sha in object_store._iter_loose_objects():
             loose_count += 1
             loose_count += 1
             from .object_store import DiskObjectStore
             from .object_store import DiskObjectStore
+
             assert isinstance(object_store, DiskObjectStore)
             assert isinstance(object_store, DiskObjectStore)
             path = object_store._get_shafile_path(sha)
             path = object_store._get_shafile_path(sha)
             try:
             try:
@@ -4669,7 +4656,7 @@ def rebase(
 
 
 
 
 def annotate(
 def annotate(
-    repo: Union[str, os.PathLike, BaseRepo],
+    repo: RepoPath,
     path,
     path,
     committish: Optional[Union[str, bytes, Commit, Tag]] = None,
     committish: Optional[Union[str, bytes, Commit, Tag]] = None,
 ):
 ):
@@ -5162,7 +5149,7 @@ def bisect_replay(repo: Union[str, os.PathLike, Repo], log_file):
         state.replay(log_content)
         state.replay(log_content)
 
 
 
 
-def reflog(repo: Union[str, os.PathLike, BaseRepo] = ".", ref=b"HEAD", all=False):
+def reflog(repo: RepoPath = ".", ref=b"HEAD", all=False):
     """Show reflog entries for a reference or all references.
     """Show reflog entries for a reference or all references.
 
 
     Args:
     Args:
@@ -5473,8 +5460,8 @@ def lfs_migrate(
                 files_to_migrate.append(path_str)
                 files_to_migrate.append(path_str)
 
 
         # Migrate files
         # Migrate files
-        for path in files_to_migrate:
-            full_path = os.path.join(r.path, path)
+        for path_str in files_to_migrate:
+            full_path = os.path.join(r.path, path_str)
             if not os.path.exists(full_path):
             if not os.path.exists(full_path):
                 continue
                 continue
 
 
@@ -5496,7 +5483,7 @@ def lfs_migrate(
 
 
             st = os.stat(full_path)
             st = os.stat(full_path)
             index_entry = index_entry_from_stat(st, blob.id, 0)
             index_entry = index_entry_from_stat(st, blob.id, 0)
-            path_bytes = path.encode() if isinstance(path, str) else path
+            path_bytes = path_str.encode() if isinstance(path_str, str) else path_str
             index[path_bytes] = index_entry
             index[path_bytes] = index_entry
 
 
             migrated += 1
             migrated += 1
@@ -5547,9 +5534,7 @@ def lfs_pointer_check(repo: Union[str, os.PathLike, Repo] = ".", paths=None):
         return results
         return results
 
 
 
 
-def lfs_fetch(
-    repo: Union[str, os.PathLike, Repo] = ".", remote="origin", refs=None
-):
+def lfs_fetch(repo: Union[str, os.PathLike, Repo] = ".", remote="origin", refs=None):
     """Fetch LFS objects from remote.
     """Fetch LFS objects from remote.
 
 
     Args:
     Args:
@@ -5806,7 +5791,9 @@ def lfs_status(repo: Union[str, os.PathLike, Repo] = "."):
                         pass
                         pass
                     else:
                     else:
                         if not isinstance(staged_obj, Blob):
                         if not isinstance(staged_obj, Blob):
-                            raise AssertionError(f"Expected Blob object, got {type(staged_obj).__name__}")
+                            raise AssertionError(
+                                f"Expected Blob object, got {type(staged_obj).__name__}"
+                            )
                         staged_pointer = LFSPointer.from_bytes(staged_obj.data)
                         staged_pointer = LFSPointer.from_bytes(staged_obj.data)
                         if staged_pointer and staged_pointer.oid != pointer.oid:
                         if staged_pointer and staged_pointer.oid != pointer.oid:
                             status["not_staged"].append(path_str)
                             status["not_staged"].append(path_str)

+ 2 - 2
dulwich/repo.py

@@ -1548,7 +1548,7 @@ class Repo(BaseRepo):
                         head = None
                         head = None
 
 
                 if checkout and head is not None:
                 if checkout and head is not None:
-                    target.reset_index()
+                    target.get_worktree().reset_index()
             except BaseException:
             except BaseException:
                 target.close()
                 target.close()
                 raise
                 raise
@@ -1822,7 +1822,7 @@ class Repo(BaseRepo):
         with open(os.path.join(worktree_controldir, "HEAD"), "wb") as f:
         with open(os.path.join(worktree_controldir, "HEAD"), "wb") as f:
             f.write(main_repo.head() + b"\n")
             f.write(main_repo.head() + b"\n")
         r = cls(os.path.normpath(path))
         r = cls(os.path.normpath(path))
-        r.reset_index()
+        r.get_worktree().reset_index()
         return r
         return r
 
 
     @classmethod
     @classmethod

+ 2 - 2
dulwich/stash.py

@@ -268,7 +268,7 @@ class Stash:
         # Create a dangling commit for the index state
         # Create a dangling commit for the index state
         # Note: We pass ref=None which is handled specially in do_commit
         # Note: We pass ref=None which is handled specially in do_commit
         # to create a commit without updating any reference
         # to create a commit without updating any reference
-        index_commit_id = self._repo.do_commit(
+        index_commit_id = self._repo.get_worktree().commit(
             tree=index_tree_id,
             tree=index_tree_id,
             message=b"Index stash",
             message=b"Index stash",
             merge_heads=[self._repo.head()],
             merge_heads=[self._repo.head()],
@@ -299,7 +299,7 @@ class Stash:
         # TODO(jelmer): Just pass parents into do_commit()?
         # TODO(jelmer): Just pass parents into do_commit()?
         self._repo.refs[self._ref] = self._repo.head()
         self._repo.refs[self._ref] = self._repo.head()
 
 
-        cid = self._repo.do_commit(
+        cid = self._repo.get_worktree().commit(
             ref=self._ref,
             ref=self._ref,
             tree=stash_tree_id,
             tree=stash_tree_id,
             message=message,
             message=message,

+ 1 - 1
dulwich/worktree.py

@@ -887,7 +887,7 @@ def add_worktree(
         wt_repo.refs.set_symbolic_ref(b"HEAD", branch)
         wt_repo.refs.set_symbolic_ref(b"HEAD", branch)
 
 
     # Reset index to match HEAD
     # Reset index to match HEAD
-    wt_repo.reset_index()
+    wt_repo.get_worktree().reset_index()
 
 
     return wt_repo
     return wt_repo
 
 

+ 1 - 1
examples/memoryrepo.py

@@ -27,7 +27,7 @@ local_repo.object_store.add_object(new_blob)
 last_tree.add(b"test", stat.S_IFREG, new_blob.id)
 last_tree.add(b"test", stat.S_IFREG, new_blob.id)
 local_repo.object_store.add_object(last_tree)
 local_repo.object_store.add_object(last_tree)
 
 
-local_repo.do_commit(
+local_repo.get_worktree().commit(
     message=b"Add a file called 'test'", ref=b"refs/heads/master", tree=last_tree.id
     message=b"Add a file called 'test'", ref=b"refs/heads/master", tree=last_tree.id
 )
 )
 
 

+ 8 - 6
examples/merge_driver.py

@@ -69,8 +69,10 @@ with open(config_path, "w") as f:
     json.dump(initial_config, f, indent=2)
     json.dump(initial_config, f, indent=2)
 
 
 # Add and commit initial files
 # Add and commit initial files
-repo.stage([".gitattributes", "config.json"])
-initial_commit = repo.do_commit(b"Initial commit", committer=b"Test <test@example.com>")
+repo.get_worktree().stage([".gitattributes", "config.json"])
+initial_commit = repo.get_worktree().commit(
+    b"Initial commit", committer=b"Test <test@example.com>"
+)
 
 
 # Register our custom merge driver globally
 # Register our custom merge driver globally
 registry = get_merge_driver_registry()
 registry = get_merge_driver_registry()
@@ -90,8 +92,8 @@ feature_config = {
 with open(config_path, "w") as f:
 with open(config_path, "w") as f:
     json.dump(feature_config, f, indent=2)
     json.dump(feature_config, f, indent=2)
 
 
-repo.stage(["config.json"])
-feature_commit = repo.do_commit(
+repo.get_worktree().stage(["config.json"])
+feature_commit = repo.get_worktree().commit(
     b"Add author and features", committer=b"Alice <alice@example.com>"
     b"Add author and features", committer=b"Alice <alice@example.com>"
 )
 )
 
 
@@ -108,8 +110,8 @@ master_config = {
 with open(config_path, "w") as f:
 with open(config_path, "w") as f:
     json.dump(master_config, f, indent=2)
     json.dump(master_config, f, indent=2)
 
 
-repo.stage(["config.json"])
-master_commit = repo.do_commit(
+repo.get_worktree().stage(["config.json"])
+master_commit = repo.get_worktree().commit(
     b"Add description and license", committer=b"Bob <bob@example.com>"
     b"Add description and license", committer=b"Bob <bob@example.com>"
 )
 )
 
 

+ 2 - 2
fuzzing/fuzz-targets/fuzz_repo.py

@@ -38,8 +38,8 @@ def TestOneInput(data) -> Optional[int]:
             return -1
             return -1
 
 
         try:
         try:
-            repo.stage(file_names)
-            repo.do_commit(
+            repo.get_worktree().stage(file_names)
+            repo.get_worktree().commit(
                 message=fdp.ConsumeRandomBytes(),
                 message=fdp.ConsumeRandomBytes(),
                 committer=fdp.ConsumeRandomBytes(),
                 committer=fdp.ConsumeRandomBytes(),
                 author=fdp.ConsumeRandomBytes(),
                 author=fdp.ConsumeRandomBytes(),

+ 1 - 1
tests/compat/test_client.py

@@ -130,7 +130,7 @@ class DulwichClientTestBase:
                 ("zop", "zop contents"),
                 ("zop", "zop contents"),
             ]:
             ]:
                 tree_id = self._add_file(local, tree_id, filename, contents)
                 tree_id = self._add_file(local, tree_id, filename, contents)
-                commit_id = local.do_commit(
+                commit_id = local.get_worktree().commit(
                     message=b"add " + filename.encode("utf-8"),
                     message=b"add " + filename.encode("utf-8"),
                     committer=b"Joe Example <joe@example.com>",
                     committer=b"Joe Example <joe@example.com>",
                     tree=tree_id,
                     tree=tree_id,

+ 2 - 2
tests/compat/test_dumb.py

@@ -191,7 +191,7 @@ class DumbHTTPClientNoPackTests(CompatTestCase):
                     dest_repo.refs[ref] = sha
                     dest_repo.refs[ref] = sha
 
 
             # Checkout files
             # Checkout files
-            dest_repo.reset_index()
+            dest_repo.get_worktree().reset_index()
 
 
             # Verify the clone
             # Verify the clone
             test_file = os.path.join(dest_path, "test0.txt")
             test_file = os.path.join(dest_path, "test0.txt")
@@ -245,7 +245,7 @@ class DumbHTTPClientNoPackTests(CompatTestCase):
                     dest_repo.refs[ref] = sha
                     dest_repo.refs[ref] = sha
 
 
             # Reset to new commit
             # Reset to new commit
-            dest_repo.reset_index()
+            dest_repo.get_worktree().reset_index()
 
 
             # Verify the new file exists
             # Verify the new file exists
             test_file2_dest = os.path.join(dest_path, "test2.txt")
             test_file2_dest = os.path.join(dest_path, "test2.txt")

+ 8 - 4
tests/compat/test_patch.py

@@ -53,9 +53,11 @@ class CompatPatchTestCase(CompatTestCase):
             with open(file_path, "w"):
             with open(file_path, "w"):
                 pass
                 pass
 
 
-        self.repo.stage(file_list)
+        self.repo.get_worktree().stage(file_list)
 
 
-        first_commit = self.repo.do_commit(b"The first commit")
+        first_commit = self.repo.get_worktree().commit(
+            message=b"The first commit",
+        )
 
 
         # Make a copy of the repository so we can apply the diff later
         # Make a copy of the repository so we can apply the diff later
         copy_path = os.path.join(self.test_dir, "copy")
         copy_path = os.path.join(self.test_dir, "copy")
@@ -70,9 +72,11 @@ class CompatPatchTestCase(CompatTestCase):
         with open(os.path.join(self.repo_path, "to_add"), "w"):
         with open(os.path.join(self.repo_path, "to_add"), "w"):
             pass
             pass
 
 
-        self.repo.stage(["to_modify", "to_delete", "to_add"])
+        self.repo.get_worktree().stage(["to_modify", "to_delete", "to_add"])
 
 
-        second_commit = self.repo.do_commit(b"The second commit")
+        second_commit = self.repo.get_worktree().commit(
+            message=b"The second commit",
+        )
 
 
         # Get the patch
         # Get the patch
         first_tree = self.repo[first_commit].tree
         first_tree = self.repo[first_commit].tree

+ 14 - 8
tests/contrib/test_swift_smoke.py

@@ -127,7 +127,7 @@ class SwiftRepoSmokeTest(unittest.TestCase):
 
 
         local_repo = repo.Repo.init(self.temp_d, mkdir=True)
         local_repo = repo.Repo.init(self.temp_d, mkdir=True)
         # Nothing in the staging area
         # Nothing in the staging area
-        local_repo.do_commit("Test commit", "fbo@localhost")
+        local_repo.get_worktree().commit("Test commit", "fbo@localhost")
         sha = local_repo.refs.read_loose_ref("refs/heads/master")
         sha = local_repo.refs.read_loose_ref("refs/heads/master")
         swift.SwiftRepo.init_bare(self.scon, self.conf)
         swift.SwiftRepo.init_bare(self.scon, self.conf)
         tcp_client = client.TCPGitClient(self.server_address, port=self.port)
         tcp_client = client.TCPGitClient(self.server_address, port=self.port)
@@ -144,7 +144,9 @@ class SwiftRepoSmokeTest(unittest.TestCase):
 
 
         local_repo = repo.Repo.init(self.temp_d, mkdir=True)
         local_repo = repo.Repo.init(self.temp_d, mkdir=True)
         # Nothing in the staging area
         # Nothing in the staging area
-        local_repo.do_commit("Test commit", "fbo@localhost", ref="refs/heads/mybranch")
+        local_repo.get_worktree().commit(
+            "Test commit", "fbo@localhost", ref="refs/heads/mybranch"
+        )
         sha = local_repo.refs.read_loose_ref("refs/heads/mybranch")
         sha = local_repo.refs.read_loose_ref("refs/heads/mybranch")
         swift.SwiftRepo.init_bare(self.scon, self.conf)
         swift.SwiftRepo.init_bare(self.scon, self.conf)
         tcp_client = client.TCPGitClient(self.server_address, port=self.port)
         tcp_client = client.TCPGitClient(self.server_address, port=self.port)
@@ -168,7 +170,7 @@ class SwiftRepoSmokeTest(unittest.TestCase):
         local_shas = {}
         local_shas = {}
         remote_shas = {}
         remote_shas = {}
         for branch in ("master", "mybranch", "pullr-108"):
         for branch in ("master", "mybranch", "pullr-108"):
-            local_shas[branch] = local_repo.do_commit(
+            local_shas[branch] = local_repo.get_worktree().commit(
                 f"Test commit {branch}",
                 f"Test commit {branch}",
                 "fbo@localhost",
                 "fbo@localhost",
                 ref=f"refs/heads/{branch}",
                 ref=f"refs/heads/{branch}",
@@ -194,8 +196,10 @@ class SwiftRepoSmokeTest(unittest.TestCase):
         for f in files:
         for f in files:
             open(os.path.join(self.temp_d, f), "w").write(f"DATA {i}")
             open(os.path.join(self.temp_d, f), "w").write(f"DATA {i}")
             i += 1
             i += 1
-        local_repo.stage(files)
-        local_repo.do_commit("Test commit", "fbo@localhost", ref="refs/heads/master")
+        local_repo.get_worktree().stage(files)
+        local_repo.get_worktree().commit(
+            "Test commit", "fbo@localhost", ref="refs/heads/master"
+        )
         swift.SwiftRepo.init_bare(self.scon, self.conf)
         swift.SwiftRepo.init_bare(self.scon, self.conf)
         tcp_client = client.TCPGitClient(self.server_address, port=self.port)
         tcp_client = client.TCPGitClient(self.server_address, port=self.port)
         tcp_client.send_pack(
         tcp_client.send_pack(
@@ -245,8 +249,10 @@ class SwiftRepoSmokeTest(unittest.TestCase):
         for f in files:
         for f in files:
             open(os.path.join(self.temp_d, f), "w").write(f"DATA {i}")
             open(os.path.join(self.temp_d, f), "w").write(f"DATA {i}")
             i += 1
             i += 1
-        local_repo.stage(files)
-        local_repo.do_commit("Test commit", "fbo@localhost", ref="refs/heads/master")
+        local_repo.get_worktree().stage(files)
+        local_repo.get_worktree().commit(
+            "Test commit", "fbo@localhost", ref="refs/heads/master"
+        )
         tcp_client.send_pack(
         tcp_client.send_pack(
             "/fakerepo", determine_wants, local_repo.generate_pack_data
             "/fakerepo", determine_wants, local_repo.generate_pack_data
         )
         )
@@ -277,7 +283,7 @@ class SwiftRepoSmokeTest(unittest.TestCase):
 
 
         local_repo = repo.Repo.init(self.temp_d, mkdir=True)
         local_repo = repo.Repo.init(self.temp_d, mkdir=True)
         # Nothing in the staging area
         # Nothing in the staging area
-        sha = local_repo.do_commit("Test commit", "fbo@localhost")
+        sha = local_repo.get_worktree().commit("Test commit", "fbo@localhost")
         otype, data = local_repo.object_store.get_raw(sha)
         otype, data = local_repo.object_store.get_raw(sha)
         commit = objects.ShaFile.from_raw_string(otype, data)
         commit = objects.ShaFile.from_raw_string(otype, data)
         tag = objects.Tag()
         tag = objects.Tag()

+ 3 - 3
tests/test_annotate.py

@@ -322,11 +322,11 @@ class IntegrationTestCase(TestCase):
             f.write(content)
             f.write(content)
 
 
         # Stage file
         # Stage file
-        self.repo.stage([filename.encode()])
+        self.repo.get_worktree().stage([filename.encode()])
 
 
         # Create commit
         # Create commit
-        commit_id = self.repo.do_commit(
-            message.encode(),
+        commit_id = self.repo.get_worktree().commit(
+            message=message.encode(),
             committer=b"Test Committer <test@example.com>",
             committer=b"Test Committer <test@example.com>",
             author=b"Test Author <test@example.com>",
             author=b"Test Author <test@example.com>",
             commit_timestamp=1000000000,
             commit_timestamp=1000000000,

+ 10 - 10
tests/test_cli.py

@@ -945,7 +945,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         # Initial commit
         # Initial commit
         tree1 = Tree()
         tree1 = Tree()
         self.repo.object_store.add_object(tree1)
         self.repo.object_store.add_object(tree1)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"Initial commit",
             message=b"Initial commit",
             tree=tree1.id,
             tree=tree1.id,
         )
         )
@@ -956,7 +956,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         tree2 = Tree()
         tree2 = Tree()
         tree2.add(b"hello.txt", 0o100644, blob.id)
         tree2.add(b"hello.txt", 0o100644, blob.id)
         self.repo.object_store.add_object(tree2)
         self.repo.object_store.add_object(tree2)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"Add hello.txt",
             message=b"Add hello.txt",
             tree=tree2.id,
             tree=tree2.id,
         )
         )
@@ -990,7 +990,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         # Initial commit
         # Initial commit
         tree1 = Tree()
         tree1 = Tree()
         self.repo.object_store.add_object(tree1)
         self.repo.object_store.add_object(tree1)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"Initial commit",
             message=b"Initial commit",
             tree=tree1.id,
             tree=tree1.id,
         )
         )
@@ -1001,7 +1001,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         tree2 = Tree()
         tree2 = Tree()
         tree2.add(b"file1.txt", 0o100644, blob1.id)
         tree2.add(b"file1.txt", 0o100644, blob1.id)
         self.repo.object_store.add_object(tree2)
         self.repo.object_store.add_object(tree2)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"Add file1.txt",
             message=b"Add file1.txt",
             tree=tree2.id,
             tree=tree2.id,
         )
         )
@@ -1013,7 +1013,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         tree3.add(b"file1.txt", 0o100644, blob1.id)
         tree3.add(b"file1.txt", 0o100644, blob1.id)
         tree3.add(b"file2.txt", 0o100644, blob2.id)
         tree3.add(b"file2.txt", 0o100644, blob2.id)
         self.repo.object_store.add_object(tree3)
         self.repo.object_store.add_object(tree3)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"Add file2.txt",
             message=b"Add file2.txt",
             tree=tree3.id,
             tree=tree3.id,
         )
         )
@@ -1049,7 +1049,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         tree = Tree()
         tree = Tree()
         tree.add(b"test.txt", 0o100644, blob.id)
         tree.add(b"test.txt", 0o100644, blob.id)
         self.repo.object_store.add_object(tree)
         self.repo.object_store.add_object(tree)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"Test commit",
             message=b"Test commit",
             tree=tree.id,
             tree=tree.id,
         )
         )
@@ -1083,7 +1083,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         tree0 = Tree()
         tree0 = Tree()
         self.repo.object_store.add_object(tree0)
         self.repo.object_store.add_object(tree0)
         trees.append(tree0)
         trees.append(tree0)
-        c0 = self.repo.do_commit(
+        c0 = self.repo.get_worktree().commit(
             message=b"Initial commit",
             message=b"Initial commit",
             tree=tree0.id,
             tree=tree0.id,
         )
         )
@@ -1103,7 +1103,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
             self.repo.object_store.add_object(tree)
             self.repo.object_store.add_object(tree)
             trees.append(tree)
             trees.append(tree)
 
 
-            c = self.repo.do_commit(
+            c = self.repo.get_worktree().commit(
                 message=f"Add file{i}.txt".encode(),
                 message=f"Add file{i}.txt".encode(),
                 tree=tree.id,
                 tree=tree.id,
             )
             )
@@ -1145,7 +1145,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         self.repo.object_store.add_object(blob1)
         self.repo.object_store.add_object(blob1)
         tree1.add(b"file.txt", 0o100644, blob1.id)
         tree1.add(b"file.txt", 0o100644, blob1.id)
         self.repo.object_store.add_object(tree1)
         self.repo.object_store.add_object(tree1)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"Initial commit",
             message=b"Initial commit",
             tree=tree1.id,
             tree=tree1.id,
         )
         )
@@ -1155,7 +1155,7 @@ class FormatPatchCommandTest(DulwichCliTestCase):
         self.repo.object_store.add_object(blob2)
         self.repo.object_store.add_object(blob2)
         tree2.add(b"file.txt", 0o100644, blob2.id)
         tree2.add(b"file.txt", 0o100644, blob2.id)
         self.repo.object_store.add_object(tree2)
         self.repo.object_store.add_object(tree2)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"Modify file.txt",
             message=b"Modify file.txt",
             tree=tree2.id,
             tree=tree2.id,
         )
         )

+ 4 - 4
tests/test_cli_cherry_pick.py

@@ -52,7 +52,7 @@ class CherryPickCommandTests(TestCase):
 
 
                 # Create a branch and switch to it
                 # Create a branch and switch to it
                 porcelain.branch_create(".", "feature")
                 porcelain.branch_create(".", "feature")
-                porcelain.checkout_branch(".", "feature")
+                porcelain.checkout(".", "feature")
 
 
                 # Add a file on feature branch
                 # Add a file on feature branch
                 with open("file2.txt", "w") as f:
                 with open("file2.txt", "w") as f:
@@ -61,7 +61,7 @@ class CherryPickCommandTests(TestCase):
                 feature_commit = porcelain.commit(".", message=b"Add feature file")
                 feature_commit = porcelain.commit(".", message=b"Add feature file")
 
 
                 # Go back to master
                 # Go back to master
-                porcelain.checkout_branch(".", "master")
+                porcelain.checkout(".", "master")
 
 
                 # Cherry-pick via CLI
                 # Cherry-pick via CLI
                 cmd = cmd_cherry_pick()
                 cmd = cmd_cherry_pick()
@@ -91,7 +91,7 @@ class CherryPickCommandTests(TestCase):
 
 
                 # Create a branch and switch to it
                 # Create a branch and switch to it
                 porcelain.branch_create(".", "feature")
                 porcelain.branch_create(".", "feature")
-                porcelain.checkout_branch(".", "feature")
+                porcelain.checkout(".", "feature")
 
 
                 # Add a file on feature branch
                 # Add a file on feature branch
                 with open("file2.txt", "w") as f:
                 with open("file2.txt", "w") as f:
@@ -100,7 +100,7 @@ class CherryPickCommandTests(TestCase):
                 feature_commit = porcelain.commit(".", message=b"Add feature file")
                 feature_commit = porcelain.commit(".", message=b"Add feature file")
 
 
                 # Go back to master
                 # Go back to master
-                porcelain.checkout_branch(".", "master")
+                porcelain.checkout(".", "master")
 
 
                 # Cherry-pick with --no-commit
                 # Cherry-pick with --no-commit
                 cmd = cmd_cherry_pick()
                 cmd = cmd_cherry_pick()

+ 10 - 10
tests/test_cli_merge.py

@@ -50,7 +50,7 @@ class CLIMergeTests(TestCase):
 
 
             # Create a branch
             # Create a branch
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -59,7 +59,7 @@ class CLIMergeTests(TestCase):
             porcelain.commit(tmpdir, message=b"Add feature")
             porcelain.commit(tmpdir, message=b"Add feature")
 
 
             # Go back to master
             # Go back to master
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
 
 
             # Test merge via CLI
             # Test merge via CLI
             old_cwd = os.getcwd()
             old_cwd = os.getcwd()
@@ -91,14 +91,14 @@ class CLIMergeTests(TestCase):
 
 
             # Create a branch and modify file1
             # Create a branch and modify file1
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Feature content\n")
                 f.write("Feature content\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.commit(tmpdir, message=b"Modify file1 in feature")
             porcelain.commit(tmpdir, message=b"Modify file1 in feature")
 
 
             # Go back to master and modify file1 differently
             # Go back to master and modify file1 differently
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Master content\n")
                 f.write("Master content\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])
@@ -157,7 +157,7 @@ class CLIMergeTests(TestCase):
 
 
             # Create a branch
             # Create a branch
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -166,7 +166,7 @@ class CLIMergeTests(TestCase):
             porcelain.commit(tmpdir, message=b"Add feature")
             porcelain.commit(tmpdir, message=b"Add feature")
 
 
             # Go back to master and add another file
             # Go back to master and add another file
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
             with open(os.path.join(tmpdir, "file3.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file3.txt"), "w") as f:
                 f.write("Master content\n")
                 f.write("Master content\n")
             porcelain.add(tmpdir, paths=["file3.txt"])
             porcelain.add(tmpdir, paths=["file3.txt"])
@@ -203,7 +203,7 @@ class CLIMergeTests(TestCase):
 
 
             # Create a branch
             # Create a branch
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -212,7 +212,7 @@ class CLIMergeTests(TestCase):
             porcelain.commit(tmpdir, message=b"Add feature")
             porcelain.commit(tmpdir, message=b"Add feature")
 
 
             # Go back to master
             # Go back to master
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
 
 
             # Test merge via CLI with --no-ff
             # Test merge via CLI with --no-ff
             old_cwd = os.getcwd()
             old_cwd = os.getcwd()
@@ -242,7 +242,7 @@ class CLIMergeTests(TestCase):
 
 
             # Create a branch
             # Create a branch
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -251,7 +251,7 @@ class CLIMergeTests(TestCase):
             porcelain.commit(tmpdir, message=b"Add feature")
             porcelain.commit(tmpdir, message=b"Add feature")
 
 
             # Go back to master and add another file
             # Go back to master and add another file
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
             with open(os.path.join(tmpdir, "file3.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file3.txt"), "w") as f:
                 f.write("Master content\n")
                 f.write("Master content\n")
             porcelain.add(tmpdir, paths=["file3.txt"])
             porcelain.add(tmpdir, paths=["file3.txt"])

+ 30 - 6
tests/test_grafts.py

@@ -159,9 +159,15 @@ class GraftsInRepoTests(GraftsInRepositoryBase, TestCase):
             "author_timezone": 0,
             "author_timezone": 0,
         }
         }
 
 
-        self._shas.append(r.do_commit(b"empty commit", **commit_kwargs))
-        self._shas.append(r.do_commit(b"empty commit", **commit_kwargs))
-        self._shas.append(r.do_commit(b"empty commit", **commit_kwargs))
+        self._shas.append(
+            r.get_worktree().commit(message=b"empty commit", **commit_kwargs)
+        )
+        self._shas.append(
+            r.get_worktree().commit(message=b"empty commit", **commit_kwargs)
+        )
+        self._shas.append(
+            r.get_worktree().commit(message=b"empty commit", **commit_kwargs)
+        )
 
 
     def test_init_with_empty_info_grafts(self) -> None:
     def test_init_with_empty_info_grafts(self) -> None:
         r = self._repo
         r = self._repo
@@ -191,6 +197,7 @@ class GraftsInMemoryRepoTests(GraftsInRepositoryBase, TestCase):
         self._shas = []
         self._shas = []
 
 
         tree = Tree()
         tree = Tree()
+        r.object_store.add_object(tree)
 
 
         commit_kwargs = {
         commit_kwargs = {
             "committer": b"Test Committer <test@nodomain.com>",
             "committer": b"Test Committer <test@nodomain.com>",
@@ -202,6 +209,23 @@ class GraftsInMemoryRepoTests(GraftsInRepositoryBase, TestCase):
             "tree": tree.id,
             "tree": tree.id,
         }
         }
 
 
-        self._shas.append(r.do_commit(b"empty commit", **commit_kwargs))
-        self._shas.append(r.do_commit(b"empty commit", **commit_kwargs))
-        self._shas.append(r.do_commit(b"empty commit", **commit_kwargs))
+        # Create commits directly for MemoryRepo since it doesn't support worktree
+        from dulwich.objects import Commit
+
+        for i in range(3):
+            c = Commit()
+            c.message = b"empty commit"
+            c.committer = commit_kwargs["committer"]
+            c.author = commit_kwargs["author"]
+            c.commit_time = commit_kwargs["commit_timestamp"]
+            c.commit_timezone = commit_kwargs["commit_timezone"]
+            c.author_time = commit_kwargs["author_timestamp"]
+            c.author_timezone = commit_kwargs["author_timezone"]
+            c.tree = commit_kwargs["tree"]
+            if self._shas:
+                c.parents = [self._shas[-1]]
+            r.object_store.add_object(c)
+            self._shas.append(c.id)
+
+        # Set HEAD to point to the last commit
+        r.refs[b"HEAD"] = self._shas[-1]

+ 24 - 20
tests/test_index.py

@@ -837,11 +837,11 @@ class GetUnstagedChangesTests(TestCase):
             with open(foo2_fullpath, "wb") as f:
             with open(foo2_fullpath, "wb") as f:
                 f.write(b"origstuff")
                 f.write(b"origstuff")
 
 
-            repo.stage(["foo1", "foo2"])
-            repo.do_commit(
-                b"test status",
-                author=b"author <email>",
+            repo.get_worktree().stage(["foo1", "foo2"])
+            repo.get_worktree().commit(
+                message=b"test status",
                 committer=b"committer <email>",
                 committer=b"committer <email>",
+                author=b"author <email>",
             )
             )
 
 
             with open(foo1_fullpath, "wb") as f:
             with open(foo1_fullpath, "wb") as f:
@@ -864,11 +864,11 @@ class GetUnstagedChangesTests(TestCase):
             with open(foo1_fullpath, "wb") as f:
             with open(foo1_fullpath, "wb") as f:
                 f.write(b"origstuff")
                 f.write(b"origstuff")
 
 
-            repo.stage(["foo1"])
-            repo.do_commit(
-                b"test status",
-                author=b"author <email>",
+            repo.get_worktree().stage(["foo1"])
+            repo.get_worktree().commit(
+                message=b"test status",
                 committer=b"committer <email>",
                 committer=b"committer <email>",
+                author=b"author <email>",
             )
             )
 
 
             os.unlink(foo1_fullpath)
             os.unlink(foo1_fullpath)
@@ -887,11 +887,11 @@ class GetUnstagedChangesTests(TestCase):
             with open(foo1_fullpath, "wb") as f:
             with open(foo1_fullpath, "wb") as f:
                 f.write(b"origstuff")
                 f.write(b"origstuff")
 
 
-            repo.stage(["foo1"])
-            repo.do_commit(
-                b"test status",
-                author=b"author <email>",
+            repo.get_worktree().stage(["foo1"])
+            repo.get_worktree().commit(
+                message=b"test status",
                 committer=b"committer <email>",
                 committer=b"committer <email>",
+                author=b"author <email>",
             )
             )
 
 
             os.remove(foo1_fullpath)
             os.remove(foo1_fullpath)
@@ -912,11 +912,11 @@ class GetUnstagedChangesTests(TestCase):
             with open(foo1_fullpath, "wb") as f:
             with open(foo1_fullpath, "wb") as f:
                 f.write(b"origstuff")
                 f.write(b"origstuff")
 
 
-            repo.stage(["foo1"])
-            repo.do_commit(
-                b"test status",
-                author=b"author <email>",
+            repo.get_worktree().stage(["foo1"])
+            repo.get_worktree().commit(
+                message=b"test status",
                 committer=b"committer <email>",
                 committer=b"committer <email>",
+                author=b"author <email>",
             )
             )
 
 
             os.remove(foo1_fullpath)
             os.remove(foo1_fullpath)
@@ -1184,8 +1184,10 @@ class TestIndexEntryFromPath(TestCase):
         with open(test_file, "wb") as f:
         with open(test_file, "wb") as f:
             f.write(b"test content")
             f.write(b"test content")
 
 
-        submodule_repo.stage(["testfile"])
-        commit_id = submodule_repo.do_commit(b"Test commit for submodule")
+        submodule_repo.get_worktree().stage(["testfile"])
+        commit_id = submodule_repo.get_worktree().commit(
+            message=b"Test commit for submodule",
+        )
 
 
         # Test reading the HEAD
         # Test reading the HEAD
         head_sha = read_submodule_head(sub_repo_dir)
         head_sha = read_submodule_head(sub_repo_dir)
@@ -1241,8 +1243,10 @@ class TestIndexEntryFromPath(TestCase):
         with open(test_file, "wb") as f:
         with open(test_file, "wb") as f:
             f.write(b"test content")
             f.write(b"test content")
 
 
-        submodule_repo.stage(["testfile"])
-        commit_id = submodule_repo.do_commit(b"Test commit for submodule")
+        submodule_repo.get_worktree().stage(["testfile"])
+        commit_id = submodule_repo.get_worktree().commit(
+            message=b"Test commit for submodule",
+        )
 
 
         # Create an entry with the correct commit SHA
         # Create an entry with the correct commit SHA
         correct_entry = IndexEntry(
         correct_entry = IndexEntry(

+ 2 - 2
tests/test_lfs.py

@@ -238,7 +238,7 @@ class LFSIntegrationTests(TestCase):
             f.write(large_content)
             f.write(large_content)
 
 
         # Add files to repo
         # Add files to repo
-        self.repo.stage([".gitattributes", "large.bin"])
+        self.repo.get_worktree().stage([".gitattributes", "large.bin"])
 
 
         # Get the blob for large.bin from the index
         # Get the blob for large.bin from the index
         index = self.repo.open_index()
         index = self.repo.open_index()
@@ -390,7 +390,7 @@ class LFSIntegrationTests(TestCase):
         porcelain.commit(self.repo, message=b"Add LFS file")
         porcelain.commit(self.repo, message=b"Add LFS file")
 
 
         # Reset index to trigger checkout with filter
         # Reset index to trigger checkout with filter
-        self.repo.reset_index()
+        self.repo.get_worktree().reset_index()
 
 
         # Check file content
         # Check file content
         with open(pointer_file, "rb") as f:
         with open(pointer_file, "rb") as f:

+ 6 - 6
tests/test_porcelain.py

@@ -6260,14 +6260,14 @@ class ReceivePackTests(PorcelainTestCase):
         with open(fullpath, "w") as f:
         with open(fullpath, "w") as f:
             f.write("stuff")
             f.write("stuff")
         porcelain.add(repo=self.repo.path, paths=fullpath)
         porcelain.add(repo=self.repo.path, paths=fullpath)
-        self.repo.do_commit(
+        self.repo.get_worktree().commit(
             message=b"test status",
             message=b"test status",
-            author=b"author <email>",
             committer=b"committer <email>",
             committer=b"committer <email>",
-            author_timestamp=1402354300,
+            author=b"author <email>",
             commit_timestamp=1402354300,
             commit_timestamp=1402354300,
-            author_timezone=0,
             commit_timezone=0,
             commit_timezone=0,
+            author_timestamp=1402354300,
+            author_timezone=0,
         )
         )
         outf = BytesIO()
         outf = BytesIO()
         exitcode = porcelain.receive_pack(self.repo.path, BytesIO(b"0000"), outf)
         exitcode = porcelain.receive_pack(self.repo.path, BytesIO(b"0000"), outf)
@@ -6837,7 +6837,7 @@ class CheckIgnoreTests(PorcelainTestCase):
         path = os.path.join(self.repo.path, "foo")
         path = os.path.join(self.repo.path, "foo")
         with open(path, "w") as f:
         with open(path, "w") as f:
             f.write("BAR")
             f.write("BAR")
-        self.repo.stage(["foo"])
+        self.repo.get_worktree().stage(["foo"])
         with open(os.path.join(self.repo.path, ".gitignore"), "w") as f:
         with open(os.path.join(self.repo.path, ".gitignore"), "w") as f:
             f.write("foo\n")
             f.write("foo\n")
         self.assertEqual([], list(porcelain.check_ignore(self.repo, [path])))
         self.assertEqual([], list(porcelain.check_ignore(self.repo, [path])))
@@ -6849,7 +6849,7 @@ class CheckIgnoreTests(PorcelainTestCase):
     def test_check_added_rel(self) -> None:
     def test_check_added_rel(self) -> None:
         with open(os.path.join(self.repo.path, "foo"), "w") as f:
         with open(os.path.join(self.repo.path, "foo"), "w") as f:
             f.write("BAR")
             f.write("BAR")
-        self.repo.stage(["foo"])
+        self.repo.get_worktree().stage(["foo"])
         with open(os.path.join(self.repo.path, ".gitignore"), "w") as f:
         with open(os.path.join(self.repo.path, ".gitignore"), "w") as f:
             f.write("foo\n")
             f.write("foo\n")
         cwd = os.getcwd()
         cwd = os.getcwd()

+ 9 - 9
tests/test_porcelain_cherry_pick.py

@@ -46,7 +46,7 @@ class PorcelainCherryPickTests(TestCase):
 
 
             # Create a branch and switch to it
             # Create a branch and switch to it
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -55,7 +55,7 @@ class PorcelainCherryPickTests(TestCase):
             feature_commit = porcelain.commit(tmpdir, message=b"Add feature file")
             feature_commit = porcelain.commit(tmpdir, message=b"Add feature file")
 
 
             # Go back to master
             # Go back to master
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
 
 
             # Cherry-pick the feature commit
             # Cherry-pick the feature commit
             new_commit = porcelain.cherry_pick(tmpdir, feature_commit)
             new_commit = porcelain.cherry_pick(tmpdir, feature_commit)
@@ -81,7 +81,7 @@ class PorcelainCherryPickTests(TestCase):
 
 
             # Create a branch and switch to it
             # Create a branch and switch to it
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -90,7 +90,7 @@ class PorcelainCherryPickTests(TestCase):
             feature_commit = porcelain.commit(tmpdir, message=b"Add feature file")
             feature_commit = porcelain.commit(tmpdir, message=b"Add feature file")
 
 
             # Go back to master
             # Go back to master
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
 
 
             # Cherry-pick with no-commit
             # Cherry-pick with no-commit
             result = porcelain.cherry_pick(tmpdir, feature_commit, no_commit=True)
             result = porcelain.cherry_pick(tmpdir, feature_commit, no_commit=True)
@@ -119,7 +119,7 @@ class PorcelainCherryPickTests(TestCase):
 
 
             # Create a branch and modify the file
             # Create a branch and modify the file
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Feature modification\n")
                 f.write("Feature modification\n")
@@ -127,7 +127,7 @@ class PorcelainCherryPickTests(TestCase):
             feature_commit = porcelain.commit(tmpdir, message=b"Modify file on feature")
             feature_commit = porcelain.commit(tmpdir, message=b"Modify file on feature")
 
 
             # Go back to master and make a different modification
             # Go back to master and make a different modification
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Master modification\n")
                 f.write("Master modification\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])
@@ -154,7 +154,7 @@ class PorcelainCherryPickTests(TestCase):
 
 
             # Create another branch with a different initial commit
             # Create another branch with a different initial commit
             porcelain.branch_create(tmpdir, "other")
             porcelain.branch_create(tmpdir, "other")
-            porcelain.checkout_branch(tmpdir, "other")
+            porcelain.checkout(tmpdir, "other")
 
 
             # Try to cherry-pick root commit - should fail
             # Try to cherry-pick root commit - should fail
             with self.assertRaises(porcelain.Error) as cm:
             with self.assertRaises(porcelain.Error) as cm:
@@ -176,7 +176,7 @@ class PorcelainCherryPickTests(TestCase):
 
 
             # Create branch and make conflicting changes
             # Create branch and make conflicting changes
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Feature content\n")
                 f.write("Feature content\n")
@@ -184,7 +184,7 @@ class PorcelainCherryPickTests(TestCase):
             feature_commit = porcelain.commit(tmpdir, message=b"Feature change")
             feature_commit = porcelain.commit(tmpdir, message=b"Feature change")
 
 
             # Go back to master and make different change
             # Go back to master and make different change
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Master content\n")
                 f.write("Master content\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])

+ 1 - 1
tests/test_porcelain_filters.py

@@ -207,7 +207,7 @@ class PorcelainFilterTests(TestCase):
         target_config.write_to_path()
         target_config.write_to_path()
 
 
         # Now checkout the files with autocrlf enabled
         # Now checkout the files with autocrlf enabled
-        target_repo.reset_index()
+        target_repo.get_worktree().reset_index()
 
 
         # Check that the working tree file has CRLF endings
         # Check that the working tree file has CRLF endings
         target_file = os.path.join(target_dir, "test.txt")
         target_file = os.path.join(target_dir, "test.txt")

+ 16 - 16
tests/test_porcelain_merge.py

@@ -48,7 +48,7 @@ class PorcelainMergeTests(TestCase):
 
 
             # Create a branch
             # Create a branch
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -57,7 +57,7 @@ class PorcelainMergeTests(TestCase):
             feature_commit = porcelain.commit(tmpdir, message=b"Add feature")
             feature_commit = porcelain.commit(tmpdir, message=b"Add feature")
 
 
             # Go back to master
             # Go back to master
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
 
 
             # Merge feature branch (should fast-forward)
             # Merge feature branch (should fast-forward)
             merge_commit, conflicts = porcelain.merge(tmpdir, "feature")
             merge_commit, conflicts = porcelain.merge(tmpdir, "feature")
@@ -100,7 +100,7 @@ class PorcelainMergeTests(TestCase):
 
 
             # Create a branch
             # Create a branch
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -109,7 +109,7 @@ class PorcelainMergeTests(TestCase):
             feature_commit = porcelain.commit(tmpdir, message=b"Add feature")
             feature_commit = porcelain.commit(tmpdir, message=b"Add feature")
 
 
             # Go back to master
             # Go back to master
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
 
 
             # Merge feature branch with no-ff
             # Merge feature branch with no-ff
             merge_commit, conflicts = porcelain.merge(tmpdir, "feature", no_ff=True)
             merge_commit, conflicts = porcelain.merge(tmpdir, "feature", no_ff=True)
@@ -140,14 +140,14 @@ class PorcelainMergeTests(TestCase):
 
 
             # Create a branch and modify file1
             # Create a branch and modify file1
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Feature content\n")
                 f.write("Feature content\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.commit(tmpdir, message=b"Modify file1 in feature")
             porcelain.commit(tmpdir, message=b"Modify file1 in feature")
 
 
             # Go back to master and modify file2
             # Go back to master and modify file2
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
                 f.write("Master file2\n")
                 f.write("Master file2\n")
             porcelain.add(tmpdir, paths=["file2.txt"])
             porcelain.add(tmpdir, paths=["file2.txt"])
@@ -179,14 +179,14 @@ class PorcelainMergeTests(TestCase):
 
 
             # Create a branch and modify file1
             # Create a branch and modify file1
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Feature content\n")
                 f.write("Feature content\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.commit(tmpdir, message=b"Modify file1 in feature")
             porcelain.commit(tmpdir, message=b"Modify file1 in feature")
 
 
             # Go back to master and modify file1 differently
             # Go back to master and modify file1 differently
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Master content\n")
                 f.write("Master content\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])
@@ -220,7 +220,7 @@ class PorcelainMergeTests(TestCase):
 
 
             # Create a branch
             # Create a branch
             porcelain.branch_create(tmpdir, "feature")
             porcelain.branch_create(tmpdir, "feature")
-            porcelain.checkout_branch(tmpdir, "feature")
+            porcelain.checkout(tmpdir, "feature")
 
 
             # Add a file on feature branch
             # Add a file on feature branch
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -229,7 +229,7 @@ class PorcelainMergeTests(TestCase):
             porcelain.commit(tmpdir, message=b"Add feature")
             porcelain.commit(tmpdir, message=b"Add feature")
 
 
             # Go back to master and add another file
             # Go back to master and add another file
-            porcelain.checkout_branch(tmpdir, "master")
+            porcelain.checkout(tmpdir, "master")
             with open(os.path.join(tmpdir, "file3.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file3.txt"), "w") as f:
                 f.write("Master content\n")
                 f.write("Master content\n")
             porcelain.add(tmpdir, paths=["file3.txt"])
             porcelain.add(tmpdir, paths=["file3.txt"])
@@ -293,7 +293,7 @@ class PorcelainMergeTreeTests(TestCase):
 
 
             # Create our branch
             # Create our branch
             porcelain.branch_create(tmpdir, "ours")
             porcelain.branch_create(tmpdir, "ours")
-            porcelain.checkout_branch(tmpdir, "ours")
+            porcelain.checkout(tmpdir, "ours")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Our content\n")
                 f.write("Our content\n")
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file2.txt"), "w") as f:
@@ -302,9 +302,9 @@ class PorcelainMergeTreeTests(TestCase):
             our_commit = porcelain.commit(tmpdir, message=b"Our commit")
             our_commit = porcelain.commit(tmpdir, message=b"Our commit")
 
 
             # Create their branch
             # Create their branch
-            porcelain.checkout_branch(tmpdir, b"master")
+            porcelain.checkout(tmpdir, b"master")
             porcelain.branch_create(tmpdir, "theirs")
             porcelain.branch_create(tmpdir, "theirs")
-            porcelain.checkout_branch(tmpdir, "theirs")
+            porcelain.checkout(tmpdir, "theirs")
             with open(os.path.join(tmpdir, "file3.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file3.txt"), "w") as f:
                 f.write("Their new file\n")
                 f.write("Their new file\n")
             porcelain.add(tmpdir, paths=["file3.txt"])
             porcelain.add(tmpdir, paths=["file3.txt"])
@@ -340,16 +340,16 @@ class PorcelainMergeTreeTests(TestCase):
 
 
             # Create our branch with changes
             # Create our branch with changes
             porcelain.branch_create(tmpdir, "ours")
             porcelain.branch_create(tmpdir, "ours")
-            porcelain.checkout_branch(tmpdir, "ours")
+            porcelain.checkout(tmpdir, "ours")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Our content\n")
                 f.write("Our content\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])
             our_commit = porcelain.commit(tmpdir, message=b"Our commit")
             our_commit = porcelain.commit(tmpdir, message=b"Our commit")
 
 
             # Create their branch with conflicting changes
             # Create their branch with conflicting changes
-            porcelain.checkout_branch(tmpdir, b"master")
+            porcelain.checkout(tmpdir, b"master")
             porcelain.branch_create(tmpdir, "theirs")
             porcelain.branch_create(tmpdir, "theirs")
-            porcelain.checkout_branch(tmpdir, "theirs")
+            porcelain.checkout(tmpdir, "theirs")
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
             with open(os.path.join(tmpdir, "file1.txt"), "w") as f:
                 f.write("Their content\n")
                 f.write("Their content\n")
             porcelain.add(tmpdir, paths=["file1.txt"])
             porcelain.add(tmpdir, paths=["file1.txt"])

+ 6 - 6
tests/test_rebase.py

@@ -385,9 +385,9 @@ class RebasePorcelainTestCase(TestCase):
         with open(os.path.join(self.test_dir, "README.md"), "wb") as f:
         with open(os.path.join(self.test_dir, "README.md"), "wb") as f:
             f.write(b"# Test Repository\n")
             f.write(b"# Test Repository\n")
 
 
-        self.repo.stage(["README.md"])
-        self.initial_commit = self.repo.do_commit(
-            b"Initial commit",
+        self.repo.get_worktree().stage(["README.md"])
+        self.initial_commit = self.repo.get_worktree().commit(
+            message=b"Initial commit",
             committer=b"Test User <test@example.com>",
             committer=b"Test User <test@example.com>",
             author=b"Test User <test@example.com>",
             author=b"Test User <test@example.com>",
         )
         )
@@ -404,7 +404,7 @@ class RebasePorcelainTestCase(TestCase):
 
 
         # Create and checkout feature branch
         # Create and checkout feature branch
         self.repo.refs[b"refs/heads/feature"] = self.initial_commit
         self.repo.refs[b"refs/heads/feature"] = self.initial_commit
-        porcelain.checkout_branch(self.repo, "feature")
+        porcelain.checkout(self.repo, "feature")
 
 
         # Add commit to feature branch
         # Add commit to feature branch
         with open(os.path.join(self.test_dir, "feature.txt"), "wb") as f:
         with open(os.path.join(self.test_dir, "feature.txt"), "wb") as f:
@@ -419,7 +419,7 @@ class RebasePorcelainTestCase(TestCase):
         )
         )
 
 
         # Switch to main and add different commit
         # Switch to main and add different commit
-        porcelain.checkout_branch(self.repo, "master")
+        porcelain.checkout(self.repo, "master")
 
 
         with open(os.path.join(self.test_dir, "main.txt"), "wb") as f:
         with open(os.path.join(self.test_dir, "main.txt"), "wb") as f:
             f.write(b"Main file\n")
             f.write(b"Main file\n")
@@ -433,7 +433,7 @@ class RebasePorcelainTestCase(TestCase):
         )
         )
 
 
         # Switch back to feature and rebase
         # Switch back to feature and rebase
-        porcelain.checkout_branch(self.repo, "feature")
+        porcelain.checkout(self.repo, "feature")
 
 
         # Perform rebase
         # Perform rebase
         new_shas = porcelain.rebase(self.repo, "master")
         new_shas = porcelain.rebase(self.repo, "master")

+ 108 - 88
tests/test_repository.py

@@ -203,9 +203,9 @@ class MemoryRepoTests(TestCase):
                 f.write("test content\n")
                 f.write("test content\n")
 
 
             # Stage and commit using dulwich
             # Stage and commit using dulwich
-            initial_repo.stage(["test.txt"])
-            initial_repo.do_commit(
-                b"Initial commit\n",
+            initial_repo.get_worktree().stage(["test.txt"])
+            initial_repo.get_worktree().commit(
+                message=b"Initial commit\n",
                 committer=b"Test Committer <test@example.com>",
                 committer=b"Test Committer <test@example.com>",
                 author=b"Test Author <test@example.com>",
                 author=b"Test Author <test@example.com>",
             )
             )
@@ -606,8 +606,10 @@ class RepositoryRootTests(TestCase):
 
 
         o = Repo.init(os.path.join(tmp_dir, "s"), mkdir=True)
         o = Repo.init(os.path.join(tmp_dir, "s"), mkdir=True)
         os.symlink("foo", os.path.join(tmp_dir, "s", "bar"))
         os.symlink("foo", os.path.join(tmp_dir, "s", "bar"))
-        o.stage("bar")
-        o.do_commit(b"add symlink")
+        o.get_worktree().stage("bar")
+        o.get_worktree().commit(
+            message=b"add symlink",
+        )
 
 
         t = o.clone(os.path.join(tmp_dir, "t"), symlinks=True)
         t = o.clone(os.path.join(tmp_dir, "t"), symlinks=True)
         o.close()
         o.close()
@@ -626,8 +628,10 @@ class RepositoryRootTests(TestCase):
         o = Repo.init(os.path.join(tmp_dir, "s"), mkdir=True)
         o = Repo.init(os.path.join(tmp_dir, "s"), mkdir=True)
         o.close()
         o.close()
         os.symlink("foo", os.path.join(tmp_dir, "s", "bar"))
         os.symlink("foo", os.path.join(tmp_dir, "s", "bar"))
-        o.stage("bar")
-        o.do_commit(b"add symlink")
+        o.get_worktree().stage("bar")
+        o.get_worktree().commit(
+            message=b"add symlink",
+        )
 
 
         t = o.clone(os.path.join(tmp_dir, "t"), symlinks=False)
         t = o.clone(os.path.join(tmp_dir, "t"), symlinks=False)
         with open(os.path.join(tmp_dir, "t", "bar")) as f:
         with open(os.path.join(tmp_dir, "t", "bar")) as f:
@@ -655,7 +659,7 @@ class RepositoryRootTests(TestCase):
 
 
         # Try to stage the malicious path - should be rejected
         # Try to stage the malicious path - should be rejected
         with self.assertRaises(ValueError):
         with self.assertRaises(ValueError):
-            repo.stage([attack_name])
+            repo.get_worktree().stage([attack_name])
 
 
         # Test with protectHFS disabled
         # Test with protectHFS disabled
         config.set(b"core", b"core.protectHFS", b"false")
         config.set(b"core", b"core.protectHFS", b"false")
@@ -849,8 +853,8 @@ exit 0
             f.write(pre_commit_success)
             f.write(pre_commit_success)
         os.chmod(pre_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
         os.chmod(pre_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
 
 
-        commit_sha = r.do_commit(
-            b"empty commit",
+        commit_sha = r.get_worktree().commit(
+            message=b"empty commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -899,8 +903,8 @@ exit 0
             f.write(commit_msg_success)
             f.write(commit_msg_success)
         os.chmod(commit_msg, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
         os.chmod(commit_msg, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
 
 
-        commit_sha = r.do_commit(
-            b"empty commit",
+        commit_sha = r.get_worktree().commit(
+            message=b"empty commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -937,7 +941,7 @@ r.stage(['foo'])
         with open(os.path.join(repo_dir, "blah"), "w") as f:
         with open(os.path.join(repo_dir, "blah"), "w") as f:
             f.write("blah")
             f.write("blah")
 
 
-        r.stage(["blah"])
+        r.get_worktree().stage(["blah"])
 
 
         pre_commit = os.path.join(r.controldir(), "hooks", "pre-commit")
         pre_commit = os.path.join(r.controldir(), "hooks", "pre-commit")
 
 
@@ -945,8 +949,8 @@ r.stage(['foo'])
             f.write(pre_commit_contents)
             f.write(pre_commit_contents)
         os.chmod(pre_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
         os.chmod(pre_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
 
 
-        commit_sha = r.do_commit(
-            b"new commit",
+        commit_sha = r.get_worktree().commit(
+            message=b"new commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -979,8 +983,8 @@ rm """
 """
 """
         )
         )
 
 
-        root_sha = r.do_commit(
-            b"empty commit",
+        root_sha = r.get_worktree().commit(
+            message=b"empty commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12345,
             commit_timestamp=12345,
@@ -996,8 +1000,8 @@ rm """
             f.write(post_commit_msg.encode(locale.getpreferredencoding()))
             f.write(post_commit_msg.encode(locale.getpreferredencoding()))
         os.chmod(post_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
         os.chmod(post_commit, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
 
 
-        commit_sha = r.do_commit(
-            b"empty commit",
+        commit_sha = r.get_worktree().commit(
+            message=b"empty commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12345,
             commit_timestamp=12345,
@@ -1021,8 +1025,8 @@ exit 1
         warnings_list, restore_warnings = setup_warning_catcher()
         warnings_list, restore_warnings = setup_warning_catcher()
         self.addCleanup(restore_warnings)
         self.addCleanup(restore_warnings)
 
 
-        commit_sha2 = r.do_commit(
-            b"empty commit",
+        commit_sha2 = r.get_worktree().commit(
+            message=b"empty commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12345,
             commit_timestamp=12345,
@@ -1071,8 +1075,8 @@ exit 1
         self.addCleanup(shutil.rmtree, worktree_temp_dir)
         self.addCleanup(shutil.rmtree, worktree_temp_dir)
         r = Repo.init(temp_dir)
         r = Repo.init(temp_dir)
         self.addCleanup(r.close)
         self.addCleanup(r.close)
-        root_sha = r.do_commit(
-            b"empty commit",
+        root_sha = r.get_worktree().commit(
+            message=b"empty commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12345,
             commit_timestamp=12345,
@@ -1083,8 +1087,8 @@ exit 1
         r.refs[b"refs/heads/master"] = root_sha
         r.refs[b"refs/heads/master"] = root_sha
         w = Repo._init_new_working_directory(worktree_temp_dir, r)
         w = Repo._init_new_working_directory(worktree_temp_dir, r)
         self.addCleanup(w.close)
         self.addCleanup(w.close)
-        new_sha = w.do_commit(
-            b"new commit",
+        new_sha = w.get_worktree().commit(
+            message=b"new commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12345,
             commit_timestamp=12345,
@@ -1122,9 +1126,9 @@ class BuildRepoRootTests(TestCase):
 
 
         with open(os.path.join(r.path, "a"), "wb") as f:
         with open(os.path.join(r.path, "a"), "wb") as f:
             f.write(b"file contents")
             f.write(b"file contents")
-        r.stage(["a"])
-        commit_sha = r.do_commit(
-            b"msg",
+        r.get_worktree().stage(["a"])
+        commit_sha = r.get_worktree().commit(
+            message=b"msg",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12345,
             commit_timestamp=12345,
@@ -1180,9 +1184,9 @@ class BuildRepoRootTests(TestCase):
         r = self._repo
         r = self._repo
         with open(os.path.join(r.path, "a"), "wb") as f:
         with open(os.path.join(r.path, "a"), "wb") as f:
             f.write(b"new contents")
             f.write(b"new contents")
-        r.stage(["a"])
-        commit_sha = r.do_commit(
-            b"modified a",
+        r.get_worktree().stage(["a"])
+        commit_sha = r.get_worktree().commit(
+            message=b"modified a",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1199,9 +1203,9 @@ class BuildRepoRootTests(TestCase):
     def test_commit_symlink(self) -> None:
     def test_commit_symlink(self) -> None:
         r = self._repo
         r = self._repo
         os.symlink("a", os.path.join(r.path, "b"))
         os.symlink("a", os.path.join(r.path, "b"))
-        r.stage(["a", "b"])
-        commit_sha = r.do_commit(
-            b"Symlink b",
+        r.get_worktree().stage(["a", "b"])
+        commit_sha = r.get_worktree().commit(
+            message=b"Symlink b",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1220,8 +1224,8 @@ class BuildRepoRootTests(TestCase):
         r = Repo.init(tmp_dir)
         r = Repo.init(tmp_dir)
         with open(os.path.join(r.path, "a"), "w") as f:
         with open(os.path.join(r.path, "a"), "w") as f:
             f.write("initial text")
             f.write("initial text")
-        c1 = r.do_commit(
-            b"initial commit",
+        c1 = r.get_worktree().commit(
+            message=b"initial commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1233,9 +1237,9 @@ class BuildRepoRootTests(TestCase):
             f.write("merged text")
             f.write("merged text")
         with open(os.path.join(r.path, ".git", "MERGE_HEAD"), "w") as f:
         with open(os.path.join(r.path, ".git", "MERGE_HEAD"), "w") as f:
             f.write("c27a2d21dd136312d7fa9e8baabb82561a1727d0\n")
             f.write("c27a2d21dd136312d7fa9e8baabb82561a1727d0\n")
-        r.stage(["a"])
-        commit_sha = r.do_commit(
-            b"deleted a",
+        r.get_worktree().stage(["a"])
+        commit_sha = r.get_worktree().commit(
+            message=b"deleted a",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1251,9 +1255,9 @@ class BuildRepoRootTests(TestCase):
     def test_commit_deleted(self) -> None:
     def test_commit_deleted(self) -> None:
         r = self._repo
         r = self._repo
         os.remove(os.path.join(r.path, "a"))
         os.remove(os.path.join(r.path, "a"))
-        r.stage(["a"])
-        commit_sha = r.do_commit(
-            b"deleted a",
+        r.get_worktree().stage(["a"])
+        commit_sha = r.get_worktree().commit(
+            message=b"deleted a",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1269,8 +1273,8 @@ class BuildRepoRootTests(TestCase):
     def test_commit_follows(self) -> None:
     def test_commit_follows(self) -> None:
         r = self._repo
         r = self._repo
         r.refs.set_symbolic_ref(b"HEAD", b"refs/heads/bla")
         r.refs.set_symbolic_ref(b"HEAD", b"refs/heads/bla")
-        commit_sha = r.do_commit(
-            b"commit with strange character",
+        commit_sha = r.get_worktree().commit(
+            message=b"commit with strange character",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1283,8 +1287,8 @@ class BuildRepoRootTests(TestCase):
 
 
     def test_commit_encoding(self) -> None:
     def test_commit_encoding(self) -> None:
         r = self._repo
         r = self._repo
-        commit_sha = r.do_commit(
-            b"commit with strange character \xee",
+        commit_sha = r.get_worktree().commit(
+            message=b"commit with strange character \xee",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1361,8 +1365,8 @@ class BuildRepoRootTests(TestCase):
         c = r.get_config()
         c = r.get_config()
         c.set(("i18n",), "commitEncoding", "iso8859-1")
         c.set(("i18n",), "commitEncoding", "iso8859-1")
         c.write_to_path()
         c.write_to_path()
-        commit_sha = r.do_commit(
-            b"commit with strange character \xee",
+        commit_sha = r.get_worktree().commit(
+            message=b"commit with strange character \xee",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1379,7 +1383,9 @@ class BuildRepoRootTests(TestCase):
         c.set((b"user",), b"name", b"Jelmer")
         c.set((b"user",), b"name", b"Jelmer")
         c.set((b"user",), b"email", b"jelmer@apache.org")
         c.set((b"user",), b"email", b"jelmer@apache.org")
         c.write_to_path()
         c.write_to_path()
-        commit_sha = r.do_commit(b"message")
+        commit_sha = r.get_worktree().commit(
+            message=b"message",
+        )
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].author)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].author)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].committer)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].committer)
 
 
@@ -1391,7 +1397,9 @@ class BuildRepoRootTests(TestCase):
         c.set((b"user",), b"name", b"Jelmer")
         c.set((b"user",), b"name", b"Jelmer")
         c.set((b"user",), b"email", b"<jelmer@apache.org>")
         c.set((b"user",), b"email", b"<jelmer@apache.org>")
         c.write_to_path()
         c.write_to_path()
-        commit_sha = r.do_commit(b"message")
+        commit_sha = r.get_worktree().commit(
+            message=b"message",
+        )
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].author)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].author)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].committer)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].committer)
 
 
@@ -1402,7 +1410,15 @@ class BuildRepoRootTests(TestCase):
         c.set((b"user",), b"name", b"Jelmer")
         c.set((b"user",), b"name", b"Jelmer")
         c.set((b"user",), b"email", b"jelmer@apache.org")
         c.set((b"user",), b"email", b"jelmer@apache.org")
 
 
-        commit_sha = r.do_commit(b"message", tree=objects.Tree().id)
+        # Create a tree object
+        tree = objects.Tree()
+        r.object_store.add_object(tree)
+
+        # Use do_commit for MemoryRepo since it doesn't support worktree
+        commit_sha = r.do_commit(
+            message=b"message",
+            tree=tree.id,
+        )
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].author)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].author)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].committer)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].committer)
 
 
@@ -1415,7 +1431,9 @@ class BuildRepoRootTests(TestCase):
         c.set((b"user",), b"name", b"Jelmer")
         c.set((b"user",), b"name", b"Jelmer")
         c.set((b"user",), b"email", b"jelmer@apache.org")
         c.set((b"user",), b"email", b"jelmer@apache.org")
         c.write_to_path()
         c.write_to_path()
-        commit_sha = r.do_commit(b"message")
+        commit_sha = r.get_worktree().commit(
+            message=b"message",
+        )
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].author)
         self.assertEqual(b"Jelmer <jelmer@apache.org>", r[commit_sha].author)
         self.assertEqual(b"joe <joe@example.com>", r[commit_sha].committer)
         self.assertEqual(b"joe <joe@example.com>", r[commit_sha].committer)
 
 
@@ -1463,8 +1481,8 @@ class BuildRepoRootTests(TestCase):
             # Generate a message
             # Generate a message
             return b"Generated commit for tree " + commit.tree[:8]
             return b"Generated commit for tree " + commit.tree[:8]
 
 
-        commit_sha = r.do_commit(
-            message_callback,  # Pass the callback as message
+        commit_sha = r.get_worktree().commit(
+            message=message_callback,
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12345,
             commit_timestamp=12345,
@@ -1501,17 +1519,17 @@ class BuildRepoRootTests(TestCase):
         r = self._repo
         r = self._repo
 
 
         # Create two parent commits first
         # Create two parent commits first
-        parent1 = r.do_commit(
-            b"Parent 1",
+        parent1 = r.get_worktree().commit(
+            message=b"Parent 1",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
         )
         )
 
 
-        parent2 = r.do_commit(
-            b"Parent 2",
+        parent2 = r.get_worktree().commit(
+            message=b"Parent 2",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
-            ref=None,  # Dangling commit
+            ref=None,
         )
         )
 
 
         def message_callback(repo, commit):
         def message_callback(repo, commit):
@@ -1519,8 +1537,8 @@ class BuildRepoRootTests(TestCase):
             self.assertEqual(2, len(commit.parents))
             self.assertEqual(2, len(commit.parents))
             return b"Merge commit with %d parents" % len(commit.parents)
             return b"Merge commit with %d parents" % len(commit.parents)
 
 
-        merge_sha = r.do_commit(
-            message_callback,
+        merge_sha = r.get_worktree().commit(
+            message=message_callback,
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             merge_heads=[parent2],
             merge_heads=[parent2],
@@ -1533,8 +1551,8 @@ class BuildRepoRootTests(TestCase):
     def test_commit_branch(self) -> None:
     def test_commit_branch(self) -> None:
         r = self._repo
         r = self._repo
 
 
-        commit_sha = r.do_commit(
-            b"commit to branch",
+        commit_sha = r.get_worktree().commit(
+            message=b"commit to branch",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1550,8 +1568,8 @@ class BuildRepoRootTests(TestCase):
 
 
         new_branch_head = commit_sha
         new_branch_head = commit_sha
 
 
-        commit_sha = r.do_commit(
-            b"commit to branch 2",
+        commit_sha = r.get_worktree().commit(
+            message=b"commit to branch 2",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1566,8 +1584,8 @@ class BuildRepoRootTests(TestCase):
 
 
     def test_commit_merge_heads(self) -> None:
     def test_commit_merge_heads(self) -> None:
         r = self._repo
         r = self._repo
-        merge_1 = r.do_commit(
-            b"commit to branch 2",
+        merge_1 = r.get_worktree().commit(
+            message=b"commit to branch 2",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1576,8 +1594,8 @@ class BuildRepoRootTests(TestCase):
             author_timezone=0,
             author_timezone=0,
             ref=b"refs/heads/new_branch",
             ref=b"refs/heads/new_branch",
         )
         )
-        commit_sha = r.do_commit(
-            b"commit with merge",
+        commit_sha = r.get_worktree().commit(
+            message=b"commit with merge",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1593,8 +1611,8 @@ class BuildRepoRootTests(TestCase):
 
 
         old_shas = set(r.object_store)
         old_shas = set(r.object_store)
         old_refs = r.get_refs()
         old_refs = r.get_refs()
-        commit_sha = r.do_commit(
-            b"commit with no ref",
+        commit_sha = r.get_worktree().commit(
+            message=b"commit with no ref",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1617,8 +1635,8 @@ class BuildRepoRootTests(TestCase):
 
 
         old_shas = set(r.object_store)
         old_shas = set(r.object_store)
         old_refs = r.get_refs()
         old_refs = r.get_refs()
-        commit_sha = r.do_commit(
-            b"commit with no ref",
+        commit_sha = r.get_worktree().commit(
+            message=b"commit with no ref",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,
@@ -1645,21 +1663,23 @@ class BuildRepoRootTests(TestCase):
     def test_stage_deleted(self) -> None:
     def test_stage_deleted(self) -> None:
         r = self._repo
         r = self._repo
         os.remove(os.path.join(r.path, "a"))
         os.remove(os.path.join(r.path, "a"))
-        r.stage(["a"])
-        r.stage(["a"])  # double-stage a deleted path
+        r.get_worktree().stage(["a"])
+        r.get_worktree().stage(["a"])  # double-stage a deleted path
         self.assertEqual([], list(r.open_index()))
         self.assertEqual([], list(r.open_index()))
 
 
     def test_stage_directory(self) -> None:
     def test_stage_directory(self) -> None:
         r = self._repo
         r = self._repo
         os.mkdir(os.path.join(r.path, "c"))
         os.mkdir(os.path.join(r.path, "c"))
-        r.stage(["c"])
+        r.get_worktree().stage(["c"])
         self.assertEqual([b"a"], list(r.open_index()))
         self.assertEqual([b"a"], list(r.open_index()))
 
 
     def test_stage_submodule(self) -> None:
     def test_stage_submodule(self) -> None:
         r = self._repo
         r = self._repo
         s = Repo.init(os.path.join(r.path, "sub"), mkdir=True)
         s = Repo.init(os.path.join(r.path, "sub"), mkdir=True)
-        s.do_commit(b"message")
-        r.stage(["sub"])
+        s.get_worktree().commit(
+            message=b"message",
+        )
+        r.get_worktree().stage(["sub"])
         self.assertEqual([b"a", b"sub"], list(r.open_index()))
         self.assertEqual([b"a", b"sub"], list(r.open_index()))
 
 
     def test_unstage_midify_file_with_dir(self) -> None:
     def test_unstage_midify_file_with_dir(self) -> None:
@@ -1677,7 +1697,7 @@ class BuildRepoRootTests(TestCase):
         )
         )
         with open(full_path, "a") as f:
         with open(full_path, "a") as f:
             f.write("something new")
             f.write("something new")
-        self._repo.unstage(["new_dir/foo"])
+        self._repo.get_worktree().unstage(["new_dir/foo"])
         status = list(porcelain.status(self._repo))
         status = list(porcelain.status(self._repo))
         self.assertEqual(
         self.assertEqual(
             [{"add": [], "delete": [], "modify": []}, [b"new_dir/foo"], []], status
             [{"add": [], "delete": [], "modify": []}, [b"new_dir/foo"], []], status
@@ -1689,7 +1709,7 @@ class BuildRepoRootTests(TestCase):
         with open(full_path, "w") as f:
         with open(full_path, "w") as f:
             f.write("hello")
             f.write("hello")
         porcelain.add(self._repo, paths=[full_path])
         porcelain.add(self._repo, paths=[full_path])
-        self._repo.unstage([file])
+        self._repo.get_worktree().unstage([file])
         status = list(porcelain.status(self._repo))
         status = list(porcelain.status(self._repo))
         self.assertEqual([{"add": [], "delete": [], "modify": []}, [], ["foo"]], status)
         self.assertEqual([{"add": [], "delete": [], "modify": []}, [], ["foo"]], status)
 
 
@@ -1705,7 +1725,7 @@ class BuildRepoRootTests(TestCase):
         with open(full_path, "w") as f:
         with open(full_path, "w") as f:
             f.write("hello")
             f.write("hello")
         porcelain.add(self._repo, paths=[full_path])
         porcelain.add(self._repo, paths=[full_path])
-        self._repo.unstage([file])
+        self._repo.get_worktree().unstage([file])
         status = list(porcelain.status(self._repo))
         status = list(porcelain.status(self._repo))
         self.assertEqual([{"add": [], "delete": [], "modify": []}, [], ["foo"]], status)
         self.assertEqual([{"add": [], "delete": [], "modify": []}, [], ["foo"]], status)
 
 
@@ -1724,7 +1744,7 @@ class BuildRepoRootTests(TestCase):
         with open(full_path, "a") as f:
         with open(full_path, "a") as f:
             f.write("broken")
             f.write("broken")
         porcelain.add(self._repo, paths=[full_path])
         porcelain.add(self._repo, paths=[full_path])
-        self._repo.unstage([file])
+        self._repo.get_worktree().unstage([file])
         status = list(porcelain.status(self._repo))
         status = list(porcelain.status(self._repo))
 
 
         self.assertEqual(
         self.assertEqual(
@@ -1744,7 +1764,7 @@ class BuildRepoRootTests(TestCase):
             author=b"John <john@example.com>",
             author=b"John <john@example.com>",
         )
         )
         os.remove(full_path)
         os.remove(full_path)
-        self._repo.unstage([file])
+        self._repo.get_worktree().unstage([file])
         status = list(porcelain.status(self._repo))
         status = list(porcelain.status(self._repo))
         self.assertEqual(
         self.assertEqual(
             [{"add": [], "delete": [], "modify": []}, [b"foo"], []], status
             [{"add": [], "delete": [], "modify": []}, [b"foo"], []], status
@@ -1756,12 +1776,12 @@ class BuildRepoRootTests(TestCase):
             f.write(b"changed")
             f.write(b"changed")
         with open(os.path.join(r.path, "b"), "wb") as f:
         with open(os.path.join(r.path, "b"), "wb") as f:
             f.write(b"added")
             f.write(b"added")
-        r.stage(["a", "b"])
+        r.get_worktree().stage(["a", "b"])
         status = list(porcelain.status(self._repo))
         status = list(porcelain.status(self._repo))
         self.assertEqual(
         self.assertEqual(
             [{"add": [b"b"], "delete": [], "modify": [b"a"]}, [], []], status
             [{"add": [b"b"], "delete": [], "modify": [b"a"]}, [], []], status
         )
         )
-        r.reset_index()
+        r.get_worktree().reset_index()
         status = list(porcelain.status(self._repo))
         status = list(porcelain.status(self._repo))
         self.assertEqual([{"add": [], "delete": [], "modify": []}, [], ["b"]], status)
         self.assertEqual([{"add": [], "delete": [], "modify": []}, [], ["b"]], status)
 
 
@@ -1782,9 +1802,9 @@ class BuildRepoRootTests(TestCase):
             # ourselves.
             # ourselves.
             self.addCleanup(os.remove, full_path)
             self.addCleanup(os.remove, full_path)
 
 
-        r.stage(names)
-        commit_sha = r.do_commit(
-            b"Files with different encodings",
+        r.get_worktree().stage(names)
+        commit_sha = r.get_worktree().commit(
+            message=b"Files with different encodings",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12395,
             commit_timestamp=12395,

+ 1 - 1
tests/test_server.py

@@ -1174,7 +1174,7 @@ class UpdateServerInfoTests(TestCase):
             self.assertEqual(b"", f.read())
             self.assertEqual(b"", f.read())
 
 
     def test_simple(self) -> None:
     def test_simple(self) -> None:
-        commit_id = self.repo.do_commit(
+        commit_id = self.repo.get_worktree().commit(
             message=b"foo",
             message=b"foo",
             committer=b"Joe Example <joe@example.com>",
             committer=b"Joe Example <joe@example.com>",
             ref=b"refs/heads/foo",
             ref=b"refs/heads/foo",

+ 7 - 5
tests/test_sparse_patterns.py

@@ -196,7 +196,7 @@ class ComputeIncludedPathsFullTests(TestCase):
         with open(full, "wb") as f:
         with open(full, "wb") as f:
             f.write(content)
             f.write(content)
         # Stage in the index
         # Stage in the index
-        self.repo.stage([relpath])
+        self.repo.get_worktree().stage([relpath])
 
 
     def test_basic_inclusion_exclusion(self):
     def test_basic_inclusion_exclusion(self):
         """Given patterns, check correct set of included paths."""
         """Given patterns, check correct set of included paths."""
@@ -237,7 +237,7 @@ class ComputeIncludedPathsConeTests(TestCase):
         os.makedirs(os.path.dirname(full), exist_ok=True)
         os.makedirs(os.path.dirname(full), exist_ok=True)
         with open(full, "wb") as f:
         with open(full, "wb") as f:
             f.write(content)
             f.write(content)
-        self.repo.stage([relpath])
+        self.repo.get_worktree().stage([relpath])
 
 
     def test_cone_mode_patterns(self):
     def test_cone_mode_patterns(self):
         """Simpler pattern handling in cone mode.
         """Simpler pattern handling in cone mode.
@@ -332,7 +332,7 @@ class DetermineIncludedPathsTests(TestCase):
         os.makedirs(os.path.dirname(path), exist_ok=True)
         os.makedirs(os.path.dirname(path), exist_ok=True)
         with open(path, "wb") as f:
         with open(path, "wb") as f:
             f.write(b"data")
             f.write(b"data")
-        self.repo.stage([relpath])
+        self.repo.get_worktree().stage([relpath])
 
 
     def test_full_mode(self):
     def test_full_mode(self):
         self._add_file_to_index("foo.py")
         self._add_file_to_index("foo.py")
@@ -370,9 +370,11 @@ class ApplyIncludedPathsTests(TestCase):
         os.makedirs(os.path.dirname(full), exist_ok=True)
         os.makedirs(os.path.dirname(full), exist_ok=True)
         with open(full, "wb") as f:
         with open(full, "wb") as f:
             f.write(content)
             f.write(content)
-        self.repo.stage([relpath])
+        self.repo.get_worktree().stage([relpath])
         # Actually commit so the object is in the store
         # Actually commit so the object is in the store
-        self.repo.do_commit(message=b"Commit " + relpath.encode())
+        self.repo.get_worktree().commit(
+            message=b"Commit " + relpath.encode(),
+        )
 
 
     def test_set_skip_worktree_bits(self):
     def test_set_skip_worktree_bits(self):
         """If a path is not in included_paths, skip_worktree bit is set."""
         """If a path is not in included_paths, skip_worktree bit is set."""

+ 14 - 9
tests/test_stash.py

@@ -50,7 +50,10 @@ class StashTests(TestCase):
         tree.add(b"initial.txt", 0o100644, blob.id)
         tree.add(b"initial.txt", 0o100644, blob.id)
         tree_id = self.repo.object_store.add_object(tree)
         tree_id = self.repo.object_store.add_object(tree)
 
 
-        self.commit_id = self.repo.do_commit(b"Initial commit", tree=tree_id)
+        self.commit_id = self.repo.get_worktree().commit(
+            message=b"Initial commit",
+            tree=tree_id,
+        )
 
 
     def tearDown(self):
     def tearDown(self):
         shutil.rmtree(self.test_dir)
         shutil.rmtree(self.test_dir)
@@ -77,7 +80,7 @@ class StashTests(TestCase):
         file_path = os.path.join(self.repo_dir, "testfile.txt")
         file_path = os.path.join(self.repo_dir, "testfile.txt")
         with open(file_path, "wb") as f:
         with open(file_path, "wb") as f:
             f.write(b"test data")
             f.write(b"test data")
-        self.repo.stage(["testfile.txt"])
+        self.repo.get_worktree().stage(["testfile.txt"])
 
 
         # Push to stash
         # Push to stash
         commit_id = stash.push(message=b"Test stash message")
         commit_id = stash.push(message=b"Test stash message")
@@ -102,13 +105,13 @@ class StashTests(TestCase):
         file1_path = os.path.join(self.repo_dir, "testfile1.txt")
         file1_path = os.path.join(self.repo_dir, "testfile1.txt")
         with open(file1_path, "wb") as f:
         with open(file1_path, "wb") as f:
             f.write(b"test data 1")
             f.write(b"test data 1")
-        self.repo.stage(["testfile1.txt"])
+        self.repo.get_worktree().stage(["testfile1.txt"])
         commit_id1 = stash.push(message=b"Test stash 1")
         commit_id1 = stash.push(message=b"Test stash 1")
 
 
         file2_path = os.path.join(self.repo_dir, "testfile2.txt")
         file2_path = os.path.join(self.repo_dir, "testfile2.txt")
         with open(file2_path, "wb") as f:
         with open(file2_path, "wb") as f:
             f.write(b"test data 2")
             f.write(b"test data 2")
-        self.repo.stage(["testfile2.txt"])
+        self.repo.get_worktree().stage(["testfile2.txt"])
         stash.push(message=b"Test stash 2")
         stash.push(message=b"Test stash 2")
 
 
         self.assertEqual(2, len(stash))
         self.assertEqual(2, len(stash))
@@ -138,7 +141,7 @@ class StashTests(TestCase):
         file_path = os.path.join(self.repo_dir, "testfile.txt")
         file_path = os.path.join(self.repo_dir, "testfile.txt")
         with open(file_path, "wb") as f:
         with open(file_path, "wb") as f:
             f.write(b"test data")
             f.write(b"test data")
-        self.repo.stage(["testfile.txt"])
+        self.repo.get_worktree().stage(["testfile.txt"])
 
 
         # Push to stash
         # Push to stash
         stash.push(message=b"Test stash message")
         stash.push(message=b"Test stash message")
@@ -173,13 +176,15 @@ class StashTests(TestCase):
         tracked_path = os.path.join(self.repo_dir, "tracked.txt")
         tracked_path = os.path.join(self.repo_dir, "tracked.txt")
         with open(tracked_path, "wb") as f:
         with open(tracked_path, "wb") as f:
             f.write(b"original content")
             f.write(b"original content")
-        self.repo.stage(["tracked.txt"])
-        self.repo.do_commit(b"Add tracked file")
+        self.repo.get_worktree().stage(["tracked.txt"])
+        self.repo.get_worktree().commit(
+            message=b"Add tracked file",
+        )
 
 
         # Modify the tracked file and stage it
         # Modify the tracked file and stage it
         with open(tracked_path, "wb") as f:
         with open(tracked_path, "wb") as f:
             f.write(b"staged changes")
             f.write(b"staged changes")
-        self.repo.stage(["tracked.txt"])
+        self.repo.get_worktree().stage(["tracked.txt"])
 
 
         # Modify it again but don't stage
         # Modify it again but don't stage
         with open(tracked_path, "wb") as f:
         with open(tracked_path, "wb") as f:
@@ -189,7 +194,7 @@ class StashTests(TestCase):
         new_file_path = os.path.join(self.repo_dir, "new.txt")
         new_file_path = os.path.join(self.repo_dir, "new.txt")
         with open(new_file_path, "wb") as f:
         with open(new_file_path, "wb") as f:
             f.write(b"new file content")
             f.write(b"new file content")
-        self.repo.stage(["new.txt"])
+        self.repo.get_worktree().stage(["new.txt"])
 
 
         # Push to stash
         # Push to stash
         stash.push(message=b"Test stash with index")
         stash.push(message=b"Test stash with index")

+ 4 - 2
tests/test_submodule.py

@@ -68,8 +68,10 @@ class SubmoduleTests(TestCase):
             f.write(b"test file content")
             f.write(b"test file content")
 
 
         # Stage and commit the file to create some basic content
         # Stage and commit the file to create some basic content
-        repo.stage(["file.txt"])
-        repo.do_commit(b"Initial commit")
+        repo.get_worktree().stage(["file.txt"])
+        repo.get_worktree().commit(
+            message=b"Initial commit",
+        )
 
 
         # Manually create the raw string for a tree with our file and a submodule
         # Manually create the raw string for a tree with our file and a submodule
         # Format for tree entries: [mode] [name]\0[sha]
         # Format for tree entries: [mode] [name]\0[sha]

+ 16 - 8
tests/test_worktree.py

@@ -57,9 +57,9 @@ class WorkTreeTestCase(TestCase):
         # Create initial commit with a file
         # Create initial commit with a file
         with open(os.path.join(self.test_dir, "a"), "wb") as f:
         with open(os.path.join(self.test_dir, "a"), "wb") as f:
             f.write(b"contents of file a")
             f.write(b"contents of file a")
-        self.repo.stage(["a"])
-        self.root_commit = self.repo.do_commit(
-            b"Initial commit",
+        self.repo.get_worktree().stage(["a"])
+        self.root_commit = self.repo.get_worktree().commit(
+            message=b"Initial commit",
             committer=b"Test Committer <test@nodomain.com>",
             committer=b"Test Committer <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             author=b"Test Author <test@nodomain.com>",
             commit_timestamp=12345,
             commit_timestamp=12345,
@@ -147,7 +147,9 @@ class WorkTreeStagingTests(WorkTreeTestCase):
         """Test staging a submodule."""
         """Test staging a submodule."""
         r = self.repo
         r = self.repo
         s = Repo.init(os.path.join(r.path, "sub"), mkdir=True)
         s = Repo.init(os.path.join(r.path, "sub"), mkdir=True)
-        s.do_commit(b"message")
+        s.get_worktree().commit(
+            message=b"message",
+        )
         self.worktree.stage(["sub"])
         self.worktree.stage(["sub"])
         self.assertEqual([b"a", b"sub"], list(r.open_index()))
         self.assertEqual([b"a", b"sub"], list(r.open_index()))
 
 
@@ -392,7 +394,9 @@ class WorkTreeBackwardCompatibilityTests(WorkTreeTestCase):
 
 
         with warnings.catch_warnings(record=True) as w:
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter("always")
             warnings.simplefilter("always")
-            self.repo.stage(["new_file"])
+            self.repo.stage(
+                ["new_file"]
+            )  # Call deprecated method on Repo, not WorkTree
             self.assertTrue(len(w) > 0)
             self.assertTrue(len(w) > 0)
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))
 
 
@@ -403,7 +407,7 @@ class WorkTreeBackwardCompatibilityTests(WorkTreeTestCase):
 
 
         with warnings.catch_warnings(record=True) as w:
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter("always")
             warnings.simplefilter("always")
-            self.repo.unstage(["a"])
+            self.repo.unstage(["a"])  # Call deprecated method on Repo, not WorkTree
             self.assertTrue(len(w) > 0)
             self.assertTrue(len(w) > 0)
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))
 
 
@@ -414,7 +418,9 @@ class WorkTreeBackwardCompatibilityTests(WorkTreeTestCase):
         # Test get_sparse_checkout_patterns
         # Test get_sparse_checkout_patterns
         with warnings.catch_warnings(record=True) as w:
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter("always")
             warnings.simplefilter("always")
-            patterns = self.repo.get_sparse_checkout_patterns()
+            patterns = (
+                self.repo.get_sparse_checkout_patterns()
+            )  # Call deprecated method on Repo
             self.assertEqual([], patterns)
             self.assertEqual([], patterns)
             self.assertTrue(len(w) > 0)
             self.assertTrue(len(w) > 0)
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))
@@ -422,7 +428,9 @@ class WorkTreeBackwardCompatibilityTests(WorkTreeTestCase):
         # Test set_sparse_checkout_patterns
         # Test set_sparse_checkout_patterns
         with warnings.catch_warnings(record=True) as w:
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter("always")
             warnings.simplefilter("always")
-            self.repo.set_sparse_checkout_patterns(["*.py"])
+            self.repo.set_sparse_checkout_patterns(
+                ["*.py"]
+            )  # Call deprecated method on Repo
             self.assertTrue(len(w) > 0)
             self.assertTrue(len(w) > 0)
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))
             self.assertTrue(issubclass(w[0].category, DeprecationWarning))