Skip to content

Commit 4cfc1c6

Browse files
committed
Added more usage of disposables
1 parent a84c5eb commit 4cfc1c6

File tree

9 files changed

+102
-44
lines changed

9 files changed

+102
-44
lines changed

src/commands.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
WorkspaceEdit,
1515
Range,
1616
Position,
17-
TextEditor
17+
TextEditor,
18+
Disposable
1819
} from "vscode";
1920
import { inputCommitMessage } from "./messages";
2021
import { Svn, Status, SvnErrorCodes } from "./svn";
@@ -27,6 +28,7 @@ import * as path from "path";
2728
import { start } from "repl";
2829
import { getConflictPickOptions } from "./conflictItems";
2930
import { applyLineChanges } from "./lineChanges";
31+
import { IDisposable } from "./util";
3032

3133
interface CommandOptions {
3234
repository?: boolean;
@@ -136,11 +138,11 @@ class NewChangeListItem implements QuickPickItem {
136138
}
137139
}
138140

139-
export class SvnCommands {
140-
private commands: any[] = [];
141+
export class SvnCommands implements IDisposable {
142+
private disposables: Disposable[];
141143

142144
constructor(private model: Model) {
143-
Commands.map(({ commandId, method, options }) => {
145+
this.disposables = Commands.map(({ commandId, method, options }) => {
144146
const command = this.createCommand(method, options);
145147
if (options.diff) {
146148
return commands.registerDiffInformationCommand(commandId, command);
@@ -1089,4 +1091,8 @@ export class SvnCommands {
10891091

10901092
return Promise.all(promises);
10911093
}
1094+
1095+
dispose(): void {
1096+
this.disposables.forEach(d => d.dispose());
1097+
}
10921098
}

src/decorationProvider.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -146,26 +146,33 @@ class SvnDecorationProvider implements DecorationProvider {
146146
}
147147

148148
export class SvnDecorations {
149+
private enabled: boolean = false;
149150
private configListener: Disposable;
150151
private modelListener: Disposable[] = [];
151152
private providers = new Map<Repository, Disposable>();
152153

153154
constructor(private model: Model) {
154-
// this.configListener = workspace.onDidChangeConfiguration(
155-
// e => e.affectsConfiguration("svn.decorations.enabled") && this.update()
156-
// );
155+
this.configListener = workspace.onDidChangeConfiguration(() =>
156+
this.update()
157+
);
157158
this.update();
158159
}
159160

160161
private update(): void {
161162
const enabled = workspace
162163
.getConfiguration()
163-
.get<boolean>("svn.decorations.enabled");
164+
.get<boolean>("svn.decorations.enabled", true);
165+
166+
if (this.enabled === enabled) {
167+
return;
168+
}
169+
164170
if (enabled) {
165171
this.enable();
166172
} else {
167173
this.disable();
168174
}
175+
this.enabled = enabled;
169176
}
170177

171178
private enable(): void {
@@ -175,11 +182,11 @@ export class SvnDecorations {
175182
this,
176183
this.modelListener
177184
);
178-
// this.model.onDidCloseRepository(
179-
// this.onDidCloseRepository,
180-
// this,
181-
// this.modelListener
182-
// );
185+
this.model.onDidCloseRepository(
186+
this.onDidCloseRepository,
187+
this,
188+
this.modelListener
189+
);
183190
this.model.repositories.forEach(this.onDidOpenRepository, this);
184191
}
185192

@@ -205,8 +212,6 @@ export class SvnDecorations {
205212

206213
dispose(): void {
207214
this.configListener.dispose();
208-
this.modelListener.forEach(d => d.dispose());
209-
this.providers.forEach(value => value.dispose);
210-
this.providers.clear();
215+
this.disable();
211216
}
212217
}

src/extension.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ async function init(context: ExtensionContext, disposables: Disposable[]) {
3333
const model = new Model(svn);
3434
const contentProvider = new SvnContentProvider(model);
3535
const svnCommands = new SvnCommands(model);
36-
disposables.push(model, contentProvider);
36+
disposables.push(model, contentProvider, svnCommands);
3737

3838
// First, check the vscode has support to DecorationProvider
3939
if (hasSupportToDecorationProvider()) {
@@ -54,10 +54,6 @@ async function init(context: ExtensionContext, disposables: Disposable[]) {
5454

5555
outputChannel.appendLine("Using svn " + info.version + " from " + info.path);
5656

57-
context.subscriptions.push(
58-
new Disposable(() => Disposable.from(...disposables).dispose())
59-
);
60-
6157
const onOutput = (str: string) => outputChannel.append(str);
6258
svn.onOutput.addListener("log", onOutput);
6359
disposables.push(

src/model.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import {
1010
import * as fs from "fs";
1111
import * as path from "path";
1212
import * as micromatch from "micromatch";
13-
import { Repository } from "./repository";
13+
import { Repository, RepositoryState } from "./repository";
1414
import { Svn } from "./svn";
15-
import { dispose, anyEvent, filterEvent } from "./util";
15+
import { dispose, anyEvent, filterEvent, IDisposable } from "./util";
1616
import { sequentialize } from "./decorators";
1717

1818
export interface ModelChangeEvent {
@@ -29,7 +29,7 @@ interface OpenRepository extends Disposable {
2929
repository: Repository;
3030
}
3131

32-
export class Model {
32+
export class Model implements IDisposable {
3333
private _onDidOpenRepository = new EventEmitter<Repository>();
3434
readonly onDidOpenRepository: Event<Repository> = this._onDidOpenRepository
3535
.event;
@@ -284,11 +284,19 @@ export class Model {
284284
}
285285

286286
private open(repository: Repository): void {
287+
const onDidDisappearRepository = filterEvent(
288+
repository.onDidChangeState,
289+
state => state === RepositoryState.Disposed
290+
);
291+
const disappearListener = onDidDisappearRepository(() => dispose());
292+
287293
const changeListener = repository.onDidChangeRepository(uri =>
288294
this._onDidChangeRepository.fire({ repository, uri })
289295
);
290296

291297
const dispose = () => {
298+
disappearListener.dispose();
299+
changeListener.dispose();
292300
changeListener.dispose();
293301
repository.dispose();
294302

@@ -303,6 +311,16 @@ export class Model {
303311
this._onDidOpenRepository.fire(repository);
304312
}
305313

314+
close(repository: Repository): void {
315+
const openRepository = this.getOpenRepository(repository);
316+
317+
if (!openRepository) {
318+
return;
319+
}
320+
321+
openRepository.dispose();
322+
}
323+
306324
async pickRepository() {
307325
if (this.openRepositories.length === 0) {
308326
throw new Error("There are no available repositories");

src/repository.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,6 @@ export class Repository {
137137
private _onDidChangeStatus = new EventEmitter<void>();
138138
readonly onDidChangeStatus: Event<void> = this._onDidChangeStatus.event;
139139

140-
private _onDidChangeBranch = new EventEmitter<void>();
141-
readonly onDidChangeBranch: Event<void> = this._onDidChangeBranch.event;
142-
143140
private _onDidChangeNewsCommit = new EventEmitter<void>();
144141
readonly onDidChangeNewsCommit: Event<void> = this._onDidChangeNewsCommit
145142
.event;
@@ -265,13 +262,24 @@ export class Repository {
265262
this.external.hideWhenEmpty = true;
266263
this.conflicts.hideWhenEmpty = true;
267264

265+
this.disposables.push(this.changes);
266+
this.disposables.push(this.unversioned);
267+
this.disposables.push(this.external);
268+
this.disposables.push(this.conflicts);
269+
268270
const svnConfig = workspace.getConfiguration("svn");
269271

270272
const updateFreqNews = svnConfig.get<number>("svn.newsCommits.update");
271273
if (updateFreqNews) {
272-
setInterval(() => {
274+
const interval = setInterval(() => {
273275
this.updateNewsCommits();
274276
}, 1000 * 60 * updateFreqNews);
277+
278+
this.disposables.push(
279+
toDisposable(() => {
280+
clearInterval(interval);
281+
})
282+
);
275283
}
276284

277285
this.updateNewsCommits();
@@ -431,6 +439,7 @@ export class Repository {
431439
`Changelist "${changelist}"`
432440
) as SvnResourceGroup;
433441
group.hideWhenEmpty = true;
442+
this.disposables.push(group);
434443

435444
this.changelists.set(changelist, group);
436445
}
@@ -507,9 +516,7 @@ export class Repository {
507516
}
508517

509518
async addFiles(files: string[]) {
510-
return await this.run(Operation.Add, () =>
511-
this.repository.addFiles(files)
512-
);
519+
return await this.run(Operation.Add, () => this.repository.addFiles(files));
513520
}
514521

515522
async addChangelist(files: string[], changelist: string) {

src/svn.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as path from "path";
77
import { Repository } from "./svnRepository";
88
import { parseInfoXml } from "./infoParser";
99
import { SpawnOptions } from "child_process";
10+
import { IDisposable, toDisposable, dispose } from "./util";
1011

1112
// List: https://github.com/apache/subversion/blob/1.6.x/subversion/svn/schema/status.rnc#L33
1213
export enum Status {
@@ -180,25 +181,47 @@ export class Svn {
180181

181182
let process = cp.spawn(this.svnPath, args, options);
182183

184+
const disposables: IDisposable[] = [];
185+
186+
const once = (
187+
ee: NodeJS.EventEmitter,
188+
name: string,
189+
fn: (...args: any[]) => void
190+
) => {
191+
ee.once(name, fn);
192+
disposables.push(toDisposable(() => ee.removeListener(name, fn)));
193+
};
194+
195+
const on = (
196+
ee: NodeJS.EventEmitter,
197+
name: string,
198+
fn: (...args: any[]) => void
199+
) => {
200+
ee.on(name, fn);
201+
disposables.push(toDisposable(() => ee.removeListener(name, fn)));
202+
};
203+
183204
let [exitCode, stdout, stderr] = await Promise.all<any>([
184205
new Promise<number>((resolve, reject) => {
185-
process.once("error", reject);
186-
process.once("exit", resolve);
206+
once(process, "error", reject);
207+
once(process, "exit", resolve);
187208
}),
188209
new Promise<Buffer>(resolve => {
189210
const buffers: Buffer[] = [];
190-
process.stdout.on("data", (b: Buffer) => buffers.push(b));
191-
process.stdout.once("close", () => resolve(Buffer.concat(buffers)));
211+
on(process.stdout, "data", (b: Buffer) => buffers.push(b));
212+
once(process.stdout, "close", () => resolve(Buffer.concat(buffers)));
192213
}),
193214
new Promise<string>(resolve => {
194215
const buffers: Buffer[] = [];
195-
process.stderr.on("data", (b: Buffer) => buffers.push(b));
196-
process.stderr.once("close", () =>
216+
on(process.stderr, "data", (b: Buffer) => buffers.push(b));
217+
once(process.stderr, "close", () =>
197218
resolve(Buffer.concat(buffers).toString())
198219
);
199220
})
200221
]);
201222

223+
dispose(disposables);
224+
202225
let encoding = "utf8";
203226

204227
// SVN with '--xml' always return 'UTF-8', and jschardet detects this encoding: 'TIS-620'

src/svnContentProvider.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
filterEvent,
1515
eventToPromise,
1616
isDescendant,
17-
toDisposable
17+
toDisposable,
18+
IDisposable
1819
} from "./util";
1920

2021
interface CacheRow {
@@ -29,7 +30,8 @@ interface Cache {
2930
const THREE_MINUTES = 1000 * 60 * 3;
3031
const FIVE_MINUTES = 1000 * 60 * 5;
3132

32-
export class SvnContentProvider implements TextDocumentContentProvider {
33+
export class SvnContentProvider
34+
implements IDisposable, TextDocumentContentProvider {
3335
private _onDidChange = new EventEmitter<Uri>();
3436
get onDidChange(): Event<Uri> {
3537
return this._onDidChange.event;

src/test/testUtil.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ export async function destroyPath(fullPath: string) {
156156
}
157157

158158
export function destroyAllTempPaths() {
159-
for (let path of tempDirList) {
159+
let path;
160+
while ((path = tempDirList.shift())) {
160161
destroyPath(path);
161162
}
162163
}

src/util.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Event, window } from "vscode";
22
import { sep } from "path";
33

4-
export interface BaseDisposable {
4+
export interface IDisposable {
55
dispose(): void;
66
}
77

@@ -37,12 +37,12 @@ export function dispose(disposables: any[]): any[] {
3737
}
3838

3939
export function combinedDisposable(
40-
disposables: BaseDisposable[]
41-
): BaseDisposable {
40+
disposables: IDisposable[]
41+
): IDisposable {
4242
return toDisposable(() => dispose(disposables));
4343
}
4444

45-
export function toDisposable(dispose: () => void): BaseDisposable {
45+
export function toDisposable(dispose: () => void): IDisposable {
4646
return { dispose };
4747
}
4848

0 commit comments

Comments
 (0)