Git - logging improvements (#148656)

This commit is contained in:
Ladislau Szomoru
2022-05-05 14:52:26 +02:00
committed by GitHub
parent 77055cffc0
commit ce88518440
9 changed files with 203 additions and 98 deletions

View File

@@ -3,11 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { window, InputBoxOptions, Uri, OutputChannel, Disposable, workspace } from 'vscode';
import { IDisposable, EmptyDisposable, toDisposable, logTimestamp } from './util';
import { window, InputBoxOptions, Uri, Disposable, workspace } from 'vscode';
import { IDisposable, EmptyDisposable, toDisposable } from './util';
import * as path from 'path';
import { IIPCHandler, IIPCServer, createIPCServer } from './ipc/ipcServer';
import { CredentialsProvider, Credentials } from './api/git';
import { OutputChannelLogger } from './log';
export class Askpass implements IIPCHandler {
@@ -15,11 +16,11 @@ export class Askpass implements IIPCHandler {
private cache = new Map<string, Credentials>();
private credentialsProviders = new Set<CredentialsProvider>();
static async create(outputChannel: OutputChannel, context?: string): Promise<Askpass> {
static async create(outputChannelLogger: OutputChannelLogger, context?: string): Promise<Askpass> {
try {
return new Askpass(await createIPCServer(context));
} catch (err) {
outputChannel.appendLine(`${logTimestamp()} [error] Failed to create git askpass IPC: ${err}`);
outputChannelLogger.logError(`Failed to create git askpass IPC: ${err}`);
return new Askpass();
}
}

View File

@@ -5,7 +5,7 @@
import * as os from 'os';
import * as path from 'path';
import { Command, commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider } from 'vscode';
import { Command, commands, Disposable, LineChange, MessageOptions, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider } from 'vscode';
import TelemetryReporter from '@vscode/extension-telemetry';
import * as nls from 'vscode-nls';
import { Branch, ForcePushMode, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourcePublisher } from './api/git';
@@ -14,8 +14,8 @@ import { Model } from './model';
import { Repository, Resource, ResourceGroupType } from './repository';
import { applyLineChanges, getModifiedRange, intersectDiffWithRange, invertLineChange, toLineRanges } from './staging';
import { fromGitUri, toGitUri, isGitUri } from './uri';
import { grep, isDescendant, logTimestamp, pathEquals, relativePath } from './util';
import { Log, LogLevel } from './log';
import { grep, isDescendant, pathEquals, relativePath } from './util';
import { LogLevel, OutputChannelLogger } from './log';
import { GitTimelineItem } from './timelineProvider';
import { ApiRepository } from './api/api1';
import { pickRemoteSource } from './remoteSource';
@@ -310,7 +310,7 @@ export class CommandCenter {
constructor(
private git: Git,
private model: Model,
private outputChannel: OutputChannel,
private outputChannelLogger: OutputChannelLogger,
private telemetryReporter: TelemetryReporter
) {
this.disposables = Commands.map(({ commandId, key, method, options }) => {
@@ -328,11 +328,25 @@ export class CommandCenter {
@command('git.setLogLevel')
async setLogLevel(): Promise<void> {
const createItem = (logLevel: LogLevel) => ({
label: LogLevel[logLevel],
logLevel,
description: Log.logLevel === logLevel ? localize('current', "Current") : undefined
});
const createItem = (logLevel: LogLevel) => {
let description: string | undefined;
const defaultDescription = localize('default', "Default");
const currentDescription = localize('current', "Current");
if (logLevel === this.outputChannelLogger.defaultLogLevel && logLevel === this.outputChannelLogger.currentLogLevel) {
description = `${defaultDescription} & ${currentDescription} `;
} else if (logLevel === this.outputChannelLogger.defaultLogLevel) {
description = defaultDescription;
} else if (logLevel === this.outputChannelLogger.currentLogLevel) {
description = currentDescription;
}
return {
label: LogLevel[logLevel],
logLevel,
description
};
};
const items = [
createItem(LogLevel.Trace),
@@ -352,8 +366,7 @@ export class CommandCenter {
return;
}
Log.logLevel = choice.logLevel;
this.outputChannel.appendLine(localize('changed', "{0} Log level changed to: {1}", logTimestamp(), LogLevel[Log.logLevel]));
this.outputChannelLogger.setLogLevel(choice.logLevel);
}
@command('git.refresh', { repository: true })
@@ -820,14 +833,14 @@ export class CommandCenter {
@command('git.stage')
async stage(...resourceStates: SourceControlResourceState[]): Promise<void> {
this.outputChannel.appendLine(`${logTimestamp()} git.stage ${resourceStates.length}`);
this.outputChannelLogger.logDebug(`git.stage ${resourceStates.length} `);
resourceStates = resourceStates.filter(s => !!s);
if (resourceStates.length === 0 || (resourceStates[0] && !(resourceStates[0].resourceUri instanceof Uri))) {
const resource = this.getSCMResource();
this.outputChannel.appendLine(`${logTimestamp()} git.stage.getSCMResource ${resource ? resource.resourceUri.toString() : null}`);
this.outputChannelLogger.logDebug(`git.stage.getSCMResource ${resource ? resource.resourceUri.toString() : null} `);
if (!resource) {
return;
@@ -870,7 +883,7 @@ export class CommandCenter {
const untracked = selection.filter(s => s.resourceGroupType === ResourceGroupType.Untracked);
const scmResources = [...workingTree, ...untracked, ...resolved, ...unresolved];
this.outputChannel.appendLine(`${logTimestamp()} git.stage.scmResources ${scmResources.length}`);
this.outputChannelLogger.logDebug(`git.stage.scmResources ${scmResources.length} `);
if (!scmResources.length) {
return;
}
@@ -2809,8 +2822,8 @@ export class CommandCenter {
const choices = new Map<string, () => void>();
const openOutputChannelChoice = localize('open git log', "Open Git Log");
const outputChannel = this.outputChannel as OutputChannel;
choices.set(openOutputChannelChoice, () => outputChannel.show());
const outputChannelLogger = this.outputChannelLogger;
choices.set(openOutputChannelChoice, () => outputChannelLogger.showOutputChannel());
const showCommandOutputChoice = localize('show command output', "Show Command Output");
if (err.stderr) {
@@ -2913,10 +2926,10 @@ export class CommandCenter {
private getSCMResource(uri?: Uri): Resource | undefined {
uri = uri ? uri : (window.activeTextEditor && window.activeTextEditor.document.uri);
this.outputChannel.appendLine(`${logTimestamp()} git.getSCMResource.uri ${uri && uri.toString()}`);
this.outputChannelLogger.logDebug(`git.getSCMResource.uri ${uri && uri.toString()}`);
for (const r of this.model.repositories.map(r => r.root)) {
this.outputChannel.appendLine(`${logTimestamp()} repo root ${r}`);
this.outputChannelLogger.logDebug(`repo root ${r}`);
}
if (!uri) {

View File

@@ -3,7 +3,11 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event, EventEmitter } from 'vscode';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { commands, Disposable, Event, EventEmitter, OutputChannel, window, workspace } from 'vscode';
import { dispose } from './util';
/**
* The severity level of a log message
@@ -18,33 +22,93 @@ export enum LogLevel {
Off = 7
}
let _logLevel: LogLevel = LogLevel.Info;
const _onDidChangeLogLevel = new EventEmitter<LogLevel>();
/**
* Output channel logger
*/
export class OutputChannelLogger {
export const Log = {
/**
* Current logging level.
*/
get logLevel(): LogLevel {
return _logLevel;
},
private _onDidChangeLogLevel = new EventEmitter<LogLevel>();
readonly onDidChangeLogLevel: Event<LogLevel> = this._onDidChangeLogLevel.event;
/**
* Current logging level.
*/
set logLevel(logLevel: LogLevel) {
if (_logLevel === logLevel) {
private _currentLogLevel: LogLevel;
get currentLogLevel(): LogLevel {
return this._currentLogLevel;
}
private _defaultLogLevel: LogLevel;
get defaultLogLevel(): LogLevel {
return this._defaultLogLevel;
}
private _outputChannel: OutputChannel;
private _disposables: Disposable[] = [];
constructor() {
// Output channel
this._outputChannel = window.createOutputChannel('Git');
commands.registerCommand('git.showOutput', () => this.showOutputChannel());
this._disposables.push(this._outputChannel);
// Initialize log level
const config = workspace.getConfiguration('git');
const logLevel: keyof typeof LogLevel = config.get('logLevel', 'Info');
this._currentLogLevel = this._defaultLogLevel = LogLevel[logLevel] ?? LogLevel.Info;
this.logInfo(localize('gitLogLevel', "Log level: {0}", LogLevel[this._currentLogLevel]));
}
private log(message: string, logLevel: LogLevel): void {
if (logLevel < this._currentLogLevel) {
return;
}
_logLevel = logLevel;
_onDidChangeLogLevel.fire(logLevel);
},
/**
* An [event](#Event) that fires when the log level has changed.
*/
get onDidChangeLogLevel(): Event<LogLevel> {
return _onDidChangeLogLevel.event;
this._outputChannel.appendLine(`[${new Date().toISOString()}] [${LogLevel[logLevel].toLowerCase()}] ${message}`);
}
};
logCritical(message: string): void {
this.log(message, LogLevel.Critical);
}
logDebug(message: string): void {
this.log(message, LogLevel.Debug);
}
logError(message: string): void {
this.log(message, LogLevel.Error);
}
logInfo(message: string): void {
this.log(message, LogLevel.Info);
}
logTrace(message: string): void {
this.log(message, LogLevel.Trace);
}
logWarning(message: string): void {
this.log(message, LogLevel.Warning);
}
logGitCommand(command: string): void {
this._outputChannel.appendLine(`[${new Date().toISOString()}] ${command}`);
}
setLogLevel(logLevel: LogLevel): void {
if (this._currentLogLevel === logLevel) {
return;
}
this._currentLogLevel = logLevel;
this._onDidChangeLogLevel.fire(logLevel);
this.logInfo(localize('changed', "Log level changed to: {0}", LogLevel[logLevel]));
}
showOutputChannel(): void {
this._outputChannel.show();
}
dispose(): void {
this._disposables = dispose(this._disposables);
}
}

View File

@@ -6,14 +6,14 @@
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { env, ExtensionContext, workspace, window, Disposable, commands, Uri, OutputChannel, version as vscodeVersion, WorkspaceFolder } from 'vscode';
import { env, ExtensionContext, workspace, window, Disposable, commands, Uri, version as vscodeVersion, WorkspaceFolder } from 'vscode';
import { findGit, Git, IGit } from './git';
import { Model } from './model';
import { CommandCenter } from './commands';
import { GitFileSystemProvider } from './fileSystemProvider';
import { GitDecorations } from './decorationProvider';
import { Askpass } from './askpass';
import { toDisposable, filterEvent, eventToPromise, logTimestamp } from './util';
import { toDisposable, filterEvent, eventToPromise } from './util';
import TelemetryReporter from '@vscode/extension-telemetry';
import { GitExtension } from './api/git';
import { GitProtocolHandler } from './protocolHandler';
@@ -24,6 +24,7 @@ import * as os from 'os';
import { GitTimelineProvider } from './timelineProvider';
import { registerAPICommands } from './api/api1';
import { TerminalEnvironmentManager } from './terminal';
import { OutputChannelLogger } from './log';
const deactivateTasks: { (): Promise<any> }[] = [];
@@ -33,7 +34,7 @@ export async function deactivate(): Promise<any> {
}
}
async function createModel(context: ExtensionContext, outputChannel: OutputChannel, telemetryReporter: TelemetryReporter, disposables: Disposable[]): Promise<Model> {
async function createModel(context: ExtensionContext, outputChannelLogger: OutputChannelLogger, telemetryReporter: TelemetryReporter, disposables: Disposable[]): Promise<Model> {
const pathValue = workspace.getConfiguration('git').get<string | string[]>('path');
let pathHints = Array.isArray(pathValue) ? pathValue : pathValue ? [pathValue] : [];
@@ -46,7 +47,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
}
const info = await findGit(pathHints, gitPath => {
outputChannel.appendLine(localize('validating', "{0} Validating found git in: {1}", logTimestamp(), gitPath));
outputChannelLogger.logInfo(localize('validating', "Validating found git in: {0}", gitPath));
if (excludes.length === 0) {
return true;
}
@@ -54,12 +55,12 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
const normalized = path.normalize(gitPath).replace(/[\r\n]+$/, '');
const skip = excludes.some(e => normalized.startsWith(e));
if (skip) {
outputChannel.appendLine(localize('skipped', "{0} Skipped found git in: {1}", logTimestamp(), gitPath));
outputChannelLogger.logInfo(localize('skipped', "Skipped found git in: {0}", gitPath));
}
return !skip;
});
const askpass = await Askpass.create(outputChannel, context.storagePath);
const askpass = await Askpass.create(outputChannelLogger, context.storagePath);
disposables.push(askpass);
const environment = askpass.getEnv();
@@ -73,7 +74,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
version: info.version,
env: environment,
});
const model = new Model(git, askpass, context.globalState, outputChannel, telemetryReporter);
const model = new Model(git, askpass, context.globalState, outputChannelLogger, telemetryReporter);
disposables.push(model);
const onRepository = () => commands.executeCommand('setContext', 'gitOpenRepositoryCount', `${model.repositories.length}`);
@@ -81,7 +82,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
model.onDidCloseRepository(onRepository, null, disposables);
onRepository();
outputChannel.appendLine(localize('using git', "{0} Using git {1} from {2}", logTimestamp(), info.version, info.path));
outputChannelLogger.logInfo(localize('using git', "Using git {0} from {1}", info.version, info.path));
const onOutput = (str: string) => {
const lines = str.split(/\r?\n/mg);
@@ -90,12 +91,12 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
lines.pop();
}
outputChannel.appendLine(`${logTimestamp()} ${lines.join('\n')}`);
outputChannelLogger.logGitCommand(lines.join('\n'));
};
git.onOutput.addListener('log', onOutput);
disposables.push(toDisposable(() => git.onOutput.removeListener('log', onOutput)));
const cc = new CommandCenter(git, model, outputChannel, telemetryReporter);
const cc = new CommandCenter(git, model, outputChannelLogger, telemetryReporter);
disposables.push(
cc,
new GitFileSystemProvider(model),
@@ -161,9 +162,8 @@ export async function _activate(context: ExtensionContext): Promise<GitExtension
const disposables: Disposable[] = [];
context.subscriptions.push(new Disposable(() => Disposable.from(...disposables).dispose()));
const outputChannel = window.createOutputChannel('Git');
commands.registerCommand('git.showOutput', () => outputChannel.show());
disposables.push(outputChannel);
const outputChannelLogger = new OutputChannelLogger();
disposables.push(outputChannelLogger);
const { name, version, aiKey } = require('../package.json') as { name: string; version: string; aiKey: string };
const telemetryReporter = new TelemetryReporter(name, version, aiKey);
@@ -177,12 +177,12 @@ export async function _activate(context: ExtensionContext): Promise<GitExtension
const onEnabled = filterEvent(onConfigChange, () => workspace.getConfiguration('git', null).get<boolean>('enabled') === true);
const result = new GitExtensionImpl();
eventToPromise(onEnabled).then(async () => result.model = await createModel(context, outputChannel, telemetryReporter, disposables));
eventToPromise(onEnabled).then(async () => result.model = await createModel(context, outputChannelLogger, telemetryReporter, disposables));
return result;
}
try {
const model = await createModel(context, outputChannel, telemetryReporter, disposables);
const model = await createModel(context, outputChannelLogger, telemetryReporter, disposables);
return new GitExtensionImpl(model);
} catch (err) {
if (!/Git installation not found/.test(err.message || '')) {
@@ -190,7 +190,7 @@ export async function _activate(context: ExtensionContext): Promise<GitExtension
}
console.warn(err.message);
outputChannel.appendLine(`${logTimestamp()} ${err.message}`);
outputChannelLogger.logWarning(err.message);
/* __GDPR__
"git.missing" : {}

View File

@@ -3,11 +3,11 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, OutputChannel, commands } from 'vscode';
import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, commands } from 'vscode';
import TelemetryReporter from '@vscode/extension-telemetry';
import { Repository, RepositoryState } from './repository';
import { memoize, sequentialize, debounce } from './decorators';
import { dispose, anyEvent, filterEvent, isDescendant, pathEquals, toDisposable, eventToPromise, logTimestamp } from './util';
import { dispose, anyEvent, filterEvent, isDescendant, pathEquals, toDisposable, eventToPromise } from './util';
import { Git } from './git';
import * as path from 'path';
import * as fs from 'fs';
@@ -18,7 +18,7 @@ import { Askpass } from './askpass';
import { IPushErrorHandlerRegistry } from './pushError';
import { ApiRepository } from './api/api1';
import { IRemoteSourcePublisherRegistry } from './remotePublisher';
import { Log, LogLevel } from './log';
import { OutputChannelLogger } from './log';
const localize = nls.loadMessageBundle();
@@ -110,7 +110,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
private disposables: Disposable[] = [];
constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannel: OutputChannel, private telemetryReporter: TelemetryReporter) {
constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannelLogger: OutputChannelLogger, private telemetryReporter: TelemetryReporter) {
workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables);
window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables);
workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.disposables);
@@ -145,9 +145,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
const autoRepositoryDetection = config.get<boolean | 'subFolders' | 'openEditors'>('autoRepositoryDetection');
// Log repository scan settings
if (Log.logLevel <= LogLevel.Trace) {
this.outputChannel.appendLine(`${logTimestamp()} Trace: autoRepositoryDetection="${autoRepositoryDetection}"`);
}
this.outputChannelLogger.logTrace(`autoRepositoryDetection="${autoRepositoryDetection}"`);
if (autoRepositoryDetection !== true && autoRepositoryDetection !== 'subFolders') {
return;
@@ -352,15 +350,13 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
}
const dotGit = await this.git.getRepositoryDotGit(repositoryRoot);
const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this, this.globalState, this.outputChannel, this.telemetryReporter);
const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this, this.globalState, this.outputChannelLogger, this.telemetryReporter);
this.open(repository);
repository.status(); // do not await this, we want SCM to know about the repo asap
} catch (ex) {
// noop
if (Log.logLevel <= LogLevel.Trace) {
this.outputChannel.appendLine(`${logTimestamp()} Trace: Opening repository for path='${repoPath}' failed; ex=${ex}`);
}
this.outputChannelLogger.logTrace(`Opening repository for path='${repoPath}' failed; ex=${ex}`);
}
}
@@ -386,7 +382,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
}
private open(repository: Repository): void {
this.outputChannel.appendLine(`${logTimestamp()} Open repository: ${repository.root}`);
this.outputChannelLogger.logInfo(`Open repository: ${repository.root}`);
const onDidDisappearRepository = filterEvent(repository.onDidChangeState, state => state === RepositoryState.Disposed);
const disappearListener = onDidDisappearRepository(() => dispose());
@@ -443,7 +439,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
return;
}
this.outputChannel.appendLine(`${logTimestamp()} Close repository: ${repository.root}`);
this.outputChannelLogger.logInfo(`Close repository: ${repository.root}`);
openRepository.dispose();
}

View File

@@ -5,7 +5,7 @@
import * as fs from 'fs';
import * as path from 'path';
import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands, Tab, TabInputTextDiff, TabInputNotebookDiff, RelativePattern } from 'vscode';
import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands, Tab, TabInputTextDiff, TabInputNotebookDiff, RelativePattern } from 'vscode';
import TelemetryReporter from '@vscode/extension-telemetry';
import * as nls from 'vscode-nls';
import { Branch, Change, ForcePushMode, GitErrorCodes, LogOptions, Ref, RefType, Remote, Status, CommitOptions, BranchQuery, FetchOptions } from './api/git';
@@ -14,9 +14,9 @@ import { debounce, memoize, throttle } from './decorators';
import { Commit, GitError, Repository as BaseRepository, Stash, Submodule, LogFileOptions } from './git';
import { StatusBarCommands } from './statusbar';
import { toGitUri } from './uri';
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, logTimestamp, onceEvent, pathEquals, relativePath } from './util';
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, onceEvent, pathEquals, relativePath } from './util';
import { IFileWatcher, watch } from './watch';
import { Log, LogLevel } from './log';
import { LogLevel, OutputChannelLogger } from './log';
import { IPushErrorHandlerRegistry } from './pushError';
import { ApiRepository } from './api/api1';
import { IRemoteSourcePublisherRegistry } from './remotePublisher';
@@ -504,10 +504,10 @@ class FileEventLogger {
constructor(
private onWorkspaceWorkingTreeFileChange: Event<Uri>,
private onDotGitFileChange: Event<Uri>,
private outputChannel: OutputChannel
private outputChannelLogger: OutputChannelLogger
) {
this.logLevelDisposable = Log.onDidChangeLogLevel(this.onDidChangeLogLevel, this);
this.onDidChangeLogLevel(Log.logLevel);
this.logLevelDisposable = outputChannelLogger.onDidChangeLogLevel(this.onDidChangeLogLevel, this);
this.onDidChangeLogLevel(outputChannelLogger.currentLogLevel);
}
private onDidChangeLogLevel(level: LogLevel): void {
@@ -518,8 +518,8 @@ class FileEventLogger {
}
this.eventDisposable = combinedDisposable([
this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannel.appendLine(`${logTimestamp()} [debug] [wt] Change: ${uri.fsPath}`)),
this.onDotGitFileChange(uri => this.outputChannel.appendLine(`${logTimestamp()} [debug] [.git] Change: ${uri.fsPath}`))
this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannelLogger.logDebug(`[wt] Change: ${uri.fsPath}`)),
this.onDotGitFileChange(uri => this.outputChannelLogger.logDebug(`[.git] Change: ${uri.fsPath}`))
]);
}
@@ -539,7 +539,7 @@ class DotGitWatcher implements IFileWatcher {
constructor(
private repository: Repository,
private outputChannel: OutputChannel
private outputChannelLogger: OutputChannelLogger
) {
const rootWatcher = watch(repository.dotGit.path);
this.disposables.push(rootWatcher);
@@ -570,9 +570,7 @@ class DotGitWatcher implements IFileWatcher {
this.transientDisposables.push(upstreamWatcher);
upstreamWatcher.event(this.emitter.fire, this.emitter, this.transientDisposables);
} catch (err) {
if (Log.logLevel <= LogLevel.Error) {
this.outputChannel.appendLine(`${logTimestamp()} Warning: Failed to watch ref '${upstreamPath}', is most likely packed.`);
}
this.outputChannelLogger.logWarning(`Failed to watch ref '${upstreamPath}', is most likely packed.`);
}
}
@@ -857,7 +855,7 @@ export class Repository implements Disposable {
private pushErrorHandlerRegistry: IPushErrorHandlerRegistry,
remoteSourcePublisherRegistry: IRemoteSourcePublisherRegistry,
globalState: Memento,
outputChannel: OutputChannel,
outputChannelLogger: OutputChannelLogger,
private telemetryReporter: TelemetryReporter
) {
const repositoryWatcher = workspace.createFileSystemWatcher(new RelativePattern(Uri.file(repository.root), '**'));
@@ -869,13 +867,11 @@ export class Repository implements Disposable {
let onRepositoryDotGitFileChange: Event<Uri>;
try {
const dotGitFileWatcher = new DotGitWatcher(this, outputChannel);
const dotGitFileWatcher = new DotGitWatcher(this, outputChannelLogger);
onRepositoryDotGitFileChange = dotGitFileWatcher.event;
this.disposables.push(dotGitFileWatcher);
} catch (err) {
if (Log.logLevel <= LogLevel.Error) {
outputChannel.appendLine(`${logTimestamp()} Failed to watch path:'${this.dotGit.path}' or commonPath:'${this.dotGit.commonPath}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
}
outputChannelLogger.logError(`Failed to watch path:'${this.dotGit.path}' or commonPath:'${this.dotGit.commonPath}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
onRepositoryDotGitFileChange = filterEvent(onRepositoryFileChange, uri => /\.git($|\/)/.test(uri.path));
}
@@ -889,7 +885,7 @@ export class Repository implements Disposable {
// Relevate repository changes should trigger virtual document change events
onRepositoryDotGitFileChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
this.disposables.push(new FileEventLogger(onRepositoryWorkingTreeFileChange, onRepositoryDotGitFileChange, outputChannel));
this.disposables.push(new FileEventLogger(onRepositoryWorkingTreeFileChange, onRepositoryDotGitFileChange, outputChannelLogger));
const root = Uri.file(repository.root);
this._sourceControl = scm.createSourceControl('git', 'Git', root);

View File

@@ -16,10 +16,6 @@ export function log(...args: any[]): void {
console.log.apply(console, ['git:', ...args]);
}
export function logTimestamp(): string {
return `[${new Date().toISOString()}]`;
}
export interface IDisposable {
dispose(): void;
}