Skip to content
This repository has been archived by the owner on Nov 27, 2023. It is now read-only.

Commit

Permalink
fix(vscode-github): stabilized input of personal access token (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
KnisterPeter authored Nov 9, 2016
1 parent 6453a15 commit f7735fc
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 99 deletions.
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
# vscode-github README

[![Current Version](http://vsmarketplacebadge.apphb.com/version/vscode-github.svg)](https://marketplace.visualstudio.com/items?itemName=KnisterPeter.vscode-github)
[![Install Count](http://vsmarketplacebadge.apphb.com/installs/vscode-github.svg)](https://marketplace.visualstudio.com/items?itemName=KnisterPeter.vscode-github)

This vscode extension integrates with GitHub.

## Features

Current it is possible to do the following:

* Store your GitHub Personal Access Token

To use this extension one needs to create a new GitHub Personal Access Token and registers it in the extension.
The 'GitHub: Set Personal Access Token' should be executed for that.

![GitHub Personal Access Token](./images/github-personal-access-token.png)

![GitHub Personal Access Token](./images/github-personal-access-token2.png)

![Set GitHub Personal Access Token](./images/set-personal-access-token.png)

* Create a new pull request based on the current branch and the last commit
The current branch will be requested to merge into master and the pull request title is the commit message summary.
* Checkout one of the open pull requests

## Requirements
![Create pull request](./images/create-pull-request.png)

To use this extension one needs to create a new GitHub Personal Access Token and registers it in the extension.
The 'GitHub: Set Personal Access Token' should be executed for that.
* Checkout one of the open pull requests
Binary file added images/create-pull-request.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/github-personal-access-token.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/github-personal-access-token2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/set-personal-access-token.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 42 additions & 62 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,52 @@
'use strict';
import * as vscode from 'vscode';
import * as execa from 'execa';

import * as git from './git';

import {getClient, GitHub, GitHubError, ListPullRequestsParameters, CreatePullRequestBody} from './github';

let github: GitHub;
let cwd: string;
let token: string;
let github: GitHub;

export function activate(context: vscode.ExtensionContext): void {
cwd = vscode.workspace.rootPath;
getToken(context).then(token => {
if (!github) {
github = getClient(token);
}
getToken(context).then(_token => {
token = _token;
});

context.subscriptions.push(
vscode.commands.registerCommand('extension.setGitHubToken',
createGithubTokenCommand(context)));
context.subscriptions.push(
vscode.commands.registerCommand('extension.createPullRequest',
createPullRequest));
wrapCommand(createPullRequest)));
context.subscriptions.push(
vscode.commands.registerCommand('extension.checkoutPullRequests',
checkoutPullRequests));
wrapCommand(checkoutPullRequests)));
}

function wrapCommand<T>(command: T): T {
const wrap: any = (...args: any[]) => {
if (Boolean(token) && Boolean(cwd)) {
return (command as any).apply(null, args);
} else {
vscode.window.showWarningMessage('Please setup your Github Personal Access Token '
+ 'and open a GitHub project in your workspace');
}
};
return wrap;
}

function getToken(context: vscode.ExtensionContext): PromiseLike<string> {
let token = context.globalState.get<string>('token');
if (token) {
return Promise.resolve(token);
return Promise.resolve(context.globalState.get<string>('token'));
}

function getGitHubClient(): GitHub {
if (!github) {
github = getClient(token);
}
return createGithubTokenCommand(context)().then(() => {
return context.globalState.get<string>('token');
});
return github;
}

function createGithubTokenCommand(context: vscode.ExtensionContext): () => PromiseLike<void> {
Expand All @@ -44,69 +57,36 @@ function createGithubTokenCommand(context: vscode.ExtensionContext): () => Promi
placeHolder: 'GitHub Personal Access Token'
};
return vscode.window.showInputBox(options)
.then(input => context.globalState.update('token', input))
.then(() => getToken(context))
.then(token => {
github = getClient(token);
.then(input => {
context.globalState.update('token', input);
token = input;
});
};
}

async function getGitHubOwnerAndRepository(): Promise<string[]> {
return execa('git', ['config', '--get-regexp', 'remote\\.origin\\.url'], {cwd})
.then(result => {
const match = result.stdout.match(/^remote.origin.url git@github.com:(.*?)\/(.*?)(?:.git)?$/);
if (!match) {
throw new Error('Not a github project?');
}
return [match[1], match[2]];
});
}

async function getCurrentBranch(): Promise<string|undefined> {
return execa('git', ['status', '--porcelain', '--branch'], {cwd})
.then(result => {
const match = result.stdout.match(/^## (.+?)(?:\.\.\..*)?/);
return match ? match[1] : undefined;
});
}

async function getCommitMessage(): Promise<string> {
return execa('git', ['log', '--oneline', '-1'], {cwd})
.then(result => {
const match = result.stdout.match(/^(?:.+?) (.*)/);
return match ? match[1] : result.stdout;
});
}

async function checkout(branch: string): Promise<void> {
return execa('git', ['checkout', branch], {cwd})
.then(() => undefined);
}

async function hasPullRequests(): Promise<boolean> {
const [owner, repository] = await getGitHubOwnerAndRepository();
const branch = await getCurrentBranch();
async function hasPullRequestForCurrentBranch(): Promise<boolean> {
const [owner, repository] = await git.getGitHubOwnerAndRepository(cwd);
const branch = await git.getCurrentBranch(cwd);
const parameters: ListPullRequestsParameters = {
state: 'open',
head: `${owner}:${branch}`
};
const response = await github.listPullRequests(owner, repository, parameters);
const response = await getGitHubClient().listPullRequests(owner, repository, parameters);
return response.body.length > 0;
}

async function createPullRequest(): Promise<void> {
try {
if (!await hasPullRequests()) {
const [owner, repository] = await getGitHubOwnerAndRepository();
const branch = await getCurrentBranch();
if (!await hasPullRequestForCurrentBranch()) {
const [owner, repository] = await git.getGitHubOwnerAndRepository(cwd);
const branch = await git.getCurrentBranch(cwd);
console.log('orb', owner, repository, branch);
const body: CreatePullRequestBody = {
title: await getCommitMessage(),
title: await git.getCommitMessage(cwd),
head: `${owner}:${branch}`,
base: `master`
};
const result = await github.createPullRequest(owner, repository, body);
const result = await getGitHubClient().createPullRequest(owner, repository, body);
console.log('result', result);
}
} catch (e) {
Expand All @@ -120,18 +100,18 @@ async function createPullRequest(): Promise<void> {

async function checkoutPullRequests(): Promise<void> {
try {
const [owner, repository] = await getGitHubOwnerAndRepository();
const [owner, repository] = await git.getGitHubOwnerAndRepository(cwd);
const parameters: ListPullRequestsParameters = {
state: 'open'
};
const response = await github.listPullRequests(owner, repository, parameters);
const response = await getGitHubClient().listPullRequests(owner, repository, parameters);
vscode.window.showQuickPick(response.body.map(pullRequest => ({
label: pullRequest.title,
description: `#${pullRequest.number}`,
pullRequest
}))).then(selected => {
if (selected) {
checkout(selected.pullRequest.head.ref);
git.checkout(cwd, selected.pullRequest.head.ref);
}
});
} catch (e) {
Expand Down
33 changes: 33 additions & 0 deletions src/git.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as execa from 'execa';

export async function getGitHubOwnerAndRepository(cwd: string): Promise<string[]> {
return execa('git', ['config', '--get-regexp', 'remote\\.origin\\.url'], {cwd})
.then(result => {
const match = result.stdout.match(/^remote.origin.url git@github.com:(.*?)\/(.*?)(?:.git)?$/);
if (!match) {
throw new Error('Not a github project?');
}
return [match[1], match[2]];
});
}

export async function getCurrentBranch(cwd: string): Promise<string|undefined> {
return execa('git', ['status', '--porcelain', '--branch'], {cwd})
.then(result => {
const match = result.stdout.match(/^## (.+?)(?:\.\.\..*)?/);
return match ? match[1] : undefined;
});
}

export async function getCommitMessage(cwd: string): Promise<string> {
return execa('git', ['log', '--oneline', '-1'], {cwd})
.then(result => {
const match = result.stdout.match(/^(?:.+?) (.*)/);
return match ? match[1] : result.stdout;
});
}

export async function checkout(cwd: string, branch: string): Promise<void> {
return execa('git', ['checkout', branch], {cwd})
.then(() => undefined);
}
33 changes: 0 additions & 33 deletions vsc-extension-quickstart.md

This file was deleted.

0 comments on commit f7735fc

Please sign in to comment.