mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-08 15:05:17 +02:00
feat: +annotation
This commit is contained in:
parent
0cf6ec1a93
commit
9c5f7c7671
2 changed files with 59 additions and 17 deletions
|
|
@ -30,12 +30,31 @@ class ChangeType(Enum):
|
|||
|
||||
|
||||
class GitRepository:
|
||||
"""A class representing a Git repository.
|
||||
|
||||
:param local_path: The local path to the Git repository.
|
||||
:param auto_init: If True, automatically initializes a new Git repository if the provided path is not a Git repository.
|
||||
|
||||
Attributes:
|
||||
_repository (Repo): The GitPython `Repo` object representing the Git repository.
|
||||
"""
|
||||
|
||||
def __init__(self, local_path=None, auto_init=True):
|
||||
"""Initialize a GitRepository instance.
|
||||
|
||||
:param local_path: The local path to the Git repository.
|
||||
:param auto_init: If True, automatically initializes a new Git repository if the provided path is not a Git repository.
|
||||
"""
|
||||
self._repository = None
|
||||
if local_path:
|
||||
self.open(local_path=local_path, auto_init=auto_init)
|
||||
|
||||
def open(self, local_path: Path, auto_init=False):
|
||||
"""Open an existing Git repository or initialize a new one if auto_init is True.
|
||||
|
||||
:param local_path: The local path to the Git repository.
|
||||
:param auto_init: If True, automatically initializes a new Git repository if the provided path is not a Git repository.
|
||||
"""
|
||||
if self.is_git_dir(local_path):
|
||||
self._repository = Repo(local_path)
|
||||
return
|
||||
|
|
@ -45,9 +64,17 @@ class GitRepository:
|
|||
return self._init(local_path)
|
||||
|
||||
def _init(self, local_path: Path):
|
||||
"""Initialize a new Git repository at the specified path.
|
||||
|
||||
:param local_path: The local path where the new Git repository will be initialized.
|
||||
"""
|
||||
self._repository = Repo.init(path=local_path)
|
||||
|
||||
def add_change(self, files: Dict):
|
||||
"""Add or remove files from the staging area based on the provided changes.
|
||||
|
||||
:param files: A dictionary where keys are file paths and values are instances of ChangeType.
|
||||
"""
|
||||
if not self.is_valid or not files:
|
||||
return
|
||||
|
||||
|
|
@ -55,16 +82,24 @@ class GitRepository:
|
|||
self._repository.index.remove(k) if v is ChangeType.DELETED else self._repository.index.add([k])
|
||||
|
||||
def commit(self, comments):
|
||||
"""Commit the staged changes with the given comments.
|
||||
|
||||
:param comments: Comments for the commit.
|
||||
"""
|
||||
if self.is_valid:
|
||||
self._repository.index.commit(comments)
|
||||
|
||||
def delete_repository(self):
|
||||
# Delete the repository directory
|
||||
"""Delete the entire repository directory."""
|
||||
if self.is_valid:
|
||||
shutil.rmtree(self._repository.working_dir)
|
||||
|
||||
@property
|
||||
def changed_files(self) -> Dict[str, str]:
|
||||
"""Return a dictionary of changed files and their change types.
|
||||
|
||||
:return: A dictionary where keys are file paths and values are change types.
|
||||
"""
|
||||
files = {i: ChangeType.UNTRACTED for i in self._repository.untracked_files}
|
||||
changed_files = {f.a_path: ChangeType(f.change_type) for f in self._repository.index.diff(None)}
|
||||
files.update(changed_files)
|
||||
|
|
@ -72,6 +107,11 @@ class GitRepository:
|
|||
|
||||
@staticmethod
|
||||
def is_git_dir(local_path):
|
||||
"""Check if the specified directory is a Git repository.
|
||||
|
||||
:param local_path: The local path to check.
|
||||
:return: True if the directory is a Git repository, False otherwise.
|
||||
"""
|
||||
git_dir = local_path / ".git"
|
||||
if git_dir.exists() and is_git_dir(git_dir):
|
||||
return True
|
||||
|
|
@ -79,16 +119,25 @@ class GitRepository:
|
|||
|
||||
@property
|
||||
def is_valid(self):
|
||||
"""Check if the Git repository is valid (exists and is initialized).
|
||||
|
||||
:return: True if the repository is valid, False otherwise.
|
||||
"""
|
||||
return bool(self._repository)
|
||||
|
||||
@property
|
||||
def status(self) -> str:
|
||||
"""Return the Git repository's status as a string."""
|
||||
if not self.is_valid:
|
||||
return ""
|
||||
return self._repository.git.status()
|
||||
|
||||
@property
|
||||
def workdir(self) -> Path | None:
|
||||
"""Return the path to the working directory of the Git repository.
|
||||
|
||||
:return: The path to the working directory or None if the repository is not valid.
|
||||
"""
|
||||
if not self.is_valid:
|
||||
return None
|
||||
return Path(self._repository.working_dir)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ async def mock_file(filename, content=""):
|
|||
await file.write(content)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_git():
|
||||
local_path = Path(__file__).parent / "git"
|
||||
async def mock_repo(local_path) -> (GitRepository, Path):
|
||||
if local_path.exists():
|
||||
shutil.rmtree(local_path)
|
||||
assert not local_path.exists()
|
||||
|
|
@ -28,6 +26,13 @@ async def test_git():
|
|||
subdir = local_path / "subdir"
|
||||
subdir.mkdir(parents=True, exist_ok=True)
|
||||
await mock_file(subdir / "c.txt")
|
||||
return repo, subdir
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_git():
|
||||
local_path = Path(__file__).parent / "git"
|
||||
repo, subdir = await mock_repo(local_path)
|
||||
|
||||
assert len(repo.changed_files) == 3
|
||||
repo.add_change(repo.changed_files)
|
||||
|
|
@ -54,19 +59,7 @@ async def test_git():
|
|||
@pytest.mark.asyncio
|
||||
async def test_git1():
|
||||
local_path = Path(__file__).parent / "git1"
|
||||
if local_path.exists():
|
||||
shutil.rmtree(local_path)
|
||||
assert not local_path.exists()
|
||||
repo = GitRepository(local_path=local_path, auto_init=True)
|
||||
assert local_path.exists()
|
||||
assert local_path == repo.workdir
|
||||
assert not repo.changed_files
|
||||
|
||||
await mock_file(local_path / "a.txt")
|
||||
await mock_file(local_path / "b.txt")
|
||||
subdir = local_path / "subdir"
|
||||
subdir.mkdir(parents=True, exist_ok=True)
|
||||
await mock_file(subdir / "c.txt")
|
||||
await mock_repo(local_path)
|
||||
|
||||
repo1 = GitRepository(local_path=local_path, auto_init=False)
|
||||
assert repo1.changed_files
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue