Skip to content

Commit 5cb3eb5

Browse files
Fatme HavaluovaFatme Havaluova
Fatme Havaluova
authored and
Fatme Havaluova
committed
Fix symlinks that are added to output package and points to not existing location
1 parent 78df478 commit 5cb3eb5

File tree

5 files changed

+91
-52
lines changed

5 files changed

+91
-52
lines changed

lib/services/platform-service.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -148,28 +148,35 @@ export class PlatformService implements IPlatformService {
148148
platform = platform.toLowerCase();
149149

150150
var platformData = this.$platformsData.getPlatformData(platform);
151+
let appDestinationDirectoryPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME);
152+
let lastModifiedTime = this.$fs.exists(appDestinationDirectoryPath).wait() ?
153+
this.$fs.getFsStats(appDestinationDirectoryPath).wait().mtime : null;
151154

152155
// Copy app folder to native project
156+
this.$fs.ensureDirectoryExists(appDestinationDirectoryPath).wait();
153157
var appSourceDirectoryPath = path.join(this.$projectData.projectDir, constants.APP_FOLDER_NAME);
154-
158+
155159
// Delete the destination app in order to prevent EEXIST errors when symlinks are used.
156-
this.$fs.deleteDirectory(path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME)).wait();
157-
shell.cp("-R", appSourceDirectoryPath, platformData.appDestinationDirectoryPath);
160+
_(this.$fs.readDirectory(path.join(appDestinationDirectoryPath).wait())
161+
.filter(directoryName => directoryName !== "tns_modules")
162+
.each(directoryName => this.$fs.deleteDirectory(path.join(appDestinationDirectoryPath, directoryName)).wait())
163+
.value();
164+
shell.cp("-Rf", appSourceDirectoryPath, platformData.appDestinationDirectoryPath);
158165

159166
// Copy App_Resources to project root folder
160167
this.$fs.ensureDirectoryExists(platformData.appResourcesDestinationDirectoryPath).wait(); // Should be deleted
161-
var appResourcesDirectoryPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME);
168+
var appResourcesDirectoryPath = path.join(appDestinationDirectoryPath, constants.APP_RESOURCES_FOLDER_NAME);
162169
if (this.$fs.exists(appResourcesDirectoryPath).wait()) {
163170
shell.cp("-Rf", path.join(appResourcesDirectoryPath, platformData.normalizedPlatformName, "*"), platformData.appResourcesDestinationDirectoryPath);
164171
this.$fs.deleteDirectory(appResourcesDirectoryPath).wait();
165172
}
166173

167174
// Process platform specific files
168-
var contents = this.$fs.readDirectory(path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME)).wait();
175+
var contents = this.$fs.readDirectory(path.join(appDestinationDirectoryPath)).wait();
169176
var files: string[] = [];
170177

171178
_.each(contents, d => {
172-
let filePath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME, d);
179+
let filePath = path.join(appDestinationDirectoryPath, d);
173180
let fsStat = this.$fs.getFsStats(filePath).wait();
174181
if(fsStat.isDirectory() && d !== constants.APP_RESOURCES_FOLDER_NAME) {
175182
this.processPlatformSpecificFiles(platform, this.$fs.enumerateFilesInDirectorySync(filePath)).wait();
@@ -182,7 +189,7 @@ export class PlatformService implements IPlatformService {
182189
// Process node_modules folder
183190
this.$pluginsService.ensureAllDependenciesAreInstalled().wait();
184191
var tnsModulesDestinationPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME, PlatformService.TNS_MODULES_FOLDER_NAME);
185-
this.$broccoliBuilder.prepareNodeModules(tnsModulesDestinationPath, this.$projectData.projectDir).wait();
192+
this.$broccoliBuilder.prepareNodeModules(tnsModulesDestinationPath, this.$projectData.projectDir, lastModifiedTime).wait();
186193

187194
this.$logger.out("Project successfully prepared");
188195
}).future<void>()();

lib/tools/broccoli/broccoli.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ interface BroccoliNode {
152152
}
153153

154154
interface IBroccoliBuilder {
155-
prepareNodeModules(outputPath: string, projectDir: string): IFuture<void>;
155+
prepareNodeModules(outputPath: string, projectDir: string, lastModifiedTime?: Date): IFuture<void>;
156156
}
157157

