Skip to content

Commit f411418

Browse files
committed
fix: properly use GitPython subcommands
1 parent 1014646 commit f411418

File tree

5 files changed

+28
-13
lines changed

5 files changed

+28
-13
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ COPY src/ ./src/
1313

1414
RUN set -eux; \
1515
pip install --no-cache-dir --upgrade pip; \
16-
pip install --no-cache-dir --timeout 1000 .[server]
16+
pip install --no-cache-dir --timeout 1000 .[server,mcp]
1717

1818
# Stage 2: Runtime image
1919
FROM python:3.13.5-slim@sha256:4c2cf9917bd1cbacc5e9b07320025bdb7cdf2df7b0ceaccb55e9dd7e30987419

src/gitingest/clone.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
from pathlib import Path
66
from typing import TYPE_CHECKING
77

8-
from gitingest.config import DEFAULT_TIMEOUT
98
import git
9+
10+
from gitingest.config import DEFAULT_TIMEOUT
1011
from gitingest.utils.git_utils import (
1112
_add_token_to_url,
1213
check_repo_exists,
1314
checkout_partial_clone,
14-
create_git_auth_header,
1515
create_git_repo,
1616
ensure_git_installed,
1717
is_github_host,
@@ -97,19 +97,19 @@ async def clone_repo(config: CloneConfig, *, token: str | None = None) -> None:
9797
"no_checkout": True,
9898
"depth": 1,
9999
}
100-
100+
101101
if partial_clone:
102102
# GitPython doesn't directly support --filter and --sparse in clone
103103
# We'll need to use git.Git() for the initial clone with these options
104104
git_cmd = git.Git()
105-
cmd_args = ["clone", "--single-branch", "--no-checkout", "--depth=1"]
105+
cmd_args = ["--single-branch", "--no-checkout", "--depth=1"]
106106
if partial_clone:
107107
cmd_args.extend(["--filter=blob:none", "--sparse"])
108108
cmd_args.extend([clone_url, local_path])
109-
git_cmd.execute(cmd_args)
109+
git_cmd.clone(*cmd_args)
110110
else:
111111
git.Repo.clone_from(clone_url, local_path, **clone_kwargs)
112-
112+
113113
logger.info("Git clone completed successfully")
114114
except git.GitCommandError as exc:
115115
msg = f"Git clone failed: {exc}"
@@ -124,7 +124,7 @@ async def clone_repo(config: CloneConfig, *, token: str | None = None) -> None:
124124
# Create repo object and perform operations
125125
try:
126126
repo = create_git_repo(local_path, url, token)
127-
127+
128128
# Ensure the commit is locally available
129129
logger.debug("Fetching specific commit", extra={"commit": commit})
130130
repo.git.fetch("--depth=1", "origin", commit)

src/gitingest/utils/git_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ async def checkout_partial_clone(config: CloneConfig, token: str | None) -> None
368368

369369
try:
370370
repo = create_git_repo(config.local_path, config.url, token)
371-
repo.git.execute(["sparse-checkout", "set", subpath])
371+
repo.git.sparse_checkout("set", subpath)
372372
except git.GitCommandError as exc:
373373
msg = f"Failed to configure sparse-checkout: {exc}"
374374
raise RuntimeError(msg) from exc

tests/conftest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ def _setup_gitpython_mocks(mocker: MockerFixture) -> dict[str, MagicMock]:
235235
mock_git_cmd.version.return_value = "git version 2.34.1"
236236
mock_git_cmd.config.return_value = "true"
237237
mock_git_cmd.execute.return_value = f"{DEMO_COMMIT}\trefs/heads/main\n"
238+
mock_git_cmd.ls_remote.return_value = f"{DEMO_COMMIT}\trefs/heads/main\n"
239+
mock_git_cmd.clone.return_value = ""
238240

239241
# Mock git.Repo class
240242
mock_repo = MagicMock()
@@ -244,6 +246,7 @@ def _setup_gitpython_mocks(mocker: MockerFixture) -> dict[str, MagicMock]:
244246
mock_repo.git.submodule = MagicMock()
245247
mock_repo.git.execute = MagicMock()
246248
mock_repo.git.config = MagicMock()
249+
mock_repo.git.sparse_checkout = MagicMock()
247250

248251
# Mock git.Repo.clone_from
249252
mock_clone_from = MagicMock(return_value=mock_repo)

tests/test_clone.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@
3535

3636

3737
@pytest.mark.asyncio
38-
async def test_clone_with_commit(repo_exists_true: AsyncMock, run_command_mock: AsyncMock) -> None:
38+
async def test_clone_with_commit(repo_exists_true: AsyncMock, gitpython_mocks: dict) -> None:
3939
"""Test cloning a repository with a specific commit hash.
4040
4141
Given a valid URL and a commit hash:
4242
When ``clone_repo`` is called,
4343
Then the repository should be cloned and checked out at that commit.
4444
"""
45-
expected_call_count = GIT_INSTALLED_CALLS + 3 # ensure_git_installed + clone + fetch + checkout
4645
commit_hash = "a" * 40 # Simulating a valid commit hash
4746
clone_config = CloneConfig(
4847
url=DEMO_URL,
@@ -54,8 +53,21 @@ async def test_clone_with_commit(repo_exists_true: AsyncMock, run_command_mock:
5453
await clone_repo(clone_config)
5554

5655
repo_exists_true.assert_any_call(clone_config.url, token=None)
57-
assert_standard_calls(run_command_mock, clone_config, commit=commit_hash)
58-
assert run_command_mock.call_count == expected_call_count
56+
57+
# Verify GitPython calls were made
58+
mock_git_cmd = gitpython_mocks["git_cmd"]
59+
mock_repo = gitpython_mocks["repo"]
60+
mock_clone_from = gitpython_mocks["clone_from"]
61+
62+
# Should have called version (for ensure_git_installed)
63+
mock_git_cmd.version.assert_called()
64+
65+
# Should have called clone_from (since partial_clone=False)
66+
mock_clone_from.assert_called_once()
67+
68+
# Should have called fetch and checkout on the repo
69+
mock_repo.git.fetch.assert_called()
70+
mock_repo.git.checkout.assert_called_with(commit_hash)
5971

6072

6173
@pytest.mark.asyncio

0 commit comments

Comments
 (0)