From f1b58ba9c0cf367057921183768aae6b495c4193 Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Thu, 11 Jul 2019 09:35:20 +0300 Subject: [PATCH 1/5] fix: do not require migration when file references or tags are used as dependencies --- lib/controllers/migrate-controller.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/controllers/migrate-controller.ts b/lib/controllers/migrate-controller.ts index 129e4c172f..9ef8eef199 100644 --- a/lib/controllers/migrate-controller.ts +++ b/lib/controllers/migrate-controller.ts @@ -356,11 +356,11 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; const devDependencies = projectData.devDependencies || {}; const dependencies = projectData.dependencies || {}; const packageName = dependency.packageName; - const version = dependencies[packageName] || devDependencies[packageName]; - const maxSatisfyingVersion = await this.getMaxDependencyVersion(dependency.packageName, version); - const dependencyVersion = await this.getDependencyVerifiedVersion(dependency, projectData); + const referencedVersion = dependencies[packageName] || devDependencies[packageName]; + const installedVersion = await this.getMaxDependencyVersion(dependency.packageName, referencedVersion); + const requiredVersion = await this.getDependencyVerifiedVersion(dependency, projectData); - return !(maxSatisfyingVersion && semver.gte(maxSatisfyingVersion, dependencyVersion)); + return !!installedVersion && semver.lt(installedVersion, requiredVersion); } protected async shouldUpdateRuntimeVersion({ targetVersion, platform, projectData }: { targetVersion: string, platform: string, projectData: IProjectData }): Promise { From 72b9e583a8d9406439b9bd338a48dd375916a98c Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Thu, 11 Jul 2019 09:36:15 +0300 Subject: [PATCH 2/5] fix: do not require migration when only the App_Resources are using the pre 4.0 structure --- lib/controllers/migrate-controller.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/controllers/migrate-controller.ts b/lib/controllers/migrate-controller.ts index 9ef8eef199..044ef18eac 100644 --- a/lib/controllers/migrate-controller.ts +++ b/lib/controllers/migrate-controller.ts @@ -154,10 +154,6 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; } } - if (!this.$androidResourcesMigrationService.hasMigrated(projectData.getAppResourcesDirectoryPath())) { - return true; - } - for (const platform in this.$devicePlatformsConstants) { const hasRuntimeDependency = this.hasRuntimeDependency({ platform, projectData }); if (hasRuntimeDependency && await this.shouldUpdateRuntimeVersion({ targetVersion: this.verifiedPlatformVersions[platform.toLowerCase()], platform, projectData })) { From 94c63aea30b1f1d2cefd60f77b8bbbb6cd10039c Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Thu, 11 Jul 2019 09:48:10 +0300 Subject: [PATCH 3/5] fix: add trace logs for the shouldMigrate reason. --- lib/controllers/migrate-controller.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/controllers/migrate-controller.ts b/lib/controllers/migrate-controller.ts index 044ef18eac..0fecf2cb29 100644 --- a/lib/controllers/migrate-controller.ts +++ b/lib/controllers/migrate-controller.ts @@ -132,24 +132,29 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; public async shouldMigrate({ projectDir }: IProjectDir): Promise { const projectData = this.$projectDataService.getProjectData(projectDir); + const shouldMigrateCommonMessage = "The app is not compatible with this CLI version and it should be migrated. Reason: "; for (let i = 0; i < this.migrationDependencies.length; i++) { const dependency = this.migrationDependencies[i]; const hasDependency = this.hasDependency(dependency, projectData); if (hasDependency && dependency.shouldMigrateAction && await dependency.shouldMigrateAction(projectData)) { + this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' requires an update.`); return true; } if (hasDependency && (dependency.replaceWith || dependency.shouldRemove)) { + this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' is deprecated.`); return true; } if (hasDependency && await this.shouldMigrateDependencyVersion(dependency, projectData)) { + this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' should be updated.`); return true; } if (!hasDependency && dependency.shouldAddIfMissing) { + this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' is missing.`); return true; } } @@ -157,6 +162,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; for (const platform in this.$devicePlatformsConstants) { const hasRuntimeDependency = this.hasRuntimeDependency({ platform, projectData }); if (hasRuntimeDependency && await this.shouldUpdateRuntimeVersion({ targetVersion: this.verifiedPlatformVersions[platform.toLowerCase()], platform, projectData })) { + this.$logger.trace(`${shouldMigrateCommonMessage}Platform '${platform}' should be updated.`); return true; } } From 335828040435ada932d817963d951484dc4d1aab Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Thu, 11 Jul 2019 10:08:33 +0300 Subject: [PATCH 4/5] fix: validate the migration per platform --- lib/commands/build.ts | 12 ++++++------ lib/commands/debug.ts | 2 +- lib/commands/migrate.ts | 11 +++++++++-- lib/commands/prepare.ts | 6 +++--- lib/commands/preview.ts | 2 +- lib/commands/run.ts | 10 ++++------ lib/commands/test.ts | 4 ++-- lib/commands/update.ts | 12 +++++++++--- lib/controllers/migrate-controller.ts | 18 ++++++++++-------- lib/definitions/migrate.d.ts | 10 +++++++--- test/update.ts | 2 ++ 11 files changed, 54 insertions(+), 35 deletions(-) diff --git a/lib/commands/build.ts b/lib/commands/build.ts index b7f45f4843..912753e508 100644 --- a/lib/commands/build.ts +++ b/lib/commands/build.ts @@ -11,8 +11,8 @@ export abstract class BuildCommandBase extends ValidatePlatformCommandBase { $platformValidationService: IPlatformValidationService, private $buildDataService: IBuildDataService, protected $logger: ILogger) { - super($options, $platformsDataService, $platformValidationService, $projectData); - this.$projectData.initializeProjectData(); + super($options, $platformsDataService, $platformValidationService, $projectData); + this.$projectData.initializeProjectData(); } public dashedOptions = { @@ -65,7 +65,7 @@ export class BuildIosCommand extends BuildCommandBase implements ICommand { $logger: ILogger, $buildDataService: IBuildDataService, private $migrateController: IMigrateController) { - super($options, $errors, $projectData, $platformsDataService, $devicePlatformsConstants, $buildController, $platformValidationService, $buildDataService, $logger); + super($options, $errors, $projectData, $platformsDataService, $devicePlatformsConstants, $buildController, $platformValidationService, $buildDataService, $logger); } public async execute(args: string[]): Promise { @@ -73,8 +73,8 @@ export class BuildIosCommand extends BuildCommandBase implements ICommand { } public async canExecute(args: string[]): Promise { - await this.$migrateController.validate({ projectDir: this.$projectData.projectDir }); const platform = this.$devicePlatformsConstants.iOS; + await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [platform] }); super.validatePlatform(platform); @@ -103,7 +103,7 @@ export class BuildAndroidCommand extends BuildCommandBase implements ICommand { $buildDataService: IBuildDataService, protected $logger: ILogger, private $migrateController: IMigrateController) { - super($options, $errors, $projectData, platformsDataService, $devicePlatformsConstants, $buildController, $platformValidationService, $buildDataService, $logger); + super($options, $errors, $projectData, platformsDataService, $devicePlatformsConstants, $buildController, $platformValidationService, $buildDataService, $logger); } public async execute(args: string[]): Promise { @@ -119,8 +119,8 @@ export class BuildAndroidCommand extends BuildCommandBase implements ICommand { } public async canExecute(args: string[]): Promise { - await this.$migrateController.validate({ projectDir: this.$projectData.projectDir }); const platform = this.$devicePlatformsConstants.Android; + await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [platform] }); this.$androidBundleValidatorHelper.validateRuntimeVersion(this.$projectData); let result = await super.canExecuteCommandBase(platform, { notConfiguredEnvOptions: { hideSyncToPreviewAppOption: true } }); if (result.canExecute) { diff --git a/lib/commands/debug.ts b/lib/commands/debug.ts index 16a3753000..a9ca28acb0 100644 --- a/lib/commands/debug.ts +++ b/lib/commands/debug.ts @@ -53,7 +53,7 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements } public async canExecute(args: string[]): Promise { - await this.$migrateController.validate({ projectDir: this.$projectData.projectDir }); + await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [this.platform] }); this.$androidBundleValidatorHelper.validateNoAab(); diff --git a/lib/commands/migrate.ts b/lib/commands/migrate.ts index d8bb4b6a54..e40cfd8651 100644 --- a/lib/commands/migrate.ts +++ b/lib/commands/migrate.ts @@ -2,6 +2,7 @@ export class MigrateCommand implements ICommand { public allowedParameters: ICommandParameter[] = []; constructor( + private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, private $migrateController: IMigrateController, private $projectData: IProjectData, private $errors: IErrors) { @@ -9,11 +10,17 @@ export class MigrateCommand implements ICommand { } public async execute(args: string[]): Promise { - await this.$migrateController.migrate({ projectDir: this.$projectData.projectDir }); + await this.$migrateController.migrate({ + projectDir: this.$projectData.projectDir, + platforms: [this.$devicePlatformsConstants.Android, this.$devicePlatformsConstants.iOS] + }); } public async canExecute(args: string[]): Promise { - const shouldMigrateResult = await this.$migrateController.shouldMigrate({ projectDir: this.$projectData.projectDir }); + const shouldMigrateResult = await this.$migrateController.shouldMigrate({ + projectDir: this.$projectData.projectDir, + platforms: [this.$devicePlatformsConstants.Android, this.$devicePlatformsConstants.iOS] + }); if (!shouldMigrateResult) { this.$errors.failWithoutHelp('Project is compatible with NativeScript "v6.0.0". To get the latest NativesScript packages execute "tns update".'); diff --git a/lib/commands/prepare.ts b/lib/commands/prepare.ts index 3b8298d599..5faef3e149 100644 --- a/lib/commands/prepare.ts +++ b/lib/commands/prepare.ts @@ -18,8 +18,8 @@ export class PrepareCommand extends ValidatePlatformCommandBase implements IComm $platformsDataService: IPlatformsDataService, private $prepareDataService: PrepareDataService, private $migrateController: IMigrateController) { - super($options, $platformsDataService, $platformValidationService, $projectData); - this.$projectData.initializeProjectData(); + super($options, $platformsDataService, $platformValidationService, $projectData); + this.$projectData.initializeProjectData(); } public async execute(args: string[]): Promise { @@ -30,10 +30,10 @@ export class PrepareCommand extends ValidatePlatformCommandBase implements IComm } public async canExecute(args: string[]): Promise { - await this.$migrateController.validate({ projectDir: this.$projectData.projectDir }); const platform = args[0]; const result = await this.$platformCommandParameter.validate(platform) && await this.$platformValidationService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, platform); + await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [platform] }); if (!result) { return false; } diff --git a/lib/commands/preview.ts b/lib/commands/preview.ts index f84de1f516..8f847fe5eb 100644 --- a/lib/commands/preview.ts +++ b/lib/commands/preview.ts @@ -41,7 +41,7 @@ export class PreviewCommand implements ICommand { this.$errors.fail(`The arguments '${args.join(" ")}' are not valid for the preview command.`); } - await this.$migrateController.validate({ projectDir: this.$projectData.projectDir }); + await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [] }); await this.$networkConnectivityValidator.validate(); return true; diff --git a/lib/commands/run.ts b/lib/commands/run.ts index 0a308a2f4a..f5e3ef9861 100644 --- a/lib/commands/run.ts +++ b/lib/commands/run.ts @@ -28,17 +28,15 @@ export class RunCommandBase implements ICommand { this.$errors.fail(ERROR_NO_VALID_SUBCOMMAND_FORMAT, "run"); } - await this.$migrateController.validate({ projectDir: this.$projectData.projectDir }); - - this.$androidBundleValidatorHelper.validateNoAab(); - - this.$projectData.initializeProjectData(); this.platform = args[0] || this.platform; - if (!this.platform && !this.$hostInfo.isDarwin) { this.platform = this.$devicePlatformsConstants.Android; } + this.$androidBundleValidatorHelper.validateNoAab(); + this.$projectData.initializeProjectData(); + const platforms = this.platform ? [this.platform] : [this.$devicePlatformsConstants.Android, this.$devicePlatformsConstants.iOS]; + await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms }); await this.$liveSyncCommandHelper.validatePlatform(this.platform); return true; diff --git a/lib/commands/test.ts b/lib/commands/test.ts index a7459796ed..8f12bea759 100644 --- a/lib/commands/test.ts +++ b/lib/commands/test.ts @@ -35,7 +35,7 @@ abstract class TestCommandBase { devices = await this.$liveSyncCommandHelper.getDeviceInstances(this.platform); } - if (!this.$options.env) { this.$options.env = { }; } + if (!this.$options.env) { this.$options.env = {}; } this.$options.env.unitTesting = true; const liveSyncInfo = this.$liveSyncCommandHelper.getLiveSyncData(this.$projectData.projectDir); @@ -49,7 +49,7 @@ abstract class TestCommandBase { } async canExecute(args: string[]): Promise { - await this.$migrateController.validate({ projectDir: this.$projectData.projectDir }); + await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [this.platform] }); this.$projectData.initializeProjectData(); this.$analyticsService.setShouldDispose(this.$options.justlaunch || !this.$options.watch); diff --git a/lib/commands/update.ts b/lib/commands/update.ts index 1a1c7f712e..0dddf6a07f 100644 --- a/lib/commands/update.ts +++ b/lib/commands/update.ts @@ -4,6 +4,7 @@ export class UpdateCommand implements ICommand { public static readonly PROJECT_UP_TO_DATE_MESSAGE = 'This project is up to date.'; constructor( + private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, private $updateController: IUpdateController, private $migrateController: IMigrateController, private $options: IOptions, @@ -13,15 +14,20 @@ export class UpdateCommand implements ICommand { } public async execute(args: string[]): Promise { - await this.$updateController.update({projectDir: this.$projectData.projectDir, version: args[0], frameworkPath: this.$options.frameworkPath}); + await this.$updateController.update({ projectDir: this.$projectData.projectDir, version: args[0], frameworkPath: this.$options.frameworkPath }); } public async canExecute(args: string[]): Promise { - if (await this.$migrateController.shouldMigrate({projectDir: this.$projectData.projectDir})) { + const shouldMigrate = await this.$migrateController.shouldMigrate({ + projectDir: this.$projectData.projectDir, + platforms: [this.$devicePlatformsConstants.Android, this.$devicePlatformsConstants.iOS] + }); + + if (shouldMigrate) { this.$errors.failWithoutHelp(UpdateCommand.SHOULD_MIGRATE_PROJECT_MESSAGE); } - if (!await this.$updateController.shouldUpdate({projectDir:this.$projectData.projectDir, version: args[0]})) { + if (!await this.$updateController.shouldUpdate({ projectDir: this.$projectData.projectDir, version: args[0] })) { this.$errors.failWithoutHelp(UpdateCommand.PROJECT_UP_TO_DATE_MESSAGE); } diff --git a/lib/controllers/migrate-controller.ts b/lib/controllers/migrate-controller.ts index 0fecf2cb29..c14e905edf 100644 --- a/lib/controllers/migrate-controller.ts +++ b/lib/controllers/migrate-controller.ts @@ -95,7 +95,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; }; } - public async migrate({ projectDir }: { projectDir: string }): Promise { + public async migrate({ projectDir, platforms }: IMigrationData): Promise { const projectData = this.$projectDataService.getProjectData(projectDir); const backupDir = path.join(projectDir, MigrateController.backupFolder); @@ -121,7 +121,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; try { await this.cleanUpProject(projectData); - await this.migrateDependencies(projectData); + await this.migrateDependencies(projectData, platforms); } catch (error) { this.restoreBackup(MigrateController.folders, backupDir, projectData.projectDir); this.$errors.failWithoutHelp(`${MigrateController.migrateFailMessage} The error is: ${error}`); @@ -130,7 +130,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; this.$logger.info(MigrateController.MIGRATE_FINISH_MESSAGE); } - public async shouldMigrate({ projectDir }: IProjectDir): Promise { + public async shouldMigrate({ projectDir, platforms }: IMigrationData): Promise { const projectData = this.$projectDataService.getProjectData(projectDir); const shouldMigrateCommonMessage = "The app is not compatible with this CLI version and it should be migrated. Reason: "; @@ -159,7 +159,9 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; } } - for (const platform in this.$devicePlatformsConstants) { + for (let platform of platforms) { + platform = platform && platform.toLowerCase(); + const hasRuntimeDependency = this.hasRuntimeDependency({ platform, projectData }); if (hasRuntimeDependency && await this.shouldUpdateRuntimeVersion({ targetVersion: this.verifiedPlatformVersions[platform.toLowerCase()], platform, projectData })) { this.$logger.trace(`${shouldMigrateCommonMessage}Platform '${platform}' should be updated.`); @@ -168,8 +170,8 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; } } - public async validate({ projectDir }: IProjectDir): Promise { - const shouldMigrate = await this.shouldMigrate({ projectDir }); + public async validate({ projectDir, platforms }: IMigrationData): Promise { + const shouldMigrate = await this.shouldMigrate({ projectDir, platforms }); if (shouldMigrate) { this.$errors.failWithoutHelp(MigrateController.UNABLE_TO_MIGRATE_APP_ERROR); } @@ -273,7 +275,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; return autoGeneratedFiles; } - private async migrateDependencies(projectData: IProjectData): Promise { + private async migrateDependencies(projectData: IProjectData, platforms: string[]): Promise { this.$logger.info("Start dependencies migration."); for (let i = 0; i < this.migrationDependencies.length; i++) { const dependency = this.migrationDependencies[i]; @@ -289,7 +291,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; await this.migrateDependency(dependency, projectData); } - for (const platform in this.$devicePlatformsConstants) { + for (const platform of platforms) { const lowercasePlatform = platform.toLowerCase(); const hasRuntimeDependency = this.hasRuntimeDependency({ platform, projectData }); if (hasRuntimeDependency && await this.shouldUpdateRuntimeVersion({ targetVersion: this.verifiedPlatformVersions[lowercasePlatform], platform, projectData })) { diff --git a/lib/definitions/migrate.d.ts b/lib/definitions/migrate.d.ts index 2db417be92..47a182c540 100644 --- a/lib/definitions/migrate.d.ts +++ b/lib/definitions/migrate.d.ts @@ -1,7 +1,11 @@ interface IMigrateController { - migrate(migrateData: IProjectDir): Promise; - shouldMigrate(data: IProjectDir): Promise; - validate(data: IProjectDir): Promise; + migrate(data: IMigrationData): Promise; + shouldMigrate(data: IMigrationData): Promise; + validate(data: IMigrationData): Promise; +} + +interface IMigrationData extends IProjectDir { + platforms: string[]; } interface IDependency { diff --git a/test/update.ts b/test/update.ts index e1795b2435..8ab22c7802 100644 --- a/test/update.ts +++ b/test/update.ts @@ -5,6 +5,7 @@ import { assert } from "chai"; import { Options } from "../lib/options"; import { StaticConfig } from "../lib/config"; import { SettingsService } from "../lib/common/test/unit-tests/stubs"; +import { DevicePlatformsConstants } from "../lib/common/mobile/device-platforms-constants"; const projectFolder = "test"; function createTestInjector( @@ -26,6 +27,7 @@ function createTestInjector( dependencies: {} }); testInjector.register("settingsService", SettingsService); + testInjector.register("devicePlatformsConstants", DevicePlatformsConstants); testInjector.register("migrateController", { shouldMigrate: () => { return false; }, }); From 54b093fd6ad79c3e6f475f67a161d04306b12b55 Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Thu, 11 Jul 2019 11:00:48 +0300 Subject: [PATCH 5/5] fix: do not allow invalid version during `tns migrate` --- lib/controllers/migrate-controller.ts | 48 +++++++++++++++------------ lib/definitions/migrate.d.ts | 3 +- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/lib/controllers/migrate-controller.ts b/lib/controllers/migrate-controller.ts index c14e905edf..fbdb6dd417 100644 --- a/lib/controllers/migrate-controller.ts +++ b/lib/controllers/migrate-controller.ts @@ -75,9 +75,9 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; { packageName: "nativescript-cardview", verifiedVersion: "3.2.0" }, { packageName: "nativescript-unit-test-runner", verifiedVersion: "0.6.4", - shouldMigrateAction: async (projectData: IProjectData) => { + shouldMigrateAction: async (projectData: IProjectData, allowInvalidVersions: boolean) => { const dependency = { packageName: "nativescript-unit-test-runner", verifiedVersion: "0.6.4", isDev: false }; - const result = this.hasDependency(dependency, projectData) && await this.shouldMigrateDependencyVersion(dependency, projectData); + const result = this.hasDependency(dependency, projectData) && await this.shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions); return result; }, migrateAction: this.migrateUnitTestRunner.bind(this) @@ -95,7 +95,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; }; } - public async migrate({ projectDir, platforms }: IMigrationData): Promise { + public async migrate({ projectDir, platforms, allowInvalidVersions = false }: IMigrationData): Promise { const projectData = this.$projectDataService.getProjectData(projectDir); const backupDir = path.join(projectDir, MigrateController.backupFolder); @@ -121,7 +121,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; try { await this.cleanUpProject(projectData); - await this.migrateDependencies(projectData, platforms); + await this.migrateDependencies(projectData, platforms, allowInvalidVersions); } catch (error) { this.restoreBackup(MigrateController.folders, backupDir, projectData.projectDir); this.$errors.failWithoutHelp(`${MigrateController.migrateFailMessage} The error is: ${error}`); @@ -130,7 +130,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; this.$logger.info(MigrateController.MIGRATE_FINISH_MESSAGE); } - public async shouldMigrate({ projectDir, platforms }: IMigrationData): Promise { + public async shouldMigrate({ projectDir, platforms, allowInvalidVersions = false }: IMigrationData): Promise { const projectData = this.$projectDataService.getProjectData(projectDir); const shouldMigrateCommonMessage = "The app is not compatible with this CLI version and it should be migrated. Reason: "; @@ -138,7 +138,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; const dependency = this.migrationDependencies[i]; const hasDependency = this.hasDependency(dependency, projectData); - if (hasDependency && dependency.shouldMigrateAction && await dependency.shouldMigrateAction(projectData)) { + if (hasDependency && dependency.shouldMigrateAction && await dependency.shouldMigrateAction(projectData, allowInvalidVersions)) { this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' requires an update.`); return true; } @@ -148,7 +148,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; return true; } - if (hasDependency && await this.shouldMigrateDependencyVersion(dependency, projectData)) { + if (hasDependency && await this.shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions)) { this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' should be updated.`); return true; } @@ -163,15 +163,15 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; platform = platform && platform.toLowerCase(); const hasRuntimeDependency = this.hasRuntimeDependency({ platform, projectData }); - if (hasRuntimeDependency && await this.shouldUpdateRuntimeVersion({ targetVersion: this.verifiedPlatformVersions[platform.toLowerCase()], platform, projectData })) { + if (hasRuntimeDependency && await this.shouldUpdateRuntimeVersion(this.verifiedPlatformVersions[platform.toLowerCase()], platform, projectData, allowInvalidVersions)) { this.$logger.trace(`${shouldMigrateCommonMessage}Platform '${platform}' should be updated.`); return true; } } } - public async validate({ projectDir, platforms }: IMigrationData): Promise { - const shouldMigrate = await this.shouldMigrate({ projectDir, platforms }); + public async validate({ projectDir, platforms, allowInvalidVersions = true }: IMigrationData): Promise { + const shouldMigrate = await this.shouldMigrate({ projectDir, platforms, allowInvalidVersions }); if (shouldMigrate) { this.$errors.failWithoutHelp(MigrateController.UNABLE_TO_MIGRATE_APP_ERROR); } @@ -275,26 +275,26 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; return autoGeneratedFiles; } - private async migrateDependencies(projectData: IProjectData, platforms: string[]): Promise { + private async migrateDependencies(projectData: IProjectData, platforms: string[], allowInvalidVersions: boolean): Promise { this.$logger.info("Start dependencies migration."); for (let i = 0; i < this.migrationDependencies.length; i++) { const dependency = this.migrationDependencies[i]; const hasDependency = this.hasDependency(dependency, projectData); - if (hasDependency && dependency.migrateAction && await dependency.shouldMigrateAction(projectData)) { + if (hasDependency && dependency.migrateAction && await dependency.shouldMigrateAction(projectData, allowInvalidVersions)) { const newDependencies = await dependency.migrateAction(projectData, path.join(projectData.projectDir, MigrateController.backupFolder)); for (const newDependency of newDependencies) { - await this.migrateDependency(newDependency, projectData); + await this.migrateDependency(newDependency, projectData, allowInvalidVersions); } } - await this.migrateDependency(dependency, projectData); + await this.migrateDependency(dependency, projectData, allowInvalidVersions); } for (const platform of platforms) { const lowercasePlatform = platform.toLowerCase(); const hasRuntimeDependency = this.hasRuntimeDependency({ platform, projectData }); - if (hasRuntimeDependency && await this.shouldUpdateRuntimeVersion({ targetVersion: this.verifiedPlatformVersions[lowercasePlatform], platform, projectData })) { + if (hasRuntimeDependency && await this.shouldUpdateRuntimeVersion(this.verifiedPlatformVersions[lowercasePlatform], platform, projectData, allowInvalidVersions)) { const verifiedPlatformVersion = this.verifiedPlatformVersions[lowercasePlatform]; const platformData = this.$platformsDataService.getPlatformData(lowercasePlatform, projectData); this.$logger.info(`Updating ${platform} platform to version '${verifiedPlatformVersion}'.`); @@ -313,7 +313,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; this.$logger.info("Migration complete."); } - private async migrateDependency(dependency: IMigrationDependency, projectData: IProjectData): Promise { + private async migrateDependency(dependency: IMigrationDependency, projectData: IProjectData, allowInvalidVersions: boolean): Promise { const hasDependency = this.hasDependency(dependency, projectData); if (hasDependency && dependency.warning) { this.$logger.warn(dependency.warning); @@ -336,7 +336,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; } const dependencyVersion = await this.getDependencyVerifiedVersion(dependency, projectData); - if (hasDependency && await this.shouldMigrateDependencyVersion(dependency, projectData)) { + if (hasDependency && await this.shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions)) { this.$logger.info(`Updating '${dependency.packageName}' to compatible version '${dependencyVersion}'`); this.$pluginsService.addToPackageJson(dependency.packageName, dependencyVersion, dependency.isDev, projectData.projectDir); return; @@ -356,7 +356,7 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; return dependency.verifiedVersion; } - private async shouldMigrateDependencyVersion(dependency: IMigrationDependency, projectData: IProjectData): Promise { + private async shouldMigrateDependencyVersion(dependency: IMigrationDependency, projectData: IProjectData, allowInvalidVersions: boolean): Promise { const devDependencies = projectData.devDependencies || {}; const dependencies = projectData.dependencies || {}; const packageName = dependency.packageName; @@ -364,13 +364,17 @@ Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`; const installedVersion = await this.getMaxDependencyVersion(dependency.packageName, referencedVersion); const requiredVersion = await this.getDependencyVerifiedVersion(dependency, projectData); - return !!installedVersion && semver.lt(installedVersion, requiredVersion); + return this.isOutdatedVersion(installedVersion, requiredVersion, allowInvalidVersions); } - protected async shouldUpdateRuntimeVersion({ targetVersion, platform, projectData }: { targetVersion: string, platform: string, projectData: IProjectData }): Promise { - const maxRuntimeVersion = await this.getMaxRuntimeVersion({ platform, projectData }); + private async shouldUpdateRuntimeVersion(targetVersion: string, platform: string, projectData: IProjectData, allowInvalidVersions: boolean): Promise { + const installedVersion = await this.getMaxRuntimeVersion({ platform, projectData }); - return !(maxRuntimeVersion && semver.gte(maxRuntimeVersion, targetVersion)); + return this.isOutdatedVersion(installedVersion, targetVersion, allowInvalidVersions); + } + + private isOutdatedVersion(version: string, targetVersion: string, allowInvalidVersions: boolean): boolean { + return !!version ? semver.lt(version, targetVersion) : !allowInvalidVersions; } private async migrateUnitTestRunner(projectData: IProjectData, migrationBackupDirPath: string): Promise { diff --git a/lib/definitions/migrate.d.ts b/lib/definitions/migrate.d.ts index 47a182c540..1931d4fc88 100644 --- a/lib/definitions/migrate.d.ts +++ b/lib/definitions/migrate.d.ts @@ -6,6 +6,7 @@ interface IMigrateController { interface IMigrationData extends IProjectDir { platforms: string[]; + allowInvalidVersions?: boolean; } interface IDependency { @@ -20,6 +21,6 @@ interface IMigrationDependency extends IDependency { verifiedVersion?: string; getVerifiedVersion?: (projectData: IProjectData) => Promise; shouldAddIfMissing?: boolean; - shouldMigrateAction?: (projectData: IProjectData) => Promise; + shouldMigrateAction?: (projectData: IProjectData, allowInvalidVersions: boolean) => Promise; migrateAction?: (projectData: IProjectData, migrationBackupDirPath: string) => Promise; } \ No newline at end of file