Skip to content

Move get_git_executable from subprocess_utils into models#393

Merged
tschm merged 3 commits intomainfrom
copilot/move-get-git-executable
Mar 8, 2026
Merged

Move get_git_executable from subprocess_utils into models#393
tschm merged 3 commits intomainfrom
copilot/move-get-git-executable

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 8, 2026

subprocess_utils.py was a 26-line file containing a single function — too thin to justify its own module. get_git_executable belongs in models.py, which already owns the git interaction layer and already imports shutil.

Changes

  • src/rhiza/models.py — Added get_git_executable() after the existing private helpers (_log_git_stderr_errors, _normalize_to_list), before the dataclass definitions; added to __all__
  • src/rhiza/commands/ — Updated imports in _sync_helpers.py, sync.py, and init.py to pull from rhiza.models
  • tests/test_subprocess_utils.py — Updated import path and patch target (rhiza.subprocess_utils.shutil.whichrhiza.models.shutil.which)
  • tests/test_models.py, tests/test_commands/test_sync.py — Updated all inline from rhiza.subprocess_utils import get_git_executable occurrences
  • src/rhiza/subprocess_utils.py — Deleted
  • docs/adr/0001-inline-get-diff-instead-of-cruft.md — Updated prose reference from subprocess_utils.get_git_executablemodels.get_git_executable
Original prompt

Summary

Move get_git_executable() from src/rhiza/subprocess_utils.py into src/rhiza/models.py and delete subprocess_utils.py. It is a 26-line file containing a single function — the definition of a module that shouldn't exist as a standalone file.

Detailed changes

1. Add get_git_executable() to src/rhiza/models.py

Add import shutil to the existing imports (it is not already imported there), then add the following function at module level near the top of the file, after the existing private helpers _log_git_stderr_errors and _normalize_to_list, and before the dataclass definitions:

def get_git_executable() -> str:
    """Get the absolute path to the git executable.

    This function ensures we use the full path to git to prevent
    security issues related to PATH manipulation.

    Returns:
        str: Absolute path to the git executable.

    Raises:
        RuntimeError: If git executable is not found in PATH.
    """
    git_path = shutil.which("git")
    if git_path is None:
        msg = "git executable not found in PATH. Please ensure git is installed and available."
        raise RuntimeError(msg)
    return git_path

Also add "get_git_executable" to the __all__ list in models.py.

Note: models.py already imports shutil (it uses shutil.copy2 in _prepare_snapshot), so no new import is needed.

2. Update all import sites — replace from rhiza.subprocess_utils import get_git_executable with from rhiza.models import get_git_executable

The following files need this import updated:

  • src/rhiza/commands/_sync_helpers.py (line 28)
  • src/rhiza/commands/sync.py (last import line in the imports block)
  • src/rhiza/commands/init.py (last import line in the imports block)
  • tests/test_models.py (multiple occurrences inside test methods — all from rhiza.subprocess_utils import get_git_executable lines)
  • tests/test_commands/test_sync.py (one occurrence inside a test method)

3. Migrate tests/test_subprocess_utils.py → update import and patch path

In tests/test_subprocess_utils.py, change:

  • from rhiza.subprocess_utils import get_git_executablefrom rhiza.models import get_git_executable
  • The patch target "rhiza.subprocess_utils.shutil.which""rhiza.models.shutil.which"

The test class and assertions can remain identical.

4. Delete src/rhiza/subprocess_utils.py

Delete the file entirely.

Notes

  • No other files are known to reference rhiza.subprocess_utils beyond those listed above (confirmed by code search).
  • The ADR at docs/adr/0001-inline-get-diff-instead-of-cruft.md mentions subprocess_utils.get_git_executable in passing — update that reference to models.get_git_executable if it appears as a code reference, otherwise leave prose unchanged.
  • models.py already imports shutil for shutil.copy2, so no new top-level import is needed.

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@tschm tschm marked this pull request as ready for review March 8, 2026 08:13
tschm and others added 2 commits March 8, 2026 12:14
Copilot AI changed the title [WIP] Move get_git_executable to models.py and delete subprocess_utils.py Move get_git_executable from subprocess_utils into models Mar 8, 2026
Copilot finished work on behalf of tschm March 8, 2026 08:16
@tschm tschm merged commit b31fbf3 into main Mar 8, 2026
16 checks passed
@tschm tschm deleted the copilot/move-get-git-executable branch March 8, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants