Skip to content
This repository was archived by the owner on Feb 2, 2021. It is now read-only.

Commit e195212

Browse files
committed
Merge pull request #575 from telerik/hdeshev/livesync-prepare-hook-release2
(livesync) Wait for filesystem changes after prepare hook.
2 parents 7201c9e + c337d26 commit e195212

File tree

1 file changed

+113
-64
lines changed

1 file changed

+113
-64
lines changed

services/usb-livesync-service-base.ts

Lines changed: 113 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import minimatch = require("minimatch");
55
import * as path from "path";
66
import * as util from "util";
77
import * as moment from "moment";
8+
import * as fiberBootstrap from "../fiber-bootstrap";
89
let gaze = require("gaze");
910

1011
interface IProjectFileInfo {
@@ -13,39 +14,68 @@ interface IProjectFileInfo {
1314
shouldIncludeFile: boolean;
1415
}
1516

17+
// https://github.com/Microsoft/TypeScript/blob/master/src/compiler/tsc.ts#L487-L489
18+
const SYNC_WAIT_THRESHOLD = 250; //milliseconds
19+
1620
class SyncBatch {
1721
private timer: NodeJS.Timer = null;
1822
private syncQueue: string[] = [];
23+
private syncInProgress: boolean = false;
1924

2025
constructor(
2126
private $logger: ILogger,
2227
private $dispatcher: IFutureDispatcher,
23-
private done: (filesToSync: Array<string>) => void) {
24-
}
28+
private syncData: ILiveSyncData,
29+
private done: () => IFuture<void>) {
30+
}
31+
32+
private get filesToSync(): string[] {
33+
let filteredFiles = this.syncQueue.filter(syncFilePath => !UsbLiveSyncServiceBase.isFileExcluded(path.relative(this.syncData.projectFilesPath, syncFilePath), this.syncData.excludedProjectDirsAndFiles, this.syncData.projectFilesPath));
34+
return filteredFiles;
35+
}
2536

26-
public addFile(filePath: string): void {
27-
if (this.timer) {
28-
clearTimeout(this.timer);
37+
public get syncPending() {
38+
return this.syncQueue.length > 0;
39+
}
40+
41+
public reset(): void {
42+
this.syncQueue = [];
43+
}
44+
45+
public syncFiles(syncAction: (filesToSync: string[]) => IFuture<void>): IFuture<void> {
46+
return (() => {
47+
if (this.filesToSync.length > 0) {
48+
syncAction(this.filesToSync).wait();
49+
this.reset();
2950
}
51+
}).future<void>()();
52+
}
3053

31-
this.syncQueue.push(filePath);
54+
public addFile(filePath: string): void {
55+
if (this.timer) {
56+
clearTimeout(this.timer);
57+
this.timer = null;
58+
}
3259

60+
this.syncQueue.push(filePath);
61+
62+
if (!this.syncInProgress) {
3363
this.timer = setTimeout(() => {
34-
let filesToSync = this.syncQueue;
35-
if (filesToSync.length > 0) {
36-
this.syncQueue = [];
37-
this.$logger.trace("Syncing %s", filesToSync.join(", "));
38-
this.$dispatcher.dispatch( () => {
39-
return (() => this.done(filesToSync)).future<void>()();
64+
if (this.syncQueue.length > 0) {
65+
this.$logger.trace("Syncing %s", this.syncQueue.join(", "));
66+
fiberBootstrap.run(() => {
67+
try {
68+
this.syncInProgress = true;
69+
this.done().wait();
70+
} finally {
71+
this.syncInProgress = false;
72+
}
4073
});
4174
}
4275
this.timer = null;
43-
}, 250); // https://github.com/Microsoft/TypeScript/blob/master/src/compiler/tsc.ts#L487-L489
44-
}
45-
46-
public get syncPending() {
47-
return this.syncQueue.length > 0;
76+
}, SYNC_WAIT_THRESHOLD);
4877
}
78+
}
4979
}
5080

5181
export class UsbLiveSyncServiceBase implements IUsbLiveSyncServiceBase {
@@ -96,7 +126,7 @@ export class UsbLiveSyncServiceBase implements IUsbLiveSyncServiceBase {
96126
}
97127

98128
let projectFiles = this.$fs.enumerateFilesInDirectorySync(data.projectFilesPath,
99-
(filePath, stat) => !this.isFileExcluded(path.relative(data.projectFilesPath, filePath), data.excludedProjectDirsAndFiles, data.projectFilesPath),
129+
(filePath, stat) => !UsbLiveSyncServiceBase.isFileExcluded(path.relative(data.projectFilesPath, filePath), data.excludedProjectDirsAndFiles, data.projectFilesPath),
100130
{ enumerateDirectories: true }
101131
);
102132

@@ -111,32 +141,30 @@ export class UsbLiveSyncServiceBase implements IUsbLiveSyncServiceBase {
111141
gaze("**/*", { cwd: data.watchGlob }, function(err: any, watcher: any) {
112142
this.on('all', (event: string, filePath: string) => {
113143
if (event === "added" || event === "changed") {
114-
if (!that.isFileExcluded(filePath, data.excludedProjectDirsAndFiles, data.projectFilesPath)) {
115-
that.$dispatcher.dispatch(() => (() => {
116-
let fileHash = that.$fs.getFsStats(filePath).wait().isFile() ? that.$fs.getFileShasum(filePath).wait() : "";
117-
if (fileHash === that.fileHashes[filePath]) {
118-
that.$logger.trace(`Skipping livesync for ${filePath} file with ${fileHash} hash.`);
119-
return;
120-
}
121-
122-
that.$logger.trace(`Adding ${filePath} file with ${fileHash} hash.`);
123-
that.fileHashes[filePath] = fileHash;
124-
125-
let canExecuteFastLiveSync = data.canExecuteFastLiveSync && data.canExecuteFastLiveSync(filePath);
126-
127-
if (synciOSSimulator && !canExecuteFastLiveSync) {
128-
that.batchSimulatorLiveSync(data, filePath);
129-
}
130-
131-
if ((!that.$options.emulator || data.platform.toLowerCase() === "android") && !canExecuteFastLiveSync) {
132-
that.batchLiveSync(data, filePath);
133-
}
134-
135-
if (canExecuteFastLiveSync) {
136-
data.fastLiveSync(filePath);
137-
}
138-
}).future<void>()());
139-
}
144+
that.$dispatcher.dispatch(() => (() => {
145+
let fileHash = that.$fs.getFsStats(filePath).wait().isFile() ? that.$fs.getFileShasum(filePath).wait() : "";
146+
if (fileHash === that.fileHashes[filePath]) {
147+
that.$logger.trace(`Skipping livesync for ${filePath} file with ${fileHash} hash.`);
148+
return;
149+
}
150+
151+
that.$logger.trace(`Adding ${filePath} file with ${fileHash} hash.`);
152+
that.fileHashes[filePath] = fileHash;
153+
154+
let canExecuteFastLiveSync = data.canExecuteFastLiveSync && data.canExecuteFastLiveSync(filePath);
155+
156+
if (synciOSSimulator && !canExecuteFastLiveSync) {
157+
that.batchSimulatorLiveSync(data, filePath);
158+
}
159+
160+
if ((!that.$options.emulator || data.platform.toLowerCase() === "android") && !canExecuteFastLiveSync) {
161+
that.batchLiveSync(data, filePath);
162+
}
163+
164+
if (canExecuteFastLiveSync) {
165+
data.fastLiveSync(filePath);
166+
}
167+
}).future<void>()());
140168
}
141169

142170
if (event === "deleted") {
@@ -265,41 +293,62 @@ export class UsbLiveSyncServiceBase implements IUsbLiveSyncServiceBase {
265293
private batch: SyncBatch = null;
266294

267295
private batchLiveSync(data: ILiveSyncData, filePath: string) : void {
296+
this.$dispatcher.dispatch( () => (() => {
268297
if (!this.batch || !this.batch.syncPending) {
269-
this.batch = new SyncBatch(
270-
this.$logger, this.$dispatcher, (filesToSync) => {
271-
this.preparePlatformForSync(data.platform);
272-
this.syncCore(data, filesToSync, true).wait();
273-
}
274-
);
298+
this.batch = new SyncBatch(this.$logger, this.$dispatcher, data, () => {
299+
return (() => {
300+
this.preparePlatformForSync(data.platform).wait();
301+
302+
setTimeout(() => {
303+
fiberBootstrap.run(() => {
304+
this.batch.syncFiles(filesToSync => this.syncCore(data, filesToSync, true)).wait();
305+
});
306+
}, SYNC_WAIT_THRESHOLD);
307+
}).future<void>()();
308+
});
275309
}
276310

277-
this.$dispatcher.dispatch( () => (() => {
278311
let fileToSync = data.beforeBatchLiveSyncAction ? data.beforeBatchLiveSyncAction(filePath).wait() : filePath;
279-
if(fileToSync) {
312+
if (fileToSync) {
280313
this.batch.addFile(fileToSync);
281314
}
282315
}).future<void>()());
283316
}
284317

285318
private batchSimulatorLiveSync(data: ILiveSyncData, filePath: string): void {
319+
this.$dispatcher.dispatch( () => (() => {
286320
if (!this.batch || !this.batch.syncPending) {
287-
this.batch = new SyncBatch(
288-
this.$logger, this.$dispatcher, (filesToSync) => {
289-
this.preparePlatformForSync(data.platform);
290-
this.$iOSEmulatorServices.syncFiles(data.appIdentifier, data.projectFilesPath, filesToSync, data.notRunningiOSSimulatorAction, data.getApplicationPathForiOSSimulatorAction, data.iOSSimulatorRelativeToProjectBasePathAction);
291-
}
292-
);
321+
this.batch = new SyncBatch(this.$logger, this.$dispatcher, data, () => {
322+
return (() => {
323+
this.preparePlatformForSync(data.platform).wait();
324+
325+
setTimeout(() => {
326+
fiberBootstrap.run(() => {
327+
this.batch.syncFiles(filesToSync =>
328+
this.$iOSEmulatorServices.syncFiles(data.appIdentifier,
329+
data.projectFilesPath,
330+
filesToSync,
331+
data.notRunningiOSSimulatorAction,
332+
data.getApplicationPathForiOSSimulatorAction,
333+
data.iOSSimulatorRelativeToProjectBasePathAction)).wait();
334+
});
335+
}, SYNC_WAIT_THRESHOLD);
336+
}).future<void>()();
337+
});
293338
}
294339

295-
this.batch.addFile(filePath);
296-
}
340+
let fileToSync = data.beforeBatchLiveSyncAction ? data.beforeBatchLiveSyncAction(filePath).wait() : filePath;
341+
this.batch.addFile(fileToSync);
297342

298-
protected preparePlatformForSync(platform: string) {
299-
//Overridden in platform-specific services.
300-
}
343+
}).future<void>()());
344+
}
345+
346+
protected preparePlatformForSync(platform: string): IFuture<void> {
347+
return null;
348+
//Overridden in platform-specific services.
349+
}
301350

302-
private isFileExcluded(path: string, exclusionList: string[], projectDir: string): boolean {
351+
public static isFileExcluded(path: string, exclusionList: string[], projectDir: string): boolean {
303352
return !!_.find(exclusionList, (pattern) => minimatch(path, pattern, { nocase: true }));
304353
}
305354

0 commit comments

Comments
 (0)