export async function selectVersion()

in packages/apps/autorest/src/autorest-as-a-service.ts [221:345]


export async function selectVersion(
  logger: IAutorestLogger,
  requestedVersion: string,
  force: boolean,
  minimumVersion?: string,
): Promise<Extension> {
  const installedVersions = await installedCores();
  let currentVersion: Extension | null = installedVersions[0] || null;

  // the consumer can say I want the latest-installed, but at least XXX.XXX
  if (minimumVersion && currentVersion && !semver.satisfies(currentVersion.version, minimumVersion)) {
    currentVersion = null;
  }

  if (currentVersion) {
    logger.debug(`The most recent installed version is ${currentVersion.version}`);

    if (requestedVersion === "latest-installed" || (requestedVersion === "latest" && false == (await networkEnabled))) {
      logger.debug(`requesting current version '${currentVersion.version}'`);
      requestedVersion = currentVersion.version;
    }
  } else {
    logger.debug(`No ${newCorePackage} (or ${oldCorePackage}) is installed.`);
  }

  let selectedVersion: Extension | null = null;
  // take the highest version that satisfies the version range.
  for (const each of installedVersions.sort((a, b) => semver.compare(a?.version, b?.version))) {
    if (semver.satisfies(each.version, requestedVersion)) {
      selectedVersion = each;
    }
  }

  // is the requested version installed?
  if (!selectedVersion || force) {
    if (!force) {
      logger.debug(`${requestedVersion} was not satisfied directly by a previous installation.`);
    }

    // if it's not a file, and the network isn't available, we can't continue.
    if (!(await isFile(requestedVersion)) && !(await networkEnabled)) {
      // no network enabled.
      throw new Exception(
        `Network access is not available, requested version '${requestedVersion}' is not installed. `,
      );
    }

    // after this point, latest-installed must mean latest.
    if (requestedVersion === "latest-installed") {
      requestedVersion = "latest";
    }

    // if they have requested 'latest' -- they really mean latest with same major version number
    if (requestedVersion === "latest") {
      requestedVersion = versionRange;
    }
    let corePackageName = newCorePackage;

    let pkg: Package | undefined = undefined;
    try {
      // try the package
      pkg = await (await extensionManager).findPackage(newCorePackage, requestedVersion);
    } catch (error) {
      // try a prerelease version from github.
      try {
        const rv = requestedVersion.replace(/^[~|^]/g, "");
        pkg = await (
          await extensionManager
        ).findPackage(
          "core",
          `https://github.com/Azure/autorest/releases/download/autorest-core-${rv}/autorest-core-${rv}.tgz`,
        );
      } catch {
        // fallback to old package name
        try {
          pkg = await (await extensionManager).findPackage(oldCorePackage, requestedVersion);
        } catch {
          // no package found!
        }
      }
      if (!pkg) {
        logger.debug(`Error trying to resolve @autorest/core version ${requestedVersion}: ${error}`);
        throw new Exception(
          `Unable to find a valid AutoRest core package '${newCorePackage}' @ '${requestedVersion}'.`,
        );
      }
      corePackageName = oldCorePackage;
    }
    if (pkg) {
      if (args.debug) {
        console.log(`Selected package: ${pkg.resolvedInfo.rawSpec} => ${pkg.name}@${pkg.version}`);
      }
    }

    // pkg.version == the actual version
    // check if it's installed already.
    selectedVersion = await (await extensionManager).getInstalledExtension(corePackageName, pkg.version);

    if (!selectedVersion || force) {
      // this will throw if there is an issue with installing the extension.
      if (args.debug) {
        console.log(`**Installing package** ${corePackageName}@${pkg.version}\n[This will take a few moments...]`);
      }

      // @autorest/core install too fast and this doesn't look good right now as Yarn doesn't give info fast enough.
      // If we migrate to yarn v2 with the api we might be able to get more info and reenable that
      const progress = logger.startProgress("installing core...");
      selectedVersion = await (
        await extensionManager
      ).installPackage(pkg, force, 5 * 60 * 1000, (status) => {
        progress.update({ ...status });
      });
      progress.stop();

      if (args.debug) {
        console.log(`Extension location: ${selectedVersion.packageJsonPath}`);
      }
    } else {
      if (args.debug) {
        console.log(`AutoRest Core ${pkg.version} is available at ${selectedVersion.modulePath}`);
      }
    }
  }
  return selectedVersion;
}