Skip to content

Commit 60ebca9

Browse files
FatmeFatme
Fatme
authored and
Fatme
committed
Merge pull request #318 from NativeScript/fatme/fix-update-1
Fix update
2 parents be50f67 + d8ae20a commit 60ebca9

9 files changed

+151
-42
lines changed

lib/commands/update-platform.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export class UpdatePlatformCommand implements ICommand {
1717
this.$errors.fail("No platform specified. Please specify platforms to update.");
1818
}
1919

20-
_.each(args, arg => this.$platformService.validatePlatformInstalled(arg));
20+
_.each(args, arg => this.$platformService.validatePlatformInstalled(arg.split("@")[0]));
2121

2222
return true;
2323
}).future<boolean>()();

lib/declarations.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ interface INodePackageManager {
55
load(config?: any): IFuture<void>;
66
install(packageName: string, options?: INpmInstallOptions): IFuture<string>;
77
getLatestVersion(packageName: string): IFuture<string>;
8+
getCachedPackagePath(packageName: string, version: string): string;
89
}
910

1011
interface INpmInstallOptions {

lib/definitions/platform.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ interface IPlatformData {
2727
validPackageNamesForDevice: string[];
2828
validPackageNamesForEmulator?: string[];
2929
frameworkFilesExtensions: string[];
30+
frameworkDirectoriesExtensions?: string[];
31+
frameworkDirectoriesNames?: string[];
3032
targetedOS?: string[];
3133
}
3234

lib/definitions/project.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,6 @@ interface IPlatformProjectService {
3030
buildProject(projectRoot: string): IFuture<void>;
3131
isPlatformPrepared(projectRoot: string): IFuture<boolean>;
3232
addLibrary(platformData: IPlatformData, libraryPath: string): IFuture<void>;
33+
canUpdatePlatform(currentVersion: string, newVersion: string): IFuture<boolean>;
34+
updatePlatform(currentVersion: string, newVersion: string): IFuture<void>;
3335
}

lib/node-package-manager.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,14 @@ export class NodePackageManager implements INodePackageManager {
3030
}
3131

3232
public addToCache(packageName: string, version: string): IFuture<void> {
33-
return this.addToCacheCore(packageName, version);
33+
return (() => {
34+
this.addToCacheCore(packageName, version).wait();
35+
36+
var packagePath = path.join(npm.cache, packageName, version, "package");
37+
if(!this.isPackageUnpacked(packagePath).wait()) {
38+
this.cacheUnpack(packageName, version).wait();
39+
}
40+
}).future<void>()();
3441
}
3542

3643
public load(config?: any): IFuture<void> {
@@ -73,6 +80,10 @@ export class NodePackageManager implements INodePackageManager {
7380
}).future<string>()();
7481
}
7582

