mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-18 23:59:43 +01:00
Add command to check for open pull requests and refactor session repository resolution
This commit is contained in:
@@ -35,46 +35,94 @@ async function openVscodeDevLink(gitAPI: GitAPI): Promise<vscode.Uri | undefined
|
||||
}
|
||||
}
|
||||
|
||||
async function createPullRequest(gitAPI: GitAPI, sessionResource: vscode.Uri | undefined, sessionMetadata: { worktreePath?: string } | undefined): Promise<void> {
|
||||
if (!sessionResource || !sessionMetadata?.worktreePath) {
|
||||
return;
|
||||
interface ResolvedSessionRepo {
|
||||
repository: Repository;
|
||||
remoteInfo: { owner: string; repo: string };
|
||||
gitRemote: { name: string; fetchUrl: string };
|
||||
head: { name: string; upstream?: { name: string; remote: string; commit: string } };
|
||||
}
|
||||
|
||||
function resolveSessionRepo(gitAPI: GitAPI, sessionMetadata: { worktreePath?: string } | undefined, showErrors: boolean): ResolvedSessionRepo | undefined {
|
||||
if (!sessionMetadata?.worktreePath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const worktreeUri = vscode.Uri.file(sessionMetadata.worktreePath);
|
||||
const repository = gitAPI.getRepository(worktreeUri);
|
||||
|
||||
if (!repository) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('Could not find a git repository for the session worktree.'));
|
||||
return;
|
||||
if (showErrors) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('Could not find a git repository for the session worktree.'));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Find the GitHub remote
|
||||
const remotes = repository.state.remotes
|
||||
.filter(remote => remote.fetchUrl && getRepositoryFromUrl(remote.fetchUrl));
|
||||
|
||||
if (remotes.length === 0) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('Could not find a GitHub remote for this repository.'));
|
||||
return;
|
||||
if (showErrors) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('Could not find a GitHub remote for this repository.'));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Prefer upstream -> origin -> first
|
||||
const gitRemote = remotes.find(r => r.name === 'upstream')
|
||||
?? remotes.find(r => r.name === 'origin')
|
||||
?? remotes[0];
|
||||
|
||||
const remoteInfo = getRepositoryFromUrl(gitRemote.fetchUrl!);
|
||||
if (!remoteInfo) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('Could not parse GitHub remote URL.'));
|
||||
if (showErrors) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('Could not parse GitHub remote URL.'));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const head = repository.state.HEAD;
|
||||
if (!head?.name) {
|
||||
if (showErrors) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('Could not determine the current branch.'));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return { repository, remoteInfo, gitRemote: { name: gitRemote.name, fetchUrl: gitRemote.fetchUrl! }, head: head as ResolvedSessionRepo['head'] };
|
||||
}
|
||||
|
||||
async function checkOpenPullRequest(gitAPI: GitAPI, _sessionResource: vscode.Uri | undefined, sessionMetadata: { worktreePath?: string } | undefined): Promise<void> {
|
||||
const resolved = resolveSessionRepo(gitAPI, sessionMetadata, false);
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current branch (the worktree branch)
|
||||
const head = repository.state.HEAD;
|
||||
if (!head?.name) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('Could not determine the current branch.'));
|
||||
try {
|
||||
const octokit = await getOctokit();
|
||||
const { data: pullRequests } = await octokit.pulls.list({
|
||||
owner: resolved.remoteInfo.owner,
|
||||
repo: resolved.remoteInfo.repo,
|
||||
head: `${resolved.remoteInfo.owner}:${resolved.head.name}`,
|
||||
state: 'open',
|
||||
});
|
||||
|
||||
vscode.commands.executeCommand('setContext', 'github.hasOpenPullRequest', pullRequests.length > 0);
|
||||
} catch {
|
||||
// Silently fail — leave context key unchanged
|
||||
}
|
||||
}
|
||||
|
||||
async function createPullRequest(gitAPI: GitAPI, sessionResource: vscode.Uri | undefined, sessionMetadata: { worktreePath?: string } | undefined): Promise<void> {
|
||||
if (!sessionResource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resolved = resolveSessionRepo(gitAPI, sessionMetadata, true);
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { repository, remoteInfo, gitRemote, head } = resolved;
|
||||
|
||||
// Ensure the branch is published to the remote
|
||||
if (!head.upstream) {
|
||||
try {
|
||||
@@ -205,5 +253,9 @@ export function registerCommands(gitAPI: GitAPI): vscode.Disposable {
|
||||
return createPullRequest(gitAPI, sessionResource, sessionMetadata);
|
||||
}));
|
||||
|
||||
disposables.add(vscode.commands.registerCommand('github.checkOpenPullRequest', async (sessionResource: vscode.Uri | undefined, sessionMetadata: { worktreePath?: string } | undefined) => {
|
||||
return checkOpenPullRequest(gitAPI, sessionResource, sessionMetadata);
|
||||
}));
|
||||
|
||||
return disposables;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import { GitHubSourceControlHistoryItemDetailsProvider } from './historyItemDeta
|
||||
import { OctokitService } from './auth.js';
|
||||
|
||||
export function activate(context: ExtensionContext): void {
|
||||
console.log('[github ext] activate() called');
|
||||
const disposables: Disposable[] = [];
|
||||
context.subscriptions.push(new Disposable(() => Disposable.from(...disposables).dispose()));
|
||||
|
||||
@@ -97,12 +96,9 @@ function initializeGitExtension(context: ExtensionContext, octokitService: Octok
|
||||
const initialize = () => {
|
||||
gitExtension!.activate()
|
||||
.then(extension => {
|
||||
console.log('[github ext] git extension activated, enabled:', extension.enabled);
|
||||
const onDidChangeGitExtensionEnablement = (enabled: boolean) => {
|
||||
console.log('[github ext] onDidChangeGitExtensionEnablement:', enabled);
|
||||
if (enabled) {
|
||||
const gitAPI = extension.getAPI(1);
|
||||
console.log('[github ext] got gitAPI, repositories:', gitAPI.repositories.length);
|
||||
|
||||
disposables.add(registerCommands(gitAPI));
|
||||
disposables.add(new GithubCredentialProviderManager(gitAPI));
|
||||
@@ -126,10 +122,8 @@ function initializeGitExtension(context: ExtensionContext, octokitService: Octok
|
||||
};
|
||||
|
||||
if (gitExtension) {
|
||||
console.log('[github ext] vscode.git extension found, initializing');
|
||||
initialize();
|
||||
} else {
|
||||
console.log('[github ext] vscode.git extension NOT found, waiting...');
|
||||
const listener = extensions.onDidChange(() => {
|
||||
if (!gitExtension && extensions.getExtension<GitExtension>('vscode.git')) {
|
||||
gitExtension = extensions.getExtension<GitExtension>('vscode.git');
|
||||
|
||||
Reference in New Issue
Block a user