mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-24 04:09:28 +00:00
Git - extract history item detail provider (#238041)
* Initial refactor of hover commands * Delete old code for hover commands * More refactoring
This commit is contained in:
@@ -85,7 +85,7 @@ export function registerCommands(gitAPI: GitAPI): vscode.Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
// Default remote (upstream -> origin -> first)
|
||||
// upstream -> origin -> first
|
||||
const remote = remotes.find(r => r.name === 'upstream')
|
||||
?? remotes.find(r => r.name === 'origin')
|
||||
?? remotes[0];
|
||||
|
||||
@@ -16,6 +16,7 @@ import { GithubRemoteSourcePublisher } from './remoteSourcePublisher';
|
||||
import { GithubBranchProtectionProviderManager } from './branchProtection';
|
||||
import { GitHubCanonicalUriProvider } from './canonicalUriProvider';
|
||||
import { VscodeDevShareProvider } from './shareProviders';
|
||||
import { GitHubSourceControlHistoryItemDetailProvider } from './historyItemDetailProvider';
|
||||
|
||||
export function activate(context: ExtensionContext): void {
|
||||
const disposables: Disposable[] = [];
|
||||
@@ -100,6 +101,7 @@ function initializeGitExtension(context: ExtensionContext, telemetryReporter: Te
|
||||
disposables.add(new GithubBranchProtectionProviderManager(gitAPI, context.globalState, logger, telemetryReporter));
|
||||
disposables.add(gitAPI.registerPushErrorHandler(new GithubPushErrorHandler(telemetryReporter)));
|
||||
disposables.add(gitAPI.registerRemoteSourcePublisher(new GithubRemoteSourcePublisher(gitAPI)));
|
||||
disposables.add(gitAPI.registerSourceControlHistoryItemDetailProvider(new GitHubSourceControlHistoryItemDetailProvider()));
|
||||
disposables.add(new GitHubCanonicalUriProvider(gitAPI));
|
||||
disposables.add(new VscodeDevShareProvider(gitAPI));
|
||||
setGitHubContext(gitAPI, disposables);
|
||||
|
||||
50
extensions/github/src/historyItemDetailProvider.ts
Normal file
50
extensions/github/src/historyItemDetailProvider.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Command, l10n } from 'vscode';
|
||||
import { Repository, SourceControlHistoryItemDetailProvider } from './typings/git';
|
||||
import { getRepositoryDefaultRemote, getRepositoryDefaultRemoteUrl } from './util';
|
||||
|
||||
const ISSUE_EXPRESSION = /(([A-Za-z0-9_.\-]+)\/([A-Za-z0-9_.\-]+))?(#|GH-)([1-9][0-9]*)($|\b)/g;
|
||||
|
||||
export class GitHubSourceControlHistoryItemDetailProvider implements SourceControlHistoryItemDetailProvider {
|
||||
async provideHoverCommands(repository: Repository): Promise<Command[] | undefined> {
|
||||
const url = getRepositoryDefaultRemoteUrl(repository);
|
||||
if (!url) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return [{
|
||||
title: l10n.t('{0} Open on GitHub', '$(github)'),
|
||||
tooltip: l10n.t('Open on GitHub'),
|
||||
command: 'github.openOnGitHub',
|
||||
arguments: [url]
|
||||
}];
|
||||
}
|
||||
|
||||
async provideMessageLinks(repository: Repository, message: string): Promise<string | undefined> {
|
||||
const descriptor = getRepositoryDefaultRemote(repository);
|
||||
if (!descriptor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return message.replace(
|
||||
ISSUE_EXPRESSION,
|
||||
(match, _group1, owner: string | undefined, repo: string | undefined, _group2, number: string | undefined) => {
|
||||
if (!number || Number.isNaN(parseInt(number))) {
|
||||
return match;
|
||||
}
|
||||
|
||||
const label = owner && repo
|
||||
? `${owner}/${repo}#${number}`
|
||||
: `#${number}`;
|
||||
|
||||
owner = owner ?? descriptor.owner;
|
||||
repo = repo ?? descriptor.repo;
|
||||
|
||||
return `[${label}](https://github.com/${owner}/${repo}/issues/${number})`;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,11 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Command, Uri, env, l10n, workspace } from 'vscode';
|
||||
import { Uri, env, l10n, workspace } from 'vscode';
|
||||
import { RemoteSourceProvider, RemoteSource, RemoteSourceAction } from './typings/git-base';
|
||||
import { getOctokit } from './auth';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { getRepositoryFromQuery, getRepositoryFromUrl, ISSUE_EXPRESSION } from './util';
|
||||
import { getRepositoryFromQuery, getRepositoryFromUrl } from './util';
|
||||
import { getBranchLink, getVscodeDevHost } from './links';
|
||||
|
||||
function asRemoteSource(raw: any): RemoteSource {
|
||||
@@ -136,42 +136,4 @@ export class GithubRemoteSourceProvider implements RemoteSourceProvider {
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
async getRemoteSourceControlHistoryItemCommands(url: string): Promise<Command[] | undefined> {
|
||||
const repository = getRepositoryFromUrl(url);
|
||||
if (!repository) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return [{
|
||||
title: l10n.t('{0} Open on GitHub', '$(github)'),
|
||||
tooltip: l10n.t('Open on GitHub'),
|
||||
command: 'github.openOnGitHub',
|
||||
arguments: [url]
|
||||
}];
|
||||
}
|
||||
|
||||
provideRemoteSourceLinks(url: string, content: string): string | undefined {
|
||||
const repository = getRepositoryFromUrl(url);
|
||||
if (!repository) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return content.replace(
|
||||
ISSUE_EXPRESSION,
|
||||
(match, _group1, owner: string | undefined, repo: string | undefined, _group2, number: string | undefined) => {
|
||||
if (!number || Number.isNaN(parseInt(number))) {
|
||||
return match;
|
||||
}
|
||||
|
||||
const label = owner && repo
|
||||
? `${owner}/${repo}#${number}`
|
||||
: `#${number}`;
|
||||
|
||||
owner = owner ?? repository.owner;
|
||||
repo = repo ?? repository.repo;
|
||||
|
||||
return `[${label}](https://github.com/${owner}/${repo}/issues/${number})`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
4
extensions/github/src/typings/git-base.d.ts
vendored
4
extensions/github/src/typings/git-base.d.ts
vendored
@@ -9,9 +9,7 @@ export { ProviderResult } from 'vscode';
|
||||
export interface API {
|
||||
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
|
||||
getRemoteSourceActions(url: string): Promise<RemoteSourceAction[]>;
|
||||
getRemoteSourceControlHistoryItemCommands(url: string): Promise<Command[] | undefined>;
|
||||
pickRemoteSource(options: PickRemoteSourceOptions): Promise<string | PickRemoteSourceResult | undefined>;
|
||||
provideRemoteSourceLinks(url: string, content: string): ProviderResult<string>;
|
||||
}
|
||||
|
||||
export interface GitBaseExtension {
|
||||
@@ -83,8 +81,6 @@ export interface RemoteSourceProvider {
|
||||
|
||||
getBranches?(url: string): ProviderResult<string[]>;
|
||||
getRemoteSourceActions?(url: string): ProviderResult<RemoteSourceAction[]>;
|
||||
getRemoteSourceControlHistoryItemCommands?(url: string): ProviderResult<Command[]>;
|
||||
getRecentRemoteSources?(query?: string): ProviderResult<RecentRemoteSource[]>;
|
||||
getRemoteSources(query?: string): ProviderResult<RemoteSource[]>;
|
||||
provideRemoteSourceLinks?(url: string, content: string): ProviderResult<string>;
|
||||
}
|
||||
|
||||
8
extensions/github/src/typings/git.d.ts
vendored
8
extensions/github/src/typings/git.d.ts
vendored
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Uri, Event, Disposable, ProviderResult, Command } from 'vscode';
|
||||
import { Uri, Event, Disposable, ProviderResult, Command, SourceControlHistoryItem } from 'vscode';
|
||||
export { ProviderResult } from 'vscode';
|
||||
|
||||
export interface Git {
|
||||
@@ -289,6 +289,11 @@ export interface BranchProtectionProvider {
|
||||
provideBranchProtection(): BranchProtection[];
|
||||
}
|
||||
|
||||
export interface SourceControlHistoryItemDetailProvider {
|
||||
provideHoverCommands(repository: Repository): Promise<Command[] | undefined>;
|
||||
provideMessageLinks(repository: Repository, message: string): Promise<string | undefined>;
|
||||
}
|
||||
|
||||
export type APIState = 'uninitialized' | 'initialized';
|
||||
|
||||
export interface PublishEvent {
|
||||
@@ -316,6 +321,7 @@ export interface API {
|
||||
registerPostCommitCommandsProvider(provider: PostCommitCommandsProvider): Disposable;
|
||||
registerPushErrorHandler(handler: PushErrorHandler): Disposable;
|
||||
registerBranchProtectionProvider(root: Uri, provider: BranchProtectionProvider): Disposable;
|
||||
registerSourceControlHistoryItemDetailProvider(provider: SourceControlHistoryItemDetailProvider): Disposable;
|
||||
}
|
||||
|
||||
export interface GitExtension {
|
||||
|
||||
@@ -38,4 +38,23 @@ export function repositoryHasGitHubRemote(repository: Repository) {
|
||||
return !!repository.state.remotes.find(remote => remote.fetchUrl ? getRepositoryFromUrl(remote.fetchUrl) : undefined);
|
||||
}
|
||||
|
||||
export const ISSUE_EXPRESSION = /(([A-Za-z0-9_.\-]+)\/([A-Za-z0-9_.\-]+))?(#|GH-)([1-9][0-9]*)($|\b)/g;
|
||||
export function getRepositoryDefaultRemoteUrl(repository: Repository): string | undefined {
|
||||
const remotes = repository.state.remotes
|
||||
.filter(remote => remote.fetchUrl && getRepositoryFromUrl(remote.fetchUrl));
|
||||
|
||||
if (remotes.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// upstream -> origin -> first
|
||||
const remote = remotes.find(remote => remote.name === 'upstream')
|
||||
?? remotes.find(remote => remote.name === 'origin')
|
||||
?? remotes[0];
|
||||
|
||||
return remote.fetchUrl;
|
||||
}
|
||||
|
||||
export function getRepositoryDefaultRemote(repository: Repository): { owner: string; repo: string } | undefined {
|
||||
const fetchUrl = getRepositoryDefaultRemoteUrl(repository);
|
||||
return fetchUrl ? getRepositoryFromUrl(fetchUrl) : undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user