From 2d0bdc071ad9642d8fca70761c40de6473aac011 Mon Sep 17 00:00:00 2001
From: Michael Hutchison
Date: Wed, 27 Feb 2019 09:57:42 +1100
Subject: [PATCH] #15 Support for portable git installations
---
media/main.css | 2 +-
src/config.ts | 4 ++++
src/dataSource.ts | 54 ++++++++++++++++++++++++++-------------------
src/extension.ts | 2 ++
src/gitGraphView.ts | 2 +-
5 files changed, 39 insertions(+), 25 deletions(-)
diff --git a/media/main.css b/media/main.css
index 19b60754..ce466b48 100644
--- a/media/main.css
+++ b/media/main.css
@@ -3,7 +3,7 @@ body{
margin:0;
padding:0;
}
-body.notGitRepository h1, body.notGitRepository p{
+body.unableToLoad h1, body.unableToLoad p{
text-align:center;
}
diff --git a/src/config.ts b/src/config.ts
index d0a88f58..b11e3aa0 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -33,4 +33,8 @@ export class Config {
public showUncommittedChanges() {
return this.workspaceConfiguration.get('showUncommittedChanges', true);
}
+ public gitPath(): string {
+ let path = vscode.workspace.getConfiguration('git').get('path', null);
+ return path !== null ? path : 'git';
+ }
}
\ No newline at end of file
diff --git a/src/dataSource.ts b/src/dataSource.ts
index 17c0ec27..a979909b 100644
--- a/src/dataSource.ts
+++ b/src/dataSource.ts
@@ -8,15 +8,23 @@ const gitLogFormat = ['%H', '%P', '%an', '%ae', '%at', '%s'].join(gitLogSeparato
const gitCommitDetailsFormat = ['%H', '%P', '%an', '%ae', '%at', '%cn', '%B'].join(gitLogSeparator);
export class DataSource {
- private workspaceDir: string;
+ private execOptions: cp.ExecOptions;
+ private gitPath!: string;
+ private gitExecPath!: string;
constructor(workspaceDir: string) {
- this.workspaceDir = workspaceDir;
+ this.execOptions = { cwd: workspaceDir };
+ this.registerGitPath();
+ }
+
+ public registerGitPath() {
+ this.gitPath = (new Config()).gitPath();
+ this.gitExecPath = this.gitPath.indexOf(' ') > -1 ? '"' + this.gitPath + '"' : this.gitPath;
}
public isGitRepository() {
return new Promise((resolve) => {
- cp.exec('git rev-parse --git-dir', { cwd: this.workspaceDir }, (err) => {
+ cp.exec(this.gitExecPath + ' rev-parse --git-dir', this.execOptions, (err) => {
resolve(!err);
});
});
@@ -24,7 +32,7 @@ export class DataSource {
public getBranches(showRemoteBranches: boolean) {
return new Promise((resolve) => {
- cp.exec('git branch' + (showRemoteBranches ? ' -a' : ''), { cwd: this.workspaceDir }, (err, stdout) => {
+ cp.exec(this.gitExecPath + ' branch' + (showRemoteBranches ? ' -a' : ''), this.execOptions, (err, stdout) => {
if (!err) {
let lines = stdout.split(eolRegex);
let branches: string[] = [];
@@ -98,7 +106,7 @@ export class DataSource {
public async commitDetails(commitHash: string) {
try {
let details = await new Promise((resolve, reject) => {
- cp.exec('git show --quiet ' + commitHash + ' --format="' + gitCommitDetailsFormat + '"', { cwd: this.workspaceDir }, (err, stdout) => {
+ cp.exec(this.gitExecPath + ' show --quiet ' + commitHash + ' --format="' + gitCommitDetailsFormat + '"', this.execOptions, (err, stdout) => {
if (!err) {
let lines = stdout.split(eolRegex);
let commitInfo = lines[0].split(gitLogSeparator);
@@ -119,7 +127,7 @@ export class DataSource {
});
let fileLookup: { [file: string]: number } = {};
await new Promise((resolve, reject) => {
- cp.exec('git diff-tree --name-status -r -m --root --find-renames --diff-filter=AMDR ' + commitHash, { cwd: this.workspaceDir }, (err, stdout) => {
+ cp.exec(this.gitExecPath + ' diff-tree --name-status -r -m --root --find-renames --diff-filter=AMDR ' + commitHash, this.execOptions, (err, stdout) => {
if (!err) {
let lines = stdout.split(eolRegex);
for (let i = 1; i < lines.length - 1; i++) {
@@ -136,7 +144,7 @@ export class DataSource {
});
});
await new Promise((resolve, reject) => {
- cp.exec('git diff-tree --numstat -r -m --root --find-renames --diff-filter=AMDR ' + commitHash, { cwd: this.workspaceDir }, (err, stdout) => {
+ cp.exec(this.gitExecPath + ' diff-tree --numstat -r -m --root --find-renames --diff-filter=AMDR ' + commitHash, this.execOptions, (err, stdout) => {
if (!err) {
let lines = stdout.split(eolRegex);
for (let i = 1; i < lines.length - 1; i++) {
@@ -164,7 +172,7 @@ export class DataSource {
public async getCommitFile(commitHash: string, filePath: string) {
return new Promise((resolve) => {
let args = ['show', commitHash + ':' + filePath], stdout = '', err = false;
- const cmd = cp.spawn('git', args, { cwd: this.workspaceDir });
+ const cmd = cp.spawn(this.gitPath, args, this.execOptions);
cmd.stdout.on('data', (d) => { stdout += d; });
cmd.on('error', () => {
resolve('');
@@ -178,48 +186,48 @@ export class DataSource {
}
public addTag(tagName: string, commitHash: string) {
- return this.runGitCommand('git tag -a ' + escapeRefName(tagName) + ' -m "" ' + commitHash);
+ return this.runGitCommand('tag -a ' + escapeRefName(tagName) + ' -m "" ' + commitHash);
}
public deleteTag(tagName: string) {
- return this.runGitCommand('git tag -d ' + escapeRefName(tagName));
+ return this.runGitCommand('tag -d ' + escapeRefName(tagName));
}
public createBranch(branchName: string, commitHash: string) {
- return this.runGitCommand('git branch ' + escapeRefName(branchName) + ' ' + commitHash);
+ return this.runGitCommand('branch ' + escapeRefName(branchName) + ' ' + commitHash);
}
public checkoutBranch(branchName: string, remoteBranch: string | null) {
- return this.runGitCommand('git checkout ' + (remoteBranch === null ? escapeRefName(branchName) : ' -b ' + escapeRefName(branchName) + ' ' + escapeRefName(remoteBranch)));
+ return this.runGitCommand('checkout ' + (remoteBranch === null ? escapeRefName(branchName) : ' -b ' + escapeRefName(branchName) + ' ' + escapeRefName(remoteBranch)));
}
public deleteBranch(branchName: string, forceDelete: boolean) {
- return this.runGitCommand('git branch --delete' + (forceDelete ? ' --force' : '') + ' ' + escapeRefName(branchName));
+ return this.runGitCommand('branch --delete' + (forceDelete ? ' --force' : '') + ' ' + escapeRefName(branchName));
}
public renameBranch(oldName: string, newName: string) {
- return this.runGitCommand('git branch -m ' + escapeRefName(oldName) + ' ' + escapeRefName(newName));
+ return this.runGitCommand('branch -m ' + escapeRefName(oldName) + ' ' + escapeRefName(newName));
}
- public mergeBranch(branchName: string){
- return this.runGitCommand('git merge ' + escapeRefName(branchName));
+ public mergeBranch(branchName: string) {
+ return this.runGitCommand('merge ' + escapeRefName(branchName));
}
public cherrypickCommit(commitHash: string, parentIndex: number) {
- return this.runGitCommand('git cherry-pick ' + commitHash + (parentIndex > 0 ? ' -m ' + parentIndex : ''));
+ return this.runGitCommand('cherry-pick ' + commitHash + (parentIndex > 0 ? ' -m ' + parentIndex : ''));
}
public revertCommit(commitHash: string, parentIndex: number) {
- return this.runGitCommand('git revert --no-edit ' + commitHash + (parentIndex > 0 ? ' -m ' + parentIndex : ''));
+ return this.runGitCommand('revert --no-edit ' + commitHash + (parentIndex > 0 ? ' -m ' + parentIndex : ''));
}
public resetToCommit(commitHash: string, resetMode: GitResetMode) {
- return this.runGitCommand('git reset --' + resetMode + ' ' + commitHash);
+ return this.runGitCommand('reset --' + resetMode + ' ' + commitHash);
}
private async runGitCommand(command: string) {
return new Promise((resolve) => {
- cp.exec(command, { cwd: this.workspaceDir }, (err) => {
+ cp.exec(this.gitExecPath + ' ' + command, this.execOptions, (err) => {
if (!err) {
resolve(null);
} else {
@@ -232,7 +240,7 @@ export class DataSource {
private async getRefs(showRemoteBranches: boolean) {
return new Promise((resolve) => {
- cp.exec('git show-ref ' + (showRemoteBranches ? '' : '--heads --tags') + ' -d', { cwd: this.workspaceDir }, (err, stdout) => {
+ cp.exec(this.gitExecPath + ' show-ref ' + (showRemoteBranches ? '' : '--heads --tags') + ' -d', this.execOptions, (err, stdout) => {
if (!err) {
let lines = stdout.split(eolRegex);
let refs: GitRef[] = [];
@@ -269,7 +277,7 @@ export class DataSource {
if (showRemoteBranches) args.push('--remotes');
}
- const cmd = cp.spawn('git', args, { cwd: this.workspaceDir });
+ const cmd = cp.spawn(this.gitPath, args, this.execOptions);
cmd.stdout.on('data', (d) => { stdout += d; });
cmd.on('error', () => {
resolve([]);
@@ -296,7 +304,7 @@ export class DataSource {
private getGitUnsavedChanges() {
try {
return new Promise((resolve, reject) => {
- cp.exec('git status -s --branch --untracked-files --porcelain', { cwd: this.workspaceDir }, (err, stdout) => {
+ cp.exec(this.gitExecPath + ' status -s --branch --untracked-files --porcelain', this.execOptions, (err, stdout) => {
if (!err) {
let lines = stdout.split(eolRegex);
resolve(lines.length > 2 ? { branch: lines[0].substring(3).split('...')[0], changes: lines.length - 2 } : null);
diff --git a/src/extension.ts b/src/extension.ts
index 15e65ac9..07e30249 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -32,6 +32,8 @@ export function activate(context: vscode.ExtensionContext) {
} else {
statusBarItem.hide();
}
+ } else if (e.affectsConfiguration('git.path') && dataSource !== null) {
+ dataSource.registerGitPath();
}
}));
}
diff --git a/src/gitGraphView.ts b/src/gitGraphView.ts
index e11f2e93..069d03bc 100644
--- a/src/gitGraphView.ts
+++ b/src/gitGraphView.ts
@@ -187,7 +187,7 @@ export class GitGraphView {
Git Graph
The current workspace is not a Git Repository, unable to show Git Graph.
Git Graph
Unable to load Git Graph. Either the current workspace is not a Git Repository, or the Git executable could not found.