Skip to content

Commit 7eb1133

Browse files
committed
Merge branch 'main' into alexr00/particular-bug
2 parents 28cf23a + e0ee291 commit 7eb1133

24 files changed

+338
-194
lines changed

common/views.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { IAccount, ILabel, IMilestone, IProject, ITeam, MergeMethod, MergeMethodsAvailability } from '../src/github/interface';
6+
import { ClosedEvent, CommentEvent } from '../src/common/timelineEvent';
7+
import { GithubItemStateEnum, IAccount, ILabel, IMilestone, IProject, ITeam, MergeMethod, MergeMethodsAvailability } from '../src/github/interface';
78
import { PreReviewState } from '../src/github/views';
89

910
export interface RemoteInfo {
@@ -168,4 +169,10 @@ export interface TitleAndDescriptionResult {
168169
description: string | undefined;
169170
}
170171

172+
export interface CloseResult {
173+
state: GithubItemStateEnum;
174+
commentEvent?: CommentEvent;
175+
closeEvent: ClosedEvent;
176+
}
177+
171178
// #endregion

package.json

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -828,11 +828,6 @@
828828
"title": "%command.pr.readyForReview.title%",
829829
"category": "%command.pull.request.category%"
830830
},
831-
{
832-
"command": "pr.close",
833-
"title": "%command.pr.close.title%",
834-
"category": "%command.pull.request.category%"
835-
},
836831
{
837832
"command": "pr.openPullRequestOnGitHub",
838833
"title": "%command.pr.openPullRequestOnGitHub.title%",
@@ -1593,13 +1588,13 @@
15931588
"command": "notifications.markPullRequestsAsRead",
15941589
"title": "%command.notifications.markPullRequestsAsRead.title%",
15951590
"category": "%command.notifications.category%",
1596-
"icon": "$(git-pull-request)"
1591+
"icon": "$(git-pull-request-done)"
15971592
},
15981593
{
15991594
"command": "notifications.markPullRequestsAsDone",
16001595
"title": "%command.notifications.markPullRequestsAsDone.title%",
16011596
"category": "%command.notifications.category%",
1602-
"icon": "$(git-pull-request)"
1597+
"icon": "$(git-pull-request-done)"
16031598
},
16041599
{
16051600
"command": "notifications.configureNotificationsViewlet",
@@ -1776,10 +1771,6 @@
17761771
"command": "review.openLocalFile",
17771772
"when": "false"
17781773
},
1779-
{
1780-
"command": "pr.close",
1781-
"when": "gitHubOpenRepositoryCount != 0 && github:inReviewMode"
1782-
},
17831774
{
17841775
"command": "pr.create",
17851776
"when": "gitHubOpenRepositoryCount != 0 && github:authenticated"

package.nls.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@
173173
"command.pr.dismissNotification.title": "Dismiss Notification",
174174
"command.pr.merge.title": "Merge Pull Request",
175175
"command.pr.readyForReview.title": "Mark Pull Request Ready For Review",
176-
"command.pr.close.title": "Close Pull Request",
177176
"command.pr.openPullRequestOnGitHub.title": "Open Pull Request on GitHub",
178177
"command.pr.openAllDiffs.title": "Open All Diffs",
179178
"command.pr.refreshPullRequest.title": "Refresh Pull Request",

src/commands.ts

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import * as vscode from 'vscode';
99
import { Repository } from './api/api';
1010
import { GitErrorCodes } from './api/api1';
1111
import { CommentReply, findActiveHandler, resolveCommentHandler } from './commentHandlerResolver';
12-
import { IComment } from './common/comment';
1312
import { commands } from './common/executeCommands';
1413
import Logger from './common/logger';
1514
import { FILE_LIST_LAYOUT, PR_SETTINGS_NAMESPACE } from './common/settingKeys';
@@ -20,7 +19,7 @@ import { formatError } from './common/utils';
2019
import { EXTENSION_ID } from './constants';
2120
import { FolderRepositoryManager } from './github/folderRepositoryManager';
2221
import { GitHubRepository } from './github/githubRepository';
23-
import { Issue, PullRequest } from './github/interface';
22+
import { Issue } from './github/interface';
2423
import { IssueModel } from './github/issueModel';
2524
import { IssueOverviewPanel } from './github/issueOverview';
2625
import { NotificationProvider } from './github/notifications';
@@ -46,9 +45,6 @@ import {
4645
import { PRNode } from './view/treeNodes/pullRequestNode';
4746
import { RepositoryChangesNode } from './view/treeNodes/repositoryChangesNode';
4847

49-
const _onDidUpdatePR = new vscode.EventEmitter<PullRequest | void>();
50-
export const onDidUpdatePR: vscode.Event<PullRequest | void> = _onDidUpdatePR.event;
51-
5248
function ensurePR(folderRepoManager: FolderRepositoryManager, pr?: PRNode): PullRequestModel;
5349
function ensurePR<TIssue extends Issue, TIssueModel extends IssueModel<TIssue>>(folderRepoManager: FolderRepositoryManager, pr?: TIssueModel): TIssueModel;
5450
function ensurePR<TIssue extends Issue, TIssueModel extends IssueModel<TIssue>>(folderRepoManager: FolderRepositoryManager, pr?: PRNode | TIssueModel): TIssueModel {
@@ -749,56 +745,6 @@ export function registerCommands(
749745
}),
750746
);
751747

752-
context.subscriptions.push(
753-
vscode.commands.registerCommand('pr.close', async (pr?: PRNode | PullRequestModel, message?: string) => {
754-
let pullRequestModel: PullRequestModel | undefined;
755-
if (pr) {
756-
pullRequestModel = pr instanceof PullRequestModel ? pr : pr.pullRequestModel;
757-
} else {
758-
const activePullRequests: PullRequestModel[] = reposManager.folderManagers
759-
.map(folderManager => folderManager.activePullRequest!)
760-
.filter(activePR => !!activePR);
761-
pullRequestModel = await chooseItem<PullRequestModel>(
762-
activePullRequests,
763-
itemValue => `${itemValue.number}: ${itemValue.title}`,
764-
{ placeHolder: vscode.l10n.t('Pull request to close') },
765-
);
766-
}
767-
if (!pullRequestModel) {
768-
return;
769-
}
770-
const pullRequest: PullRequestModel = pullRequestModel;
771-
const yes = vscode.l10n.t('Yes');
772-
return vscode.window
773-
.showWarningMessage(
774-
vscode.l10n.t('Are you sure you want to close this pull request on GitHub? This will close the pull request without merging.'),
775-
{ modal: true },
776-
yes,
777-
vscode.l10n.t('No'),
778-
)
779-
.then(async value => {
780-
if (value === yes) {
781-
try {
782-
let newComment: IComment | undefined = undefined;
783-
if (message) {
784-
newComment = await pullRequest.createIssueComment(message);
785-
}
786-
787-
const newPR = await pullRequest.close();
788-
vscode.commands.executeCommand('pr.refreshList');
789-
_onDidUpdatePR.fire(newPR);
790-
return newComment;
791-
} catch (e) {
792-
vscode.window.showErrorMessage(`Unable to close pull request. ${formatError(e)}`);
793-
_onDidUpdatePR.fire();
794-
}
795-
}
796-
797-
_onDidUpdatePR.fire();
798-
});
799-
}),
800-
);
801-
802748
context.subscriptions.push(
803749
vscode.commands.registerCommand('pr.dismissNotification', node => {
804750
if (node instanceof PRNode) {

src/common/timelineEvent.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export enum EventType {
1919
HeadRefDeleted,
2020
Merged,
2121
CrossReferenced,
22+
Closed,
23+
Reopened,
2224
Other,
2325
}
2426

@@ -121,4 +123,18 @@ export interface CrossReferencedEvent {
121123
willCloseTarget: boolean;
122124
}
123125

124-
export type TimelineEvent = CommitEvent | ReviewEvent | CommentEvent | NewCommitsSinceReviewEvent | MergedEvent | AssignEvent | HeadRefDeleteEvent | CrossReferencedEvent;
126+
export interface ClosedEvent {
127+
id: string
128+
event: EventType.Closed;
129+
actor: IActor;
130+
createdAt: string;
131+
}
132+
133+
export interface ReopenedEvent {
134+
id: string;
135+
event: EventType.Reopened;
136+
actor: IActor;
137+
createdAt: string;
138+
}
139+
140+
export type TimelineEvent = CommitEvent | ReviewEvent | CommentEvent | NewCommitsSinceReviewEvent | MergedEvent | AssignEvent | HeadRefDeleteEvent | CrossReferencedEvent | ClosedEvent | ReopenedEvent;

src/github/activityBarViewProvider.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as vscode from 'vscode';
7-
import { onDidUpdatePR, openPullRequestOnGitHub } from '../commands';
7+
import { openPullRequestOnGitHub } from '../commands';
88
import { IComment } from '../common/comment';
99
import { disposeAll } from '../common/lifecycle';
1010
import { ReviewEvent as CommonReviewEvent } from '../common/timelineEvent';
@@ -31,18 +31,6 @@ export class PullRequestViewProvider extends WebviewViewBase implements vscode.W
3131
) {
3232
super(extensionUri);
3333

34-
this._register(onDidUpdatePR(
35-
pr => {
36-
if (pr) {
37-
this._item.update(pr);
38-
}
39-
40-
this._postMessage({
41-
command: 'update-state',
42-
state: this._item.state,
43-
});
44-
}));
45-
4634
this._register(this._folderRepositoryManager.onDidMergePullRequest(_ => {
4735
this._postMessage({
4836
command: 'update-state',

src/github/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export namespace OctokitCommon {
3939
export type PullsCreateReviewResponseData = Endpoints['POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews']['response']['data'];
4040
export type PullsCreateReviewCommentResponseData = Endpoints['POST /repos/{owner}/{repo}/pulls/{pull_number}/comments']['response']['data'];
4141
export type PullsGetResponseData = OctokitRest.RestEndpointMethodTypes['pulls']['get']['response']['data'];
42+
export type IssuesGetResponseData = OctokitRest.RestEndpointMethodTypes['issues']['get']['response']['data'];
4243
export type PullsGetResponseUser = Exclude<PullsGetResponseData['user'], null>;
4344
export type PullsListCommitsResponseData = Endpoints['GET /repos/{owner}/{repo}/pulls/{pull_number}/commits']['response']['data'];
4445
export type PullsListRequestedReviewersResponseData = Endpoints['GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers']['response']['data'];

src/github/folderRepositoryManager.ts

Lines changed: 60 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ export class FolderRepositoryManager extends Disposable {
11541154
Logger.debug(`Fetch pull request category ${categoryQuery} - enter`, this.id);
11551155
const { octokit, query, schema } = await githubRepository.ensure();
11561156

1157-
const user = await githubRepository.getAuthenticatedUser();
1157+
const user = (await githubRepository.getAuthenticatedUser()).login;
11581158
// Search api will not try to resolve repo that redirects, so get full name first
11591159
repo = await githubRepository.getMetadata();
11601160
const { data, headers } = await octokit.call(octokit.api.search.issuesAndPullRequests, {
@@ -1749,8 +1749,12 @@ export class FolderRepositoryManager extends Disposable {
17491749
}
17501750

17511751
private async getBranchDeletionItems() {
1752+
interface BranchDeletionMetadata extends PullRequestMetadata {
1753+
isOpen?: boolean;
1754+
}
1755+
17521756
const allConfigs = await this.repository.getConfigs();
1753-
const branchInfos: Map<string, { remote?: string; metadata?: PullRequestMetadata }> = new Map();
1757+
const branchInfos: Map<string, { remote?: string; metadata?: BranchDeletionMetadata[] }> = new Map();
17541758

17551759
allConfigs.forEach(config => {
17561760
const key = config.key;
@@ -1763,14 +1767,23 @@ export class FolderRepositoryManager extends Disposable {
17631767
branchInfos.set(branchName, {});
17641768
}
17651769

1766-
const value = branchInfos.get(branchName);
1770+
const value = branchInfos.get(branchName)!;
17671771
if (matches[2] === 'remote') {
1768-
value!['remote'] = config.value;
1772+
value['remote'] = config.value;
17691773
}
17701774

17711775
if (matches[2] === 'github-pr-owner-number') {
17721776
const metadata = PullRequestGitHelper.parsePullRequestMetadata(config.value);
1773-
value!['metadata'] = metadata;
1777+
if (!value?.metadata) {
1778+
value['metadata'] = [];
1779+
}
1780+
if (metadata) {
1781+
// Check if the metadata already exists in the array
1782+
const existingMetadata = value.metadata.find(m => m.owner === metadata.owner && m.repositoryName === metadata.repositoryName && m.prNumber === metadata.prNumber);
1783+
if (!existingMetadata) {
1784+
value['metadata'].push(metadata);
1785+
}
1786+
}
17741787
}
17751788

17761789
branchInfos.set(branchName, value!);
@@ -1779,67 +1792,73 @@ export class FolderRepositoryManager extends Disposable {
17791792
Logger.debug(`Found ${branchInfos.size} possible branches to delete`, this.id);
17801793
Logger.trace(`Branches to delete: ${JSON.stringify(Array.from(branchInfos.keys()))}`, this.id);
17811794

1782-
const actions: (vscode.QuickPickItem & { metadata: PullRequestMetadata; legacy?: boolean })[] = [];
1795+
const actions: (vscode.QuickPickItem & { metadata: BranchDeletionMetadata[]; legacy?: boolean })[] = [];
17831796
branchInfos.forEach((value, key) => {
17841797
if (value.metadata) {
17851798
const activePRUrl = this.activePullRequest && this.activePullRequest.base.repositoryCloneUrl;
1786-
const matchesActiveBranch = activePRUrl
1787-
? (activePRUrl.owner === value.metadata.owner &&
1788-
activePRUrl.repositoryName === value.metadata.repositoryName &&
1789-
this.activePullRequest?.number === value.metadata.prNumber)
1790-
: false;
1799+
const activeMetadata = value.metadata.find(metadata =>
1800+
metadata.owner === activePRUrl?.owner &&
1801+
metadata.repositoryName === activePRUrl?.repositoryName &&
1802+
metadata.prNumber === this.activePullRequest?.number
1803+
);
17911804

1792-
if (!matchesActiveBranch) {
1805+
if (!activeMetadata) {
17931806
actions.push({
17941807
label: `${key}`,
1795-
description: `${value.metadata!.repositoryName}/${value.metadata!.owner} #${value.metadata.prNumber
1796-
}`,
17971808
picked: false,
1798-
metadata: value.metadata!,
1809+
metadata: value.metadata,
17991810
});
18001811
} else {
1801-
Logger.debug(`Skipping ${value.metadata.prNumber}, active PR is #${this.activePullRequest?.number}`, this.id);
1812+
Logger.debug(`Skipping ${activeMetadata.prNumber}, active PR is #${this.activePullRequest?.number}`, this.id);
18021813
Logger.trace(`Skipping active branch ${key}`, this.id);
18031814
}
18041815
}
18051816
});
18061817

18071818
const results = await Promise.all(
18081819
actions.map(async action => {
1809-
const metadata = action.metadata;
1810-
const githubRepo = this._githubRepositories.find(
1811-
repo =>
1812-
repo.remote.owner.toLowerCase() === metadata!.owner.toLowerCase() &&
1813-
repo.remote.repositoryName.toLowerCase() === metadata!.repositoryName.toLowerCase(),
1814-
);
1820+
const allOld = (await Promise.all(
1821+
action.metadata.map(async metadata => {
1822+
const githubRepo = this._githubRepositories.find(
1823+
repo =>
1824+
repo.remote.owner.toLowerCase() === metadata!.owner.toLowerCase() &&
1825+
repo.remote.repositoryName.toLowerCase() === metadata!.repositoryName.toLowerCase(),
1826+
);
1827+
1828+
if (!githubRepo) {
1829+
return action;
1830+
}
18151831

1816-
if (!githubRepo) {
1817-
return action;
1832+
const { remote, query, schema } = await githubRepo.ensure();
1833+
try {
1834+
const { data } = await query<PullRequestState>({
1835+
query: schema.PullRequestState,
1836+
variables: {
1837+
owner: remote.owner,
1838+
name: remote.repositoryName,
1839+
number: metadata!.prNumber,
1840+
},
1841+
});
1842+
metadata.isOpen = data.repository?.pullRequest.state === 'OPEN';
1843+
return data.repository?.pullRequest.state !== 'OPEN';
1844+
} catch { }
1845+
return false;
1846+
}))).every(result => result);
1847+
if (allOld) {
1848+
action.legacy = true;
18181849
}
18191850

1820-
const { remote, query, schema } = await githubRepo.ensure();
1821-
try {
1822-
const { data } = await query<PullRequestState>({
1823-
query: schema.PullRequestState,
1824-
variables: {
1825-
owner: remote.owner,
1826-
name: remote.repositoryName,
1827-
number: metadata!.prNumber,
1828-
},
1829-
});
1830-
1831-
action.legacy = data.repository?.pullRequest.state !== 'OPEN';
1832-
} catch { }
1833-
18341851
return action;
18351852
}),
18361853
);
18371854

18381855
results.forEach(result => {
1856+
result.description = `${result.metadata[0].repositoryName}/${result.metadata[0].owner} ${result.metadata.map(metadata => {
1857+
const prString = `#${metadata.prNumber}`;
1858+
return metadata.isOpen ? vscode.l10n.t('{0} is open', prString) : prString;
1859+
}).join(', ')}`;
18391860
if (result.legacy) {
18401861
result.picked = true;
1841-
} else {
1842-
result.description = vscode.l10n.t('{0} is still Open', result.description!);
18431862
}
18441863
});
18451864

@@ -2011,7 +2030,7 @@ export class FolderRepositoryManager extends Disposable {
20112030
quickPick.items = results;
20122031
quickPick.selectedItems = results.filter(result => {
20132032
// Do not pick the default branch for the repo.
2014-
return result.picked && !((result.label === defaults.base) && (result.metadata.owner === defaults.owner) && (result.metadata.repositoryName === defaults.repo));
2033+
return result.picked && !((result.label === defaults.base) && (result.metadata.find(metadata => metadata.owner === defaults.owner && metadata.repositoryName === defaults.repo)));
20152034
});
20162035
quickPick.busy = false;
20172036
if (results.length === 0) {

src/github/githubRepository.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,8 +886,8 @@ export class GitHubRepository extends Disposable {
886886
}
887887
}
888888

889-
async getAuthenticatedUser(): Promise<string> {
890-
return (await this._credentialStore.getCurrentUser(this.remote.authProviderId)).login;
889+
async getAuthenticatedUser(): Promise<IAccount> {
890+
return await this._credentialStore.getCurrentUser(this.remote.authProviderId);
891891
}
892892

893893
async getAuthenticatedUserEmails(): Promise<string[]> {

0 commit comments

Comments
 (0)