提交 0fe4c5fb 编写于 作者: T Tomas Vik

fix: use the same git binary as VS Code

上级 36fd8f83
...@@ -17,7 +17,7 @@ const { GitContentProvider } = require('./review/git_content_provider'); ...@@ -17,7 +17,7 @@ const { GitContentProvider } = require('./review/git_content_provider');
const { REVIEW_URI_SCHEME } = require('./constants'); const { REVIEW_URI_SCHEME } = require('./constants');
const { USER_COMMANDS, PROGRAMMATIC_COMMANDS } = require('./command_names'); const { USER_COMMANDS, PROGRAMMATIC_COMMANDS } = require('./command_names');
const { CiCompletionProvider } = require('./completion/ci_completion_provider'); const { CiCompletionProvider } = require('./completion/ci_completion_provider');
const { GitExtensionWrapper } = require('./git/git_extension_wrapper'); const { gitExtensionWrapper } = require('./git/git_extension_wrapper');
const { const {
toggleResolved, toggleResolved,
deleteComment, deleteComment,
...@@ -112,7 +112,7 @@ const activate = context => { ...@@ -112,7 +112,7 @@ const activate = context => {
tokenService.init(context); tokenService.init(context);
tokenServiceWrapper.init(context); tokenServiceWrapper.init(context);
registerCiCompletion(context); registerCiCompletion(context);
context.subscriptions.push(GitExtensionWrapper.registerToGitExtension()); gitExtensionWrapper.init();
}; };
exports.activate = activate; exports.activate = activate;
import { GitExtension } from '../api/git'; import * as vscode from 'vscode';
import { GitExtensionWrapper } from './git_extension_wrapper'; import { GitExtensionWrapper } from './git_extension_wrapper';
import { GitLabRemoteSourceProviderRepository } from '../gitlab/clone/gitlab_remote_source_provider_repository'; import { GitLabRemoteSourceProviderRepository } from '../gitlab/clone/gitlab_remote_source_provider_repository';
import { gitlabCredentialsProvider } from '../gitlab/clone/gitlab_credentials_provider'; import { gitlabCredentialsProvider } from '../gitlab/clone/gitlab_credentials_provider';
...@@ -12,20 +12,17 @@ describe('GitExtensionWrapper', () => { ...@@ -12,20 +12,17 @@ describe('GitExtensionWrapper', () => {
beforeEach(async () => { beforeEach(async () => {
fakeExtension = new FakeGitExtension(); fakeExtension = new FakeGitExtension();
(vscode.extensions.getExtension as jest.Mock).mockReturnValue({ exports: fakeExtension });
}); });
it('creates a new GitLabRemoteSourceProviderRepository', async () => { it('creates a new GitLabRemoteSourceProviderRepository', async () => {
// TODO: maybe introduce something like an initialize method instead of doing the work in constructor new GitExtensionWrapper().init();
// eslint-disable-next-line no-new
new GitExtensionWrapper((fakeExtension as unknown) as GitExtension);
expect(GitLabRemoteSourceProviderRepository).toHaveBeenCalledWith(fakeExtension.gitApi); expect(GitLabRemoteSourceProviderRepository).toHaveBeenCalledWith(fakeExtension.gitApi);
}); });
it('adds credentials provider to the Git Extension', async () => { it('adds credentials provider to the Git Extension', async () => {
// TODO: maybe introduce something like an initialize method instead of doing the work in constructor new GitExtensionWrapper().init();
// eslint-disable-next-line no-new
new GitExtensionWrapper((fakeExtension as unknown) as GitExtension);
expect(fakeExtension.gitApi.credentialsProviders).toEqual([gitlabCredentialsProvider]); expect(fakeExtension.gitApi.credentialsProviders).toEqual([gitlabCredentialsProvider]);
}); });
......
...@@ -3,56 +3,66 @@ ...@@ -3,56 +3,66 @@
* Licensed under the MIT License. See LICENSE in the project root for license information. * Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { extensions, Disposable } from 'vscode'; import * as assert from 'assert';
import { GitExtension } from '../api/git'; import * as vscode from 'vscode';
import { API, GitExtension } from '../api/git';
import { gitlabCredentialsProvider } from '../gitlab/clone/gitlab_credentials_provider'; import { gitlabCredentialsProvider } from '../gitlab/clone/gitlab_credentials_provider';
import { GitLabRemoteSourceProviderRepository } from '../gitlab/clone/gitlab_remote_source_provider_repository'; import { GitLabRemoteSourceProviderRepository } from '../gitlab/clone/gitlab_remote_source_provider_repository';
import { handleError, log } from '../log'; import { handleError, log } from '../log';
export class GitExtensionWrapper implements Disposable { export class GitExtensionWrapper implements vscode.Disposable {
disposables = new Set<Disposable>(); disposables = new Set<vscode.Disposable>();
constructor(private gitExtension: GitExtension) { private gitApi?: API;
this.disposables.add(
gitExtension.onDidChangeEnablement(this.onDidChangeGitExtensionEnablement, this), private gitExtension?: GitExtension;
);
this.onDidChangeGitExtensionEnablement(gitExtension.enabled);
}
private onDidChangeGitExtensionEnablement(enabled: boolean) { private onDidChangeGitExtensionEnablement(enabled: boolean) {
if (enabled) { if (enabled) {
this.initialize(); this.register();
} else { } else {
this.dispose(); this.dispose();
} }
} }
private initialize() { get gitBinaryPath(): string {
const path = this.gitApi?.git.path;
assert(path, 'Could not get git binary path from the Git extension.');
return path;
}
private register() {
assert(this.gitExtension);
try { try {
const gitAPI = this.gitExtension.getAPI(1); this.gitApi = this.gitExtension.getAPI(1);
this.disposables.add(new GitLabRemoteSourceProviderRepository(gitAPI)); this.disposables.add(new GitLabRemoteSourceProviderRepository(this.gitApi));
this.disposables.add(gitAPI.registerCredentialsProvider(gitlabCredentialsProvider)); this.disposables.add(this.gitApi.registerCredentialsProvider(gitlabCredentialsProvider));
} catch (err) { } catch (err) {
handleError(err); handleError(err);
} }
} }
dispose(): void { dispose(): void {
this.gitApi = undefined;
this.disposables.forEach(d => d?.dispose()); this.disposables.forEach(d => d?.dispose());
this.disposables.clear(); this.disposables.clear();
} }
static registerToGitExtension(): Disposable { init(): void {
try { try {
const gitExtension = extensions.getExtension<GitExtension>('vscode.git')?.exports; this.gitExtension = vscode.extensions.getExtension<GitExtension>('vscode.git')?.exports;
if (gitExtension !== undefined) { if (this.gitExtension !== undefined) {
return new GitExtensionWrapper(gitExtension); this.disposables.add(
this.gitExtension.onDidChangeEnablement(this.onDidChangeGitExtensionEnablement, this),
);
this.onDidChangeGitExtensionEnablement(this.gitExtension.enabled);
} }
log('Could not get Git Extension'); log('Could not get Git Extension');
} catch (error) { } catch (error) {
handleError(error); handleError(error);
} }
return { dispose: () => undefined };
} }
} }
export const gitExtensionWrapper = new GitExtensionWrapper();
...@@ -4,6 +4,7 @@ import { promises as fs } from 'fs'; ...@@ -4,6 +4,7 @@ import { promises as fs } from 'fs';
import * as path from 'path'; import * as path from 'path';
import simpleGit, { SimpleGit } from 'simple-git'; import simpleGit, { SimpleGit } from 'simple-git';
import { GitService, GitServiceOptions } from './git_service'; import { GitService, GitServiceOptions } from './git_service';
import { gitExtensionWrapper } from './git/git_extension_wrapper';
describe('git_service', () => { describe('git_service', () => {
const ORIGIN = 'origin'; const ORIGIN = 'origin';
...@@ -38,6 +39,7 @@ describe('git_service', () => { ...@@ -38,6 +39,7 @@ describe('git_service', () => {
(vscode.workspace.getConfiguration as jest.Mock).mockReturnValue({ (vscode.workspace.getConfiguration as jest.Mock).mockReturnValue({
instanceUrl: 'https://gitlab.com', instanceUrl: 'https://gitlab.com',
}); });
jest.spyOn(gitExtensionWrapper, 'gitBinaryPath', 'get').mockReturnValue('git');
}); });
afterEach(() => { afterEach(() => {
......
import * as execa from 'execa'; import * as execa from 'execa';
import { UserFriendlyError } from './errors/user_friendly_error'; import { UserFriendlyError } from './errors/user_friendly_error';
import { gitExtensionWrapper } from './git/git_extension_wrapper';
import { parseGitRemote, GitRemote } from './git/git_remote_parser'; import { parseGitRemote, GitRemote } from './git/git_remote_parser';
import { log } from './log'; import { log } from './log';
import { getInstanceUrl } from './utils/get_instance_url'; import { getInstanceUrl } from './utils/get_instance_url';
...@@ -20,8 +21,8 @@ export class GitService { ...@@ -20,8 +21,8 @@ export class GitService {
} }
private async fetch(cmd: string): Promise<string> { private async fetch(cmd: string): Promise<string> {
const [git, ...args] = cmd.trim().split(' '); const [, ...args] = cmd.trim().split(' ');
const { stdout } = await execa(git, args, { const { stdout } = await execa(gitExtensionWrapper.gitBinaryPath, args, {
cwd: this.workspaceFolder, cwd: this.workspaceFolder,
preferLocal: false, preferLocal: false,
}); });
......
...@@ -4,6 +4,7 @@ import simpleGit, { SimpleGit } from 'simple-git'; ...@@ -4,6 +4,7 @@ import simpleGit, { SimpleGit } from 'simple-git';
import { getInstanceUrl } from './get_instance_url'; import { getInstanceUrl } from './get_instance_url';
import { tokenService } from '../services/token_service'; import { tokenService } from '../services/token_service';
import { GITLAB_COM_URL } from '../constants'; import { GITLAB_COM_URL } from '../constants';
import { gitExtensionWrapper } from '../git/git_extension_wrapper';
describe('get_instance_url', () => { describe('get_instance_url', () => {
const ORIGIN = 'origin'; const ORIGIN = 'origin';
...@@ -22,6 +23,10 @@ describe('get_instance_url', () => { ...@@ -22,6 +23,10 @@ describe('get_instance_url', () => {
}); });
}); });
beforeEach(() => {
jest.spyOn(gitExtensionWrapper, 'gitBinaryPath', 'get').mockReturnValue('git');
});
it('returns configured instanceUrl if the config contains one', async () => { it('returns configured instanceUrl if the config contains one', async () => {
(vscode.workspace.getConfiguration as jest.Mock).mockReturnValue({ (vscode.workspace.getConfiguration as jest.Mock).mockReturnValue({
instanceUrl: 'https://test.com', instanceUrl: 'https://test.com',
......
...@@ -5,10 +5,11 @@ import { GITLAB_COM_URL } from '../constants'; ...@@ -5,10 +5,11 @@ import { GITLAB_COM_URL } from '../constants';
import { tokenService } from '../services/token_service'; import { tokenService } from '../services/token_service';
import { log } from '../log'; import { log } from '../log';
import { parseGitRemote } from '../git/git_remote_parser'; import { parseGitRemote } from '../git/git_remote_parser';
import { gitExtensionWrapper } from '../git/git_extension_wrapper';
async function fetch(cmd: string, workspaceFolder: string): Promise<string | null> { async function fetch(cmd: string, workspaceFolder: string): Promise<string | null> {
const [git, ...args] = cmd.trim().split(' '); const [, ...args] = cmd.trim().split(' ');
const { stdout } = await execa(git, args, { const { stdout } = await execa(gitExtensionWrapper.gitBinaryPath, args, {
cwd: workspaceFolder, cwd: workspaceFolder,
preferLocal: false, preferLocal: false,
}); });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册