Skip to content

Commit 65d682e

Browse files
meganroggeCopilot
andcommitted
Fix cherry-pick conflicts and repository selection
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c91de8f commit 65d682e

5 files changed

Lines changed: 60 additions & 54 deletions

File tree

extensions/copilot/src/platform/git/vscode-node/gitServiceImpl.ts

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,16 @@ export class GitServiceImpl extends Disposable implements IGitService {
197197
async getRepositoryFetchUrls(uri: URI): Promise<Pick<RepoContext, 'rootUri' | 'remoteFetchUrls'> | undefined> {
198198
this.logService.trace(`[GitServiceImpl][getRepositoryFetchUrls] URI: ${uri.toString()}`);
199199

200+
const openRepositoryRemotes = this.getOpenRepositoryFetchUrls(uri);
201+
if (openRepositoryRemotes) {
202+
this.logService.trace(`[GitServiceImpl][getRepositoryFetchUrls] Remotes (open repository): ${JSON.stringify(openRepositoryRemotes)}`);
203+
return openRepositoryRemotes;
204+
}
205+
200206
if (uri.scheme === 'file') {
201207
try {
202208
const uriStat = await vscode.workspace.fs.stat(uri);
203-
if (uriStat.type === vscode.FileType.Directory) {
209+
if ((uriStat.type & vscode.FileType.Directory) !== 0) {
204210
const config = await this.readLocalGitConfig(uri);
205211
const parsedRemotes = parseGitRemotes(config);
206212
const origin = parsedRemotes.find(remote => remote.name === 'origin');
@@ -225,32 +231,25 @@ export class GitServiceImpl extends Disposable implements IGitService {
225231
// content exclusion reads as "no repository rules apply to this file".
226232
await this.waitForInitialDiscovery();
227233

234+
const discoveredRepositoryRemotes = this.getOpenRepositoryFetchUrls(uri);
235+
if (discoveredRepositoryRemotes) {
236+
this.logService.trace(`[GitServiceImpl][getRepositoryFetchUrls] Remotes (open repository): ${JSON.stringify(discoveredRepositoryRemotes)}`);
237+
return discoveredRepositoryRemotes;
238+
}
239+
228240
const gitAPI = this.gitExtensionService.getExtensionApi();
229241
if (!gitAPI) {
230242
return undefined;
231243
}
232244

233-
// Query opened repositories
234-
const repository = gitAPI.getRepository(uri);
235-
if (repository) {
236-
const repositoryContext = GitServiceImpl.repoToRepoContext(repository);
237-
const remotes = {
238-
rootUri: repository.rootUri,
239-
remoteFetchUrls: repositoryContext ? Array.from(getOrderedRemoteUrlsFromContext(repositoryContext)) : [],
240-
};
241-
242-
this.logService.trace(`[GitServiceImpl][getRepositoryFetchUrls] Remotes (open repository): ${JSON.stringify(remotes)}`);
243-
return remotes;
244-
}
245-
246245
if (uri.scheme !== 'file') {
247246
this.logService.trace(`[GitServiceImpl][getRepositoryFetchUrls] No open repository found for non-file URI`);
248247
return undefined;
249248
}
250249

251250
try {
252251
const uriStat = await vscode.workspace.fs.stat(uri);
253-
if (uriStat.type !== vscode.FileType.Directory) {
252+
if ((uriStat.type & vscode.FileType.Directory) === 0) {
254253
uri = URI.file(path.dirname(uri.fsPath));
255254
}
256255

@@ -277,12 +276,25 @@ export class GitServiceImpl extends Disposable implements IGitService {
277276
}
278277
}
279278

279+
private getOpenRepositoryFetchUrls(uri: URI): Pick<RepoContext, 'rootUri' | 'remoteFetchUrls'> | undefined {
280+
const repository = this.gitExtensionService.getExtensionApi()?.getRepository(uri);
281+
if (!repository) {
282+
return undefined;
283+
}
284+
285+
const repositoryContext = GitServiceImpl.repoToRepoContext(repository);
286+
return {
287+
rootUri: repository.rootUri,
288+
remoteFetchUrls: repositoryContext ? Array.from(getOrderedRemoteUrlsFromContext(repositoryContext)) : [],
289+
};
290+
}
291+
280292
private async readLocalGitConfig(rootUri: URI): Promise<string> {
281293
const dotGitUri = URI.file(path.join(rootUri.fsPath, '.git'));
282294
const dotGitStat = await vscode.workspace.fs.stat(dotGitUri);
283295
let gitDirectory = dotGitUri.fsPath;
284296

285-
if (dotGitStat.type === vscode.FileType.File) {
297+
if ((dotGitStat.type & vscode.FileType.File) !== 0) {
286298
const dotGit = (await vscode.workspace.fs.readFile(dotGitUri)).toString();
287299
const gitDirectoryMatch = /^gitdir:\s*(?<path>.+)\s*$/m.exec(dotGit);
288300
if (!gitDirectoryMatch?.groups?.path) {

src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessionsProvider.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -902,18 +902,14 @@ function githubRemoteRepoLabel(uri: URI): string | undefined {
902902
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : undefined;
903903
}
904904

905-
<<<<<<< HEAD
906-
=======
907905
function resolveGitHubRepositoryId(folder: ISessionFolder): string | undefined {
908906
const gitHubInfo = folder.gitRepository?.gitHubInfo.get();
909907
if (gitHubInfo) {
910908
return `${gitHubInfo.owner}/${gitHubInfo.repo}`;
911909
}
912-
913910
return githubRemoteRepoLabel(folder.root);
914911
}
915912

916-
>>>>>>> d2368d90653 (chat: fix GitHub context repository selection (#334594))
917913
/**
918914
* Adapts an existing {@link IAgentSession} from the chat layer into the new {@link ICopilotChatSession} facade.
919915
*/
@@ -2648,15 +2644,6 @@ export class CopilotChatSessionsProvider extends Disposable implements ISessions
26482644
}
26492645

26502646
private async _browseForGitHubContext(commandId: string, icon: ThemeIcon, currentWorkspace: ISessionWorkspace | undefined): Promise<ISessionWorkspace | undefined> {
2651-
<<<<<<< HEAD
2652-
const gitHubInfo = currentWorkspace?.folders
2653-
.map(folder => folder.gitRepository?.gitHubInfo.get())
2654-
.find(info => info !== undefined);
2655-
const repoId = gitHubInfo
2656-
? `${gitHubInfo.owner}/${gitHubInfo.repo}`
2657-
: currentWorkspace?.folders.map(folder => githubRemoteRepoLabel(folder.root)).find(id => id !== undefined);
2658-
const selection = await this.commandService.executeCommand<IGitHubContextSelection>(commandId, repoId);
2659-
=======
26602647
const repositoryIds = new Set<string>();
26612648
for (const folder of currentWorkspace?.folders ?? []) {
26622649
const repositoryId = resolveGitHubRepositoryId(folder);
@@ -2675,7 +2662,6 @@ export class CopilotChatSessionsProvider extends Disposable implements ISessions
26752662
}
26762663

26772664
const selection = await this.commandService.executeCommand<IGitHubContextSelection>(commandId, repository);
2678-
>>>>>>> d2368d90653 (chat: fix GitHub context repository selection (#334594))
26792665
if (!selection) {
26802666
return undefined;
26812667
}

src/vs/sessions/contrib/providers/copilotChatSessions/test/browser/copilotChatSessionsProvider.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { IChatResponseModel } from '../../../../../../workbench/contrib/chat/com
3636
import { IChatAgentData } from '../../../../../../workbench/contrib/chat/common/participants/chatAgents.js';
3737
import { IGitRepository, IGitService } from '../../../../../../workbench/contrib/git/common/gitService.js';
3838
import { ISessionChangeEvent } from '../../../../../services/sessions/common/sessionsProvider.js';
39-
import { ChatModelSource, GITHUB_REMOTE_FILE_SCHEME, IChat, ISession, ISessionWorkspace, SESSION_WORKSPACE_GROUP_GITHUB, SessionStatus } from '../../../../../services/sessions/common/session.js';
39+
import { ChatModelSource, GITHUB_REMOTE_FILE_SCHEME, IChat, ISession, ISessionWorkspace, SESSION_WORKSPACE_GROUP_GITHUB, SESSION_WORKSPACE_GROUP_LOCAL, SessionStatus } from '../../../../../services/sessions/common/session.js';
4040
import { CloudSandboxEnabledSettingId, type ICloudSandboxCreateSessionRequest } from '../../../../../../platform/agentHost/common/cloudSandboxAgentHost.js';
4141
import { RemoteAgentHostsEnabledSettingId } from '../../../../../../platform/agentHost/common/remoteAgentHostService.js';
4242
import { CloudSandboxAgentHostContribution, type ICloudSandboxProvisionedSession } from '../../../remoteAgentHost/browser/cloudSandboxAgentHostContribution.js';
@@ -495,8 +495,6 @@ suite('CopilotChatSessionsProvider', () => {
495495
});
496496
});
497497

498-
<<<<<<< HEAD
499-
=======
500498
test('selects a repository before browsing GitHub context when the repository is ambiguous', async () => {
501499
const calls: { commandId: string; repoId: unknown }[] = [];
502500
const harness: IGitHubContextBrowseHarness = {
@@ -639,7 +637,6 @@ suite('CopilotChatSessionsProvider', () => {
639637
]);
640638
});
641639

642-
>>>>>>> d2368d90653 (chat: fix GitHub context repository selection (#334594))
643640
test('sessionTypes excludes Local', () => {
644641
const provider = createProvider(disposables, model);
645642
assert.ok(!provider.sessionTypes.some(type => type.id === SessionType.Local));

src/vs/workbench/contrib/chat/browser/actions/chatContext.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import { localize } from '../../../../../nls.js';
1111
import { agentHostAuthority } from '../../../../../platform/agentHost/common/agentHostUri.js';
1212
import { IRemoteAgentHostService } from '../../../../../platform/agentHost/common/remoteAgentHostService.js';
1313
import { IClipboardService } from '../../../../../platform/clipboard/common/clipboardService.js';
14+
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
1415
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
1516
import { ILabelService } from '../../../../../platform/label/common/label.js';
16-
import { IQuickPickSeparator } from '../../../../../platform/quickinput/common/quickInput.js';
17+
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from '../../../../../platform/quickinput/common/quickInput.js';
1718
import { IWorkbenchContribution } from '../../../../common/contributions.js';
1819
import { EditorResourceAccessor, SideBySideEditor } from '../../../../common/editor.js';
1920
import { DiffEditorInput } from '../../../../common/editor/diffEditorInput.js';
@@ -38,8 +39,6 @@ import { URI } from '../../../../../base/common/uri.js';
3839
import { ITerminalCommand, TerminalCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js';
3940
import { getChatSessionType } from '../../common/model/chatUri.js';
4041
import { buildHostLocalEventsPath } from '../copilotCliEventsUri.js';
41-
<<<<<<< HEAD
42-
=======
4342
import { IGitService } from '../../../git/common/gitService.js';
4443
import { getGitHubRemoteInfo } from '../../../git/common/utils.js';
4544
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
@@ -58,7 +57,6 @@ interface IGitHubRepositoryPick extends IQuickPickItem {
5857
readonly repoId?: string;
5958
readonly folderUri?: URI;
6059
}
61-
>>>>>>> d2368d90653 (chat: fix GitHub context repository selection (#334594))
6260

6361
/**
6462
* Command ID that extensions can call to enable debug tools for the current
@@ -108,8 +106,6 @@ export class ChatContextContributions extends Disposable implements IWorkbenchCo
108106
this._store.add(contextPickService.registerChatContextItem(instantiationService.createInstance(ClipboardImageContextValuePick)));
109107
this._store.add(contextPickService.registerChatContextItem(instantiationService.createInstance(ScreenshotContextValuePick)));
110108
this._store.add(contextPickService.registerChatContextItem(instantiationService.createInstance(SessionReferenceContextPickerPick)));
111-
<<<<<<< HEAD
112-
=======
113109
this._store.add(contextPickService.registerChatContextItem(instantiationService.createInstance(GitHubContextValuePick, 'issue')));
114110
this._store.add(contextPickService.registerChatContextItem(instantiationService.createInstance(GitHubContextValuePick, 'pullRequest')));
115111
}
@@ -219,6 +215,12 @@ export class GitHubContextValuePick implements IChatContextValueItem {
219215
repositoryIds.add(`${info.owner}/${info.repo}`);
220216
}
221217
}
218+
if (repositoryIds.size === 0 && workspaceFolders.length === 1) {
219+
return [{
220+
label: workspaceFolders[0].name,
221+
folderUri: workspaceFolders[0].uri,
222+
}];
223+
}
222224
return Array.from(repositoryIds)
223225
.sort()
224226
.map(repoId => ({ label: repoId, repoId }));
@@ -233,7 +235,6 @@ export class GitHubContextValuePick implements IChatContextValueItem {
233235
);
234236
const info = repository && getGitHubRemoteInfo(repository.state.get());
235237
return info ? `${info.owner}/${info.repo}` : undefined;
236-
>>>>>>> d2368d90653 (chat: fix GitHub context repository selection (#334594))
237238
}
238239
}
239240

src/vs/workbench/contrib/chat/test/browser/actions/chatContext.test.ts

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,18 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import assert from 'assert';
7+
import { Codicon } from '../../../../../../base/common/codicons.js';
8+
import { observableValue } from '../../../../../../base/common/observable.js';
79
import { URI } from '../../../../../../base/common/uri.js';
8-
<<<<<<< HEAD
9-
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../../base/test/common/utils.js';
10-
import { shouldShowOpenEditorsContext } from '../../../browser/actions/chatContext.js';
11-
=======
1210
import { mock, upcastPartial } from '../../../../../../base/test/common/mock.js';
1311
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../../base/test/common/utils.js';
1412
import { ICommandService } from '../../../../../../platform/commands/common/commands.js';
1513
import { IQuickInputService } from '../../../../../../platform/quickinput/common/quickInput.js';
1614
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from '../../../../../../platform/workspace/common/workspace.js';
1715
import { GitHubContextValuePick, shouldShowOpenEditorsContext } from '../../../browser/actions/chatContext.js';
1816
import { ChatContextPickService } from '../../../browser/attachments/chatContextPickService.js';
19-
>>>>>>> d2368d90653 (chat: fix GitHub context repository selection (#334594))
2017
import { IChatWidget } from '../../../browser/chat.js';
18+
import { IGitRepository, IGitService } from '../../../../git/common/gitService.js';
2119

2220
function widget(overrides: Partial<Pick<IChatWidget, 'viewModel' | 'lockedAgentId'>>): Pick<IChatWidget, 'viewModel' | 'lockedAgentId'> {
2321
return {
@@ -33,8 +31,6 @@ function widgetWithSession(sessionResource: URI): Pick<IChatWidget, 'viewModel'
3331
});
3432
}
3533

36-
<<<<<<< HEAD
37-
=======
3834
function repository(remoteUrl: string, rootUri = URI.file(`/workspace/${remoteUrl.length}`)): IGitRepository {
3935
return new class extends mock<IGitRepository>() {
4036
override readonly rootUri = rootUri;
@@ -97,11 +93,9 @@ function workspaceContextService(folders: readonly { readonly uri: URI; readonly
9793
}
9894
}();
9995
}
100-
101-
>>>>>>> d2368d90653 (chat: fix GitHub context repository selection (#334594))
10296
suite('ChatContext', () => {
10397

104-
ensureNoDisposablesAreLeakedInTestSuite();
98+
const disposables = ensureNoDisposablesAreLeakedInTestSuite();
10599

106100
test('shows Open Editors for regular Copilot CLI sessions with eligible editors', () => {
107101
assert.strictEqual(
@@ -130,8 +124,6 @@ suite('ChatContext', () => {
130124
false
131125
);
132126
});
133-
<<<<<<< HEAD
134-
=======
135127

136128
test('opens global GitHub context search without a GitHub repository', async () => {
137129
const commandService = new TestCommandService();
@@ -156,6 +148,25 @@ suite('ChatContext', () => {
156148
});
157149
});
158150

151+
test('uses the sole workspace folder when GitHub repository metadata is incomplete', async () => {
152+
const commandService = new TestCommandService();
153+
const folderUri = URI.file('/workspace/vscode');
154+
const pick = new GitHubContextValuePick(
155+
'issue',
156+
new TestGitService([]),
157+
new class extends mock<IQuickInputService>() { }(),
158+
commandService,
159+
workspaceContextService([{ uri: folderUri, name: 'VS Code' }]),
160+
);
161+
162+
await pick.asAttachment();
163+
164+
assert.deepStrictEqual(commandService.command, {
165+
id: 'github.copilot.chat.cloudSessions.openIssue',
166+
repository: folderUri,
167+
});
168+
});
169+
159170
test('opens GitHub context picker directly for one repository', async () => {
160171
const commandService = new TestCommandService();
161172
commandService.result = {
@@ -308,5 +319,4 @@ suite('ChatContext', () => {
308319
'Issue...',
309320
]);
310321
});
311-
>>>>>>> d2368d90653 (chat: fix GitHub context repository selection (#334594))
312322
});

0 commit comments

Comments
 (0)