Skip to content

Commit 6131c9b

Browse files
authored
interactive commit: fix cancel button and other issues (#7267)
1 parent 6b08cf6 commit 6131c9b

File tree

1 file changed

+28
-27
lines changed

1 file changed

+28
-27
lines changed

src/github/copilotRemoteAgent.ts

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const CONTINUE = vscode.l10n.t('Continue');
4444
// With Pending Changes
4545
const PUSH_CHANGES = vscode.l10n.t('Include changes');
4646
const CONTINUE_WITHOUT_PUSHING = vscode.l10n.t('Ignore changes');
47+
const COMMIT_YOUR_CHANGES = vscode.l10n.t('Commit your changes to continue coding agent session. Close integrated terminal to cancel.');
4748

4849
const FOLLOW_UP_REGEX = /open-pull-request-webview.*((%7B.*?%7D)|(\{.*?\}))/;
4950
const COPILOT = '@copilot';
@@ -394,41 +395,47 @@ export class CopilotRemoteAgentManager extends Disposable {
394395
* Opens a terminal and waits for user to successfully commit
395396
* This is a fallback for when the commit cannot be done automatically (eg: GPG signing password needed)
396397
*/
397-
private async handleInteractiveCommit(repository: Repository, commitMessage: string): Promise<boolean> {
398+
private async handleInteractiveCommit(repository: Repository, cancellationToken?: vscode.CancellationToken): Promise<boolean> {
398399
return new Promise<boolean>((resolve) => {
399400
const startingCommit = repository.state.HEAD?.commit;
400401

401402
// Create terminal with git commit command
402403
const terminal = vscode.window.createTerminal({
403404
name: 'GitHub Coding Agent',
404405
cwd: repository.rootUri.fsPath,
405-
message: vscode.l10n.t('Commit your changes to continue coding agent session')
406+
message: `\x1b[1m${vscode.l10n.t(COMMIT_YOUR_CHANGES)}\x1b[0m`
406407
});
407408

408409
// Show terminal and send commit command
409410
terminal.show();
410-
terminal.sendText(`# Complete this commit to continue with your coding agent session. Ctrl+C to cancel.`);
411-
terminal.sendText(`git commit -m "${commitMessage}"`);
412-
413411
let disposed = false;
414412
let timeoutId: NodeJS.Timeout;
415413
let stateListener: vscode.Disposable | undefined;
416414
let disposalListener: vscode.Disposable | undefined;
415+
let cancellationListener: vscode.Disposable | undefined;
417416

418417
const cleanup = () => {
419418
if (disposed) return;
420419
disposed = true;
421420
clearTimeout(timeoutId);
422421
stateListener?.dispose();
423422
disposalListener?.dispose();
423+
cancellationListener?.dispose();
424424
terminal.dispose();
425425
};
426426

427+
// Listen for cancellation if token is provided
428+
if (cancellationToken) {
429+
cancellationListener = cancellationToken.onCancellationRequested(() => {
430+
cleanup();
431+
resolve(false);
432+
});
433+
}
434+
427435
// Listen for repository state changes
428436
stateListener = repository.state.onDidChange(() => {
429437
// Check if commit was successful (HEAD changed and no more staged changes)
430-
if (repository.state.HEAD?.commit !== startingCommit &&
431-
repository.state.indexChanges.length === 0) {
438+
if (repository.state.HEAD?.commit !== startingCommit) {
432439
cleanup();
433440
resolve(true);
434441
}
@@ -437,22 +444,17 @@ export class CopilotRemoteAgentManager extends Disposable {
437444
// Set a timeout to avoid waiting forever
438445
timeoutId = setTimeout(() => {
439446
cleanup();
440-
vscode.window.showWarningMessage(
441-
vscode.l10n.t('Commit timeout. Please try the operation again after committing your changes.')
442-
);
443447
resolve(false);
444448
}, 5 * 60 * 1000); // 5 minutes timeout
445449

446450
// Listen for terminal disposal (user closed it)
447451
disposalListener = vscode.window.onDidCloseTerminal((closedTerminal) => {
448452
if (closedTerminal === terminal) {
449-
// Give a brief moment for potential state changes to propagate
450453
setTimeout(() => {
451454
if (!disposed) {
452455
cleanup();
453456
// Check one more time if commit happened just before terminal was closed
454-
resolve(repository.state.HEAD?.commit !== startingCommit &&
455-
repository.state.indexChanges.length === 0);
457+
resolve(repository.state.HEAD?.commit !== startingCommit);
456458
}
457459
}, 1000);
458460
}
@@ -494,31 +496,20 @@ export class CopilotRemoteAgentManager extends Disposable {
494496
} catch (e) {
495497
// Instead of immediately failing, open terminal for interactive commit
496498
const commitSuccessful = await vscode.window.withProgress({
497-
title: vscode.l10n.t('Waiting for commit to complete in the integrated terminal...'),
499+
title: COMMIT_YOUR_CHANGES,
498500
cancellable: true,
499501
location: vscode.ProgressLocation.Notification
500502
}, async (progress, token) => {
501-
const commitPromise = this.handleInteractiveCommit(repository, commitMessage);
502-
if (token) {
503-
token.onCancellationRequested(() => {
504-
return false;
505-
});
506-
}
503+
const commitPromise = this.handleInteractiveCommit(repository, token);
507504
return await commitPromise;
508505
});
509506
if (!commitSuccessful) {
510-
return { error: vscode.l10n.t('Commit was unsuccessful. Manually commit or stash your changes and try again.'), state: 'error' };
507+
return { error: vscode.l10n.t('Exclude your uncommitted changes and try again.'), state: 'error' };
511508
}
512509
}
513510
await repository.push(remote.remoteName, asyncBranch, true);
514511
ref = asyncBranch;
515-
} catch (e) {
516-
return { error: vscode.l10n.t('Could not auto-push pending changes. Manually commit or stash your changes and try again. ({0})', e.message), state: 'error' };
517-
} finally {
518-
// Swap back to the original branch without your pending changes
519-
// TODO: Better if we show a confirmation dialog in chat
520512
if (repository.state.HEAD?.name !== baseRef) {
521-
// show notification asking the user if they want to switch back to the original branch
522513
const SWAP_BACK_TO_ORIGINAL_BRANCH = vscode.l10n.t(`Swap back to '{0}'`, baseRef);
523514
vscode.window.showInformationMessage(
524515
vscode.l10n.t(`Pending changes pushed to remote branch '{0}'.`, ref),
@@ -529,6 +520,16 @@ export class CopilotRemoteAgentManager extends Disposable {
529520
}
530521
});
531522
}
523+
} catch (e) {
524+
if (repository.state.HEAD?.name !== baseRef) {
525+
try {
526+
await repository.checkout(baseRef);
527+
} catch (checkoutError) {
528+
Logger.error(`Failed to checkout back to original branch '${baseRef}': ${checkoutError}`, CopilotRemoteAgentManager.ID);
529+
}
530+
}
531+
Logger.error(`Failed to auto-commit and push pending changes: ${e}`, CopilotRemoteAgentManager.ID);
532+
return { error: vscode.l10n.t('Could not auto-push pending changes. Manually commit or stash your changes and try again. ({0})', e.message), state: 'error' };
532533
}
533534
}
534535

0 commit comments

Comments
 (0)