diff --git a/CHANGELOG.md b/CHANGELOG.md index df01e13..cf9ba91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] +### Added +- Adds `gitlens.advanced.messages` setting to specify which messages should be suppressed + +### Changed +- Changes from using `globalState` to use `gitlens.advanced.messages` setting for message suppression - provides more control and avoids strange intermittent with `globalState` + ## [6.1.2] - 2017-11-21 ### Fixed - Fixes [#207](https://github.com/eamodio/vscode-gitlens/issues/207) - Applying and deleting stashes suddenly stopped working diff --git a/README.md b/README.md index 500fcb1..0b9036b 100644 --- a/README.md +++ b/README.md @@ -463,6 +463,7 @@ GitLens is highly customizable and provides many configuration settings to allow |`gitlens.advanced.git`|Specifies the git path to use |`gitlens.advanced.repositorySearchDepth`|Specifies how many folders deep to search for repositories |`gitlens.advanced.menus`|Specifies which commands will be added to which menus +|`gitlens.advanced.messages`|Specifies which messages should be suppressed |`gitlens.advanced.caching.enabled`|Specifies whether git output will be cached |`gitlens.advanced.caching.maxLines`|Specifies the threshold for caching larger documents |`gitlens.advanced.maxQuickHistory`|Specifies the maximum number of QuickPick history entries to show diff --git a/package.json b/package.json index e6a422e..440fa16 100644 --- a/package.json +++ b/package.json @@ -974,6 +974,55 @@ "description": "Specifies which commands will be added to which menus", "scope": "window" }, + "gitlens.advanced.messages": { + "type": "object", + "default": { + "suppressCommitHasNoPreviousCommitWarning": false, + "suppressCommitNotFoundWarning": false, + "suppressFileNotUnderSourceControlWarning": false, + "suppressGitVersionWarning": false, + "suppressLineUncommittedWarning": false, + "suppressNoRepositoryWarning": false, + "suppressUpdateNotice": false, + "suppressWelcomeNotice": false + }, + "properties": { + "suppressCommitHasNoPreviousCommitWarning": { + "type": "boolean", + "default": false + }, + "suppressCommitNotFoundWarning": { + "type": "boolean", + "default": false + }, + "suppressFileNotUnderSourceControlWarning": { + "type": "boolean", + "default": false + }, + "suppressGitVersionWarning": { + "type": "boolean", + "default": false + }, + "suppressLineUncommittedWarning": { + "type": "boolean", + "default": false + }, + "suppressNoRepositoryWarning": { + "type": "boolean", + "default": false + }, + "suppressUpdateNotice": { + "type": "boolean", + "default": false + }, + "suppressWelcomeNotice": { + "type": "boolean", + "default": false + } + }, + "description": "Specifies which messages should be suppressed", + "scope": "window" + }, "gitlens.advanced.quickPick.closeOnFocusOut": { "type": "boolean", "default": true, diff --git a/src/commands.ts b/src/commands.ts index bb5b3a8..bbe694c 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -87,7 +87,7 @@ export function configureCommands( context.subscriptions.push(new Commands.ToggleFileBlameCommand(annotationController)); context.subscriptions.push(new Commands.ToggleFileRecentChangesCommand(annotationController)); context.subscriptions.push(new Commands.ToggleLineBlameCommand(currentLineController)); - context.subscriptions.push(new Commands.ResetSuppressedWarningsCommand(context)); + context.subscriptions.push(new Commands.ResetSuppressedWarningsCommand()); context.subscriptions.push(new Commands.ShowLastQuickPickCommand()); context.subscriptions.push(new Commands.ShowQuickBranchHistoryCommand(git)); context.subscriptions.push(new Commands.ShowQuickCurrentBranchHistoryCommand(git)); diff --git a/src/commands/resetSuppressedWarnings.ts b/src/commands/resetSuppressedWarnings.ts index e438d83..30f8ddf 100644 --- a/src/commands/resetSuppressedWarnings.ts +++ b/src/commands/resetSuppressedWarnings.ts @@ -1,20 +1,15 @@ 'use strict'; -import { Objects } from '../system'; -import { ExtensionContext } from 'vscode'; +import { ConfigurationTarget } from 'vscode'; import { Command, Commands } from './common'; -import { SuppressedKeys } from '../messages'; +import { configuration } from '../configuration'; export class ResetSuppressedWarningsCommand extends Command { - constructor( - private readonly context: ExtensionContext - ) { + constructor() { super(Commands.ResetSuppressedWarnings); } async execute() { - for (const key of Objects.values(SuppressedKeys)) { - await this.context.globalState.update(key, undefined); - } + await configuration.update(configuration.name('advanced')('messages').value, undefined, ConfigurationTarget.Global); } } \ No newline at end of file diff --git a/src/configuration.ts b/src/configuration.ts index b9d63a7..656ab3d 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1,5 +1,5 @@ 'use strict'; -import { ConfigurationChangeEvent, Event, EventEmitter, ExtensionContext, Uri, workspace } from 'vscode'; +import { ConfigurationChangeEvent, ConfigurationTarget, Event, EventEmitter, ExtensionContext, Uri, workspace } from 'vscode'; import { FileAnnotationType } from './annotations/annotationController'; import { ExtensionKey } from './constants'; import { LineAnnotationType } from './currentLineController'; @@ -90,6 +90,16 @@ export interface IAdvancedConfig { remote: boolean; }; }; + messages: { + suppressCommitHasNoPreviousCommitWarning: boolean, + suppressCommitNotFoundWarning: boolean, + suppressFileNotUnderSourceControlWarning: boolean, + suppressGitVersionWarning: boolean, + suppressLineUncommittedWarning: boolean, + suppressNoRepositoryWarning: boolean, + suppressUpdateNotice: boolean, + suppressWelcomeNotice: boolean + }; quickPick: { closeOnFocusOut: boolean; }; @@ -363,45 +373,45 @@ const emptyConfig: IConfig = { file: { gutter: { format: '', - dateFormat: null, - compact: false, - heatmap: { + dateFormat: null, + compact: false, + heatmap: { enabled: false, - location: 'left' - }, - hover: { + location: 'left' + }, + hover: { details: false, - changes: false, - wholeLine: false - } + changes: false, + wholeLine: false + } }, - hover: { + hover: { details: false, - changes: false, - heatmap: { + changes: false, + heatmap: { enabled: false - } + } }, - recentChanges: { + recentChanges: { hover: { details: false, - changes: false - } + changes: false + } } }, - line: { + line: { hover: { details: false, - changes: false - }, - trailing: { + changes: false + }, + trailing: { format: '', - dateFormat: null, - hover: { + dateFormat: null, + hover: { details: false, - changes: false, - wholeLine: false - } + changes: false, + wholeLine: false + } } } }, @@ -472,9 +482,9 @@ const emptyConfig: IConfig = { codeLens: { unsavedChanges: { recentChangeAndAuthors: '', - recentChangeOnly: '', - authorsOnly: '' - } + recentChangeOnly: '', + authorsOnly: '' + } } }, theme: themeDefaults, @@ -484,16 +494,16 @@ const emptyConfig: IConfig = { advanced: { caching: { enabled: false, - maxLines: 0 - }, + maxLines: 0 + }, git: '', maxQuickHistory: 0, menus: { explorerContext: { fileDiff: false, - history: false, - remote: false - }, + history: false, + remote: false + }, editorContext: { blame: false, copy: false, @@ -516,6 +526,16 @@ const emptyConfig: IConfig = { remote: false } }, + messages: { + suppressCommitHasNoPreviousCommitWarning: false, + suppressCommitNotFoundWarning: false, + suppressFileNotUnderSourceControlWarning: false, + suppressGitVersionWarning: false, + suppressLineUncommittedWarning: false, + suppressNoRepositoryWarning: false, + suppressUpdateNotice: false, + suppressWelcomeNotice: false + }, quickPick: { closeOnFocusOut: false }, @@ -563,6 +583,10 @@ export class Configuration { name(name: K) { return Functions.propOf(emptyConfig, name); } + + update(section: string, value: any, target: ConfigurationTarget) { + return workspace.getConfiguration(ExtensionKey).update(section, value, target); + } } export const configuration = new Configuration(); \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 16a8290..9440782 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,8 @@ 'use strict'; -import { ExtensionContext, extensions, languages, window, workspace } from 'vscode'; +import { Objects } from './system'; +import { ConfigurationTarget, ExtensionContext, extensions, languages, window, workspace } from 'vscode'; import { AnnotationController } from './annotations/annotationController'; -import { Configuration, IConfig } from './configuration'; +import { configuration, Configuration, IConfig } from './configuration'; import { ApplicationInsightsKey, CommandContext, ExtensionKey, GlobalState, QualifiedExtensionId, setCommandContext } from './constants'; import { CodeLensController } from './codeLensController'; import { configureCommands } from './commands'; @@ -12,14 +13,13 @@ import { GitRevisionCodeLensProvider } from './gitRevisionCodeLensProvider'; import { GitContextTracker, GitService } from './gitService'; import { Keyboard } from './keyboard'; import { Logger } from './logger'; -import { Messages, SuppressedKeys } from './messages'; +import { Messages, SuppressedMessages } from './messages'; import { Telemetry } from './telemetry'; // this method is called when your extension is activated export async function activate(context: ExtensionContext) { Configuration.configure(context); Logger.configure(context); - Messages.configure(context); Telemetry.configure(ApplicationInsightsKey); const gitlens = extensions.getExtension(QualifiedExtensionId)!; @@ -49,8 +49,11 @@ export async function activate(context: ExtensionContext) { telemetryContext['git.version'] = gitVersion; Telemetry.setContext(telemetryContext); + const previousVersion = context.globalState.get(GlobalState.GitLensVersion); + + await migrateSettings(context, previousVersion); notifyOnUnsupportedGitVersion(context, gitVersion); - notifyOnNewGitLensVersion(context, gitlensVersion); + notifyOnNewGitLensVersion(context, gitlensVersion, previousVersion); await context.globalState.update(GlobalState.GitLensVersion, gitlensVersion); @@ -87,14 +90,50 @@ export async function activate(context: ExtensionContext) { // this method is called when your extension is deactivated export function deactivate() { } -async function notifyOnNewGitLensVersion(context: ExtensionContext, version: string) { - if (context.globalState.get(SuppressedKeys.UpdateNotice, false)) return; +const migration = { + major: 6, + minor: 1, + patch: 2 +}; - const previousVersion = context.globalState.get(GlobalState.GitLensVersion); +async function migrateSettings(context: ExtensionContext, previousVersion: string | undefined) { + if (previousVersion === undefined) return; + + const [major, minor, patch] = previousVersion.split('.'); + if (parseInt(major, 10) >= migration.major && parseInt(minor, 10) >= migration.minor && parseInt(patch, 10) >= migration.patch) return; + + try { + const section = configuration.name('advanced')('messages').value; + const messages: { [key: string]: boolean } = configuration.get(section); + + let migrated = false; + + for (const m of Objects.values(SuppressedMessages)) { + const suppressed = context.globalState.get(m); + if (suppressed === undefined) continue; + + migrated = true; + messages[m] = suppressed; + + context.globalState.update(m, undefined); + } + + if (!migrated) return; + + await configuration.update(section, messages, ConfigurationTarget.Global); + } + catch (ex) { + Logger.error(ex, 'migrateSettings'); + } +} + +async function notifyOnNewGitLensVersion(context: ExtensionContext, version: string, previousVersion: string | undefined) { + if (configuration.get(configuration.name('advanced')('messages')(SuppressedMessages.UpdateNotice).value)) return; if (previousVersion === undefined) { Logger.log(`GitLens first-time install`); await Messages.showWelcomeMessage(); + return; } diff --git a/src/messages.ts b/src/messages.ts index 04b46f0..3ff8432 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -1,10 +1,11 @@ 'use strict'; -import { commands, ExtensionContext, Uri, window } from 'vscode'; +import { commands, ConfigurationTarget, Uri, window } from 'vscode'; import { BuiltInCommands } from './constants'; import { GitCommit } from './gitService'; import { Logger } from './logger'; +import { configuration } from './configuration'; -export enum SuppressedKeys { +export enum SuppressedMessages { CommitHasNoPreviousCommitWarning = 'suppressCommitHasNoPreviousCommitWarning', CommitNotFoundWarning = 'suppressCommitNotFoundWarning', FileNotUnderSourceControlWarning = 'suppressFileNotUnderSourceControlWarning', @@ -17,40 +18,34 @@ export enum SuppressedKeys { export class Messages { - static context: ExtensionContext; - - static configure(context: ExtensionContext) { - this.context = context; - } - static showCommitHasNoPreviousCommitWarningMessage(commit?: GitCommit): Promise { - if (commit === undefined) return Messages.showMessage('info', `Commit has no previous commit`, SuppressedKeys.CommitHasNoPreviousCommitWarning); - return Messages.showMessage('info', `Commit ${commit.shortSha} (${commit.author}, ${commit.fromNow()}) has no previous commit`, SuppressedKeys.CommitHasNoPreviousCommitWarning); + if (commit === undefined) return Messages.showMessage('info', `Commit has no previous commit`, SuppressedMessages.CommitHasNoPreviousCommitWarning); + return Messages.showMessage('info', `Commit ${commit.shortSha} (${commit.author}, ${commit.fromNow()}) has no previous commit`, SuppressedMessages.CommitHasNoPreviousCommitWarning); } static showCommitNotFoundWarningMessage(message: string): Promise { - return Messages.showMessage('warn', `${message}. The commit could not be found`, SuppressedKeys.CommitNotFoundWarning); + return Messages.showMessage('warn', `${message}. The commit could not be found`, SuppressedMessages.CommitNotFoundWarning); } static showFileNotUnderSourceControlWarningMessage(message: string): Promise { - return Messages.showMessage('warn', `${message}. The file is probably not under source control`, SuppressedKeys.FileNotUnderSourceControlWarning); + return Messages.showMessage('warn', `${message}. The file is probably not under source control`, SuppressedMessages.FileNotUnderSourceControlWarning); } static showLineUncommittedWarningMessage(message: string): Promise { - return Messages.showMessage('warn', `${message}. The line has uncommitted changes`, SuppressedKeys.LineUncommittedWarning); + return Messages.showMessage('warn', `${message}. The line has uncommitted changes`, SuppressedMessages.LineUncommittedWarning); } static showNoRepositoryWarningMessage(message: string): Promise { - return Messages.showMessage('warn', `${message}. No repository could be found`, SuppressedKeys.NoRepositoryWarning); + return Messages.showMessage('warn', `${message}. No repository could be found`, SuppressedMessages.NoRepositoryWarning); } static showUnsupportedGitVersionErrorMessage(version: string): Promise { - return Messages.showMessage('error', `GitLens requires a newer version of Git (>= 2.2.0) than is currently installed (${version}). Please install a more recent version of Git.`, SuppressedKeys.GitVersionWarning); + return Messages.showMessage('error', `GitLens requires a newer version of Git (>= 2.2.0) than is currently installed (${version}). Please install a more recent version of Git.`, SuppressedMessages.GitVersionWarning); } static async showUpdateMessage(version: string): Promise { const viewReleaseNotes = 'View Release Notes'; - const result = await Messages.showMessage('info', `GitLens has been updated to v${version}`, SuppressedKeys.UpdateNotice, undefined, viewReleaseNotes); + const result = await Messages.showMessage('info', `GitLens has been updated to v${version}`, SuppressedMessages.UpdateNotice, undefined, viewReleaseNotes); if (result === viewReleaseNotes) { commands.executeCommand(BuiltInCommands.Open, Uri.parse('https://marketplace.visualstudio.com/items/eamodio.gitlens/changelog')); } @@ -59,17 +54,17 @@ export class Messages { static async showWelcomeMessage(): Promise { const viewDocs = 'View Docs'; - const result = await Messages.showMessage('info', `Thank you for choosing GitLens! GitLens is powerful, feature rich, and highly configurable, so please be sure to view the docs and tailor it to suit your needs.`, SuppressedKeys.WelcomeNotice, null, viewDocs); + const result = await Messages.showMessage('info', `Thank you for choosing GitLens! GitLens is powerful, feature rich, and highly configurable, so please be sure to view the docs and tailor it to suit your needs.`, SuppressedMessages.WelcomeNotice, null, viewDocs); if (result === viewDocs) { commands.executeCommand(BuiltInCommands.Open, Uri.parse('https://marketplace.visualstudio.com/items/eamodio.gitlens')); } return result; } - private static async showMessage(type: 'info' | 'warn' | 'error', message: string, suppressionKey: SuppressedKeys, dontShowAgain: string | null = 'Don\'t Show Again', ...actions: any[]): Promise { + private static async showMessage(type: 'info' | 'warn' | 'error', message: string, suppressionKey: SuppressedMessages, dontShowAgain: string | null = 'Don\'t Show Again', ...actions: any[]): Promise { Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain})`); - if (Messages.context.globalState.get(suppressionKey, false)) { + if (configuration.get(configuration.name('advanced')('messages')(suppressionKey).value)) { Logger.log(`ShowMessage(${type}, ${message}, ${suppressionKey}, ${dontShowAgain}) skipped`); return undefined; } @@ -95,7 +90,11 @@ export class Messages { if (dontShowAgain === null || result === dontShowAgain) { Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) don't show again requested`); - await Messages.context.globalState.update(suppressionKey, true); + + const section = configuration.name('advanced')('messages').value; + const messages: { [key: string]: boolean } = configuration.get(section); + messages[suppressionKey] = true; + await configuration.update(section, messages, ConfigurationTarget.Global); if (result === dontShowAgain) return undefined; } diff --git a/src/views/explorerCommands.ts b/src/views/explorerCommands.ts index f49b779..845611a 100644 --- a/src/views/explorerCommands.ts +++ b/src/views/explorerCommands.ts @@ -1,6 +1,6 @@ import { Arrays } from '../system'; -import { commands, Disposable, InputBoxOptions, Terminal, TextDocumentShowOptions, Uri, window, workspace } from 'vscode'; -import { ExtensionKey, ExtensionTerminalName } from '../constants'; +import { commands, ConfigurationTarget, Disposable, InputBoxOptions, Terminal, TextDocumentShowOptions, Uri, window } from 'vscode'; +import { ExtensionTerminalName } from '../constants'; import { BranchHistoryNode, ExplorerNode, GitExplorer, GitExplorerView } from '../views/gitExplorer'; import { configuration, GitExplorerFilesLayout } from '../configuration'; import { CommitFileNode, CommitNode, RemoteNode, StashNode, StatusUpstreamNode } from './explorerNodes'; @@ -136,7 +136,7 @@ export class ExplorerCommands extends Disposable { } private async setFilesLayout(layout: GitExplorerFilesLayout) { - return workspace.getConfiguration(ExtensionKey).update(configuration.name('gitExplorer')('files')('layout').value, layout, true); + return configuration.update(configuration.name('gitExplorer')('files')('layout').value, layout, ConfigurationTarget.Global); } async terminalCheckoutBranch(node: ExplorerNode) {