158158
interface IDiffResult {
@@ -162,6 +162,7 @@ interface IDiffResult {
162162

163163
interface IBroccoliPlugin {
164164
rebuild(diff: IDiffResult): any;
165+
rebuildChangedDirectories?(changedDirectories: string[]): void;
165166
cleanup? () : void;
166167
}
167168

lib/tools/broccoli/builder.ts

+52-14
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,67 @@ let broccoli = require('broccoli');
55
let path = require('path');
66
import Future = require("fibers/future");
77
import {TreeDiffer} from './tree-differ';
8-
import destCopy = require('./node-modules-dest-copy');
8+
import destCopyLib = require('./node-modules-dest-copy');
9+
10+
var gulp = require("gulp");
11+
var vinylFilterSince = require('vinyl-filter-since')
12+
var through = require("through2");
913

1014
export class Builder implements IBroccoliBuilder {
15+
private nodeModules: any = {};
16+
1117
constructor(private $fs: IFileSystem,
1218
private $nodeModulesTree: INodeModulesTree,
1319
private $projectDataService: IProjectDataService,
20+
private $injector: IInjector,
1421
private $logger: ILogger) { }
1522

16-
public prepareNodeModules(absoluteOutputPath: string, projectDir: string): IFuture<void> {
23+
public prepareNodeModules(absoluteOutputPath: string, projectDir: string, lastModifiedTime?: Date): IFuture<void> {
1724
return (() => {
18-
// TODO: figure out a better way for doing this
19-
this.$projectDataService.initialize(projectDir);
20-
let cachedNodeModulesPath = this.$projectDataService.getValue("node-modules-cache-path").wait();
21-
if (cachedNodeModulesPath && this.$fs.exists(cachedNodeModulesPath).wait()) {
22-
let diffTree = new TreeDiffer(cachedNodeModulesPath);
23-
let diffTreeResult = diffTree.diffTree(path.join(projectDir, absoluteOutputPath, "node_modules"));
24-
25-
if(diffTreeResult.changedDirectories.length > 0 || diffTreeResult.removedDirectories.length > 0) {
26-
this.rebuildNodeModulesTree(absoluteOutputPath, projectDir).wait();
27-
}
28-
} else {
29-
this.rebuildNodeModulesTree(absoluteOutputPath, projectDir).wait();
25+
let nodeModulesPath = path.join(projectDir, "node_modules");
26+
27+
if(lastModifiedTime) {
28+
let pipeline = gulp.src(path.join(projectDir, "node_modules/**"))
29+
.pipe(vinylFilterSince(lastModifiedTime))
30+
.pipe(through.obj( (chunk: any, enc: any, cb: Function) => {
31+
let rootModuleName = chunk.path.split(nodeModulesPath)[1].split(path.sep)[1];
32+
if(rootModuleName) {
33+
let rootModuleFullPath = path.join(nodeModulesPath, rootModuleName);
34+
this.nodeModules[rootModuleFullPath] = rootModuleFullPath;
35+
}
36+
37+
cb(null);
38+
}))
39+
.pipe(gulp.dest(absoluteOutputPath));
40+
41+
let future = new Future<void>();
42+
43+
pipeline.on('end', (err: any, data: any) => {
44+
if(err) {
45+
future.throw(err);
46+
} else {
47+
future.return();
48+
}
49+
});
50+
51+
future.wait();
52+
} else {
53+
let nodeModulesDirectories = this.$fs.readDirectory(nodeModulesPath).wait();
54+
_.each(nodeModulesDirectories, nodeModuleDirectoryName => {
55+
let nodeModuleFullPath = path.join(nodeModulesPath, nodeModuleDirectoryName);
56+
this.nodeModules[nodeModuleFullPath] = nodeModuleFullPath;
57+
});
3058
}
59+
60+
let destCopy = this.$injector.resolve(destCopyLib.DestCopy, {
61+
inputPath: projectDir,
62+
cachePath: "",
63+
outputRoot: absoluteOutputPath,
64+
projectDir: projectDir
65+
});
66+
67+
destCopy.rebuildChangedDirectories(_.keys(this.nodeModules));
68+
3169
}).future<void>()();
3270
}
3371

lib/tools/broccoli/node-modules-dest-copy.ts

+20-30
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,25 @@ import constants = require("./../../constants");
1414
* and tees a copy to the given path outside the tmp dir.
1515
*/
1616
export class DestCopy implements IBroccoliPlugin {
17-
constructor(private inputPath: string, private cachePath: string, private outputRoot: string, private projectDir: string) {}
18-
19-
public rebuild(treeDiff: IDiffResult): void {
20-
let dependencies = this.getDependencies();
21-
let devDependencies = this.getDevDependencies(this.projectDir);
17+
private dependencies: IDictionary<any> = null;
18+
private devDependencies: IDictionary<any> = null;
2219

23-
treeDiff.changedDirectories.forEach(changedDirectory => {
24-
let changedDirectoryAbsolutePath = path.join(this.inputPath, constants.NODE_MODULES_FOLDER_NAME, changedDirectory);
20+
constructor(private inputPath: string, private cachePath: string, private outputRoot: string, private projectDir: string) {
21+
this.dependencies = Object.create(null);
22+
this.devDependencies = this.getDevDependencies(projectDir);
23+
}
24+
25+
public rebuildChangedDirectories(changedDirectories: string[]): void {
26+
_.each(changedDirectories, changedDirectoryAbsolutePath => {
2527
let packageJsonFiles = [path.join(changedDirectoryAbsolutePath, "package.json")];
2628
let nodeModulesFolderPath = path.join(changedDirectoryAbsolutePath, "node_modules");
2729
packageJsonFiles = packageJsonFiles.concat(this.enumeratePackageJsonFilesSync(nodeModulesFolderPath));
28-
30+
2931
_.each(packageJsonFiles, packageJsonFilePath => {
3032
let fileContent = require(packageJsonFilePath);
3133
let isPlugin = fileContent.nativescript;
3234

33-
if(!devDependencies[fileContent.name]) { // Don't flatten dev dependencies
35+
if(!this.devDependencies[fileContent.name]) { // Don't flatten dev dependencies
3436

3537
let currentDependency = {
3638
name: fileContent.name,
@@ -39,7 +41,7 @@ export class DestCopy implements IBroccoliPlugin {
3941
isPlugin: isPlugin
4042
};
4143

42-
let addedDependency = dependencies[currentDependency.name];
44+
let addedDependency = this.dependencies[currentDependency.name];
4345
if (addedDependency) {
4446
if (semver.gt(currentDependency.version, addedDependency.version)) {
4547
let currentDependencyMajorVersion = semver.major(currentDependency.version);
@@ -49,22 +51,26 @@ export class DestCopy implements IBroccoliPlugin {
4951
let logger = $injector.resolve("$logger");
5052
currentDependencyMajorVersion === addedDependencyMajorVersion ? logger.out(message) : logger.warn(message);
5153

52-
dependencies[currentDependency.name] = currentDependency;
54+
this.dependencies[currentDependency.name] = currentDependency;
5355
}
5456
} else {
55-
dependencies[currentDependency.name] = currentDependency;
57+
this.dependencies[currentDependency.name] = currentDependency;
5658
}
5759
}
5860
});
5961
});
6062

61-
_.each(dependencies, dependency => {
62-
shelljs.cp("-R", dependency.directory, this.outputRoot);
63+
_.each(this.dependencies, dependency => {
64+
shelljs.cp("-Rf", dependency.directory, this.outputRoot);
6365
shelljs.rm("-rf", path.join(this.outputRoot, dependency.name, "node_modules"));
6466
if(dependency.isPlugin) {
6567
shelljs.rm("-rf", path.join(this.outputRoot, dependency.name, "platforms"));
6668
}
6769
});
70+
}
71+
72+
public rebuild(treeDiff: IDiffResult): void {
73+
this.rebuildChangedDirectories(treeDiff.changedDirectories);
6874

6975
// Cache input tree
7076
let projectFilePath = path.join(this.projectDir, constants.PACKAGE_JSON_FILE_NAME);
@@ -73,22 +79,6 @@ export class DestCopy implements IBroccoliPlugin {
7379
fs.writeFileSync(projectFilePath, JSON.stringify(projectFileContent, null, "\t"), { encoding: "utf8" });
7480
}
7581

76-
private getDependencies(): IDictionary<any> {
77-
let result = Object.create(null);
78-
if(fs.existsSync(this.outputRoot)) {
79-
let dirs = fs.readdirSync(this.outputRoot);
80-
_.each(dirs, dir => {
81-
let filePath = path.join(dir, constants.PACKAGE_JSON_FILE_NAME);
82-
if(fs.existsSync(filePath)) {
83-
let fileContent = require(filePath);
84-
result[fileContent.name] = fileContent;
85-
}
86-
});
87-
}
88-
89-
return result;
90-
}
91-
9282
private getDevDependencies(projectDir: string): IDictionary<any> {
9383
let projectFilePath = path.join(projectDir, constants.PACKAGE_JSON_FILE_NAME);
9484
let projectFileContent = require(projectFilePath);

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"fibers": "https://github.com/icenium/node-fibers/tarball/v1.0.5.1",
3838
"filesize": "2.0.3",
3939
"gaze": "0.5.1",
40+
"gulp": "3.9.0",
4041
"iconv-lite": "0.4.4",
4142
"inquirer": "0.8.2",
4243
"ios-sim-portable": "1.0.8",
@@ -65,7 +66,9 @@
6566
"shelljs": "0.3.0",
6667
"tabtab": "https://github.com/Icenium/node-tabtab/tarball/master",
6768
"temp": "0.8.1",
69+
"through2": "2.0.0",
6870
"utf-8-validate": "https://github.com/telerik/utf-8-validate/tarball/master",
71+
"vinyl-filter-since": "2.0.0",
6972
"winreg": "0.0.12",
7073
"ws": "0.7.1",
7174
"xcode": "https://github.com/NativeScript/node-xcode/archive/NativeScript-0.9.tar.gz",

0 commit comments

Comments
 (0)