Skip to content

Commit 48e4e82

Browse files
Fix the updating of changed node modules in platform folder
When getting the stats for file from node_modules in the broccoli builder the event loop gets messed up from the Glob fiber and the cli fiber. That's why we need lock in the Glob fiber.
1 parent 777e18e commit 48e4e82

File tree

5 files changed

+37
-8
lines changed

5 files changed

+37
-8
lines changed

lib/declarations.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ interface IApplicationPackage {
4848
interface ILockFile {
4949
lock(): IFuture<void>;
5050
unlock(): IFuture<void>;
51+
check(): IFuture<boolean>;
5152
}
5253

5354
interface IOpener {

lib/definitions/lockfile.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ declare module "lockfile" {
33
export function lockSync(lockFilename: string, lockParams: ILockSyncParams): void;
44
export function unlock(lockFilename: string, callback: (err: Error) => void): void;
55
export function unlockSync(lockFilename: string): void;
6+
export function check(lockFilename: string, lockParams: ILockParams, callback: (err: Error, isLocked: boolean) => void): boolean;
67

78
interface ILockSyncParams {
89
retries: number;

lib/lockfile.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,18 @@ export class LockFile implements ILockFile {
4242
});
4343
return future;
4444
}
45+
46+
public check(): IFuture<boolean> {
47+
let future = new Future<boolean>();
48+
lockfile.check(this.lockFilePath, LockFile.LOCK_PARAMS, (err: Error, isLocked: boolean) => {
49+
if(err) {
50+
future.throw(err);
51+
} else {
52+
future.return(isLocked);
53+
}
54+
});
55+
return future;
56+
}
4557
}
58+
4659
$injector.register("lockfile", LockFile);

lib/tools/broccoli/builder.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ export class Builder implements IBroccoliBuilder {
1818
private $projectData: IProjectData,
1919
private $projectDataService: IProjectDataService,
2020
private $injector: IInjector,
21-
private $logger: ILogger
22-
) {
23-
}
21+
private $logger: ILogger,
22+
private $lockfile: ILockFile) { }
2423

2524
public getChangedNodeModules(absoluteOutputPath: string, platform: string, lastModifiedTime?: Date): IFuture<any> {
2625
return (() => {
@@ -38,10 +37,13 @@ export class Builder implements IBroccoliBuilder {
3837
stat: true
3938
}, (er: Error, files: string[]) => {
4039
fiberBootstrap.run(() => {
40+
this.$lockfile.lock().wait();
4141
if (er) {
4242
if (!future.isResolved()) {
4343
future.throw(er);
4444
}
45+
46+
this.$lockfile.unlock().wait();
4547
match.abort();
4648
return;
4749
}
@@ -59,6 +61,7 @@ export class Builder implements IBroccoliBuilder {
5961
}
6062
if (file === constants.NODE_MODULES_FOLDER_NAME) {
6163
isNodeModulesModified = true;
64+
this.$lockfile.unlock().wait();
6265
match.abort();
6366
if (!future.isResolved()) {
6467
future.return();
@@ -69,29 +72,38 @@ export class Builder implements IBroccoliBuilder {
6972
let rootModuleFullPath = path.join(nodeModulesPath, rootModuleName);
7073
nodeModules[rootModuleFullPath] = rootModuleFullPath;
7174
}
75+
76+
this.$lockfile.unlock().wait();
7277
});
7378
});
7479
match.on("end", () => {
7580
if (!future.isResolved()) {
76-
future.return();
81+
let intervalId = setInterval(() => {
82+
fiberBootstrap.run(() => {
83+
if (!this.$lockfile.check().wait()) {
84+
future.return();
85+
clearInterval(intervalId);
86+
}
87+
});
88+
}, 100);
7789
}
7890
});
7991

8092
future.wait();
8193
}
8294

83-
if(isNodeModulesModified && this.$fs.exists(absoluteOutputPath).wait()) {
95+
if (isNodeModulesModified && this.$fs.exists(absoluteOutputPath).wait()) {
8496
let currentPreparedTnsModules = this.$fs.readDirectory(absoluteOutputPath).wait();
8597
let tnsModulesPath = path.join(projectDir, constants.APP_FOLDER_NAME, constants.TNS_MODULES_FOLDER_NAME);
86-
if(!this.$fs.exists(tnsModulesPath).wait()) {
98+
if (!this.$fs.exists(tnsModulesPath).wait()) {
8799
tnsModulesPath = path.join(projectDir, constants.NODE_MODULES_FOLDER_NAME, constants.TNS_CORE_MODULES_NAME);
88100
}
89101
let tnsModulesInApp = this.$fs.readDirectory(tnsModulesPath).wait();
90102
let modulesToDelete = _.difference(currentPreparedTnsModules, tnsModulesInApp);
91103
_.each(modulesToDelete, moduleName => this.$fs.deleteDirectory(path.join(absoluteOutputPath, moduleName)).wait());
92104
}
93105

94-
if(!lastModifiedTime || isNodeModulesModified) {
106+
if (!lastModifiedTime || isNodeModulesModified) {
95107
this.listModules(nodeModulesPath, nodeModules);
96108
}
97109

test/npm-support.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {DeviceAppDataProvider} from "../lib/providers/device-app-data-provider";
2828
import {MobilePlatformsCapabilities} from "../lib/mobile-platforms-capabilities";
2929
import {DevicePlatformsConstants} from "../lib/common/mobile/device-platforms-constants";
3030
import { XmlValidator } from "../lib/xml-validator";
31+
import { LockFile } from "../lib/lockfile";
3132
import Future = require("fibers/future");
3233

3334
import path = require("path");
@@ -48,7 +49,7 @@ function createTestInjector(): IInjector {
4849
testInjector.register("platformService", PlatformServiceLib.PlatformService);
4950
testInjector.register("logger", stubs.LoggerStub);
5051
testInjector.register("npmInstallationManager", {});
51-
testInjector.register("lockfile", {});
52+
testInjector.register("lockfile", LockFile);
5253
testInjector.register("prompter", {});
5354
testInjector.register("androidProjectService", {});
5455
testInjector.register("iOSProjectService", {});
@@ -235,6 +236,7 @@ describe("Npm support tests", () => {
235236

236237
it("Ensures that tns_modules absent when bundling", () => {
237238
let fs = testInjector.resolve("fs");
239+
let lockfile = testInjector.resolve("lockfile");
238240
let options = testInjector.resolve("options");
239241
let tnsModulesFolderPath = path.join(appDestinationFolderPath, "app", "tns_modules");
240242

0 commit comments

Comments
 (0)