mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-01-16 01:25:42 -05:00
Adds experimental support for Open in GitHub
This commit is contained in:
@@ -10,6 +10,7 @@ export * from './models/models';
|
||||
export * from './parsers/blameParser';
|
||||
export * from './parsers/logParser';
|
||||
export * from './parsers/statusParser';
|
||||
export * from './hosting/hostingProvider';
|
||||
|
||||
let git: IGit;
|
||||
|
||||
@@ -210,6 +211,16 @@ export class Git {
|
||||
return gitCommand(root, ...params);
|
||||
}
|
||||
|
||||
static remote(repoPath: string): Promise<string> {
|
||||
const params = ['remote', '-v'];
|
||||
return gitCommand(repoPath, ...params);
|
||||
}
|
||||
|
||||
static remote_url(repoPath: string, remote: string): Promise<string> {
|
||||
const params = ['remote', 'get-url', remote];
|
||||
return gitCommand(repoPath, ...params);
|
||||
}
|
||||
|
||||
static status(repoPath: string): Promise<string> {
|
||||
const params = ['status', '--porcelain=v2', '--branch'];
|
||||
return gitCommand(repoPath, ...params);
|
||||
|
||||
@@ -71,6 +71,10 @@ export class GitUri extends Uri {
|
||||
: `${path.basename(this.fsPath)}${separator}${directory}`;
|
||||
}
|
||||
|
||||
getRelativePath(): string {
|
||||
return Git.normalizePath(path.relative(this.repoPath, this.fsPath));
|
||||
}
|
||||
|
||||
static async fromUri(uri: Uri, git: GitService) {
|
||||
if (uri instanceof GitUri) return uri;
|
||||
|
||||
|
||||
32
src/git/hosting/factory.ts
Normal file
32
src/git/hosting/factory.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
import { HostingProvider } from './hostingProvider';
|
||||
import { GitHubService } from './github';
|
||||
import { Logger } from '../../logger';
|
||||
|
||||
export { HostingProvider };
|
||||
|
||||
const serviceMap = new Map<string, (domain: string, path: string) => HostingProvider>([
|
||||
['github.com', (domain: string, path: string) => new GitHubService(domain, path)]
|
||||
]);
|
||||
|
||||
const UrlRegex = /^(?:git:\/\/(.*?)\/|https:\/\/(.*?)\/|http:\/\/(.*?)\/|git@(.*):\/\/|ssh:\/\/git@(.*?)\/)(.*)$/;
|
||||
|
||||
export class HostingProviderFactory {
|
||||
|
||||
static getHostingProvider(url: string): HostingProvider {
|
||||
try {
|
||||
const match = UrlRegex.exec(url);
|
||||
const domain = match[1] || match[2] || match[3] || match[4] || match[5];
|
||||
const path = match[6].replace(/\.git/, '');
|
||||
|
||||
const serviceCreator = serviceMap.get(domain);
|
||||
if (!serviceCreator) return undefined;
|
||||
|
||||
return serviceCreator(domain, path);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error(ex);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/git/hosting/github.ts
Normal file
26
src/git/hosting/github.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
import { HostingProvider } from './hostingProvider';
|
||||
|
||||
export class GitHubService extends HostingProvider {
|
||||
|
||||
constructor(public domain: string, public path: string) {
|
||||
super(domain, path);
|
||||
}
|
||||
|
||||
get name() {
|
||||
return 'GitHub';
|
||||
}
|
||||
|
||||
protected getUrlForBranch(branch: string): string {
|
||||
return `${this.baseUrl}/tree/${branch}`;
|
||||
}
|
||||
|
||||
protected getUrlForCommit(sha: string): string {
|
||||
return `${this.baseUrl}/commit/${sha}`;
|
||||
}
|
||||
|
||||
protected getUrlForFile(fileName: string, sha?: string): string {
|
||||
if (sha) return `${this.baseUrl}/blob/${sha}/${fileName}`;
|
||||
return `${this.baseUrl}?path=${fileName}`;
|
||||
}
|
||||
}
|
||||
48
src/git/hosting/hostingProvider.ts
Normal file
48
src/git/hosting/hostingProvider.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
import { commands, Uri } from 'vscode';
|
||||
import { BuiltInCommands } from '../../constants';
|
||||
|
||||
export type HostingProviderOpenType = 'branch' | 'commit' | 'file';
|
||||
|
||||
export abstract class HostingProvider {
|
||||
|
||||
constructor(public domain: string, public path: string) { }
|
||||
|
||||
abstract get name(): string;
|
||||
|
||||
protected get baseUrl() {
|
||||
return `https://${this.domain}/${this.path}`;
|
||||
}
|
||||
|
||||
protected abstract getUrlForBranch(branch: string): string;
|
||||
protected abstract getUrlForCommit(sha: string): string;
|
||||
protected abstract getUrlForFile(fileName: string, sha?: string): string;
|
||||
|
||||
private async _openUrl(url: string): Promise<{}> {
|
||||
return url && commands.executeCommand(BuiltInCommands.Open, Uri.parse(url));
|
||||
}
|
||||
|
||||
open(type: 'branch', branch: string): Promise<{}>;
|
||||
open(type: 'commit', sha: string): Promise<{}>;
|
||||
open(type: 'file', fileName: string, sha?: string): Promise<{}>;
|
||||
open(type: HostingProviderOpenType, ...args: string[]): Promise<{}>;
|
||||
open(type: HostingProviderOpenType, branchOrShaOrFileName: string, sha?: string): Promise<{}> {
|
||||
switch (type) {
|
||||
case 'branch': return this.openBranch(branchOrShaOrFileName);
|
||||
case 'commit': return this.openCommit(branchOrShaOrFileName);
|
||||
case 'file': return this.openFile(branchOrShaOrFileName, sha);
|
||||
}
|
||||
}
|
||||
|
||||
openBranch(branch: string) {
|
||||
return this._openUrl(this.getUrlForBranch(branch));
|
||||
}
|
||||
|
||||
openCommit(sha: string) {
|
||||
return this._openUrl(this.getUrlForCommit(sha));
|
||||
}
|
||||
|
||||
openFile(fileName: string, sha?: string) {
|
||||
return this._openUrl(this.getUrlForFile(fileName, sha));
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,5 @@ export * from './branch';
|
||||
export * from './commit';
|
||||
export * from './log';
|
||||
export * from './logCommit';
|
||||
export * from './remote';
|
||||
export * from './status';
|
||||
27
src/git/models/remote.ts
Normal file
27
src/git/models/remote.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
import { HostingProvider, HostingProviderFactory } from '../hosting/factory';
|
||||
|
||||
export type GitRemoteType = 'fetch' | 'push';
|
||||
|
||||
export class GitRemote {
|
||||
|
||||
name: string;
|
||||
url: string;
|
||||
type: GitRemoteType;
|
||||
|
||||
provider?: HostingProvider;
|
||||
|
||||
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 = HostingProviderFactory.getHostingProvider(this.url);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user