diff --git a/package.json b/package.json index 0ab263ee..74482a4e 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,11 @@ "title": "Set Personal Access Token...", "category": "GitHub" }, + { + "command": "vscode-github.setGitHubEnterpriseToken", + "title": "Setup GitHub Enterprise Token...", + "category": "GitHub" + }, { "command": "vscode-github.browseProject", "title": "Browse project", diff --git a/src/extension.ts b/src/extension.ts index b65f9915..8403168a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,11 +1,11 @@ -import {join} from 'path'; +import { join } from 'path'; import * as sander from 'sander'; import * as vscode from 'vscode'; import * as git from './git'; -import {GitHubError, PullRequest, MergeMethod} from './github'; -import {GitHubManager} from './github-manager'; -import {StatusBarManager} from './status-bar-manager'; +import { GitHubError, PullRequest, MergeMethod } from './github'; +import { GitHubManager, Tokens } from './github-manager'; +import { StatusBarManager } from './status-bar-manager'; export function activate(context: vscode.ExtensionContext): void { context.subscriptions.push(new Extension(context)); @@ -22,6 +22,8 @@ class Extension { private statusBarManager: StatusBarManager; constructor(context: vscode.ExtensionContext) { + this.migrateToken(context); + this.channel = vscode.window.createOutputChannel('github'); context.subscriptions.push(this.channel); this.channel.appendLine('Visual Studio Code GitHub Extension'); @@ -29,15 +31,17 @@ class Extension { this.githubManager = new GitHubManager(this.cwd, this.channel); this.statusBarManager = new StatusBarManager(context, this.cwd, this.githubManager, this.channel); - const token = context.globalState.get('token'); - if (token) { - this.githubManager.connect(token); + const tokens = context.globalState.get('tokens'); + if (tokens) { + this.githubManager.connect(tokens); } - this.checkVersionAndToken(context, token); + this.checkVersionAndToken(context, tokens); context.subscriptions.push( vscode.commands.registerCommand('vscode-github.browseProject', this.wrapCommand(this.browseProject)), vscode.commands.registerCommand('vscode-github.setGitHubToken', this.createGithubTokenCommand(context)), + vscode.commands.registerCommand('vscode-github.setGitHubEnterpriseToken', + this.createGithubEnterpriseTokenCommand(context)), vscode.commands.registerCommand('vscode-github.createSimplePullRequest', this.wrapCommand(this.createSimplePullRequest)), vscode.commands.registerCommand('vscode-github.createPullRequest', this.wrapCommand(this.createPullRequest)), @@ -54,7 +58,17 @@ class Extension { ); } - private async withinProgressUI(task: (progress: vscode.Progress<{message?: string}>) => Promise): Promise { + private migrateToken(context: vscode.ExtensionContext): void { + const token = context.globalState.get('token'); + if (token) { + const tokens = context.globalState.get('tokens', {}); + tokens['github.com'] = token; + context.globalState.update('tokens', tokens); + context.globalState.update(token, undefined); + } + } + + private async withinProgressUI(task: (progress: vscode.Progress<{ message?: string }>) => Promise): Promise { const options: vscode.ProgressOptions = { location: vscode.ProgressLocation.SourceControl, title: 'GitHub' @@ -69,11 +83,11 @@ class Extension { return vscode.workspace.rootPath; } - private async checkVersionAndToken(context: vscode.ExtensionContext, token: string|undefined): Promise { + private async checkVersionAndToken(context: vscode.ExtensionContext, tokens: Tokens | undefined): Promise { const content = await sander.readFile(join(context.extensionPath, 'package.json')); const version = JSON.parse(content.toString()).version as string; - const storedVersion = context.globalState.get('version-test'); - if (version !== storedVersion && !Boolean(token)) { + const storedVersion = context.globalState.get('version-test'); + if (version !== storedVersion && (!tokens || Object.keys(tokens).length === 0)) { context.globalState.update('version-test', version); vscode.window.showInformationMessage( 'To enable the Visual Studio Code GitHub Support, please set a Personal Access Token'); @@ -97,14 +111,14 @@ class Extension { } private logAndShowError(e: Error): void { - this.channel.appendLine(e.message); - if (e instanceof GitHubError) { - console.error(e.response); - vscode.window.showErrorMessage('GitHub error: ' + e.message); - } else { - console.error(e); - vscode.window.showErrorMessage('Error: ' + e.message); - } + this.channel.appendLine(e.message); + if (e instanceof GitHubError) { + console.error(e.response); + vscode.window.showErrorMessage('GitHub error: ' + e.message); + } else { + console.error(e); + vscode.window.showErrorMessage('Error: ' + e.message); + } } private createGithubTokenCommand(context: vscode.ExtensionContext): () => void { @@ -116,8 +130,32 @@ class Extension { }; const input = await vscode.window.showInputBox(options); if (input) { - context.globalState.update('token', input); - await this.githubManager.connect(input); + const tokens = context.globalState.get('tokens', {}); + tokens['github.com'] = input; + context.globalState.update('tokens', tokens); + await this.githubManager.connect(tokens); + } + }; + } + + private createGithubEnterpriseTokenCommand(context: vscode.ExtensionContext): () => void { + return async() => { + const hostInput = await vscode.window.showInputBox({ + ignoreFocusOut: true, + placeHolder: 'GitHub Enterprise Hostname' + }); + if (hostInput) { + const tokenInput = await vscode.window.showInputBox({ + ignoreFocusOut: true, + password: true, + placeHolder: 'GitHub Enterprise Token' + }); + if (tokenInput) { + const tokens = context.globalState.get('tokens', {}); + tokens[hostInput] = tokenInput; + context.globalState.update('tokens', tokens); + this.githubManager.connect(tokens); + } } }; } @@ -163,7 +201,7 @@ class Extension { progress.report(`Gather data`); let [owner, repo] = await git.getGitHubOwnerAndRepository(this.cwd); const repository = await this.githubManager.getRepository(); - let pullRequest: PullRequest|undefined; + let pullRequest: PullRequest | undefined; if (repository.parent) { let branch: string; const items = [{ @@ -176,7 +214,7 @@ class Extension { branch: repository.parent.default_branch }]; const selectedRepository = await vscode.window.showQuickPick(items, - {placeHolder: 'Select a repository to create the pull request in'}); + { placeHolder: 'Select a repository to create the pull request in' }); if (!selectedRepository) { return; } @@ -250,7 +288,7 @@ class Extension { }); } - private async getMergeMethdod(): Promise { + private async getMergeMethdod(): Promise { const preferedMethod = vscode.workspace.getConfiguration('github').get('preferedMergeMethod'); if (preferedMethod) { return preferedMethod; @@ -366,7 +404,7 @@ class Extension { }); } - private async getUser(): Promise { + private async getUser(): Promise { return await vscode.window.showInputBox({ ignoreFocusOut: true, placeHolder: 'username, email or fullname' diff --git a/src/github-manager.ts b/src/github-manager.ts index 2e873b90..0aa46929 100644 --- a/src/github-manager.ts +++ b/src/github-manager.ts @@ -4,6 +4,10 @@ import * as git from './git'; import {getClient, GitHub, GitHubError, PullRequest, ListPullRequestsParameters, CreatePullRequestBody, PullRequestStatus, Merge, MergeMethod, Repository} from './github'; +export interface Tokens { + [host: string]: string; +} + export class GitHubManager { private cwd: string; @@ -26,8 +30,13 @@ export class GitHubManager { return Boolean(this.github); } - public async connect(token: string): Promise { - this.github = getClient(await this.getApiEndpoint(), token); + public async getGitHubHostname(): Promise { + return git.getGitHubHostname(this.cwd); + } + + public async connect(tokens: Tokens): Promise { + const hostname = await git.getGitHubHostname(this.cwd); + this.github = getClient(await this.getApiEndpoint(), tokens[hostname]); } private async getApiEndpoint(): Promise {