-
Notifications
You must be signed in to change notification settings - Fork 52.3k
fix(cli): forward --worktree to run_oneshot so -z -w works (#67458) #67484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -173,6 +173,7 @@ def run_oneshot( | |
| provider: Optional[str] = None, | ||
| toolsets: object = None, | ||
| usage_file: Optional[str] = None, | ||
| worktree: bool = False, | ||
| ) -> int: | ||
| """Execute a single prompt and print only the final content block. | ||
|
|
||
|
|
@@ -187,6 +188,9 @@ def run_oneshot( | |
| cost, token counts, model, api_calls) is written there after the | ||
| run — even when the run fails — so pipelines can account for | ||
| spend per invocation. | ||
| worktree: When True, create an isolated git worktree so the agent's | ||
| commits don't land on the current branch (same as ``-w`` in | ||
| interactive mode). | ||
|
|
||
| Returns the exit code. Caller should sys.exit() with the return. | ||
| """ | ||
|
|
@@ -230,6 +234,34 @@ def run_oneshot( | |
| # to its inline/synchronous path. See declare_stateless_channel(). | ||
| declare_stateless_channel() | ||
|
|
||
| # Set up isolated git worktree when -w/--worktree is requested. | ||
| _wt_info = None | ||
| if worktree: | ||
| try: | ||
| from cli import ( | ||
| _cleanup_worktree, | ||
| _git_repo_root, | ||
| _prune_stale_worktrees, | ||
| _setup_worktree, | ||
| ) | ||
|
|
||
| repo = _git_repo_root() | ||
| if repo: | ||
| _prune_stale_worktrees(repo) | ||
| _wt_info = _setup_worktree() | ||
| if not _wt_info: | ||
| sys.stderr.write( | ||
| "hermes -z: --worktree failed (are you inside a git repo?).\n" | ||
| ) | ||
| return 1 | ||
| os.environ["HERMES_CWD"] = _wt_info["path"] | ||
| os.environ["TERMINAL_CWD"] = _wt_info["path"] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Save the prior CWD environment values and restore them in the final cleanup path. As written, a direct caller retains |
||
| except Exception as exc: | ||
| sys.stderr.write( | ||
| f"hermes -z: --worktree setup failed: {exc}\n" | ||
| ) | ||
| return 1 | ||
|
|
||
| # Redirect stderr AND stdout to devnull for the entire call tree. | ||
| # We'll print the final response to the real stdout at the end. | ||
| real_stdout = sys.stdout | ||
|
|
@@ -263,6 +295,14 @@ def run_oneshot( | |
| devnull.close() | ||
| except Exception: | ||
| pass | ||
| # Clean up worktree on exit (unless it has unpushed commits — same | ||
| # policy as interactive mode). | ||
| if _wt_info is not None: | ||
| try: | ||
| from cli import _cleanup_worktree | ||
| _cleanup_worktree(_wt_info) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| except Exception: | ||
| pass | ||
|
|
||
| if failure is not None: | ||
| # Re-raise control-flow exceptions so the parent handles them as usual | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_setup_worktree()prints creation messages to stdout (cli.py:1630-1632), but-zpromises stdout contains only the final response. Route this helper's output to stderr before calling it.