83+
public getCachedPackagePath(packageName: string, version: string): string {
84+
return path.join(npm.cache, packageName, version, "package");
85+
}
86+
7687
private installCore(packageName: string, pathToSave: string, version: string): IFuture<string> {
7788
return (() => {
7889
if (options.frameworkPath) {
@@ -84,8 +95,8 @@ export class NodePackageManager implements INodePackageManager {
8495
}
8596
return options.frameworkPath;
8697
} else {
87-
var version: string = version || this.getLatestVersion(packageName).wait();
88-
var packagePath = path.join(npm.cache, packageName, version, "package");
98+
version = version || this.getLatestVersion(packageName).wait();
99+
var packagePath = this.getCachedPackagePath(packageName, version);
89100
if (!this.isPackageCached(packagePath).wait()) {
90101
this.addToCacheCore(packageName, version).wait();
91102
}

lib/services/android-project-service.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ class AndroidProjectService implements IPlatformProjectService {
2323
private $logger: ILogger,
2424
private $projectData: IProjectData,
2525
private $propertiesParser: IPropertiesParser) {
26-
2726
}
2827

2928
public get platformData(): IPlatformData {
@@ -38,7 +37,7 @@ class AndroidProjectService implements IPlatformProjectService {
3837
util.format("%s-%s.%s", this.$projectData.projectName, "debug", "apk"),
3938
util.format("%s-%s.%s", this.$projectData.projectName, "release", "apk")
4039
],
41-
frameworkFilesExtensions: [".jar", ".dat"]
40+
frameworkFilesExtensions: [".jar", ".dat", ".so"]
4241
};
4342
}
4443

@@ -123,6 +122,16 @@ class AndroidProjectService implements IPlatformProjectService {
123122
}).future<string>()();
124123
}
125124

125+
public canUpdatePlatform(currentVersion: string, newVersion: string): IFuture<boolean> {
126+
return (() => {
127+
return true;
128+
}).future<boolean>()();
129+
}
130+
131+
updatePlatform(currentVersion: string, newVersion: string): IFuture<void> {
132+
return (() => { }).future<void>()();
133+
}
134+
126135
private updateMetadata(projectRoot: string): void {
127136
var projMetadataDir = path.join(projectRoot, "assets", "metadata");
128137
var libsmetadataDir = path.join(projectRoot, "../../lib", this.platformData.normalizedPlatformName, AndroidProjectService.METADATA_DIRNAME);

lib/services/ios-project-service.ts

+45-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ class IOSProjectService implements IPlatformProjectService {
2020
private $childProcess: IChildProcess,
2121
private $errors: IErrors,
2222
private $logger: ILogger,
23-
private $iOSEmulatorServices: Mobile.IEmulatorPlatformServices) { }
23+
private $iOSEmulatorServices: Mobile.IEmulatorPlatformServices,
24+
private $npm: INodePackageManager) { }
2425

2526
public get platformData(): IPlatformData {
2627
return {
@@ -37,7 +38,9 @@ class IOSProjectService implements IPlatformProjectService {
3738
validPackageNamesForEmulator: [
3839
this.$projectData.projectName + ".app"
3940
],
40-
frameworkFilesExtensions: [".a", ".h", ".bin"],
41+
frameworkFilesExtensions: [".a", ".framework", ".bin"],
42+
frameworkDirectoriesExtensions: [".framework"],
43+
frameworkDirectoriesNames: ["Metadata"],
4144
targetedOS: ['darwin']
4245
};
4346
}
@@ -70,7 +73,7 @@ class IOSProjectService implements IPlatformProjectService {
7073
var xcodeProjectName = util.format("%s.xcodeproj", IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER);
7174

7275
shell.cp("-R", path.join(frameworkDir, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER, "*"), path.join(projectRoot, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER));
73-
shell.cp("-R", path.join(frameworkDir, xcodeProjectName), path.join(projectRoot));
76+
shell.cp("-R", path.join(frameworkDir, xcodeProjectName), projectRoot);
7477

7578
var directoryContent = this.$fs.readDirectory(frameworkDir).wait();
7679
var frameworkFiles = _.difference(directoryContent, [IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER, xcodeProjectName]);
@@ -193,7 +196,45 @@ class IOSProjectService implements IPlatformProjectService {
193196
this.$fs.writeFile(pbxProjPath, project.writeSync()).wait();
194197
this.$logger.info("The iOS Deployment Target is now 8.0 in order to support Cocoa Touch Frameworks.");
195198
}).future<void>()();
196-
}
199+
}
200+
201+
public canUpdatePlatform(currentVersion: string, newVersion: string): IFuture<boolean> {
202+
return (() => {
203+
var currentXcodeProjectFile = this.buildPathToXcodeProjectFile(currentVersion);
204+
var currentXcodeProjectFileContent = this.$fs.readFile(currentXcodeProjectFile).wait();
205+
206+
var newXcodeProjectFile = this.buildPathToXcodeProjectFile(newVersion);
207+
var newXcodeProjectFileContent = this.$fs.readFile(newXcodeProjectFile).wait();
208+
209+
return currentXcodeProjectFileContent === newXcodeProjectFileContent;
210+
211+
}).future<boolean>()();
212+
}
213+
214+
public updatePlatform(currentVersion: string, newVersion: string): IFuture<void> {
215+
return (() => {
216+
// Copy old file to options["profile-dir"]
217+
var sourceFile = path.join(this.platformData.projectRoot, util.format("%s.xcodeproj", this.$projectData.projectName));
218+
var destinationFile = path.join(options.profileDir, "xcodeproj");
219+
this.$fs.deleteDirectory(destinationFile).wait();
220+
shell.cp("-R", path.join(sourceFile, "*"), destinationFile);
221+
this.$logger.info("Backup file %s at location %s", sourceFile, destinationFile);
222+
this.$fs.deleteDirectory(path.join(this.platformData.projectRoot, util.format("%s.xcodeproj", this.$projectData.projectName))).wait();
223+
224+
// Copy xcodeProject file
225+
var cachedPackagePath = path.join(this.$npm.getCachedPackagePath(this.platformData.frameworkPackageName, newVersion), constants.PROJECT_FRAMEWORK_FOLDER_NAME, util.format("%s.xcodeproj", IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER));
226+
shell.cp("-R", path.join(cachedPackagePath, "*"), path.join(this.platformData.projectRoot, util.format("%s.xcodeproj", this.$projectData.projectName)));
227+
this.$logger.info("Copied from %s at %s.", cachedPackagePath, this.platformData.projectRoot);
228+
229+
230+
var pbxprojFilePath = path.join(this.platformData.projectRoot, this.$projectData.projectName + IOSProjectService.XCODE_PROJECT_EXT_NAME, "project.pbxproj");
231+
this.replaceFileContent(pbxprojFilePath).wait();
232+
}).future<void>()();
233+
}
234+
235+
private buildPathToXcodeProjectFile(version: string): string {
236+
return path.join(this.$npm.getCachedPackagePath(this.platformData.frameworkPackageName, version), constants.PROJECT_FRAMEWORK_FOLDER_NAME, util.format("%s.xcodeproj", IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER), "project.pbxproj");
237+
}
197238

