Skip to content

fix: make the update command behave similar to the logic before 6.0.0 #4809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 41 additions & 32 deletions lib/controllers/update-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ import * as constants from "../constants";
import { UpdateControllerBase } from "./update-controller-base";

export class UpdateController extends UpdateControllerBase implements IUpdateController {
private getTemplateManifest: Function;
static readonly updatableDependencies: string[] = [constants.TNS_CORE_MODULES_NAME, constants.TNS_CORE_MODULES_WIDGETS_NAME];
static readonly folders: string[] = [
constants.LIB_DIR_NAME,
constants.HOOKS_DIR_NAME,
constants.WEBPACK_CONFIG_NAME,
constants.PACKAGE_JSON_FILE_NAME,
constants.PACKAGE_LOCK_JSON_FILE_NAME
];

static readonly backupFolder: string = ".update_backup";
static readonly updateFailMessage: string = "Could not update the project!";
static readonly backupFailMessage: string = "Could not backup project folders!";

constructor(
protected $fs: IFileSystem,
protected $platformsDataService: IPlatformsDataService,
Expand All @@ -16,23 +30,11 @@ export class UpdateController extends UpdateControllerBase implements IUpdateCon
private $pluginsService: IPluginsService,
private $pacoteService: IPacoteService,
private $projectDataService: IProjectDataService) {
super($fs, $platformCommandHelper, $platformsDataService, $packageInstallationManager, $packageManager);
this.getTemplateManifest = _.memoize(this._getTemplateManifest, (...args) => {
return args.join("@");
});
super($fs, $platformCommandHelper, $platformsDataService, $packageInstallationManager, $packageManager);
this.getTemplateManifest = _.memoize(this._getTemplateManifest, (...args) => {
return args.join("@");
});
}
private getTemplateManifest: Function;
static readonly folders: string[] = [
constants.LIB_DIR_NAME,
constants.HOOKS_DIR_NAME,
constants.WEBPACK_CONFIG_NAME,
constants.PACKAGE_JSON_FILE_NAME,
constants.PACKAGE_LOCK_JSON_FILE_NAME
];

static readonly backupFolder: string = ".update_backup";
static readonly updateFailMessage: string = "Could not update the project!";
static readonly backupFailMessage: string = "Could not backup project folders!";

public async update(updateOptions: IUpdateOptions): Promise<void> {
const projectData = this.$projectDataService.getProjectData(updateOptions.projectDir);
Expand All @@ -55,16 +57,16 @@ export class UpdateController extends UpdateControllerBase implements IUpdateCon
}
}

public async shouldUpdate({projectDir, version}: {projectDir: string, version?: string}): Promise<boolean> {
public async shouldUpdate({ projectDir, version }: { projectDir: string, version?: string }): Promise<boolean> {
const projectData = this.$projectDataService.getProjectData(projectDir);
const templateName = this.getTemplateName(projectData);
const templateManifest = await this.getTemplateManifest(templateName, version);
const dependencies = templateManifest.dependencies;
const devDependencies = templateManifest.devDependencies;
const dependencies = this.getUpdatableDependencies(templateManifest.dependencies);
const devDependencies = this.getUpdatableDependencies(templateManifest.devDependencies);

if (
await this.hasDependenciesToUpdate({dependencies, areDev: false, projectData}) ||
await this.hasDependenciesToUpdate({dependencies: devDependencies, areDev: true, projectData})
await this.hasDependenciesToUpdate({ dependencies, areDev: false, projectData }) ||
await this.hasDependenciesToUpdate({ dependencies: devDependencies, areDev: true, projectData })
) {
return true;
}
Expand Down Expand Up @@ -93,12 +95,14 @@ export class UpdateController extends UpdateControllerBase implements IUpdateCon
private async updateProject(projectData: IProjectData, version: string): Promise<void> {
const templateName = this.getTemplateName(projectData);
const templateManifest = await this.getTemplateManifest(templateName, version);
const dependencies = this.getUpdatableDependencies(templateManifest.dependencies);
const devDependencies = this.getUpdatableDependencies(templateManifest.devDependencies);

this.$logger.info("Start updating dependencies.");
await this.updateDependencies({ dependencies: templateManifest.dependencies, areDev: false, projectData});
await this.updateDependencies({ dependencies, areDev: false, projectData });
this.$logger.info("Finished updating dependencies.");
this.$logger.info("Start updating devDependencies.");
await this.updateDependencies({ dependencies: templateManifest.devDependencies, areDev: true, projectData});
await this.updateDependencies({ dependencies: devDependencies, areDev: true, projectData });
this.$logger.info("Finished updating devDependencies.");

this.$logger.info("Start updating runtimes.");
Expand All @@ -114,7 +118,7 @@ export class UpdateController extends UpdateControllerBase implements IUpdateCon
});
}

