Skip to content

Commit

Permalink
Refactored all Git & Visual Studio Code version requirements, and Git…
Browse files Browse the repository at this point in the history
… config keys, to use enums.
  • Loading branch information
mhutchie committed Apr 17, 2021
1 parent b9112e6 commit 77cdae7
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 92 deletions.
4 changes: 2 additions & 2 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { CodeReviewData, CodeReviews, ExtensionState } from './extensionState';
import { GitGraphView } from './gitGraphView';
import { Logger } from './logger';
import { RepoManager } from './repoManager';
import { GitExecutable, UNABLE_TO_FIND_GIT_MSG, abbrevCommit, abbrevText, copyToClipboard, doesVersionMeetRequirement, getExtensionVersion, getPathFromUri, getRelativeTimeDiff, getRepoName, getSortedRepositoryPaths, isPathInWorkspace, openFile, resolveToSymbolicPath, showErrorMessage, showInformationMessage } from './utils';
import { GitExecutable, UNABLE_TO_FIND_GIT_MSG, VsCodeVersionRequirement, abbrevCommit, abbrevText, copyToClipboard, doesVersionMeetRequirement, getExtensionVersion, getPathFromUri, getRelativeTimeDiff, getRepoName, getSortedRepositoryPaths, isPathInWorkspace, openFile, resolveToSymbolicPath, showErrorMessage, showInformationMessage } from './utils';
import { Disposable } from './utils/disposable';
import { Event } from './utils/event';

