Skip to content

Commit 772310b

Browse files
committed
resolves #130: Replace GitPython with dulwich
1 parent 322a0d1 commit 772310b

File tree

12 files changed

+163
-75
lines changed

12 files changed

+163
-75
lines changed

changelog/130.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Replace GitPython with dulwich

infrahub_sdk/checks.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
from typing import TYPE_CHECKING, Any
99

1010
import ujson
11-
from git.repo import Repo
1211
from pydantic import BaseModel, Field
1312

13+
from infrahub_sdk.repository import GitRepoManager
14+
1415
from .exceptions import InfrahubCheckNotFoundError, UninitializedError
1516

1617
if TYPE_CHECKING:
@@ -46,7 +47,7 @@ def __init__(
4647
params: dict | None = None,
4748
client: InfrahubClient | None = None,
4849
):
49-
self.git: Repo | None = None
50+
self.git: GitRepoManager | None = None
5051
self.initializer = initializer or InfrahubCheckInitializer()
5152

5253
self.logs: list[dict[str, Any]] = []
@@ -140,10 +141,9 @@ def branch_name(self) -> str:
140141
return self.branch
141142

142143
if not self.git:
143-
self.git = Repo(self.root_directory)
144+
self.git = GitRepoManager(self.root_directory)
144145

145146
self.branch = str(self.git.active_branch)
146-
147147
return self.branch
148148

149149
@abstractmethod

infrahub_sdk/generator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from abc import abstractmethod
55
from typing import TYPE_CHECKING
66

7-
from git.repo import Repo
7+
from infrahub_sdk.repository import GitRepoManager
88

99
from .exceptions import UninitializedError
1010

@@ -30,7 +30,7 @@ def __init__(
3030
) -> None:
3131
self.query = query
3232
self.branch = branch
33-
self.git: Repo | None = None
33+
self.git: GitRepoManager | None = None
3434
self.params = params or {}
3535
self.root_directory = root_directory or os.getcwd()
3636
self.generator_instance = generator_instance
@@ -81,7 +81,7 @@ def branch_name(self) -> str:
8181
return self.branch
8282

8383
if not self.git:
84-
self.git = Repo(self.root_directory)
84+
self.git = GitRepoManager(self.root_directory)
8585

8686
self.branch = str(self.git.active_branch)
8787

infrahub_sdk/pytest_plugin/items/base.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import pytest
88
import ujson
9-
from git.exc import InvalidGitRepositoryError
109

1110
from ..exceptions import InvalidResourceConfigError
1211
from ..models import InfrahubInputOutputTest
@@ -28,7 +27,6 @@ def __init__(
2827
**kwargs: dict[str, Any],
2928
):
3029
super().__init__(*args, **kwargs) # type: ignore[arg-type]
31-
3230
self.resource_name: str = resource_name
3331
self.resource_config: InfrahubRepositoryConfigElement = resource_config
3432
self.test: InfrahubTest = test
@@ -68,9 +66,6 @@ def runtest(self) -> None:
6866
"""Run the test logic."""
6967

7068
def repr_failure(self, excinfo: pytest.ExceptionInfo, style: str | None = None) -> str:
71-
if isinstance(excinfo.value, InvalidGitRepositoryError):
72-
return f"Invalid Git repository at {excinfo.value}"
73-
7469
return str(excinfo.value)
7570

7671
def reportinfo(self) -> tuple[Path | str, int | None, str]:

infrahub_sdk/repository.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
5+
from dulwich.objects import Tree
6+
from dulwich.repo import Repo
7+
8+
9+
class GitRepoManager:
10+
def __init__(self, root_directory: str, branch: str = "main"):
11+
self.root_directory = root_directory
12+
self.git: Repo | None = None
13+
self.branch = branch
14+
15+
self.initialize_repo()
16+
17+
def initialize_repo(self) -> None:
18+
# Check if the directory already has a repository
19+
20+
root_path = Path(self.root_directory)
21+
22+
if root_path.exists() and (root_path / ".git").is_dir():
23+
self.git = Repo(self.root_directory) # Open existing repo
24+
else:
25+
self.git = Repo.init(self.root_directory, default_branch=self.branch.encode("utf-8"))
26+
self.create_initial_commit()
27+
# Ensure the repository is valid
28+
if not self.git:
29+
raise ValueError("Failed to initialize or open a repository.")
30+
31+
def create_initial_commit(self) -> None:
32+
if not self.git:
33+
raise ValueError("Git repository not initialized.")
34+
35+
"""Create an initial commit if no commits exist."""
36+
# Create an empty tree object
37+
tree = Tree()
38+
self.git.object_store.add_object(tree)
39+
40+
# Create the initial commit without an index (use empty tree)
41+
author = committer = b"Initial Commit <[email protected]>"
42+
commit_msg = b"Initial commit"
43+
44+
ref = f"refs/heads/{self.branch}".encode()
45+
46+
self.git.do_commit(author=author, committer=committer, message=commit_msg, ref=ref)
47+
48+
# Set HEAD reference to point to the main branch
49+
self.git.refs.set_symbolic_ref(b"HEAD", ref)
50+
51+
@property
52+
def active_branch(self) -> str | None:
53+
"""Get the name of the current active branch."""
54+
if not self.git:
55+
raise ValueError("Repository is not initialized.")
56+
57+
# Read the symbolic reference of HEAD to get the current commit SHA
58+
head_ref = self.git.refs[b"HEAD"]
59+
if head_ref:
60+
commit_sha = head_ref.decode("utf-8") # Commit SHA from HEAD
61+
# Now look for the branch that points to this commit SHA
62+
for ref in self.git.refs.as_dict().keys():
63+
if ref.startswith(b"refs/heads/"):
64+
branch_ref = ref.decode("utf-8")
65+
# Check if this branch points to the same commit SHA
66+
if self.git.refs[ref] == commit_sha.encode("utf-8"):
67+
return branch_ref.split("/")[-1]
68+
return None # If no matching branch is found
69+
raise ValueError("No HEAD reference found, cannot determine active branch.")

