diff --git a/src/aipass/drone/apps/handlers/git/commit_handler.py b/src/aipass/drone/apps/handlers/git/commit_handler.py index 3481eecb..df5d00dc 100644 --- a/src/aipass/drone/apps/handlers/git/commit_handler.py +++ b/src/aipass/drone/apps/handlers/git/commit_handler.py @@ -57,16 +57,28 @@ def commit_changes( message: str, branch_dir: Path | None = None, all_files: bool = False, + files: list[str] | None = None, ) -> dict: """Commit changes. With --all, stages the entire repo (not CWD-scoped). Post-DPLAN-0173: only devpulse commits, agents don't PR. Repo-wide staging is the correct default since dispatched agents work across multiple branch directories. + + With file paths, stages only those specific files (selective commit). """ repo_root = find_repo_root() - if all_files: + if files: + add_result = subprocess.run( + ["git", "add", "--"] + files, + capture_output=True, + text=True, + cwd=str(repo_root), + ) + if add_result.returncode != 0: + return {"stdout": "", "stderr": f"Failed to stage: {add_result.stderr.strip()}", "exit_code": 1} + elif all_files: import shutil ruff_bin = shutil.which("ruff") @@ -124,7 +136,7 @@ def commit_changes( json_handler.log_operation( "commit_changes", - {"message": message, "all_files": all_files, "exit_code": result.returncode}, + {"message": message, "all_files": all_files, "files": files, "exit_code": result.returncode}, ) return { diff --git a/src/aipass/drone/apps/modules/git_module.py b/src/aipass/drone/apps/modules/git_module.py index fb94515e..e7fa34d0 100644 --- a/src/aipass/drone/apps/modules/git_module.py +++ b/src/aipass/drone/apps/modules/git_module.py @@ -447,13 +447,22 @@ def _handle_commit(args: list[str]) -> dict: if not args: return { "stdout": "", - "stderr": "Usage: drone @git commit [--all]", + "stderr": "Usage: drone @git commit [--all | file1 file2 ...]", "exit_code": 1, } all_files = "--all" in args - msg_parts = [a for a in args if a != "--all"] - message = " ".join(msg_parts) + clean_args = [a for a in args if a != "--all"] + + if not clean_args: + return { + "stdout": "", + "stderr": "Commit message cannot be empty", + "exit_code": 1, + } + + message = clean_args[0] + files = clean_args[1:] if len(clean_args) > 1 else None if not message: return { @@ -462,7 +471,7 @@ def _handle_commit(args: list[str]) -> dict: "exit_code": 1, } - return commit_handler.commit_changes(message, all_files=all_files) + return commit_handler.commit_changes(message, all_files=all_files, files=files) def _handle_checkout(args: list[str]) -> dict: