Skip to content

Commit

Permalink
Closes #148 - Adds custom provider support
Browse files Browse the repository at this point in the history
  • Loading branch information
eamodio committed Sep 30, 2017
1 parent d111fb0 commit e70dd6d
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 25 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,

- Adds a `Search Commits` command (`gitlens.showCommitSearch`) with a shortcut of `alt+/` to search for commits by message, author, file(s), or commit id

- Adds commands to open files, commits, branches, and the repository in the supported remote services, currently **BitBucket, GitHub, GitLab, and Visual Studio Team Services** — only available if a Git upstream service is configured in the repository
- Adds commands to open files, commits, branches, and the repository in the supported remote services, **BitBucket, GitHub, GitLab, and Visual Studio Team Services** or a [**user-defined** remote services](#custom-remotes-settings) — only available if a Git upstream service is configured in the repository
- Also supports [remote services with custom domains](#custom-remotes-settings), such as **BitBucket, Bitbucket Server (previously called Stash), GitHub, GitHub Enterprise, GitLab**
- `Open Branches in Remote` command (`gitlens.openBranchesInRemote`) — opens the branches in the supported remote service
- `Open Branch in Remote` command (`gitlens.openBranchInRemote`) — opens the current branch commits in the supported remote service
Expand Down Expand Up @@ -371,7 +371,7 @@ GitLens is highly customizable and provides many configuration settings to allow

|Name | Description
|-----|------------
|`gitlens.remotes`|Specifies any custom domains for remote (code-hosting) services<br />Example: ```"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "GitHub" }]```
|`gitlens.remotes`|Specifies user-defined remote (code-hosting) services or custom domains for built-in remote services<br /><br />Example:<br />```"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "GitHub" }]```<br /><br />Example:<br />```"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "Custom", "name": "My Company", "urls": { "repository": "https://git.corporate-url.com/${repo}", "branches": "https://git.corporate-url.com/${repo}/branches", "branch": "https://git.corporate-url.com/${repo}/commits/${branch}", "commit": "https://git.corporate-url.com/${repo}/commit/${id}", "file": "https://git.corporate-url.com/${repo}?path=${file}${line}", "fileInBranch": "https://git.corporate-url.com/${repo}/blob/${branch}/${file}${line}", "fileInCommit": "https://git.corporate-url.com/${repo}/blob/${id}/${file}${line}", "fileLine": "#L${line}", "fileRange": "#L${start}-L${end}" } }```

### Status Bar Settings

Expand Down
62 changes: 60 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@
"enum": [
"Bitbucket",
"BitbucketServer",
"Custom",
"GitHub",
"GitLab"
],
Expand All @@ -506,11 +507,68 @@
"domain": {
"type": "string",
"description": "Specifies the domain name of the custom remote service"
}
},
"name": {
"type": "string",
"description": "Specifies an optional friendly name for the custom remote service"
},
"urls": {
"type": "object",
"required": [
"repository",
"branches",
"branch",
"commit",
"file",
"fileInCommit",
"fileInBranch",
"fileLine",
"fileRange"
],
"properties": {
"repository": {
"type": "string",
"description": "Specifies the format of a respository url for the custom remote service\nAvailable tokens\n ${repo} - repository path"
},
"branches": {
"type": "string",
"description": "Specifies the format of a branches url for the custom remote service\nAvailable tokens\n ${repo} - repository path\n ${branch} - branch"
},
"branch": {
"type": "string",
"description": "Specifies the format of a branch url for the custom remote service\nAvailable tokens\n ${repo} - repository path\n ${branch} - branch"
},
"commit": {
"type": "string",
"description": "Specifies the format of a commit url for the custom remote service\nAvailable tokens\n ${repo} - repository path\n ${id} - commit id"
},
"file": {
"type": "string",
"description": "Specifies the format of a file url for the custom remote service\nAvailable tokens\n ${repo} - repository path\n ${file} - file name\n ${line} - formatted line information"
},
"fileInBranch": {
"type": "string",
"description": "Specifies the format of a branch file url for the custom remote service\nAvailable tokens\n ${repo} - repository path\n ${file} - file name\n ${branch} - branch\n ${line} - formatted line information"
},
"fileInCommit": {
"type": "string",
"description": "Specifies the format of a commit file url for the custom remote service\nAvailable tokens\n ${repo} - repository path\n ${file} - file name\n ${id} - commit id\n ${line} - formatted line information"
},
"fileLine": {
"type": "string",
"description": "Specifies the format of a line in a file url for the custom remote service\nAvailable tokens\n ${line} - line"
},
"fileRange": {
"type": "string",
"description": "Specifies the format of a range in a file url for the custom remote service\nAvailable tokens\n ${start} - starting line\n ${end} - ending line"
}
}
},
"description": "Specifies the url formats of the custom remote service"
}
},
"uniqueItems": true,
"description": "Specifies any custom domains for remote (code-hosting) services"
"description": "Specifies user-defined remote (code-hosting) services or custom domains for built-in remote services"
},
"gitlens.statusBar.enabled": {
"type": "boolean",
Expand Down
14 changes: 14 additions & 0 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ export const LineHighlightLocations = {

export type CustomRemoteType =
'Bitbucket' |
'Custom' |
'GitHub' |
'GitLab';
export const CustomRemoteType = {
Bitbucket: 'Bitbucket' as CustomRemoteType,
BitbucketServer: 'BitbucketServer' as CustomRemoteType,
Custom: 'Custom' as CustomRemoteType,
GitHub: 'GitHub' as CustomRemoteType,
GitLab: 'GitLab' as CustomRemoteType
};
Expand Down Expand Up @@ -163,6 +165,18 @@ export interface IGitExplorerConfig {
export interface IRemotesConfig {
type: CustomRemoteType;
domain: string;
name?: string;
urls?: {
repository: string;
branches: string;
branch: string;
commit: string;
file: string;
fileInBranch: string;
fileInCommit: string;
fileLine: string;
fileRange: string;
};
}

export interface IThemeConfig {
Expand Down
4 changes: 2 additions & 2 deletions src/git/remotes/bitbucket-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { RemoteProvider } from './provider';

export class BitbucketServerService extends RemoteProvider {

constructor(public domain: string, public path: string, public custom: boolean = false) {
super(domain, path);
constructor(domain: string, path: string, name?: string, custom: boolean = false) {
super(domain, path, name, custom);
}

get name() {
Expand Down
4 changes: 2 additions & 2 deletions src/git/remotes/bitbucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { RemoteProvider } from './provider';

export class BitbucketService extends RemoteProvider {

constructor(public domain: string, public path: string, public custom: boolean = false) {
super(domain, path);
constructor(domain: string, path: string, name?: string, custom: boolean = false) {
super(domain, path, name, custom);
}

get name() {
Expand Down
48 changes: 48 additions & 0 deletions src/git/remotes/custom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict';
import { Strings } from '../../system';
import { Range } from 'vscode';
import { IRemotesConfig } from '../../configuration';
import { RemoteProvider } from './provider';

export class CustomService extends RemoteProvider {

constructor(domain: string, path: string, private readonly config: IRemotesConfig) {
super(domain, path, config.name, true);
}

get name() {
return this.formatName('Custom');
}

protected getUrlForRepository(): string {
return Strings.interpolate(this.config.custom!.repository, { repo: this.path });
}

protected getUrlForBranches(): string {
return Strings.interpolate(this.config.custom!.branches, { repo: this.path });
}

protected getUrlForBranch(branch: string): string {
return Strings.interpolate(this.config.custom!.branch, { repo: this.path, branch: branch });
}

protected getUrlForCommit(sha: string): string {
return Strings.interpolate(this.config.custom!.commit, { repo: this.path, id: sha });
}

protected getUrlForFile(fileName: string, branch?: string, sha?: string, range?: Range): string {
let line = '';
if (range) {
if (range.start.line === range.end.line) {
line = Strings.interpolate(this.config.custom!.fileLine, { line: range.start.line });
}
else {
line = Strings.interpolate(this.config.custom!.fileRange, { start: range.start.line, end: range.end.line });
}
}

if (sha) return Strings.interpolate(this.config.custom!.fileInCommit, { repo: this.path, id: sha, file: fileName, line: line });
if (branch) return Strings.interpolate(this.config.custom!.fileInBranch, { repo: this.path, branch: branch, file: fileName, line: line });
return Strings.interpolate(this.config.custom!.file, { repo: this.path, file: fileName, line: line });
}
}
20 changes: 11 additions & 9 deletions src/git/remotes/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { BitbucketService } from './bitbucket';
import { BitbucketServerService } from './bitbucket-server';
import { CustomRemoteType, IConfig, IRemotesConfig } from '../../configuration';
import { ExtensionKey } from '../../constants';
import { CustomService } from './custom';
import { GitHubService } from './github';
import { GitLabService } from './gitlab';
import { Logger } from '../../logger';
Expand Down Expand Up @@ -62,11 +63,11 @@ export class RemoteProviderFactory {

this._remotesCfg = cfg.remotes;
if (this._remotesCfg != null && this._remotesCfg.length > 0) {
for (const svc of this._remotesCfg) {
const provider = this.getCustomProvider(svc.type);
for (const remoteCfg of this._remotesCfg) {
const provider = this.getCustomProvider(remoteCfg);
if (provider === undefined) continue;

this._providerMap.set(svc.domain.toLowerCase(), provider);
this._providerMap.set(remoteCfg.domain.toLowerCase(), provider);
}

if (!silent) {
Expand All @@ -76,12 +77,13 @@ export class RemoteProviderFactory {
}
}

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);
private static getCustomProvider(cfg: IRemotesConfig) {
switch (cfg.type) {
case CustomRemoteType.Bitbucket: return (domain: string, path: string) => new BitbucketService(domain, path, cfg.name, true);
case CustomRemoteType.BitbucketServer: return (domain: string, path: string) => new BitbucketServerService(domain, path, cfg.name, true);
case CustomRemoteType.Custom: return (domain: string, path: string) => new CustomService(domain, path, cfg);
case CustomRemoteType.GitHub: return (domain: string, path: string) => new GitHubService(domain, path, cfg.name, true);
case CustomRemoteType.GitLab: return (domain: string, path: string) => new GitLabService(domain, path, cfg.name, true);
}
return undefined;
}
Expand Down
4 changes: 2 additions & 2 deletions src/git/remotes/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { RemoteProvider } from './provider';

export class GitHubService extends RemoteProvider {

constructor(public domain: string, public path: string, public custom: boolean = false) {
super(domain, path);
constructor(domain: string, path: string, name?: string, custom: boolean = false) {
super(domain, path, name, custom);
}

get name() {
Expand Down
4 changes: 2 additions & 2 deletions src/git/remotes/gitlab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { RemoteProvider } from './provider';

export class GitLabService extends RemoteProvider {

constructor(public domain: string, public path: string, public custom: boolean = false) {
super(domain, path);
constructor(domain: string, path: string, name?: string, custom: boolean = false) {
super(domain, path, name, custom);
}

get name() {
Expand Down
17 changes: 15 additions & 2 deletions src/git/remotes/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@ export function getNameFromRemoteResource(resource: RemoteResource) {

export abstract class RemoteProvider {

constructor(public domain: string, public path: string, public custom: boolean = false) { }
private _name: string | undefined;

constructor(
public readonly domain: string,
public readonly path: string,
name?: string,
public readonly custom: boolean = false
) {
this._name = name;
}

abstract get name(): string;

Expand All @@ -35,6 +44,7 @@ export abstract class RemoteProvider {
}

protected formatName(name: string) {
if (this._name !== undefined) return this._name;
return `${name}${this.custom ? ` (${this.domain})` : ''}`;
}

Expand All @@ -43,6 +53,9 @@ export abstract class RemoteProvider {
return [ this.path.substring(0, index), this.path.substring(index + 1) ];
}

protected getUrlForRepository(): string {
return this.baseUrl;
}
protected abstract getUrlForBranches(): string;
protected abstract getUrlForBranch(branch: string): string;
protected abstract getUrlForCommit(sha: string): string;
Expand All @@ -66,7 +79,7 @@ export abstract class RemoteProvider {
}

openRepo() {
return this._openUrl(this.baseUrl);
return this._openUrl(this.getUrlForRepository());
}

openBranches() {
Expand Down
4 changes: 2 additions & 2 deletions src/git/remotes/visualStudio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { RemoteProvider } from './provider';

export class VisualStudioService extends RemoteProvider {

constructor(public domain: string, public path: string) {
super(domain, path);
constructor(domain: string, path: string, name?: string) {
super(domain, path, name);
}

get name() {
Expand Down

0 comments on commit e70dd6d

Please sign in to comment.