infrahub_sdk/testing/repository.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
from pathlib import Path
88
from typing import TYPE_CHECKING
99

10-
from git.repo import Repo
11-
1210
from infrahub_sdk.graphql import Mutation
1311
from infrahub_sdk.protocols import CoreGenericRepository
12+
from infrahub_sdk.repository import GitRepoManager
1413

1514
if TYPE_CHECKING:
1615
from infrahub_sdk import InfrahubClient
@@ -37,14 +36,14 @@ class GitRepo:
3736

3837
type: GitRepoType = GitRepoType.INTEGRATED
3938

40-
_repo: Repo | None = None
39+
_repo: GitRepoManager | None = None
4140
initial_branch: str = "main"
4241
directories_to_ignore: list[str] = field(default_factory=list)
4342
remote_directory_name: str = "/remote"
4443
_branches: list[str] = field(default_factory=list)
4544

4645
@property
47-
def repo(self) -> Repo:
46+
def repo(self) -> GitRepoManager:
4847
if self._repo:
4948
return self._repo
5049
raise ValueError("Repo hasn't been initialized yet")
@@ -62,12 +61,8 @@ def init(self) -> None:
6261
dst=self.dst_directory / self.name,
6362
ignore=shutil.ignore_patterns(".git"),
6463
)
65-
self._repo = Repo.init(self.dst_directory / self.name, initial_branch=self.initial_branch)
66-
for untracked in self.repo.untracked_files:
67-
self.repo.index.add(untracked)
68-
self.repo.index.commit("First commit")
6964

70-
self.repo.git.checkout(self.initial_branch)
65+
self._repo = GitRepoManager(str(Path(self.dst_directory / self.name)), branch=self.initial_branch)
7166

7267
async def add_to_infrahub(self, client: InfrahubClient, branch: str | None = None) -> dict:
7368
input_data = {

infrahub_sdk/transforms.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from abc import abstractmethod
77
from typing import TYPE_CHECKING, Any
88

9-
from git import Repo
9+
from infrahub_sdk.repository import GitRepoManager
1010

1111
from .exceptions import InfrahubTransformNotFoundError, UninitializedError
1212

@@ -31,7 +31,7 @@ def __init__(
3131
server_url: str = "",
3232
client: InfrahubClient | None = None,
3333
):
34-
self.git: Repo
34+
self.git: GitRepoManager
3535

3636
self.branch = branch
3737
self.server_url = server_url or os.environ.get("INFRAHUB_URL", "http://127.0.0.1:8000")
@@ -60,7 +60,7 @@ def branch_name(self) -> str:
6060
return self.branch
6161

6262
if not hasattr(self, "git") or not self.git:
63-
self.git = Repo(self.root_directory)
63+
self.git = GitRepoManager(self.root_directory)
6464

6565
self.branch = str(self.git.active_branch)
6666

infrahub_sdk/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99

1010
import httpx
1111
import ujson
12-
from git.repo import Repo
1312
from graphql import (
1413
FieldNode,
1514
InlineFragmentNode,
1615
SelectionSetNode,
1716
)
1817

18+
from infrahub_sdk.repository import GitRepoManager
19+
1920
from .exceptions import JsonDecodeError
2021

2122
if TYPE_CHECKING:
@@ -246,7 +247,7 @@ def get_branch(branch: str | None = None, directory: str | Path = ".") -> str:
246247
if branch:
247248
return branch
248249

249-
repo = Repo(directory)
250+
repo = GitRepoManager(directory)
250251
return str(repo.active_branch)
251252

252253

poetry.lock

Lines changed: 63 additions & 45 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)