csharpWatcherService.ts 3.2 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import cp = require('child_process');

import {FileChangeType} from 'vs/platform/files/common/files';
import decoder = require('vs/base/node/decoder');
import glob = require('vs/base/common/glob');
import uri from 'vs/base/common/uri';

import {IRawFileChange} from 'vs/workbench/services/files/node/watcher/common';

export class OutOfProcessWin32FolderWatcher {

	private static changeTypeMap: FileChangeType[] = [FileChangeType.UPDATED, FileChangeType.ADDED, FileChangeType.DELETED];

	private handle: cp.ChildProcess;

23 24 25 26 27 28 29
	constructor(
		private watchedFolder: string,
		private ignored: string[],
		private eventCallback: (events: IRawFileChange[]) => void,
		private errorCallback: (error: string) => void,
		private verboseLogging: boolean
	) {
E
Erich Gamma 已提交
30 31 32 33
		this.startWatcher();
	}

	private startWatcher(): void {
B
Benjamin Pasero 已提交
34
		const args = [this.watchedFolder];
E
Erich Gamma 已提交
35 36 37 38 39 40
		if (this.verboseLogging) {
			args.push('-verbose');
		}

		this.handle = cp.spawn(uri.parse(require.toUrl('vs/workbench/services/files/node/watcher/win32/CodeHelper.exe')).fsPath, args);

B
Benjamin Pasero 已提交
41
		const stdoutLineDecoder = new decoder.LineDecoder();
E
Erich Gamma 已提交
42 43 44 45 46

		// Events over stdout
		this.handle.stdout.on('data', (data: NodeBuffer) => {

			// Collect raw events from output
B
Benjamin Pasero 已提交
47
			const rawEvents: IRawFileChange[] = [];
E
Erich Gamma 已提交
48
			stdoutLineDecoder.write(data).forEach((line) => {
B
Benjamin Pasero 已提交
49
				const eventParts = line.split('|');
E
Erich Gamma 已提交
50
				if (eventParts.length === 2) {
B
Benjamin Pasero 已提交
51 52
					const changeType = Number(eventParts[0]);
					const absolutePath = eventParts[1];
E
Erich Gamma 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

					// File Change Event (0 Changed, 1 Created, 2 Deleted)
					if (changeType >= 0 && changeType < 3) {

						// Support ignores
						if (this.ignored && this.ignored.some(ignore => glob.match(ignore, absolutePath))) {
							return;
						}

						// Otherwise record as event
						rawEvents.push({
							type: OutOfProcessWin32FolderWatcher.changeTypeMap[changeType],
							path: absolutePath
						});
					}

					// 3 Logging
					else {
						console.log('%c[File Watcher]', 'color: darkgreen', eventParts[1]);
					}
				}
			});

			// Trigger processing of events through the delayer to batch them up properly
			if (rawEvents.length > 0) {
				this.eventCallback(rawEvents);
			}
		});

		// Errors
		this.handle.on('error', (error: Error) => this.onError(error));
		this.handle.stderr.on('data', (data: NodeBuffer) => this.onError(data));

		// Exit
		this.handle.on('exit', (code: any, signal: any) => this.onExit(code, signal));
	}

90 91
	private onError(error: Error | NodeBuffer): void {
		this.errorCallback('[FileWatcher] process error: ' + error.toString());
E
Erich Gamma 已提交
92 93 94 95
	}

	private onExit(code: any, signal: any): void {
		if (this.handle) { // exit while not yet being disposed is unexpected!
96
			this.errorCallback('[FileWatcher] terminated unexpectedly (code: ' + code + ', signal: ' + signal + ')');
E
Erich Gamma 已提交
97 98 99 100 101 102 103 104 105 106 107
			this.startWatcher(); // restart
		}
	}

	public dispose(): void {
		if (this.handle) {
			this.handle.kill();
			this.handle = null;
		}
	}
}