diff --git a/src/commands/common.ts b/src/commands/common.ts index ca0d4fc..bbce656 100644 --- a/src/commands/common.ts +++ b/src/commands/common.ts @@ -139,14 +139,13 @@ export abstract class Command extends Disposable { constructor(command: Commands | Commands[]) { super(() => this.dispose()); - if (!Array.isArray(command)) { - command = [command]; - } + if (typeof command === 'string') { + this._disposable = commands.registerCommand(command, (...args: any[]) => this._execute(command, ...args), this); - const subscriptions = []; - for (const cmd of command) { - subscriptions.push(commands.registerCommand(cmd, (...args: any[]) => this._execute(cmd, ...args), this)); + return; } + + const subscriptions = command.map(cmd => commands.registerCommand(cmd, (...args: any[]) => this._execute(cmd, ...args), this)); this._disposable = Disposable.from(...subscriptions); } diff --git a/src/commands/showFileBlame.ts b/src/commands/showFileBlame.ts index b8c8a23..2c606b2 100644 --- a/src/commands/showFileBlame.ts +++ b/src/commands/showFileBlame.ts @@ -1,8 +1,8 @@ 'use strict'; -import { TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode'; +import { TextEditor, TextEditorEdit, Uri, window } from 'vscode'; import { AnnotationController, FileAnnotationType } from '../annotations/annotationController'; import { Commands, EditorCommand } from './common'; -import { ExtensionKey, IConfig } from '../configuration'; +import { configuration } from '../configuration'; import { Logger } from '../logger'; export interface ShowFileBlameCommandArgs { @@ -23,13 +23,10 @@ export class ShowFileBlameCommand extends EditorCommand { try { if (args.type === undefined) { - args = { ...args }; - - const cfg = workspace.getConfiguration().get(ExtensionKey)!; - args.type = cfg.blame.file.annotationType; + args = { ...args, type: configuration.get(configuration.name('blame')('file')('annotationType').value) }; } - return this.annotationController.showAnnotations(editor, args.type, args.sha !== undefined ? args.sha : editor.selection.active.line); + return this.annotationController.showAnnotations(editor, args.type!, args.sha !== undefined ? args.sha : editor.selection.active.line); } catch (ex) { Logger.error(ex, 'ShowFileBlameCommand'); diff --git a/src/commands/showLineBlame.ts b/src/commands/showLineBlame.ts index a8c0a2b..fc2d299 100644 --- a/src/commands/showLineBlame.ts +++ b/src/commands/showLineBlame.ts @@ -1,8 +1,8 @@ 'use strict'; -import { TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode'; +import { TextEditor, TextEditorEdit, Uri, window } from 'vscode'; import { CurrentLineController, LineAnnotationType } from '../currentLineController'; import { Commands, EditorCommand } from './common'; -import { ExtensionKey, IConfig } from '../configuration'; +import { configuration } from '../configuration'; import { Logger } from '../logger'; export interface ShowLineBlameCommandArgs { @@ -22,13 +22,10 @@ export class ShowLineBlameCommand extends EditorCommand { try { if (args.type === undefined) { - args = { ...args }; - - const cfg = workspace.getConfiguration().get(ExtensionKey)!; - args.type = cfg.blame.line.annotationType; + args = { ...args, type: configuration.get(configuration.name('blame')('line')('annotationType').value) }; } - return this.currentLineController.showAnnotations(editor, args.type); + return this.currentLineController.showAnnotations(editor, args.type!); } catch (ex) { Logger.error(ex, 'ShowLineBlameCommand'); diff --git a/src/commands/toggleFileBlame.ts b/src/commands/toggleFileBlame.ts index 830dfae..67a47a3 100644 --- a/src/commands/toggleFileBlame.ts +++ b/src/commands/toggleFileBlame.ts @@ -1,9 +1,9 @@ 'use strict'; -import { TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode'; +import { TextEditor, TextEditorEdit, Uri, window } from 'vscode'; import { AnnotationController, FileAnnotationType } from '../annotations/annotationController'; import { Commands, EditorCommand } from './common'; import { UriComparer } from '../comparers'; -import { ExtensionKey, IConfig } from '../configuration'; +import { configuration } from '../configuration'; import { Logger } from '../logger'; export interface ToggleFileBlameCommandArgs { @@ -32,13 +32,10 @@ export class ToggleFileBlameCommand extends EditorCommand { try { if (args.type === undefined) { - args = { ...args }; - - const cfg = workspace.getConfiguration().get(ExtensionKey)!; - args.type = cfg.blame.file.annotationType; + args = { ...args, type: configuration.get(configuration.name('blame')('file')('annotationType').value) }; } - return this.annotationController.toggleAnnotations(editor, args.type, args.sha !== undefined ? args.sha : editor.selection.active.line); + return this.annotationController.toggleAnnotations(editor, args.type!, args.sha !== undefined ? args.sha : editor.selection.active.line); } catch (ex) { Logger.error(ex, 'ToggleFileBlameCommand'); diff --git a/src/commands/toggleLineBlame.ts b/src/commands/toggleLineBlame.ts index 1926c10..7de6deb 100644 --- a/src/commands/toggleLineBlame.ts +++ b/src/commands/toggleLineBlame.ts @@ -1,8 +1,8 @@ 'use strict'; -import { TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode'; +import { TextEditor, TextEditorEdit, Uri, window } from 'vscode'; import { CurrentLineController, LineAnnotationType } from '../currentLineController'; import { Commands, EditorCommand } from './common'; -import { ExtensionKey, IConfig } from '../configuration'; +import { configuration } from '../configuration'; import { Logger } from '../logger'; export interface ToggleLineBlameCommandArgs { @@ -22,13 +22,10 @@ export class ToggleLineBlameCommand extends EditorCommand { try { if (args.type === undefined) { - args = { ...args }; - - const cfg = workspace.getConfiguration().get(ExtensionKey)!; - args.type = cfg.blame.line.annotationType; + args = { ...args, type: configuration.get(configuration.name('blame')('line')('annotationType').value) }; } - return this.currentLineController.toggleAnnotations(editor, args.type); + return this.currentLineController.toggleAnnotations(editor, args.type!); } catch (ex) { Logger.error(ex, 'ToggleLineBlameCommand'); diff --git a/src/configuration.ts b/src/configuration.ts index f78448a..e3dbf05 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1,11 +1,11 @@ 'use strict'; +import { Functions } from './system'; import { ConfigurationChangeEvent, ConfigurationTarget, Event, EventEmitter, ExtensionContext, Uri, workspace } from 'vscode'; import { FileAnnotationType } from './annotations/annotationController'; import { ExtensionKey } from './constants'; import { LineAnnotationType } from './currentLineController'; import { GitExplorerView } from './views/gitExplorer'; import { OutputLevel } from './logger'; -import { Functions } from './system'; export { ExtensionKey }; diff --git a/src/extension.ts b/src/extension.ts index 8576e6b..8cc2f2e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -20,31 +20,31 @@ import { Telemetry } from './telemetry'; // this method is called when your extension is activated export async function activate(context: ExtensionContext) { - Configuration.configure(context); + const start = process.hrtime(); + Logger.configure(context); - Telemetry.configure(ApplicationInsightsKey); + Configuration.configure(context); const gitlens = extensions.getExtension(QualifiedExtensionId)!; const gitlensVersion = gitlens.packageJSON.version; - Logger.log(`GitLens(v${gitlensVersion}) active`); - - const cfg = workspace.getConfiguration().get(ExtensionKey)!; + const cfg = configuration.get(); try { await GitService.initialize(cfg.advanced.git); } catch (ex) { - Logger.error(ex, 'Extension.activate'); + Logger.error(ex, `GitLens(v${gitlensVersion}).activate`); if (ex.message.includes('Unable to find git')) { - await window.showErrorMessage(`GitLens was unable to find Git. Please make sure Git is installed. Also ensure that Git is either in the PATH, or that 'gitlens.advanced.git' is pointed to its installed location.`); + await window.showErrorMessage(`GitLens was unable to find Git. Please make sure Git is installed. Also ensure that Git is either in the PATH, or that '${ExtensionKey}.${configuration.name('advanced')('git').value}' is pointed to its installed location.`); } setCommandContext(CommandContext.Enabled, false); return; } const gitVersion = GitService.getGitVersion(); - Logger.log(`Git version: ${gitVersion}`); + + Telemetry.configure(ApplicationInsightsKey); const telemetryContext: { [id: string]: any } = Object.create(null); telemetryContext.version = gitlensVersion; @@ -57,7 +57,7 @@ export async function activate(context: ExtensionContext) { notifyOnUnsupportedGitVersion(context, gitVersion); notifyOnNewGitLensVersion(context, gitlensVersion, previousVersion); - await context.globalState.update(GlobalState.GitLensVersion, gitlensVersion); + context.globalState.update(GlobalState.GitLensVersion, gitlensVersion); const git = new GitService(); context.subscriptions.push(git); @@ -94,6 +94,9 @@ export async function activate(context: ExtensionContext) { // Slightly delay enabling the explorer to not stop the rest of GitLens from being usable setTimeout(() => setCommandContext(CommandContext.GitExplorer, true), 1000); + + const duration = process.hrtime(start); + Logger.log(`GitLens(v${gitlensVersion}) activated in ${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms`); } // this method is called when your extension is deactivated diff --git a/src/git/git.ts b/src/git/git.ts index df8a8ca..1531f45 100644 --- a/src/git/git.ts +++ b/src/git/git.ts @@ -137,8 +137,13 @@ export class Git { } static async getGitInfo(gitPath?: string): Promise { + const start = process.hrtime(); + git = await findGitPath(gitPath); - Logger.log(`Git found: ${git.version} @ ${git.path === 'git' ? 'PATH' : git.path}`); + + const duration = process.hrtime(start); + Logger.log(`Git found: ${git.version} @ ${git.path === 'git' ? 'PATH' : git.path} in ${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms`); + return git; } diff --git a/src/gitService.ts b/src/gitService.ts index d83a4ed..6d7da36 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -122,6 +122,7 @@ export class GitService extends Disposable { configuration.onDidChange(this.onConfigurationChanged, this) ); this.onConfigurationChanged(configuration.initializingChangeEvent); + this._repositoriesLoadingPromise = this.onWorkspaceFoldersChanged(); } @@ -276,7 +277,6 @@ export class GitService extends Disposable { const anyRepoChangedFn = this.onAnyRepositoryChanged.bind(this); const rootPath = await this.getRepoPathCore(folderUri.fsPath, true); - await this.getRepoPathCore(folderUri.fsPath, true); if (rootPath !== undefined) { repositories.push(new Repository(folder, rootPath, true, this, anyRepoChangedFn, this._suspended)); } @@ -306,13 +306,17 @@ export class GitService extends Disposable { const paths = await this.repositorySearchCore(folderUri.fsPath, depth, excludes); const duration = process.hrtime(start); - Logger.log(`${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms to search (depth=${depth}) for repositories in ${folderUri.fsPath}`); + Logger.log(`Searching (depth=${depth}) for repositories in ${folderUri.fsPath} took ${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms`); - for (const p of paths) { - const rp = await this.getRepoPathCore(path.dirname(p), true); - if (rp !== undefined && rp !== rootPath) { - repositories.push(new Repository(folder, rp, false, this, anyRepoChangedFn, this._suspended)); - } + for (let p of paths) { + p = path.dirname(p); + // If we are the same as the root, skip it + if (Git.normalizePath(p) === rootPath) continue; + + const rp = await this.getRepoPathCore(p, true); + if (rp === undefined) continue; + + repositories.push(new Repository(folder, rp, false, this, anyRepoChangedFn, this._suspended)); } // const uris = await workspace.findFiles(new RelativePattern(folder, '**/.git/HEAD')); diff --git a/src/keyboard.ts b/src/keyboard.ts index fed5446..7a19b12 100644 --- a/src/keyboard.ts +++ b/src/keyboard.ts @@ -101,10 +101,10 @@ export class Keyboard extends Disposable { constructor() { super(() => this.dispose()); + _instance = this; + const subscriptions = keys.map(key => commands.registerCommand(`${ExtensionKey}.key.${key}`, () => this.execute(key), this)); this._disposable = Disposable.from(...subscriptions); - - _instance = this; } dispose() { diff --git a/src/quickPicks/common.ts b/src/quickPicks/common.ts index ec759fd..56ae375 100644 --- a/src/quickPicks/common.ts +++ b/src/quickPicks/common.ts @@ -1,8 +1,8 @@ 'use strict'; import { Strings } from '../system'; -import { CancellationTokenSource, commands, Disposable, QuickPickItem, QuickPickOptions, TextDocumentShowOptions, TextEditor, Uri, window, workspace } from 'vscode'; +import { CancellationTokenSource, commands, Disposable, QuickPickItem, QuickPickOptions, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; import { Commands, openEditor } from '../commands'; -import { ExtensionKey, IAdvancedConfig } from '../configuration'; +import { configuration } from '../configuration'; import { GlyphChars } from '../constants'; import { GitLog, GitLogCommit, GitStashCommit } from '../gitService'; import { Keyboard, KeyboardScope, KeyMapping, Keys } from '../keyboard'; @@ -10,8 +10,7 @@ import { ResultsExplorer } from '../views/resultsExplorer'; // import { Logger } from '../logger'; export function getQuickPickIgnoreFocusOut() { - const cfg = workspace.getConfiguration(ExtensionKey).get('advanced')!; - return !cfg.quickPick.closeOnFocusOut; + return configuration.get(configuration.name('advanced')('quickPick')('closeOnFocusOut').value); } export function showQuickPickProgress(message: string, mapping?: KeyMapping, delay: boolean = false): CancellationTokenSource { diff --git a/src/telemetry.ts b/src/telemetry.ts index 0386a20..fcdd9bb 100644 --- a/src/telemetry.ts +++ b/src/telemetry.ts @@ -1,6 +1,7 @@ 'use strict'; import { Disposable, env, version, workspace } from 'vscode'; -import { ExtensionKey, IConfig } from './configuration'; +import { configuration } from './configuration'; +import { Logger } from './logger'; import * as os from 'os'; let _reporter: TelemetryReporter; @@ -8,10 +9,17 @@ let _reporter: TelemetryReporter; export class Telemetry extends Disposable { static configure(key: string) { - const cfg = workspace.getConfiguration().get(ExtensionKey)!; - if (!cfg.advanced.telemetry.enabled || !workspace.getConfiguration('telemetry').get('enableTelemetry', true)) return; + if (!configuration.get(configuration.name('advanced')('telemetry')('enabled').value) || + !workspace.getConfiguration('telemetry').get('enableTelemetry', true)) { + return; + } + + const start = process.hrtime(); _reporter = new TelemetryReporter(key); + + const duration = process.hrtime(start); + Logger.log(`Telemetry.configure took ${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms`); } static setContext(context?: { [key: string]: string }) {