Expand Down Expand Up @@ -65,7 +65,7 @@ export class CommandManager extends Disposable {

// Register Extension Contexts
try {
this.registerContext('git-graph:codiconsSupported', doesVersionMeetRequirement(vscode.version, '1.42.0'));
this.registerContext('git-graph:codiconsSupported', doesVersionMeetRequirement(vscode.version, VsCodeVersionRequirement.Codicons));
} catch (_) {
this.logger.logError('Unable to set Visual Studio Code Context "git-graph:codiconsSupported"');
}
Expand Down
66 changes: 30 additions & 36 deletions src/dataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { AskpassEnvironment, AskpassManager } from './askpass/askpassManager';
import { getConfig } from './config';
import { Logger } from './logger';
import { CommitOrdering, DateType, DeepWriteable, ErrorInfo, GitCommit, GitCommitDetails, GitCommitStash, GitConfigLocation, GitFileChange, GitFileStatus, GitPushBranchMode, GitRepoConfig, GitRepoConfigBranches, GitResetMode, GitSignature, GitSignatureStatus, GitStash, GitTagDetails, MergeActionOn, RebaseActionOn, SquashMessageFormat, TagType, Writeable } from './types';
import { GitExecutable, UNABLE_TO_FIND_GIT_MSG, UNCOMMITTED, abbrevCommit, constructIncompatibleGitVersionMessage, doesVersionMeetRequirement, getPathFromStr, getPathFromUri, openGitTerminal, pathWithTrailingSlash, realpath, resolveSpawnOutput, showErrorMessage } from './utils';
import { GitExecutable, GitVersionRequirement, UNABLE_TO_FIND_GIT_MSG, UNCOMMITTED, abbrevCommit, constructIncompatibleGitVersionMessage, doesVersionMeetRequirement, getPathFromStr, getPathFromUri, openGitTerminal, pathWithTrailingSlash, realpath, resolveSpawnOutput, showErrorMessage } from './utils';
import { Disposable } from './utils/disposable';
import { Event } from './utils/event';

Expand All @@ -17,21 +17,15 @@ const INVALID_BRANCH_REGEXP = /^\(.* .*\)$/;
const REMOTE_HEAD_BRANCH_REGEXP = /^remotes\/.*\/HEAD$/;
const GIT_LOG_SEPARATOR = 'XX7Nal-YARtTpjCikii9nJxER19D6diSyk-AWkPb';

export const GIT_CONFIG = {
DIFF: {
GUI_TOOL: 'diff.guitool',
TOOL: 'diff.tool'
},
REMOTE: {
PUSH_DEFAULT: 'remote.pushdefault'
},
USER: {
EMAIL: 'user.email',
NAME: 'user.name'
}
};
export const enum GitConfigKey {
DiffGuiTool = 'diff.guitool',
DiffTool = 'diff.tool',
RemotePushDefault = 'remote.pushdefault',
UserEmail = 'user.email',
UserName = 'user.name'
}

const GPG_STATUS_CODE_PARSING_DETAILS: { [statusCode: string]: GpgStatusCodeParsingDetails } = {
const GPG_STATUS_CODE_PARSING_DETAILS: Readonly<{ [statusCode: string]: GpgStatusCodeParsingDetails }> = {
'GOODSIG': { status: GitSignatureStatus.GoodAndValid, uid: true },
'BADSIG': { status: GitSignatureStatus.Bad, uid: true },
'ERRSIG': { status: GitSignatureStatus.CannotBeChecked, uid: false },
Expand Down Expand Up @@ -95,9 +89,9 @@ export class DataSource extends Disposable {
* Set the Git executable used by the DataSource.
* @param gitExecutable The Git executable.
*/
public setGitExecutable(gitExecutable: GitExecutable | null) {
private setGitExecutable(gitExecutable: GitExecutable | null) {
this.gitExecutable = gitExecutable;
this.gitExecutableSupportsGpgInfo = gitExecutable !== null ? doesVersionMeetRequirement(gitExecutable.version, '2.4.0') : false;
this.gitExecutableSupportsGpgInfo = gitExecutable !== null && doesVersionMeetRequirement(gitExecutable.version, GitVersionRequirement.GpgInfo);
this.generateGitCommandFormats();
}

Expand Down Expand Up @@ -314,22 +308,22 @@ export class DataSource extends Disposable {
return {
config: {
branches: branches,
diffTool: getConfigValue(consolidatedConfigs, GIT_CONFIG.DIFF.TOOL),
guiDiffTool: getConfigValue(consolidatedConfigs, GIT_CONFIG.DIFF.GUI_TOOL),
pushDefault: getConfigValue(consolidatedConfigs, GIT_CONFIG.REMOTE.PUSH_DEFAULT),
diffTool: getConfigValue(consolidatedConfigs, GitConfigKey.DiffTool),
guiDiffTool: getConfigValue(consolidatedConfigs, GitConfigKey.DiffGuiTool),
pushDefault: getConfigValue(consolidatedConfigs, GitConfigKey.RemotePushDefault),
remotes: remotes.map((remote) => ({
name: remote,
url: getConfigValue(localConfigs, 'remote.' + remote + '.url'),
pushUrl: getConfigValue(localConfigs, 'remote.' + remote + '.pushurl')
})),
user: {
name: {
local: getConfigValue(localConfigs, GIT_CONFIG.USER.NAME),
global: getConfigValue(globalConfigs, GIT_CONFIG.USER.NAME)
local: getConfigValue(localConfigs, GitConfigKey.UserName),
global: getConfigValue(globalConfigs, GitConfigKey.UserName)
},
email: {
local: getConfigValue(localConfigs, GIT_CONFIG.USER.EMAIL),
global: getConfigValue(globalConfigs, GIT_CONFIG.USER.EMAIL)
local: getConfigValue(localConfigs, GitConfigKey.UserEmail),
global: getConfigValue(globalConfigs, GitConfigKey.UserEmail)
}
}
},
Expand Down Expand Up @@ -503,8 +497,8 @@ export class DataSource extends Disposable {
* @returns The tag details.
*/
public getTagDetails(repo: string, tagName: string): Promise<GitTagDetailsData> {
if (this.gitExecutable !== null && !doesVersionMeetRequirement(this.gitExecutable.version, '1.7.8')) {
return Promise.resolve({ details: null, error: constructIncompatibleGitVersionMessage(this.gitExecutable, '1.7.8', 'retrieving Tag Details') });
if (this.gitExecutable !== null && !doesVersionMeetRequirement(this.gitExecutable.version, GitVersionRequirement.TagDetails)) {
return Promise.resolve({ details: null, error: constructIncompatibleGitVersionMessage(this.gitExecutable, GitVersionRequirement.TagDetails, 'retrieving Tag Details') });
}

const ref = 'refs/tags/' + tagName;
Expand Down Expand Up @@ -758,8 +752,8 @@ export class DataSource extends Disposable {
if (pruneTags) {
if (!prune) {
return Promise.resolve('In order to Prune Tags, pruning must also be enabled when fetching from ' + (remote !== null ? 'a remote' : 'remote(s)') + '.');
} else if (this.gitExecutable !== null && !doesVersionMeetRequirement(this.gitExecutable.version, '2.17.0')) {
return Promise.resolve(constructIncompatibleGitVersionMessage(this.gitExecutable, '2.17.0', 'pruning tags when fetching'));
} else if (this.gitExecutable !== null && !doesVersionMeetRequirement(this.gitExecutable.version, GitVersionRequirement.FetchAndPruneTags)) {
return Promise.resolve(constructIncompatibleGitVersionMessage(this.gitExecutable, GitVersionRequirement.FetchAndPruneTags, 'pruning tags when fetching'));
}
args.push('--prune-tags');
}
Expand Down Expand Up @@ -1139,23 +1133,23 @@ export class DataSource extends Disposable {
/**
* Set a configuration value for a repository.
* @param repo The path of the repository.
* @param key The key to be set.
* @param key The Git Config Key to be set.
* @param value The value to be set.
* @param location The location where the configuration value should be set.
* @returns The ErrorInfo from the executed command.
*/
public setConfigValue(repo: string, key: string, value: string, location: GitConfigLocation) {
public setConfigValue(repo: string, key: GitConfigKey, value: string, location: GitConfigLocation) {
return this.runGitCommand(['config', '--' + location, key, value], repo);
}

/**
* Unset a configuration value for a repository.
* @param repo The path of the repository.
* @param key The key to be unset.
* @param key The Git Config Key to be unset.
* @param location The location where the configuration value should be unset.
* @returns The ErrorInfo from the executed command.
*/
public unsetConfigValue(repo: string, key: string, location: GitConfigLocation) {
public unsetConfigValue(repo: string, key: GitConfigKey, location: GitConfigLocation) {
return this.runGitCommand(['config', '--' + location, '--unset-all', key], repo);
}

Expand Down Expand Up @@ -1236,8 +1230,8 @@ export class DataSource extends Disposable {
public pushStash(repo: string, message: string, includeUntracked: boolean): Promise<ErrorInfo> {
if (this.gitExecutable === null) {
return Promise.resolve(UNABLE_TO_FIND_GIT_MSG);
} else if (!doesVersionMeetRequirement(this.gitExecutable.version, '2.13.2')) {
return Promise.resolve(constructIncompatibleGitVersionMessage(this.gitExecutable, '2.13.2'));
} else if (!doesVersionMeetRequirement(this.gitExecutable.version, GitVersionRequirement.PushStash)) {
return Promise.resolve(constructIncompatibleGitVersionMessage(this.gitExecutable, GitVersionRequirement.PushStash));
}

let args = ['stash', 'push'];
Expand Down Expand Up @@ -1994,6 +1988,6 @@ interface GitTagDetailsData {
}

interface GpgStatusCodeParsingDetails {
status: GitSignatureStatus,
uid: boolean
readonly status: GitSignatureStatus,
readonly uid: boolean
}
14 changes: 7 additions & 7 deletions src/gitGraphView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as path from 'path';
import * as vscode from 'vscode';
import { AvatarManager } from './avatarManager';
import { getConfig } from './config';
import { DataSource, GIT_CONFIG, GitCommitDetailsData } from './dataSource';
import { DataSource, GitCommitDetailsData, GitConfigKey } from './dataSource';
import { ExtensionState } from './extensionState';
import { Logger } from './logger';
import { RepoFileWatcher } from './repoFileWatcher';
Expand Down Expand Up @@ -325,10 +325,10 @@ export class GitGraphView extends Disposable {
case 'deleteUserDetails':
errorInfos = [];
if (msg.name) {
errorInfos.push(await this.dataSource.unsetConfigValue(msg.repo, GIT_CONFIG.USER.NAME, msg.location));
errorInfos.push(await this.dataSource.unsetConfigValue(msg.repo, GitConfigKey.UserName, msg.location));
}
if (msg.email) {
errorInfos.push(await this.dataSource.unsetConfigValue(msg.repo, GIT_CONFIG.USER.EMAIL, msg.location));
errorInfos.push(await this.dataSource.unsetConfigValue(msg.repo, GitConfigKey.UserEmail, msg.location));
}
this.sendMessage({
command: 'deleteUserDetails',
Expand All @@ -355,15 +355,15 @@ export class GitGraphView extends Disposable {
break;
case 'editUserDetails':
errorInfos = [
await this.dataSource.setConfigValue(msg.repo, GIT_CONFIG.USER.NAME, msg.name, msg.location),
await this.dataSource.setConfigValue(msg.repo, GIT_CONFIG.USER.EMAIL, msg.email, msg.location)
await this.dataSource.setConfigValue(msg.repo, GitConfigKey.UserName, msg.name, msg.location),
await this.dataSource.setConfigValue(msg.repo, GitConfigKey.UserEmail, msg.email, msg.location)
];
if (errorInfos[0] === null && errorInfos[1] === null) {
if (msg.deleteLocalName) {
errorInfos.push(await this.dataSource.unsetConfigValue(msg.repo, GIT_CONFIG.USER.NAME, GitConfigLocation.Local));
errorInfos.push(await this.dataSource.unsetConfigValue(msg.repo, GitConfigKey.UserName, GitConfigLocation.Local));
}
if (msg.deleteLocalEmail) {
errorInfos.push(await this.dataSource.unsetConfigValue(msg.repo, GIT_CONFIG.USER.EMAIL, GitConfigLocation.Local));
errorInfos.push(await this.dataSource.unsetConfigValue(msg.repo, GitConfigKey.UserEmail, GitConfigLocation.Local));
}
}
this.sendMessage({
Expand Down
19 changes: 15 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,15 +772,26 @@ export async function getGitExecutableFromPaths(paths: string[]): Promise<GitExe
}


/* Version Handling */
/* Version Handling / Requirements */

export const enum GitVersionRequirement {
FetchAndPruneTags = '2.17.0',
GpgInfo = '2.4.0',
PushStash = '2.13.2',
TagDetails = '1.7.8'
}

export const enum VsCodeVersionRequirement {
Codicons = '1.42.0'
}

/**
* Checks whether a version is at least a required version.
* @param version The version to check.
* @param requiredVersion The minimum required version.
* @returns TRUE => `version` is at least `requiredVersion`, FALSE => `version` is older than `requiredVersion`.
*/
export function doesVersionMeetRequirement(version: string, requiredVersion: string) {
export function doesVersionMeetRequirement(version: string, requiredVersion: GitVersionRequirement | VsCodeVersionRequirement) {
const v1 = parseVersion(version);
const v2 = parseVersion(requiredVersion);

Expand Down Expand Up @@ -824,10 +835,10 @@ function parseVersion(version: string) {
/**
* Construct a message that explains to the user that the Git executable is not compatible with a feature.
* @param executable The Git executable.
* @param version The minimum required version number.
* @param version The minimum required version.
* @param feature An optional name for the feature.
* @returns The message for the user.
*/
export function constructIncompatibleGitVersionMessage(executable: GitExecutable, version: string, feature?: string) {
export function constructIncompatibleGitVersionMessage(executable: GitExecutable, version: GitVersionRequirement, feature?: string) {
return 'A newer version of Git (>= ' + version + ') is required for ' + (feature ? feature : 'this feature') + '. Git ' + executable.version + ' is currently installed. Please install a newer version of Git to use this feature.';
}
Loading

0 comments on commit 77cdae7

Please sign in to comment.