Path: blob/main/extensions/copilot/src/extension/chatSessions/vscode-node/pullRequestFileChangesService.ts
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as l10n from '@vscode/l10n';6import * as vscode from 'vscode';7import { PullRequestSearchItem } from '../../../platform/github/common/githubAPI';8import { IOctoKitService } from '../../../platform/github/common/githubService';9import { ILogService } from '../../../platform/log/common/logService';10import { createServiceIdentifier } from '../../../util/common/services';11import { toPRContentUri } from './prContentProvider';1213export const IPullRequestFileChangesService = createServiceIdentifier<IPullRequestFileChangesService>('IPullRequestFileChangesService');1415export interface IPullRequestFileChangesService {16readonly _serviceBrand: undefined;17getFileChangesMultiDiffPart(pullRequest: PullRequestSearchItem): Promise<vscode.ChatResponseMultiDiffPart | undefined>;18}1920export class PullRequestFileChangesService implements IPullRequestFileChangesService {21declare readonly _serviceBrand: undefined;2223constructor(24@IOctoKitService private readonly _octoKitService: IOctoKitService,25@ILogService private readonly logService: ILogService,26) { }2728async getFileChangesMultiDiffPart(pullRequest: PullRequestSearchItem): Promise<vscode.ChatResponseMultiDiffPart | undefined> {29try {30this.logService.trace(`Getting file changes for PR #${pullRequest.number}`);31const repoOwner = pullRequest.repository.owner.login;32const repoName = pullRequest.repository.name;3334if (!repoOwner || !repoName) {35this.logService.warn('No repo ID available for fetching PR file changes');36return undefined;37}3839this.logService.trace(`Fetching PR files from ${repoOwner}/${repoName} for PR #${pullRequest.number}`);40const files = await this._octoKitService.getPullRequestFiles(repoOwner, repoName, pullRequest.number, { createIfNone: { detail: l10n.t('Sign in to GitHub to view pull request file changes.') } });41this.logService.trace(`Got ${files?.length || 0} files from API`);4243if (!files || files.length === 0) {44this.logService.trace('No file changes found for pull request');45return undefined;46}4748// Check if we have base and head commit SHAs49if (!pullRequest.baseRefOid || !pullRequest.headRefOid) {50this.logService.warn('PR missing base or head commit SHA, cannot create diff URIs');51return undefined;52}5354const diffEntries: vscode.ChatResponseDiffEntry[] = [];5556for (const file of files) {57// Always use remote URIs to ensure we show the exact PR content58// Local files may be on different branches or have different changes59this.logService.trace(`Creating remote URIs for ${file.filename}`);6061const goToFileUri = toPRContentUri(file.filename, {62owner: repoOwner,63repo: repoName,64prNumber: pullRequest.number,65commitSha: pullRequest.headRefOid,66isBase: false,67status: file.status68});6970const originalUri = file.status !== 'added'71? toPRContentUri(file.previous_filename || file.filename, {72owner: repoOwner,73repo: repoName,74prNumber: pullRequest.number,75commitSha: pullRequest.baseRefOid,76isBase: true,77previousFileName: file.previous_filename,78status: file.status79})80: undefined;8182const modifiedUri = file.status !== 'removed'83? goToFileUri84: undefined;8586this.logService.trace(`DiffEntry -> original='${originalUri?.toString()}' modified='${modifiedUri?.toString()}' (+${file.additions} -${file.deletions})`);87diffEntries.push({88originalUri,89modifiedUri,90goToFileUri,91added: file.additions,92removed: file.deletions,93});94}9596const title = `Changes in Pull Request #${pullRequest.number}`;97return new vscode.ChatResponseMultiDiffPart(diffEntries, title, false);98} catch (error) {99this.logService.error(`Failed to get file changes multi diff part: ${error}`);100return undefined;101}102}103}104105106