Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/chatSessions/vscode-node/pullRequestFileChangesService.ts
13399 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as l10n from '@vscode/l10n';
7
import * as vscode from 'vscode';
8
import { PullRequestSearchItem } from '../../../platform/github/common/githubAPI';
9
import { IOctoKitService } from '../../../platform/github/common/githubService';
10
import { ILogService } from '../../../platform/log/common/logService';
11
import { createServiceIdentifier } from '../../../util/common/services';
12
import { toPRContentUri } from './prContentProvider';
13
14
export const IPullRequestFileChangesService = createServiceIdentifier<IPullRequestFileChangesService>('IPullRequestFileChangesService');
15
16
export interface IPullRequestFileChangesService {
17
readonly _serviceBrand: undefined;
18
getFileChangesMultiDiffPart(pullRequest: PullRequestSearchItem): Promise<vscode.ChatResponseMultiDiffPart | undefined>;
19
}
20
21
export class PullRequestFileChangesService implements IPullRequestFileChangesService {
22
declare readonly _serviceBrand: undefined;
23
24
constructor(
25
@IOctoKitService private readonly _octoKitService: IOctoKitService,
26
@ILogService private readonly logService: ILogService,
27
) { }
28
29
async getFileChangesMultiDiffPart(pullRequest: PullRequestSearchItem): Promise<vscode.ChatResponseMultiDiffPart | undefined> {
30
try {
31
this.logService.trace(`Getting file changes for PR #${pullRequest.number}`);
32
const repoOwner = pullRequest.repository.owner.login;
33
const repoName = pullRequest.repository.name;
34
35
if (!repoOwner || !repoName) {
36
this.logService.warn('No repo ID available for fetching PR file changes');
37
return undefined;
38
}
39
40
this.logService.trace(`Fetching PR files from ${repoOwner}/${repoName} for PR #${pullRequest.number}`);
41
const files = await this._octoKitService.getPullRequestFiles(repoOwner, repoName, pullRequest.number, { createIfNone: { detail: l10n.t('Sign in to GitHub to view pull request file changes.') } });
42
this.logService.trace(`Got ${files?.length || 0} files from API`);
43
44
if (!files || files.length === 0) {
45
this.logService.trace('No file changes found for pull request');
46
return undefined;
47
}
48
49
// Check if we have base and head commit SHAs
50
if (!pullRequest.baseRefOid || !pullRequest.headRefOid) {
51
this.logService.warn('PR missing base or head commit SHA, cannot create diff URIs');
52
return undefined;
53
}
54
55
const diffEntries: vscode.ChatResponseDiffEntry[] = [];
56
57
for (const file of files) {
58
// Always use remote URIs to ensure we show the exact PR content
59
// Local files may be on different branches or have different changes
60
this.logService.trace(`Creating remote URIs for ${file.filename}`);
61
62
const goToFileUri = toPRContentUri(file.filename, {
63
owner: repoOwner,
64
repo: repoName,
65
prNumber: pullRequest.number,
66
commitSha: pullRequest.headRefOid,
67
isBase: false,
68
status: file.status
69
});
70
71
const originalUri = file.status !== 'added'
72
? toPRContentUri(file.previous_filename || file.filename, {
73
owner: repoOwner,
74
repo: repoName,
75
prNumber: pullRequest.number,
76
commitSha: pullRequest.baseRefOid,
77
isBase: true,
78
previousFileName: file.previous_filename,
79
status: file.status
80
})
81
: undefined;
82
83
const modifiedUri = file.status !== 'removed'
84
? goToFileUri
85
: undefined;
86
87
this.logService.trace(`DiffEntry -> original='${originalUri?.toString()}' modified='${modifiedUri?.toString()}' (+${file.additions} -${file.deletions})`);
88
diffEntries.push({
89
originalUri,
90
modifiedUri,
91
goToFileUri,
92
added: file.additions,
93
removed: file.deletions,
94
});
95
}
96
97
const title = `Changes in Pull Request #${pullRequest.number}`;
98
return new vscode.ChatResponseMultiDiffPart(diffEntries, title, false);
99
} catch (error) {
100
this.logService.error(`Failed to get file changes multi diff part: ${error}`);
101
return undefined;
102
}
103
}
104
}
105
106