Skip to content

Commit bb05870

Browse files
Copilotrebornixalexr00
authored
Fix spurious error when checking out a PR with untracked files and add "never show again" option (#7306)
* Initial plan * Implement fix for spurious error when checking out PR with untracked files Co-authored-by: rebornix <876920+rebornix@users.noreply.github.com> * Address review feedback: Remove test and add "never show again" option Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> * Use local state instead of setting for never show again preference Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> * Wording --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rebornix <876920+rebornix@users.noreply.github.com> Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
1 parent 102dc48 commit bb05870

1 file changed

Lines changed: 30 additions & 10 deletions

File tree

src/commands.ts

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
import * as pathLib from 'path';
88
import * as vscode from 'vscode';
99
import { Repository } from './api/api';
10-
import { GitErrorCodes } from './api/api1';
10+
import { GitErrorCodes, Status } from './api/api1';
1111
import { CommentReply, findActiveHandler, resolveCommentHandler } from './commentHandlerResolver';
1212
import { commands } from './common/executeCommands';
1313
import Logger from './common/logger';
14+
import * as PersistentState from './common/persistentState';
1415
import { FILE_LIST_LAYOUT, PR_SETTINGS_NAMESPACE } from './common/settingKeys';
1516
import { editQuery } from './common/settingsUtils';
1617
import { ITelemetry } from './common/telemetry';
@@ -52,50 +53,69 @@ import { RepositoryChangesNode } from './view/treeNodes/repositoryChangesNode';
5253
// Modal dialog options for handling uncommitted changes during PR checkout
5354
const STASH_CHANGES = vscode.l10n.t('Stash changes');
5455
const DISCARD_CHANGES = vscode.l10n.t('Discard changes');
56+
const DONT_SHOW_AGAIN = vscode.l10n.t('Try to checkout anyway and don\'t show again');
57+
58+
// Constants for persistent state storage
59+
const UNCOMMITTED_CHANGES_SCOPE = vscode.l10n.t('uncommitted changes warning');
60+
const UNCOMMITTED_CHANGES_STORAGE_KEY = 'showWarning';
5561

5662
/**
5763
* Shows a modal dialog when there are uncommitted changes during PR checkout
5864
* @param repository The git repository with uncommitted changes
5965
* @returns Promise<boolean> true if user chose to proceed (after staging/discarding), false if cancelled
6066
*/
6167
async function handleUncommittedChanges(repository: Repository): Promise<boolean> {
62-
const hasWorkingTreeChanges = repository.state.workingTreeChanges.length > 0;
68+
// Check if user has disabled the warning using persistent state
69+
if (PersistentState.fetch(UNCOMMITTED_CHANGES_SCOPE, UNCOMMITTED_CHANGES_STORAGE_KEY) === false) {
70+
return true; // User has disabled warnings, proceed without showing dialog
71+
}
72+
73+
// Filter out untracked files as they typically don't conflict with PR checkout
74+
const trackedWorkingTreeChanges = repository.state.workingTreeChanges.filter(change => change.status !== Status.UNTRACKED);
75+
const hasTrackedWorkingTreeChanges = trackedWorkingTreeChanges.length > 0;
6376
const hasIndexChanges = repository.state.indexChanges.length > 0;
6477

65-
if (!hasWorkingTreeChanges && !hasIndexChanges) {
66-
return true; // No uncommitted changes, proceed
78+
if (!hasTrackedWorkingTreeChanges && !hasIndexChanges) {
79+
return true; // No tracked uncommitted changes, proceed
6780
}
6881

6982
const modalResult = await vscode.window.showInformationMessage(
70-
vscode.l10n.t('You have uncommitted changes that would be overwritten by checking out this pull request.'),
83+
vscode.l10n.t('You have uncommitted changes that might be overwritten by checking out this pull request.'),
7184
{
7285
modal: true,
7386
detail: vscode.l10n.t('Choose how to handle your uncommitted changes before checking out the pull request.'),
7487
},
7588
STASH_CHANGES,
7689
DISCARD_CHANGES,
90+
DONT_SHOW_AGAIN,
7791
);
7892

7993
if (!modalResult) {
8094
return false; // User cancelled
8195
}
8296

97+
if (modalResult === DONT_SHOW_AGAIN) {
98+
// Store preference to never show this dialog again using persistent state
99+
PersistentState.store(UNCOMMITTED_CHANGES_SCOPE, UNCOMMITTED_CHANGES_STORAGE_KEY, false);
100+
return true; // Proceed with checkout
101+
}
102+
83103
try {
84104
if (modalResult === STASH_CHANGES) {
85105
// Stash all changes (working tree changes + any unstaged changes)
86106
const allChangedFiles = [
87-
...repository.state.workingTreeChanges.map(change => change.uri.fsPath),
107+
...trackedWorkingTreeChanges.map(change => change.uri.fsPath),
88108
...repository.state.indexChanges.map(change => change.uri.fsPath),
89109
];
90110
if (allChangedFiles.length > 0) {
91111
await repository.add(allChangedFiles);
92112
await vscode.commands.executeCommand('git.stash', repository);
93113
}
94114
} else if (modalResult === DISCARD_CHANGES) {
95-
// Discard all working tree changes
96-
const workingTreeFiles = repository.state.workingTreeChanges.map(change => change.uri.fsPath);
97-
if (workingTreeFiles.length > 0) {
98-
await repository.clean(workingTreeFiles);
115+
// Discard all tracked working tree changes
116+
const trackedWorkingTreeFiles = trackedWorkingTreeChanges.map(change => change.uri.fsPath);
117+
if (trackedWorkingTreeFiles.length > 0) {
118+
await repository.clean(trackedWorkingTreeFiles);
99119
}
100120
}
101121
return true; // Successfully handled changes, proceed with checkout

0 commit comments

Comments
 (0)