"""Git operations for myclaude using GitPython.""" import shutil import tempfile from contextlib import contextmanager from pathlib import Path from typing import Generator from git import GitCommandError, Repo @contextmanager def temp_clone(repo_url: str, keep: bool = False) -> Generator[tuple[Path, Repo], None, None]: """Clone a git repository into a temporary directory. The temporary directory is automatically cleaned up on exit unless keep is True, in which case it is preserved for inspection. Args: repo_url: The SSH URL of the repository to clone. keep: If True, the temporary directory is not deleted after use. Yields: A tuple of (path to the cloned repo, Repo object). Raises: RuntimeError: If the clone operation fails. """ tmp_dir = tempfile.mkdtemp() try: try: repo = Repo.clone_from(repo_url, tmp_dir) except GitCommandError as e: raise RuntimeError( f"Failed to clone repository '{repo_url}': {e}" ) from e yield Path(tmp_dir), repo finally: if keep: print(f"[debug] Temporary directory kept at: {tmp_dir}") else: shutil.rmtree(tmp_dir, ignore_errors=True) def commit_and_push(repo: Repo, message: str) -> None: """Stage all changes, commit, and push to the remote origin. Args: repo: A GitPython Repo object with an 'origin' remote configured. message: The commit message. Raises: RuntimeError: If there are no changes to commit. """ repo.git.add(A=True) if not repo.is_dirty(index=True, working_tree=False): raise RuntimeError("Nothing to commit: no changes detected.") repo.index.commit(message) repo.remotes.origin.push()