diff --git a/src/commands.ts b/src/commands.ts index 36cc8cb..99dde41 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -48,7 +48,7 @@ import * as humanise from './humanise'; import { partition } from './util'; import { toFossilUri } from './uri'; import { FossilPreviewManager } from './preview'; -import type { FossilCWD, FossilExecutable } from './fossilExecutable'; +import type { FossilCWD, FossilExecutable, Reason } from './fossilExecutable'; import { localize } from './main'; import type { Credentials } from './gitExport'; @@ -196,7 +196,7 @@ export class CommandCenter { @command(Inline.Repository) async refresh(repository: Repository): Promise { - await repository.status('forced refresh'); + await repository.status('forced refresh' as Reason); } @command() diff --git a/src/fossilExecutable.ts b/src/fossilExecutable.ts index 61d7f6a..4d02d65 100644 --- a/src/fossilExecutable.ts +++ b/src/fossilExecutable.ts @@ -19,6 +19,7 @@ export type FossilStdOut = Distinct< 'raw fossil stdout' | 'fossil status stdout' | 'RenderedHTML' >; export type FossilStdErr = Distinct; +export type Reason = Distinct | undefined; /** cwd for executing fossil */ export type FossilCWD = @@ -185,7 +186,7 @@ export class FossilExecutable { fossilCwd: FossilCWD, args: FossilArgs ): Promise { - const res = await this._loggingExec(args, '', { cwd: fossilCwd }); + const res = await this._loggingExec(args, { cwd: fossilCwd }); if (!res.exitCode) { return res.stdout; } @@ -295,13 +296,13 @@ export class FossilExecutable { private async _loggingExec( args: FossilArgs, - reason: string, - options: FossilSpawnOptions + options: FossilSpawnOptions, + reason?: Reason ) { const startTimeHR = process.hrtime(); const waitAndLog = (timeout: number): ReturnType => { return setTimeout(() => { - this.logArgs(args, reason, 'still running'); + this.logArgs(args, 'still running', reason); logTimeout = waitAndLog(timeout * 4); }, timeout); }; @@ -312,8 +313,8 @@ export class FossilExecutable { const durationHR = process.hrtime(startTimeHR); this.logArgs( args, - reason, - `${Math.floor(msFromHighResTime(durationHR))}ms` + `${Math.floor(msFromHighResTime(durationHR))}ms`, + reason ); return resultRaw; } @@ -321,13 +322,17 @@ export class FossilExecutable { public async exec( cwd: FossilCWD, args: FossilArgs, - reason = '', + reason?: Reason, options: Omit = {} as const ): Promise { - const resultRaw = await this._loggingExec(args, reason, { - cwd, - ...options, - }); + const resultRaw = await this._loggingExec( + args, + { + cwd, + ...options, + }, + reason + ); const result: ExecResult = { ...resultRaw, stdout: resultRaw.stdout.toString('utf8') as FossilStdOut, @@ -388,7 +393,7 @@ export class FossilExecutable { private log(output: string): void { this.outputChannel.info(output); } - private logArgs(args: FossilArgs, reason: string, info: string): void { + private logArgs(args: FossilArgs, info: string, reason: Reason): void { if (args[0] == 'clone') { // replace password with 9 asterisks args = [...args]; diff --git a/src/model.ts b/src/model.ts index 8d8eb3b..119af24 100644 --- a/src/model.ts +++ b/src/model.ts @@ -19,7 +19,7 @@ import { commands, ConfigurationChangeEvent, } from 'vscode'; -import type { FossilExecutable } from './fossilExecutable'; +import type { FossilExecutable, Reason } from './fossilExecutable'; import { anyEvent, filterEvent, dispose, eventToPromise } from './util'; import { memoize, debounce, sequentialize } from './decorators'; import * as path from 'path'; @@ -343,7 +343,9 @@ export class Model implements Disposable { for (const { oldUri, newUri } of e.files) { const repository = this.getRepository(oldUri); if (repository) { - await repository.updateModelState('file rename event'); + await repository.updateModelState( + 'file rename event' as Reason + ); if ( repository.isInAnyGroup(oldUri) || repository.isDirInAnyGroup(oldUri) diff --git a/src/openedRepository.ts b/src/openedRepository.ts index 8e3f3e6..9b4648d 100644 --- a/src/openedRepository.ts +++ b/src/openedRepository.ts @@ -15,6 +15,7 @@ import { FossilSpawnOptions, FossilArgs, ExecResult, + Reason, } from './fossilExecutable'; import { NewBranchOptions } from './interaction'; import { FossilCWD } from './fossilExecutable'; @@ -205,7 +206,7 @@ export class OpenedRepository { const result = await executable.exec( cwd, ['info'], - `getting root for '${anypath}'` + `getting root for '${anypath}'` as Reason ); const root = result.stdout.match(/local-root:\s*(.+)\/\s/); if (root) { @@ -216,7 +217,7 @@ export class OpenedRepository { async exec( args: FossilArgs, - reason = '', + reason?: Reason, options: Omit = {} as const ): Promise { return this.executable.exec(this.root, args, reason, options); @@ -539,7 +540,7 @@ export class OpenedRepository { /** Report the change status of files in the current checkout */ @throttle - async getStatus(reason: string): Promise { + async getStatus(reason: Reason): Promise { return this.exec(['status', '--differ', '--merge'], reason); } @@ -655,7 +656,7 @@ export class OpenedRepository { async config(keys: T[]): Promise> { const result = await this.exec( ['sqlite', '--readonly'], - 'reading configuration for github', + 'reading configuration for github' as Reason, { stdin_data: '.mode json\n' + diff --git a/src/preview.ts b/src/preview.ts index 454e483..9d9b886 100644 --- a/src/preview.ts +++ b/src/preview.ts @@ -1,4 +1,9 @@ -import { FossilExecutable, FossilCWD, FossilArgs } from './fossilExecutable'; +import { + FossilExecutable, + FossilCWD, + FossilArgs, + Reason, +} from './fossilExecutable'; import * as path from 'path'; import { Uri, @@ -271,7 +276,7 @@ class FossilPreview implements IDisposable { mimetype, ...(where == 'Technote' ? ['--technote', 'now'] : []), ], - '', + '' as Reason, { stdin_data: source, } @@ -303,10 +308,15 @@ class FossilPreview implements IDisposable { ]; } - const result = await this.executable.exec(this.dirname, args, '', { - stdin_data: this.current_content[0], - logErrors: false, - }); + const result = await this.executable.exec( + this.dirname, + args, + 'preview' as Reason, + { + stdin_data: this.current_content[0], + logErrors: false, + } + ); let html: RenderedHTML; if (!result.exitCode) { html = result.stdout as RenderedHTML; diff --git a/src/repository.ts b/src/repository.ts index e3c0249..e9f7cf6 100644 --- a/src/repository.ts +++ b/src/repository.ts @@ -73,7 +73,7 @@ import type { InteractionAPI, NewBranchOptions } from './interaction'; import { FossilUriParams, toFossilUri } from './uri'; import { localize } from './main'; -import type { ExecFailure, ExecResult } from './fossilExecutable'; +import type { ExecFailure, ExecResult, Reason } from './fossilExecutable'; const iconsRootPath = path.join(path.dirname(__dirname), 'resources', 'icons'); type AvailableIcons = @@ -427,7 +427,7 @@ export class Repository implements IDisposable, InteractionAPI { ); this._sourceControl.statusBarCommands = statusBar.commands; - this.updateModelState('opening repository'); + this.updateModelState('opening repository' as Reason); this.disposables.push(new AutoIncomingOutgoing(this)); } @@ -440,7 +440,7 @@ export class Repository implements IDisposable, InteractionAPI { } @throttle - async status(reason: string): Promise { + async status(reason: Reason): Promise { const statusPromise = this.repository.getStatus(reason); await this.runWithProgress(Operation.Status, () => statusPromise); this.updateInputBoxPlaceholder(); @@ -467,7 +467,7 @@ export class Repository implements IDisposable, InteractionAPI { @throttle private async updateWhenIdleAndWait(): Promise { await this.whenIdleAndFocused(); - await this.updateModelState('idle update'); + await this.updateModelState('idle update' as Reason); await delay(5000); } @@ -1065,7 +1065,7 @@ export class Repository implements IDisposable, InteractionAPI { */ @throttle public async updateModelState( - reason = 'model state is updating' + reason: Reason = 'model state is updating' as Reason ): Promise { const result = await this.repository.getStatus(reason); if (result.exitCode) { diff --git a/src/test/suite/mergeSuite.ts b/src/test/suite/mergeSuite.ts index cdc6f30..1c39a00 100644 --- a/src/test/suite/mergeSuite.ts +++ b/src/test/suite/mergeSuite.ts @@ -14,6 +14,7 @@ import * as assert from 'assert/strict'; import * as fs from 'fs/promises'; import { FossilBranch, OpenedRepository } from '../../openedRepository'; import { Suite } from 'mocha'; +import { Reason } from '../../fossilExecutable'; export function MergeSuite(this: Suite): void { test('Merge error is shown', async () => { @@ -112,7 +113,7 @@ export function MergeSuite(this: Suite): void { sinon.assert.calledOnce(sqp); sinon.assert.calledOnce(sib); - await repository.updateModelState('test'); + await repository.updateModelState('test' as Reason); assertGroups(repository, new Map(), new Map()); }).timeout(5000); diff --git a/src/test/suite/renameSuite.ts b/src/test/suite/renameSuite.ts index f1ca3f5..7547980 100644 --- a/src/test/suite/renameSuite.ts +++ b/src/test/suite/renameSuite.ts @@ -14,6 +14,7 @@ import * as fs from 'fs/promises'; import { OpenedRepository, ResourceStatus } from '../../openedRepository'; import { delay, eventToPromise } from '../../util'; import { Suite, before } from 'mocha'; +import { Reason } from '../../fossilExecutable'; export function RenameSuite(this: Suite): void { before(async () => { @@ -81,7 +82,7 @@ export function RenameSuite(this: Suite): void { sinon.assert.calledOnceWithExactly( status, ['status', '--differ', '--merge'], - 'file rename event' + 'file rename event' as Reason ); sinon.assert.calledOnceWithExactly( sim, diff --git a/src/test/suite/resourceActionsSuite.ts b/src/test/suite/resourceActionsSuite.ts index 6c78ca5..95d575b 100644 --- a/src/test/suite/resourceActionsSuite.ts +++ b/src/test/suite/resourceActionsSuite.ts @@ -8,7 +8,7 @@ import { TextDocumentShowOptions, } from 'vscode'; import * as sinon from 'sinon'; -import { FossilCWD } from '../../fossilExecutable'; +import { FossilCWD, Reason } from '../../fossilExecutable'; import { assertGroups, cleanupFossil, @@ -76,7 +76,7 @@ export function resourceActionsSuite(this: Suite): void { let statusStub = fakeFossilStatus(execStub, 'EXTRA a.txt\nEXTRA b.txt'); const repository = getRepository(); - await repository.updateModelState('test'); + await repository.updateModelState('test' as Reason); sinon.assert.calledOnce(statusStub); assert.equal(repository.untrackedGroup.resourceStates.length, 2); assertGroups(repository, new Map(), new Map()); @@ -105,7 +105,7 @@ export function resourceActionsSuite(this: Suite): void { await cleanupFossil(repository); const execStub = getExecStub(this.ctx.sandbox); const statusStub = fakeFossilStatus(execStub, 'ADDED a\nADDED b'); - await repository.updateModelState('test'); + await repository.updateModelState('test' as Reason); sinon.assert.calledOnce(statusStub); assert.equal(repository.workingGroup.resourceStates.length, 2); assert.equal(repository.stagingGroup.resourceStates.length, 0); diff --git a/src/test/suite/stateSuite.ts b/src/test/suite/stateSuite.ts index 1b18c83..f2e4b11 100644 --- a/src/test/suite/stateSuite.ts +++ b/src/test/suite/stateSuite.ts @@ -11,6 +11,7 @@ import * as assert from 'assert/strict'; import * as fs from 'fs/promises'; import { OpenedRepository } from '../../openedRepository'; import { Suite, before } from 'mocha'; +import { Reason } from '../../fossilExecutable'; function PullAndPushSuite(this: Suite): void { const noRemotes = async ( @@ -432,7 +433,7 @@ export function StageSuite(this: Suite): void { const execStub = getExecStub(this.ctx.sandbox); await fakeFossilStatus(execStub, status); const repository = getRepository(); - await repository.updateModelState('test'); + await repository.updateModelState('test' as Reason); }; test('Stage from working group', async () => {