private async updateDependencies( {dependencies, areDev, projectData} : {dependencies: IDictionary<string>, areDev: boolean, projectData: IProjectData}) {
private async updateDependencies({ dependencies, areDev, projectData }: { dependencies: IDictionary<string>, areDev: boolean, projectData: IProjectData }) {
for (const dependency in dependencies) {
const templateVersion = dependencies[dependency];
if (!this.hasDependency({ packageName: dependency, isDev: areDev }, projectData)) {
Expand All @@ -134,11 +138,10 @@ export class UpdateController extends UpdateControllerBase implements IUpdateCon
const projectVersion = dependencies[dependency] || devDependencies[dependency];
const maxSatisfyingTargetVersion = await this.getMaxDependencyVersion(dependency, targetVersion);
const maxSatisfyingProjectVersion = await this.getMaxDependencyVersion(dependency, projectVersion);

return maxSatisfyingProjectVersion && maxSatisfyingTargetVersion && semver.gt(maxSatisfyingTargetVersion, maxSatisfyingProjectVersion);
}

private async hasDependenciesToUpdate({dependencies, areDev, projectData}: {dependencies: IDictionary<string>, areDev: boolean, projectData:IProjectData}) {
private async hasDependenciesToUpdate({ dependencies, areDev, projectData }: { dependencies: IDictionary<string>, areDev: boolean, projectData: IProjectData }) {
for (const dependency in dependencies) {
const templateVersion = dependencies[dependency];
if (!this.hasDependency({ packageName: dependency, isDev: areDev }, projectData)) {
Expand All @@ -165,26 +168,32 @@ export class UpdateController extends UpdateControllerBase implements IUpdateCon
}

private async shouldUpdateRuntimeVersion(templateRuntimeVersion: string, frameworkPackageName: string, platform: string, projectData: IProjectData): Promise<boolean> {
const hasRuntimeDependency = this.hasRuntimeDependency({platform, projectData});
const hasRuntimeDependency = this.hasRuntimeDependency({ platform, projectData });

if (!hasRuntimeDependency) {
return false;
}

const maxTemplateRuntimeVersion = await this.getMaxDependencyVersion(frameworkPackageName, templateRuntimeVersion);
const maxRuntimeVersion = await this.getMaxRuntimeVersion({platform, projectData});
const maxRuntimeVersion = await this.getMaxRuntimeVersion({ platform, projectData });

return maxTemplateRuntimeVersion && maxRuntimeVersion && semver.gt(maxTemplateRuntimeVersion, maxRuntimeVersion);
}

private async _getTemplateManifest(templateName: string, version: string) {
let packageVersion = version ? version : await this.$packageInstallationManager.getLatestCompatibleVersionSafe(templateName);
packageVersion = semver.valid(version) ? version : await this.$packageManager.getTagVersion(templateName, packageVersion);
packageVersion = packageVersion ? packageVersion : await this.$packageInstallationManager.getLatestCompatibleVersionSafe(templateName);
private async _getTemplateManifest(templateName: string, version?: string) {
const packageVersion = semver.valid(version) ||
await this.$packageManager.getTagVersion(templateName, version) ||
await this.$packageInstallationManager.getLatestCompatibleVersionSafe(templateName);

return await this.$pacoteService.manifest(`${templateName}@${packageVersion}`, { fullMetadata: true });
}

private getUpdatableDependencies(dependencies: IDictionary<string>): IDictionary<string> {
return _.pickBy(dependencies, (value, key) => {
return UpdateController.updatableDependencies.indexOf(key) > -1;
});
}

private getTemplateName(projectData: IProjectData) {
let template;
switch (projectData.projectType) {
Expand Down
3 changes: 3 additions & 0 deletions lib/package-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ export class PackageManager implements IPackageManager {

public async getTagVersion(packageName: string, tag: string): Promise<string> {
let version: string = null;
if (!tag) {
return null;
}

try {
const result = await this.view(packageName, { "dist-tags": true });
Expand Down