198239
private validateDynamicFramework(libraryPath: string): IFuture<void> {
199240
return (() => {

lib/services/platform-service.ts

+65-32
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ export class PlatformService implements IPlatformService {
310310
this.$errors.fail("No platform specified.")
311311
}
312312

313-
platform = platform.toLowerCase();
313+
var parts = platform.split("@");
314+
platform = parts[0].toLowerCase();
314315

315316
if (!this.isValidPlatform(platform)) {
316317
this.$errors.fail("Invalid platform %s. Valid platforms are %s.", platform, helpers.formatListOfNames(this.$platformsData.platformsNames));
@@ -442,19 +443,28 @@ export class PlatformService implements IPlatformService {
442443
var currentVersion = data && data.version ? data.version : "0.2.0";
443444
var newVersion = version || this.$npm.getLatestVersion(platformData.frameworkPackageName).wait();
444445

445-
if(!semver.valid(newVersion)) {
446-
this.$errors.fail("The version %s is not valid. The version should consists from 3 parts seperated by dot.", newVersion);
447-
}
446+
if(platformData.platformProjectService.canUpdatePlatform(currentVersion, newVersion).wait()) {
448447

449-
if(semver.gt(currentVersion, newVersion)) { // Downgrade
450-
var isUpdateConfirmed = this.$prompter.confirm("You are going to update to lower version. Are you sure?", () => "n").wait();
451-
if(isUpdateConfirmed) {
448+
if(!semver.valid(newVersion)) {
449+
this.$errors.fail("The version %s is not valid. The version should consists from 3 parts separated by dot.", newVersion);
450+
}
451+
452+
if(semver.gt(currentVersion, newVersion)) { // Downgrade
453+
var isUpdateConfirmed = this.$prompter.confirm(util.format("You are going to downgrade to android runtime v.%s. Are you sure?", newVersion), () => "n").wait();
454+
if(isUpdateConfirmed) {
455+
this.updatePlatformCore(platformData, currentVersion, newVersion).wait();
456+
}
457+
} else if(semver.eq(currentVersion, newVersion)) {
458+
this.$errors.fail("Current and new version are the same.");
459+
} else {
452460
this.updatePlatformCore(platformData, currentVersion, newVersion).wait();
453461
}
454-
} else if(semver.eq(currentVersion, newVersion)) {
455-
this.$errors.fail("Current and new version are the same.");
456462
} else {
457-
this.updatePlatformCore(platformData, currentVersion, newVersion).wait();
463+
var isUpdateConfirmed = this.$prompter.confirm(util.format("We need to override xcodeproj file. The old one will be saved at %s. Are you sure?", options.profileDir), () => "y").wait();
464+
if(isUpdateConfirmed) {
465+
platformData.platformProjectService.updatePlatform(currentVersion, newVersion).wait();
466+
this.updatePlatformCore(platformData, currentVersion, newVersion).wait();
467+
}
458468
}
459469

460470
}).future<void>()();
@@ -463,16 +473,36 @@ export class PlatformService implements IPlatformService {
463473
private updatePlatformCore(platformData: IPlatformData, currentVersion: string, newVersion: string): IFuture<void> {
464474
return (() => {
465475
// Remove old framework files
466-
var oldFrameworkFiles = this.getFrameworkFiles(platformData, currentVersion).wait();
467-
_.each(oldFrameworkFiles, file => {
468-
this.$fs.deleteFile(path.join(platformData.projectRoot, file)).wait();
476+
var oldFrameworkData = this.getFrameworkFiles(platformData, currentVersion).wait();
477+
478+
_.each(oldFrameworkData.frameworkFiles, file => {
479+
var fileToDelete = path.join(platformData.projectRoot, file);
480+
this.$logger.trace("Deleting %s", fileToDelete);
481+
this.$fs.deleteFile(fileToDelete).wait();
482+
});
483+
484+
_.each(oldFrameworkData.frameworkDirectories, dir => {
485+
var dirToDelete = path.join(platformData.projectRoot, dir);
486+
this.$logger.trace("Deleting %s", dirToDelete);
487+
this.$fs.deleteDirectory(dirToDelete).wait();
469488
});
470489

471490
// Add new framework files
472-
var newFrameworkFiles = this.getFrameworkFiles(platformData, newVersion).wait();
473-
var cacheDirectoryPath = this.getNpmCacheDirectoryCore(platformData.frameworkPackageName, newVersion);
474-
_.each(newFrameworkFiles, file => {
475-
shell.cp("-f", path.join(cacheDirectoryPath, file), path.join(platformData.projectRoot, file));
491+
var newFrameworkData = this.getFrameworkFiles(platformData, newVersion).wait();
492+
var cacheDirectoryPath = this.$npm.getCachedPackagePath(platformData.frameworkPackageName, newVersion);
493+
494+
_.each(newFrameworkData.frameworkFiles, file => {
495+
var sourceFile = path.join(cacheDirectoryPath, constants.PROJECT_FRAMEWORK_FOLDER_NAME, file);
496+
var destinationFile = path.join(platformData.projectRoot, file);
497+
this.$logger.trace("Replacing %s with %s", sourceFile, destinationFile);
498+
shell.cp("-f", sourceFile, destinationFile);
499+
});
500+
501+
_.each(newFrameworkData.frameworkDirectories, dir => {
502+
var sourceDirectory = path.join(cacheDirectoryPath, constants.PROJECT_FRAMEWORK_FOLDER_NAME, dir);
503+
var destinationDirectory = path.join(platformData.projectRoot, dir);
504+
this.$logger.trace("Copying %s to %s", sourceDirectory, destinationDirectory);
505+
shell.cp("-fR", path.join(sourceDirectory, "*"), destinationDirectory);
476506
});
477507

478508
// Update .tnsproject file
@@ -484,32 +514,35 @@ export class PlatformService implements IPlatformService {
484514
}).future<void>()();
485515
}
486516

487-
private getFrameworkFiles(platformData: IPlatformData, version: string): IFuture<string[]> {
517+
private getFrameworkFiles(platformData: IPlatformData, version: string): IFuture<any> {
488518
return (() => {
489-
var npmCacheDirectoryPath = this.getNpmCacheDirectory(platformData.frameworkPackageName, version).wait();
490-
var allFiles = this.$fs.enumerateFilesInDirectorySync(npmCacheDirectoryPath);
519+
var cachedPackagePath = this.$npm.getCachedPackagePath(platformData.frameworkPackageName, version);
520+
this.ensurePackageIsCached(cachedPackagePath, platformData.frameworkPackageName, version).wait();
521+
522+
var allFiles = this.$fs.enumerateFilesInDirectorySync(cachedPackagePath);
491523
var filteredFiles = _.filter(allFiles, file => _.contains(platformData.frameworkFilesExtensions, path.extname(file)));
492-
var relativeToCacheFiles = _.map(filteredFiles, file => file.substr(npmCacheDirectoryPath.length));
493524

494-
return relativeToCacheFiles;
525+
var allFrameworkDirectories = _.map(this.$fs.readDirectory(path.join(cachedPackagePath, constants.PROJECT_FRAMEWORK_FOLDER_NAME)).wait(), dir => path.join(cachedPackagePath, constants.PROJECT_FRAMEWORK_FOLDER_NAME, dir));
526+
var filteredFrameworkDirectories = _.filter(allFrameworkDirectories, dir => this.$fs.getFsStats(dir).wait().isDirectory() && (_.contains(platformData.frameworkFilesExtensions, path.extname(dir)) || _.contains(platformData.frameworkDirectoriesNames, path.basename(dir))));
495527

496-
}).future<string[]>()();
528+
return {
529+
frameworkFiles: this.mapFrameworkFiles(cachedPackagePath, filteredFiles),
530+
frameworkDirectories: this.mapFrameworkFiles(cachedPackagePath, filteredFrameworkDirectories)
531+
}
532+
533+
}).future<any>()();
497534
}
498535

499-
private getNpmCacheDirectory(packageName: string, version: string): IFuture<string> {
536+
private ensurePackageIsCached(cachedPackagePath: string, packageName: string, version: string): IFuture<void> {
500537
return (() => {
501-
var npmCacheDirectoryPath = this.getNpmCacheDirectoryCore(packageName, version);
502-
503-
if(!this.$fs.exists(npmCacheDirectoryPath).wait()) {
538+
if(!this.$fs.exists(cachedPackagePath).wait()) {
504539
this.$npm.addToCache(packageName, version).wait();
505540
}
506-
507-
return npmCacheDirectoryPath;
508-
}).future<string>()();
541+
}).future<void>()();
509542
}
510543

511-
private getNpmCacheDirectoryCore(packageName: string, version: string): string {
512-
return path.join(this.$npm.getCacheRootPath(), packageName, version, "package");
544+
private mapFrameworkFiles(npmCacheDirectoryPath: string, files: string[]): string[] {
545+
return _.map(files, file => file.substr(npmCacheDirectoryPath.length + constants.PROJECT_FRAMEWORK_FOLDER_NAME.length + 1))
513546
}
514547
}
515548
$injector.register("platformService", PlatformService);

test/stubs.ts

+10
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ export class NPMStub implements INodePackageManager {
201201
getLatestVersion(packageName: string): IFuture<string> {
202202
return Future.fromResult("");
203203
}
204+
205+
getCachedPackagePath(packageName: string, version: string): string {
206+
return "";
207+
}
204208
}
205209

206210
export class ProjectDataStub implements IProjectData {
@@ -273,6 +277,12 @@ export class PlatformProjectServiceStub implements IPlatformProjectService {
273277
addLibrary(platformData: IPlatformData, libraryPath: string): IFuture<void> {
274278
return Future.fromResult();
275279
}
280+
canUpdatePlatform(currentVersion: string, newVersion: string): IFuture<boolean> {
281+
return Future.fromResult(false);
282+
}
283+
updatePlatform(currentVersion: string, newVersion: string): IFuture<void> {
284+
return Future.fromResult();
285+
}
276286
}
277287

278288
export class ProjectDataService implements IProjectDataService {

0 commit comments

Comments
 (0)