Skip to content

Commit dcbba86

Browse files
Merge branch 'microsoft:main' into not-close-file
2 parents 96783c3 + e287ca8 commit dcbba86

27 files changed

+1244
-754
lines changed

.vscode/launch.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,11 @@
102102
"type": "node",
103103
"request": "launch",
104104
"name": "Attach Web Test",
105-
"program": "${workspaceFolder}/node_modules/vscode-test-web/out/index.js",
105+
"program": "${workspaceFolder}/node_modules/@vscode/test-web/out/server/index.js",
106106
"args": [
107107
"--extensionTestsPath=dist/browser/test/index.js",
108108
"--extensionDevelopmentPath=.",
109109
"--browserType=chromium",
110-
"--attach=9229"
111110
],
112111
"cascadeTerminateToConfigurations": [
113112
"Launch Web Test"

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
# Changelog
22

3+
## 0.114.2
4+
5+
### Fixes
6+
7+
- Copilot never shows as assignee. https://github.com/microsoft/vscode-pull-request-github/issues/7324
8+
39
## 0.114.1
410

11+
### Fixes
12+
513
- Element with id Local Pull Request Branches is already registered. https://github.com/microsoft/vscode-pull-request-github/issues/7264
614

715
## 0.114.0

build/hygiene.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function hygiene(some) {
5656
const indentation = es.through(function (file) {
5757
const lines = file.__lines;
5858

59-
lines.forEach((line, i) => {
59+
lines?.forEach((line, i) => {
6060
if (/^\s*$/.test(line)) {
6161
// empty or whitespace lines are OK
6262
} else if (/^[\t]*[^\s]/.test(line)) {

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"onFileSystem:newIssue",
5353
"onFileSystem:pr",
5454
"onFileSystem:githubpr",
55+
"onFileSystem:githubcommit",
5556
"onFileSystem:review",
5657
"onWebviewPanel:pr.codingAgentSessionLogView"
5758
],
@@ -81,7 +82,8 @@
8182
"name": "githubpr",
8283
"fullName": "GitHub Pull Requests",
8384
"description": "Chat participant for GitHub Pull Requests extension",
84-
"when": "config.githubPullRequests.experimental.chat"
85+
"when": "config.githubPullRequests.experimental.chat",
86+
"isSticky": true
8587
}
8688
],
8789
"configuration": {
@@ -3978,13 +3980,13 @@
39783980
"@types/webpack-env": "^1.16.0",
39793981
"@typescript-eslint/eslint-plugin": "6.10.0",
39803982
"@typescript-eslint/parser": "6.10.0",
3981-
"@vscode/test-electron": "^2.3.8",
3983+
"@vscode/test-electron": "^2.5.2",
39823984
"@vscode/test-web": "^0.0.71",
39833985
"assert": "^2.0.0",
39843986
"buffer": "^6.0.3",
39853987
"constants-browserify": "^1.0.0",
39863988
"crypto-browserify": "3.12.0",
3987-
"css-loader": "5.1.3",
3989+
"css-loader": "7.1.2",
39883990
"esbuild-loader": "4.2.2",
39893991
"eslint": "7.22.0",
39903992
"eslint-cli": "1.1.1",
@@ -4010,17 +4012,16 @@
40104012
"p-all": "^1.0.0",
40114013
"path-browserify": "1.0.1",
40124014
"process": "^0.11.10",
4013-
"raw-loader": "4.0.2",
40144015
"react-testing-library": "7.0.1",
40154016
"sinon": "9.0.0",
40164017
"source-map-support": "0.5.19",
40174018
"stream-browserify": "^3.0.0",
4018-
"style-loader": "2.0.0",
4019+
"style-loader": "4.0.0",
40194020
"svg-inline-loader": "^0.8.2",
40204021
"temp": "0.9.4",
40214022
"terser-webpack-plugin": "5.1.1",
40224023
"timers-browserify": "^2.0.12",
4023-
"ts-loader": "8.0.18",
4024+
"ts-loader": "9.5.2",
40244025
"tty": "1.0.1",
40254026
"typescript": "4.5.5",
40264027
"typescript-formatter": "^7.2.2",

src/common/uri.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,29 @@ export interface GitUriOptions {
9292
base: boolean;
9393
}
9494

95+
export interface GitHubCommitUriParams {
96+
commit: string;
97+
owner: string;
98+
repo: string;
99+
}
100+
101+
export function fromGitHubCommitUri(uri: vscode.Uri): GitHubCommitUriParams | undefined {
102+
if (uri.scheme !== Schemes.GitHubCommit || uri.query === '') {
103+
return undefined;
104+
}
105+
try {
106+
return JSON.parse(uri.query) as GitHubCommitUriParams;
107+
} catch (e) { }
108+
}
109+
110+
export function toGitHubCommitUri(fileName: string, params: GitHubCommitUriParams): vscode.Uri {
111+
return vscode.Uri.from({
112+
scheme: Schemes.GitHubCommit,
113+
path: `/${fileName}`,
114+
query: JSON.stringify(params)
115+
});
116+
}
117+
95118
const ImageMimetypes = ['image/png', 'image/gif', 'image/jpeg', 'image/webp', 'image/tiff', 'image/bmp'];
96119
// Known media types that VS Code can handle: https://github.com/microsoft/vscode/blob/a64e8e5673a44e5b9c2d493666bde684bd5a135c/src/vs/base/common/mime.ts#L33-L84
97120
export const KnownMediaExtensions = [
@@ -651,6 +674,7 @@ export enum Schemes {
651674
Repo = 'repo', // New issue file for passing data
652675
Git = 'git', // File content from the git extension
653676
PRQuery = 'prquery', // PR query tree item
677+
GitHubCommit = 'githubcommit' // file content from GitHub for a commit
654678
}
655679

656680
export const COPILOT_QUERY = vscode.Uri.from({ scheme: Schemes.PRQuery, path: 'copilot' });

src/extension.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { CommentDecorationProvider } from './view/commentDecorationProvider';
3939
import { CompareChanges } from './view/compareChangesTreeDataProvider';
4040
import { CreatePullRequestHelper } from './view/createPullRequestHelper';
4141
import { FileTypeDecorationProvider } from './view/fileTypeDecorationProvider';
42+
import { GitHubCommitFileSystemProvider } from './view/githubFileContentProvider';
4243
import { getInMemPRFileSystemProvider } from './view/inMemPRContentProvider';
4344
import { PullRequestChangesTreeDataProvider } from './view/prChangesTreeDataProvider';
4445
import { PRNotificationDecorationProvider } from './view/prNotificationDecorationProvider';
@@ -227,7 +228,7 @@ async function init(
227228
context.subscriptions.push(issuesFeatures);
228229
await issuesFeatures.initialize();
229230

230-
const notificationsFeatures = new NotificationsFeatureRegister(credentialStore, reposManager, telemetry);
231+
const notificationsFeatures = new NotificationsFeatureRegister(credentialStore, reposManager, telemetry, context);
231232
context.subscriptions.push(notificationsFeatures);
232233

233234
context.subscriptions.push(new GitLensIntegration());
@@ -436,6 +437,8 @@ async function deferredActivate(context: vscode.ExtensionContext, showPRControll
436437
const readOnlyMessage = new vscode.MarkdownString(vscode.l10n.t('Cannot edit this pull request file. [Check out](command:pr.checkoutFromReadonlyFile) this pull request to edit.'));
437438
readOnlyMessage.isTrusted = { enabledCommands: ['pr.checkoutFromReadonlyFile'] };
438439
context.subscriptions.push(vscode.workspace.registerFileSystemProvider(Schemes.Pr, inMemPRFileSystemProvider, { isReadonly: readOnlyMessage }));
440+
const githubFilesystemProvider = new GitHubCommitFileSystemProvider(reposManager, apiImpl, credentialStore);
441+
context.subscriptions.push(vscode.workspace.registerFileSystemProvider(Schemes.GitHubCommit, githubFilesystemProvider, { isReadonly: new vscode.MarkdownString(vscode.l10n.t('GitHub commits cannot be edited')) }));
439442

440443
await init(context, apiImpl, credentialStore, repositories, prTree, liveshareApiPromise, showPRController, reposManager, createPrHelper, copilotRemoteAgentManager, themeWatcher);
441444
return apiImpl;

src/github/githubRepository.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Disposable, disposeAll } from '../common/lifecycle';
1212
import Logger from '../common/logger';
1313
import { GitHubRemote, parseRemote } from '../common/remote';
1414
import { ITelemetry } from '../common/telemetry';
15+
import { PullRequestCommentController } from '../view/pullRequestCommentController';
1516
import { PRCommentControllerRegistry } from '../view/pullRequestCommentControllerRegistry';
1617
import { mergeQuerySchemaWithShared, OctokitCommon, Schema } from './common';
1718
import { CredentialStore, GitHub } from './credentials';
@@ -204,10 +205,10 @@ export class GitHubRepository extends Disposable {
204205

205206
await this.ensure();
206207
this.commentsController = vscode.comments.createCommentController(
207-
`github-browse-${this.remote.normalizedHost}-${this.remote.owner}-${this.remote.repositoryName}`,
208+
`${PullRequestCommentController.PREFIX}-${this.remote.gitProtocol.normalizeUri()?.authority}-${this.remote.owner}-${this.remote.repositoryName}`,
208209
`Pull Request (${this.remote.owner}/${this.remote.repositoryName})`,
209210
);
210-
this.commentsHandler = new PRCommentControllerRegistry(this.commentsController, this._telemetry);
211+
this.commentsHandler = new PRCommentControllerRegistry(this.commentsController, this.telemetry);
211212
this._register(this.commentsHandler);
212213
this._register(this.commentsController);
213214
} catch (e) {
@@ -234,7 +235,7 @@ export class GitHubRepository extends Disposable {
234235
public remote: GitHubRemote,
235236
public readonly rootUri: vscode.Uri,
236237
private readonly _credentialStore: CredentialStore,
237-
private readonly _telemetry: ITelemetry,
238+
public readonly telemetry: ITelemetry,
238239
silent: boolean = false
239240
) {
240241
super();
@@ -264,7 +265,7 @@ export class GitHubRepository extends Disposable {
264265
"action": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
265266
}
266267
*/
267-
this._telemetry.sendTelemetryErrorEvent('pr.codespacesTokenError', {
268+
this.telemetry.sendTelemetryErrorEvent('pr.codespacesTokenError', {
268269
action: action.context
269270
});
270271

@@ -566,6 +567,19 @@ export class GitHubRepository extends Disposable {
566567
return success;
567568
}
568569

570+
async getCommitParent(ref: string): Promise<string | undefined> {
571+
Logger.debug(`Fetch commit for ref ${ref} - enter`, this.id);
572+
try {
573+
const { octokit, remote } = await this.ensure();
574+
const commit = (await octokit.call(octokit.api.repos.getCommit, { owner: remote.owner, repo: remote.repositoryName, ref })).data;
575+
return commit.parents[0].sha;
576+
} catch (e) {
577+
Logger.error(`Fetching commit for ref ${ref} failed: ${e}`, this.id);
578+
}
579+
Logger.debug(`Fetch commit for ref ${ref} - done`, this.id);
580+
}
581+
582+
569583
async getAllPullRequests(page?: number): Promise<PullRequestData | undefined> {
570584
let remote: GitHubRemote | undefined;
571585
try {
@@ -950,7 +964,7 @@ export class GitHubRepository extends Disposable {
950964
if (model) {
951965
model.update(pullRequest);
952966
} else {
953-
model = new PullRequestModel(this._credentialStore, this._telemetry, this, this.remote, pullRequest);
967+
model = new PullRequestModel(this._credentialStore, this.telemetry, this, this.remote, pullRequest);
954968
const prModel = model;
955969
const disposables: vscode.Disposable[] = [];
956970
disposables.push(model.onDidChange(() => this._onPullRequestModelChanged(prModel)));

src/github/markdownUtils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,9 @@ export async function issueMarkdown(
168168
year: 'numeric',
169169
})} \n`,
170170
);
171+
const titleWithDraft = (issue instanceof PullRequestModel && issue.isDraft) ? `\[DRAFT\] ${issue.title}` : issue.title;
171172
const title = marked
172-
.parse(issue.title, {
173+
.parse(titleWithDraft, {
173174
renderer: new PlainTextRenderer(),
174175
})
175176
.trim();

src/github/pullRequestModel.ts

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import gql from 'graphql-tag';
1010
import * as vscode from 'vscode';
1111
import { Repository } from '../api/api';
1212
import { COPILOT_ACCOUNTS, DiffSide, IComment, IReviewThread, SubjectType, ViewedState } from '../common/comment';
13-
import { getModifiedContentFromDiffHunk, parseDiff } from '../common/diffHunk';
13+
import { getGitChangeType, getModifiedContentFromDiffHunk, parseDiff } from '../common/diffHunk';
1414
import { commands } from '../common/executeCommands';
1515
import { GitChangeType, InMemFileChange, SlimFileChange } from '../common/file';
1616
import { GitHubRef } from '../common/githubRef';
1717
import Logger from '../common/logger';
1818
import { Remote } from '../common/remote';
1919
import { ITelemetry } from '../common/telemetry';
2020
import { ClosedEvent, EventType, ReviewEvent, TimelineEvent } from '../common/timelineEvent';
21-
import { resolvePath, reviewPath, Schemes, toPRUri, toReviewUri } from '../common/uri';
21+
import { resolvePath, Schemes, toGitHubCommitUri, toPRUri, toReviewUri } from '../common/uri';
2222
import { formatError, isDescendant } from '../common/utils';
2323
import { InMemFileChangeModel, RemoteFileChangeModel } from '../view/fileChangeModel';
2424
import { OctokitCommon } from './common';
@@ -1111,6 +1111,7 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
11111111
pullRequestId: this.graphNodeId,
11121112
teamIds: teamReviewers.map(t => t.id),
11131113
userIds: reviewers.filter(r => r.accountType !== AccountType.Bot).map(r => r.id),
1114+
botIds: reviewers.filter(r => r.accountType === AccountType.Bot).map(r => r.id),
11141115
union
11151116
},
11161117
},
@@ -1332,47 +1333,32 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
13321333
return vscode.commands.executeCommand('vscode.changes', vscode.l10n.t('Changes in Pull Request #{0}', pullRequestModel.number), args);
13331334
}
13341335

1335-
static async openCommitChanges(folderManager: FolderRepositoryManager, commitSha: string) {
1336+
static async openCommitChanges(githubRepository: GitHubRepository, commitSha: string) {
13361337
try {
1337-
// Get the repository from the folder manager
1338-
const repository = folderManager.repository;
1339-
if (!repository) {
1340-
vscode.window.showErrorMessage(vscode.l10n.t('No repository found'));
1341-
return;
1342-
}
1343-
1344-
// Get the commit to find its parent
1345-
const commit = await repository.getCommit(commitSha);
1346-
if (!commit.parents || commit.parents.length === 0) {
1338+
const parentCommit = await githubRepository.getCommitParent(commitSha);
1339+
if (!parentCommit) {
13471340
vscode.window.showErrorMessage(vscode.l10n.t('Commit {0} has no parent', commitSha.substring(0, 7)));
13481341
return;
13491342
}
1350-
const parentSha = commit.parents[0];
13511343

1352-
// Get the changes between the commit and its parent
1353-
const changes = await repository.diffBetween(parentSha, commitSha);
1354-
if (!changes || changes.length === 0) {
1344+
const changes = await githubRepository.compareCommits(parentCommit, commitSha);
1345+
if (!changes?.files || changes.files.length === 0) {
13551346
vscode.window.showInformationMessage(vscode.l10n.t('No changes found in commit {0}', commitSha.substring(0, 7)));
13561347
return;
13571348
}
13581349

13591350
// Create URI pairs for the multi diff editor using review scheme
13601351
const args: [vscode.Uri, vscode.Uri | undefined, vscode.Uri | undefined][] = [];
1361-
for (const change of changes) {
1362-
const rightRelativePath = path.relative(repository.rootUri.fsPath, change.uri.fsPath);
1363-
const rightPath = reviewPath(rightRelativePath, commitSha);
1364-
let rightUri = toReviewUri(rightPath, rightRelativePath, undefined, commitSha, false, { base: false }, repository.rootUri);
1365-
1366-
const leftRelativePath = path.relative(repository.rootUri.fsPath, change.originalUri.fsPath);
1367-
const leftPath = reviewPath(leftRelativePath, parentSha);
1368-
let leftUri = toReviewUri(leftPath, (change.status === GitChangeType.RENAME) ? path.relative(repository.rootUri.fsPath, change.originalUri.fsPath) : leftRelativePath, undefined, parentSha, false, { base: true }, repository.rootUri);
1369-
1370-
if (change.status === GitChangeType.ADD) {
1352+
for (const change of changes.files) {
1353+
const rightUri = toGitHubCommitUri(change.filename, { commit: commitSha, owner: githubRepository.remote.owner, repo: githubRepository.remote.repositoryName });
1354+
const leftUri = toGitHubCommitUri(change.previous_filename ?? change.filename, { commit: parentCommit, owner: githubRepository.remote.owner, repo: githubRepository.remote.repositoryName });
1355+
const changeType = getGitChangeType(change.status);
1356+
if (changeType === GitChangeType.ADD) {
13711357
// For added files, show against empty
13721358
args.push([rightUri, undefined, rightUri]);
1373-
} else if (change.status === GitChangeType.DELETE) {
1359+
} else if (changeType === GitChangeType.DELETE) {
13741360
// For deleted files, show old version against empty
1375-
args.push([rightPath, leftUri, undefined]);
1361+
args.push([rightUri, leftUri, undefined]);
13761362
} else {
13771363
args.push([rightUri, leftUri, rightUri]);
13781364
}
@@ -1381,7 +1367,7 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
13811367
/* __GDPR__
13821368
"pr.openCommitChanges" : {}
13831369
*/
1384-
folderManager.telemetry.sendTelemetryEvent('pr.openCommitChanges');
1370+
githubRepository.telemetry.sendTelemetryEvent('pr.openCommitChanges');
13851371

13861372
return commands.executeCommand('vscode.changes', vscode.l10n.t('Changes in Commit {0}', commitSha.substring(0, 7)), args);
13871373
} catch (error) {
@@ -2095,3 +2081,18 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
20952081
};
20962082
}
20972083
}
2084+
2085+
export async function isCopilotOnMyBehalf(pullRequestModel: PullRequestModel, currentUser: IAccount, coAuthors?: IAccount[]): Promise<boolean> {
2086+
if (!COPILOT_ACCOUNTS[pullRequestModel.author.login]) {
2087+
return false;
2088+
}
2089+
2090+
if (!coAuthors) {
2091+
coAuthors = await pullRequestModel.getCoAuthors();
2092+
}
2093+
if (!coAuthors || coAuthors.length === 0) {
2094+
return false;
2095+
}
2096+
2097+
return coAuthors.some(c => c.login === currentUser.login);
2098+
}

src/github/pullRequestOverview.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
ReviewState,
3434
} from './interface';
3535
import { IssueOverviewPanel } from './issueOverview';
36-
import { PullRequestModel } from './pullRequestModel';
36+
import { isCopilotOnMyBehalf, PullRequestModel } from './pullRequestModel';
3737
import { PullRequestView } from './pullRequestOverviewCommon';
3838
import { pickEmail, reviewersQuickPick } from './quickPicks';
3939
import { parseReviewers } from './utils';
@@ -222,6 +222,7 @@ export class PullRequestOverviewPanel extends IssueOverviewPanel<PullRequestMode
222222
isBranchUpToDateWithBase,
223223
mergeability,
224224
emailForCommit,
225+
coAuthors,
225226
] = await Promise.all([
226227
this._folderRepositoryManager.resolvePullRequest(
227228
pullRequestModel.remote.owner,
@@ -241,6 +242,7 @@ export class PullRequestOverviewPanel extends IssueOverviewPanel<PullRequestMode
241242
this._folderRepositoryManager.isHeadUpToDateWithBase(pullRequestModel),
242243
pullRequestModel.getMergeability(),
243244
this._folderRepositoryManager.getPreferredEmail(pullRequestModel),
245+
pullRequestModel.getCoAuthors()
244246
]);
245247
if (!pullRequest) {
246248
throw new Error(
@@ -293,7 +295,8 @@ export class PullRequestOverviewPanel extends IssueOverviewPanel<PullRequestMode
293295
isIssue: false,
294296
emailForCommit,
295297
currentUserReviewState: reviewState,
296-
revertable: pullRequest.state === GithubItemStateEnum.Merged
298+
revertable: pullRequest.state === GithubItemStateEnum.Merged,
299+
isCopilotOnMyBehalf: await isCopilotOnMyBehalf(pullRequest, currentUser, coAuthors)
297300
};
298301
this._postMessage({
299302
command: 'pr.initialize',
@@ -538,7 +541,7 @@ export class PullRequestOverviewPanel extends IssueOverviewPanel<PullRequestMode
538541
private async openCommitChanges(message: IRequestMessage<OpenCommitChangesArgs>): Promise<void> {
539542
try {
540543
const { commitSha } = message.args;
541-
await PullRequestModel.openCommitChanges(this._folderRepositoryManager, commitSha);
544+
await PullRequestModel.openCommitChanges(this._item.githubRepository, commitSha);
542545
} catch (error) {
543546
Logger.error(`Failed to open commit changes: ${formatError(error)}`, PullRequestOverviewPanel.ID);
544547
vscode.window.showErrorMessage(vscode.l10n.t('Failed to open commit changes: {0}', formatError(error)));

0 commit comments

Comments
 (0)