mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-01-13 17:23:11 -05:00
Reworks remote parsing
Combines same url into same remote Adds a change event for custom remote providers Adds a repo change event for custom remote providers
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithBranch } from './common';
|
||||
import { GlyphChars } from '../constants';
|
||||
@@ -52,7 +51,8 @@ export class OpenBranchInRemoteCommand extends ActiveEditorCommand {
|
||||
if (args.branch === undefined) return undefined;
|
||||
}
|
||||
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(repoPath), _ => _.url, _ => !!_.provider);
|
||||
const remotes = (await this.git.getRemotes(repoPath)).filter(r => r.provider !== undefined);
|
||||
|
||||
return commands.executeCommand(Commands.OpenInRemote, uri, {
|
||||
resource: {
|
||||
type: 'branch',
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithRemote } from './common';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
@@ -34,7 +33,7 @@ export class OpenBranchesInRemoteCommand extends ActiveEditorCommand {
|
||||
if (!repoPath) return undefined;
|
||||
|
||||
try {
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(repoPath), r => r.url, r => !!r.provider);
|
||||
const remotes = (await this.git.getRemotes(repoPath)).filter(r => r.provider !== undefined);
|
||||
|
||||
return commands.executeCommand(Commands.OpenInRemote, uri, {
|
||||
resource: {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
|
||||
import { GitBlameCommit, GitService, GitUri } from '../gitService';
|
||||
@@ -53,7 +52,8 @@ export class OpenCommitInRemoteCommand extends ActiveEditorCommand {
|
||||
args.sha = commit.sha;
|
||||
}
|
||||
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(gitUri.repoPath), _ => _.url, _ => !!_.provider);
|
||||
const remotes = (await this.git.getRemotes(gitUri.repoPath)).filter(r => r.provider !== undefined);
|
||||
|
||||
return commands.executeCommand(Commands.OpenInRemote, uri, {
|
||||
resource: {
|
||||
type: 'commit',
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, Range, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithBranch, isCommandViewContextWithCommit } from './common';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
@@ -45,7 +44,7 @@ export class OpenFileInRemoteCommand extends ActiveEditorCommand {
|
||||
}
|
||||
|
||||
try {
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(gitUri.repoPath), _ => _.url, _ => !!_.provider);
|
||||
const remotes = (await this.git.getRemotes(gitUri.repoPath)).filter(r => r.provider !== undefined);
|
||||
const range = (args.range && editor !== undefined)
|
||||
? new Range(editor.selection.start.with({ line: editor.selection.start.line + 1 }), editor.selection.end.with({ line: editor.selection.end.line + 1 }))
|
||||
: undefined;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithRemote } from './common';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
@@ -34,7 +33,7 @@ export class OpenRepoInRemoteCommand extends ActiveEditorCommand {
|
||||
if (!repoPath) return undefined;
|
||||
|
||||
try {
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(repoPath), r => r.url, r => !!r.provider);
|
||||
const remotes = (await this.git.getRemotes(repoPath)).filter(r => r.provider !== undefined);
|
||||
|
||||
return commands.executeCommand(Commands.OpenInRemote, uri, {
|
||||
resource: {
|
||||
|
||||
@@ -14,6 +14,7 @@ export * from './parsers/blameParser';
|
||||
export * from './parsers/branchParser';
|
||||
export * from './parsers/diffParser';
|
||||
export * from './parsers/logParser';
|
||||
export * from './parsers/remoteParser';
|
||||
export * from './parsers/stashParser';
|
||||
export * from './parsers/statusParser';
|
||||
export * from './remotes/provider';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { Disposable, Event, EventEmitter, TextDocument, TextDocumentChangeEvent, TextEditor, window, workspace } from 'vscode';
|
||||
import { TextDocumentComparer } from '../comparers';
|
||||
import { CommandContext, setCommandContext } from '../constants';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { GitService, GitUri, RepoChangedReasons } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export interface BlameabilityChangeEvent {
|
||||
@@ -32,6 +32,7 @@ export class GitContextTracker extends Disposable {
|
||||
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
|
||||
subscriptions.push(workspace.onDidSaveTextDocument(this._onTextDocumentSaved, this));
|
||||
subscriptions.push(this.git.onDidBlameFail(this._onBlameFailed, this));
|
||||
subscriptions.push(this.git.onDidChangeRepo(this._onRepoChanged, this));
|
||||
|
||||
this._disposable = Disposable.from(...subscriptions);
|
||||
|
||||
@@ -54,6 +55,13 @@ export class GitContextTracker extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
async _onRepoChanged(reasons: RepoChangedReasons[]) {
|
||||
if (!reasons.includes(RepoChangedReasons.Remotes)) return;
|
||||
|
||||
const gitUri = this._editor === undefined ? undefined : await GitUri.fromUri(this._editor.document.uri, this.git);
|
||||
this._updateContextHasRemotes(gitUri);
|
||||
}
|
||||
|
||||
private _onActiveTextEditorChanged(editor: TextEditor | undefined) {
|
||||
this._editor = editor;
|
||||
this._updateContext(this._gitEnabled ? editor : undefined);
|
||||
|
||||
@@ -5,23 +5,9 @@ export type GitRemoteType = 'fetch' | 'push';
|
||||
|
||||
export class GitRemote {
|
||||
|
||||
name: string;
|
||||
url: string;
|
||||
type: GitRemoteType;
|
||||
|
||||
provider?: RemoteProvider;
|
||||
|
||||
constructor(remote: string) {
|
||||
remote = remote.trim();
|
||||
|
||||
const [name, info] = remote.split('\t');
|
||||
this.name = name;
|
||||
|
||||
const [url, typeInfo] = info.split(' ');
|
||||
this.url = url;
|
||||
|
||||
this.type = typeInfo.substring(1, typeInfo.length - 1) as GitRemoteType;
|
||||
|
||||
this.provider = RemoteProviderFactory.getRemoteProvider(this.url);
|
||||
constructor(public readonly repoPath: string, public readonly name: string, public readonly url: string, public readonly domain: string, public readonly path: string, public readonly types: GitRemoteType[]) {
|
||||
this.provider = RemoteProviderFactory.getRemoteProvider(this.domain, this.path);
|
||||
}
|
||||
}
|
||||
50
src/git/parsers/remoteParser.ts
Normal file
50
src/git/parsers/remoteParser.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
'use strict';
|
||||
import { GitRemote } from './../git';
|
||||
import { GitRemoteType } from '../models/remote';
|
||||
|
||||
const remoteRegex = /^(.*)\t(.*)\s\((.*)\)$/gm;
|
||||
const urlRegex = /^(?:git:\/\/(.*?)\/|https:\/\/(.*?)\/|http:\/\/(.*?)\/|git@(.*):|ssh:\/\/(?:.*@)?(.*?)(?::.*?)?\/)(.*)$/;
|
||||
|
||||
export class GitRemoteParser {
|
||||
|
||||
static parse(data: string, repoPath: string): GitRemote[] {
|
||||
if (!data) return [];
|
||||
|
||||
const remotes: GitRemote[] = [];
|
||||
const groups = Object.create(null);
|
||||
|
||||
let match: RegExpExecArray | null = null;
|
||||
do {
|
||||
match = remoteRegex.exec(data);
|
||||
if (match == null) break;
|
||||
|
||||
const url = match[2];
|
||||
|
||||
const [domain, path] = this.parseGitUrl(url);
|
||||
|
||||
let remote: GitRemote | undefined = groups[url];
|
||||
if (remote === undefined) {
|
||||
remote = new GitRemote(repoPath, match[1], url, domain, path, [match[3] as GitRemoteType]);
|
||||
remotes.push(remote);
|
||||
groups[url] = remote;
|
||||
}
|
||||
else {
|
||||
remote.types.push(match[3] as GitRemoteType);
|
||||
}
|
||||
} while (match != null);
|
||||
|
||||
if (!remotes.length) return [];
|
||||
|
||||
return remotes;
|
||||
}
|
||||
|
||||
static parseGitUrl(url: string): [string, string] {
|
||||
const match = urlRegex.exec(url);
|
||||
if (match == null) return ['', ''];
|
||||
|
||||
return [
|
||||
match[1] || match[2] || match[3] || match[4] || match[5],
|
||||
match[6].replace(/\.git\/?$/, '')
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
import { ExtensionContext, workspace } from 'vscode';
|
||||
import { Objects } from '../../system';
|
||||
import { Event, EventEmitter, ExtensionContext, workspace } from 'vscode';
|
||||
import { BitbucketService } from './bitbucket';
|
||||
import { BitbucketServerService } from './bitbucket-server';
|
||||
import { CustomRemoteType, IConfig, IRemotesConfig } from '../../configuration';
|
||||
@@ -9,22 +10,9 @@ import { GitLabService } from './gitlab';
|
||||
import { Logger } from '../../logger';
|
||||
import { RemoteProvider } from './provider';
|
||||
import { VisualStudioService } from './visualStudio';
|
||||
import { Objects } from '../../system';
|
||||
|
||||
export { RemoteProvider };
|
||||
|
||||
const UrlRegex = /^(?:git:\/\/(.*?)\/|https:\/\/(.*?)\/|http:\/\/(.*?)\/|git@(.*):|ssh:\/\/(?:.*@)?(.*?)(?::.*?)?\/)(.*)$/;
|
||||
|
||||
function getCustomProvider(type: CustomRemoteType) {
|
||||
switch (type) {
|
||||
case CustomRemoteType.Bitbucket: return (domain: string, path: string) => new BitbucketService(domain, path, true);
|
||||
case CustomRemoteType.BitbucketServer: return (domain: string, path: string) => new BitbucketServerService(domain, path, true);
|
||||
case CustomRemoteType.GitHub: return (domain: string, path: string) => new GitHubService(domain, path, true);
|
||||
case CustomRemoteType.GitLab: return (domain: string, path: string) => new GitLabService(domain, path, true);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const defaultProviderMap = new Map<string, (domain: string, path: string) => RemoteProvider>([
|
||||
['bitbucket.org', (domain: string, path: string) => new BitbucketService(domain, path)],
|
||||
['github.com', (domain: string, path: string) => new GitHubService(domain, path)],
|
||||
@@ -32,48 +20,29 @@ const defaultProviderMap = new Map<string, (domain: string, path: string) => Rem
|
||||
['visualstudio.com', (domain: string, path: string) => new VisualStudioService(domain, path)]
|
||||
]);
|
||||
|
||||
let providerMap: Map<string, (domain: string, path: string) => RemoteProvider>;
|
||||
let remotesCfg: IRemotesConfig[];
|
||||
|
||||
function onConfigurationChanged() {
|
||||
const cfg = workspace.getConfiguration().get<IConfig>(ExtensionKey);
|
||||
if (cfg === undefined) return;
|
||||
|
||||
if (!Objects.areEquivalent(cfg.remotes, remotesCfg)) {
|
||||
providerMap = new Map(defaultProviderMap);
|
||||
|
||||
remotesCfg = cfg.remotes;
|
||||
if (remotesCfg != null && remotesCfg.length > 0) {
|
||||
for (const svc of remotesCfg) {
|
||||
const provider = getCustomProvider(svc.type);
|
||||
if (provider === undefined) continue;
|
||||
|
||||
providerMap.set(svc.domain.toLowerCase(), provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class RemoteProviderFactory {
|
||||
|
||||
static configure(context: ExtensionContext) {
|
||||
context.subscriptions.push(workspace.onDidChangeConfiguration(onConfigurationChanged));
|
||||
onConfigurationChanged();
|
||||
private static _providerMap: Map<string, (domain: string, path: string) => RemoteProvider>;
|
||||
private static _remotesCfg: IRemotesConfig[];
|
||||
|
||||
private static _onDidChange = new EventEmitter<void>();
|
||||
public static get onDidChange(): Event<void> {
|
||||
return this._onDidChange.event;
|
||||
}
|
||||
|
||||
static getRemoteProvider(url: string): RemoteProvider | undefined {
|
||||
static configure(context: ExtensionContext) {
|
||||
context.subscriptions.push(workspace.onDidChangeConfiguration(() => this.onConfigurationChanged()));
|
||||
this.onConfigurationChanged(true);
|
||||
}
|
||||
|
||||
static getRemoteProvider(domain: string, path: string): RemoteProvider | undefined {
|
||||
try {
|
||||
const match = UrlRegex.exec(url);
|
||||
if (match == null) return undefined;
|
||||
let key = domain.toLowerCase();
|
||||
if (key.endsWith('visualstudio.com')) {
|
||||
key = 'visualstudio.com';
|
||||
}
|
||||
|
||||
const domain = match[1] || match[2] || match[3] || match[4] || match[5];
|
||||
const path = match[6].replace(/\.git\/?$/, '');
|
||||
|
||||
const key = domain.toLowerCase().endsWith('visualstudio.com')
|
||||
? 'visualstudio.com'
|
||||
: domain;
|
||||
|
||||
const creator = providerMap.get(key.toLowerCase());
|
||||
const creator = this._providerMap.get(key);
|
||||
if (creator === undefined) return undefined;
|
||||
|
||||
return creator(domain, path);
|
||||
@@ -83,4 +52,37 @@ export class RemoteProviderFactory {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private static onConfigurationChanged(silent: boolean = false) {
|
||||
const cfg = workspace.getConfiguration().get<IConfig>(ExtensionKey);
|
||||
if (cfg === undefined) return;
|
||||
|
||||
if (!Objects.areEquivalent(cfg.remotes, this._remotesCfg)) {
|
||||
this._providerMap = new Map(defaultProviderMap);
|
||||
|
||||
this._remotesCfg = cfg.remotes;
|
||||
if (this._remotesCfg != null && this._remotesCfg.length > 0) {
|
||||
for (const svc of this._remotesCfg) {
|
||||
const provider = this.getCustomProvider(svc.type);
|
||||
if (provider === undefined) continue;
|
||||
|
||||
this._providerMap.set(svc.domain.toLowerCase(), provider);
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static getCustomProvider(type: CustomRemoteType) {
|
||||
switch (type) {
|
||||
case CustomRemoteType.Bitbucket: return (domain: string, path: string) => new BitbucketService(domain, path, true);
|
||||
case CustomRemoteType.BitbucketServer: return (domain: string, path: string) => new BitbucketServerService(domain, path, true);
|
||||
case CustomRemoteType.GitHub: return (domain: string, path: string) => new GitHubService(domain, path, true);
|
||||
case CustomRemoteType.GitLab: return (domain: string, path: string) => new GitLabService(domain, path, true);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,8 @@ import { Functions, Iterables, Objects } from './system';
|
||||
import { Disposable, Event, EventEmitter, FileSystemWatcher, Location, Position, Range, TextDocument, TextDocumentChangeEvent, TextEditor, Uri, workspace } from 'vscode';
|
||||
import { IConfig } from './configuration';
|
||||
import { DocumentSchemes, ExtensionKey, GlyphChars } from './constants';
|
||||
import { Git, GitAuthor, GitBlame, GitBlameCommit, GitBlameLine, GitBlameLines, GitBlameParser, GitBranch, GitBranchParser, GitCommit, GitDiff, GitDiffChunkLine, GitDiffParser, GitLog, GitLogCommit, GitLogParser, GitRemote, GitStash, GitStashParser, GitStatus, GitStatusFile, GitStatusParser, IGit, setDefaultEncoding } from './git/git';
|
||||
import { RemoteProviderFactory } from './git/remotes/factory';
|
||||
import { Git, GitAuthor, GitBlame, GitBlameCommit, GitBlameLine, GitBlameLines, GitBlameParser, GitBranch, GitBranchParser, GitCommit, GitDiff, GitDiffChunkLine, GitDiffParser, GitLog, GitLogCommit, GitLogParser, GitRemote, GitRemoteParser, GitStash, GitStashParser, GitStatus, GitStatusFile, GitStatusParser, IGit, setDefaultEncoding } from './git/git';
|
||||
import { GitUri, IGitCommitInfo, IGitUriData } from './git/gitUri';
|
||||
import { Logger } from './logger';
|
||||
import * as fs from 'fs';
|
||||
@@ -64,8 +65,9 @@ export const GitRepoSearchBy = {
|
||||
Sha: 'sha' as GitRepoSearchBy
|
||||
};
|
||||
|
||||
export type RepoChangedReasons = 'stash' | 'unknown';
|
||||
export type RepoChangedReasons = 'remotes' | 'stash' | 'unknown';
|
||||
export const RepoChangedReasons = {
|
||||
Remotes: 'remotes' as RepoChangedReasons,
|
||||
Stash: 'stash' as RepoChangedReasons,
|
||||
Unknown: 'unknown' as RepoChangedReasons
|
||||
};
|
||||
@@ -113,6 +115,7 @@ export class GitService extends Disposable {
|
||||
const subscriptions: Disposable[] = [];
|
||||
|
||||
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
|
||||
subscriptions.push(RemoteProviderFactory.onDidChange(this._onRemoteProviderChanged, this));
|
||||
|
||||
this._disposable = Disposable.from(...subscriptions);
|
||||
}
|
||||
@@ -193,6 +196,11 @@ export class GitService extends Disposable {
|
||||
this.config = cfg;
|
||||
}
|
||||
|
||||
private _onRemoteProviderChanged() {
|
||||
this._remotesCache.clear();
|
||||
this._fireRepoChange(RepoChangedReasons.Remotes);
|
||||
}
|
||||
|
||||
private _onTextDocumentChanged(e: TextDocumentChangeEvent) {
|
||||
if (!this.UseCaching) return;
|
||||
if (e.document.uri.scheme !== DocumentSchemes.File) return;
|
||||
@@ -895,7 +903,7 @@ export class GitService extends Disposable {
|
||||
}
|
||||
|
||||
const data = await Git.remote(repoPath);
|
||||
const remotes = data.split('\n').filter(_ => !!_).map(_ => new GitRemote(_));
|
||||
const remotes = GitRemoteParser.parse(data, repoPath);
|
||||
if (this.UseCaching) {
|
||||
this._remotesCache.set(repoPath, remotes);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables, Strings } from '../system';
|
||||
import { Iterables, Strings } from '../system';
|
||||
import { CancellationTokenSource, QuickPickOptions, Uri, window } from 'vscode';
|
||||
import { Commands, ShowCommitSearchCommandArgs, ShowQuickBranchHistoryCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './common';
|
||||
@@ -35,7 +35,7 @@ export class BranchHistoryQuickPick {
|
||||
} as ShowQuickBranchHistoryCommandArgs
|
||||
]);
|
||||
|
||||
const remotes = Arrays.uniqueBy(await git.getRemotes((uri && uri.repoPath) || git.repoPath), _ => _.url, _ => !!_.provider);
|
||||
const remotes = (await git.getRemotes((uri && uri.repoPath) || git.repoPath)).filter(r => r.provider !== undefined);
|
||||
if (remotes.length) {
|
||||
items.splice(0, 0, new OpenRemotesCommandQuickPickItem(remotes, {
|
||||
type: 'branch',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables, Strings } from '../system';
|
||||
import { Iterables, Strings } from '../system';
|
||||
import { commands, QuickPickOptions, TextDocumentShowOptions, Uri, window } from 'vscode';
|
||||
import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffDirectoryCommandCommandArgs, DiffWithPreviousCommandArgs, ShowQuickCommitDetailsCommandArgs, StashApplyCommandArgs, StashDeleteCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem, OpenFilesCommandQuickPickItem, QuickPickItem } from './common';
|
||||
@@ -153,7 +153,7 @@ export class CommitDetailsQuickPick {
|
||||
]));
|
||||
|
||||
if (!stash) {
|
||||
const remotes = Arrays.uniqueBy(await git.getRemotes(commit.repoPath), _ => _.url, _ => !!_.provider);
|
||||
const remotes = (await git.getRemotes(commit.repoPath)).filter(r => r.provider !== undefined);
|
||||
if (remotes.length) {
|
||||
items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, {
|
||||
type: 'commit',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables, Strings } from '../system';
|
||||
import { Iterables, Strings } from '../system';
|
||||
import { QuickPickItem, QuickPickOptions, Uri, window } from 'vscode';
|
||||
import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs, ShowQuickCommitDetailsCommandArgs, ShowQuickCommitFileDetailsCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem } from './common';
|
||||
@@ -125,7 +125,7 @@ export class CommitFileDetailsQuickPick {
|
||||
}
|
||||
items.push(new OpenCommitFileRevisionCommandQuickPickItem(commit));
|
||||
|
||||
const remotes = Arrays.uniqueBy(await git.getRemotes(commit.repoPath), _ => _.url, _ => !!_.provider);
|
||||
const remotes = (await git.getRemotes(commit.repoPath)).filter(r => r.provider !== undefined);
|
||||
if (remotes.length) {
|
||||
if (commit.workingFileName && commit.status !== 'D') {
|
||||
const branch = await git.getBranch(commit.repoPath || git.repoPath);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables, Strings } from '../system';
|
||||
import { Iterables, Strings } from '../system';
|
||||
import { CancellationTokenSource, QuickPickOptions, Uri, window } from 'vscode';
|
||||
import { Commands, ShowQuickCurrentBranchHistoryCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands';
|
||||
import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './common';
|
||||
@@ -136,7 +136,7 @@ export class FileHistoryQuickPick {
|
||||
]));
|
||||
}
|
||||
|
||||
const remotes = Arrays.uniqueBy(await git.getRemotes(uri.repoPath!), _ => _.url, _ => !!_.provider);
|
||||
const remotes = (await git.getRemotes(uri.repoPath!)).filter(r => r.provider !== undefined);
|
||||
if (remotes.length) {
|
||||
items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, {
|
||||
type: 'revision',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
import { Arrays, Iterables } from '../system';
|
||||
import { Iterables } from '../system';
|
||||
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||
import { ExplorerNode, MessageNode, ResourceType } from './explorerNode';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
@@ -14,7 +14,7 @@ export class RemotesNode extends ExplorerNode {
|
||||
}
|
||||
|
||||
async getChildren(): Promise<ExplorerNode[]> {
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(this.uri.repoPath!), r => r.url, r => !!r.provider);
|
||||
const remotes = await this.git.getRemotes(this.uri.repoPath!);
|
||||
if (remotes === undefined || remotes.length === 0) return [new MessageNode('No remotes configured')];
|
||||
|
||||
remotes.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
Reference in New Issue
Block a user