run method

  1. @override
void run()
override

Runs this command.

The return value is wrapped in a Future if necessary and returned by CommandRunner.runCommand.

Implementation

@override
void run() async {
  // Get the list of packages to install.
  List<String> packagesRequested = argResults!.rest;
  showUsage(packagesRequested.isEmpty, () => printUsage());

  String nativeMode = argResults!['native'];

  // Get the Bash instance.
  final bash = await XPM.bash;

  // Get the local database instance.
  final db = await DB.instance();

  // Install each package.
  for (String packageRequested in packagesRequested) {
    Package? packageInDB;
    if (nativeMode != 'only') {
      packageInDB = await db.packages.filter().nameEqualTo(packageRequested).findFirst();
    }

    if (packageInDB == null) {
      if (nativeMode != 'off') {
        final nativeManager = await NativePackageManagerDetector.detect();
        if (nativeManager != null) {
          Logger.info('Installing "$packageRequested" from native package manager...');
          try {
            await nativeManager.install(packageRequested);
            final nativePackage = await nativeManager.get(packageRequested);
            if (nativePackage != null) {
              // Add the package to the local database to be managed by xpm
              await db.writeTxn(() async {
                final newPackage = Package()
                  ..name = nativePackage.name
                  ..version = nativePackage.version ?? 'native'
                  ..desc = nativePackage.description
                  ..installed = nativePackage.version ?? 'native'
                  ..isNative = true;
                await db.packages.put(newPackage);
              });
              Logger.success('Successfully installed "$packageRequested".');
            } else {
              Logger.error('Failed to install "$packageRequested".');
            }
          } catch (e) {
            leave(message: 'Failed to install "$packageRequested": $e', exitCode: generalError);
          }
        } else {
          leave(message: 'Package "{@gold}$packageRequested{@end}" not found.', exitCode: cantExecute);
        }
      } else {
        leave(message: 'Package "{@gold}$packageRequested{@end}" not found.', exitCode: cantExecute);
      }
    } else {
      var repo = packageInDB.repo.value!;
      final prepare = Prepare(repo, packageInDB, args: argResults);
      if (packageInDB.installed != null && await Executable(packageRequested).exists()) {
        Logger.info('Reinstalling "$packageRequested"...');
      } else {
        Logger.info('Installing "$packageRequested"...');
      }

      // Run the installation script.
      final runner = Run();
      try {
        await runner.simple(bash, ['-c', 'source ${await prepare.toInstall()}']);
      } on ShellException catch (e) {
        sharedStdIn.terminate();
        String error = 'Failed to install "$packageRequested"';
        if (argResults!['verbose'] == true) {
          error += ': ${e.message}';
        } else {
          error += '.';
        }

        leave(message: error, exitCode: e.result?.exitCode ?? generalError);
      }

      // Check if the package was installed successfully.
      final script = packageInDB.script;
      if (script != null) {
        final bashScript = BashScript(script);
        bool hasValidation = await bashScript.hasFunction('validate');
        String? error;
        if (hasValidation) {
          Logger.info('Checking installation of $packageRequested...');
          try {
            await runner.simple(bash, ['-c', 'source ${await prepare.toValidate()}']);
          } on ShellException catch (e) {
            error = 'Package "$packageRequested" installed with errors';
            if (argResults!['verbose'] == true) {
              error += ': ${e.message}';
            } else {
              error += '.';
            }
          }
        } else {
          Logger.warning('No validation found for $packageRequested.');
        }

        // Update the local database to reflect the installation.
        await db.writeTxn(() async {
          if (packageInDB != null) {
            packageInDB.installed = packageInDB.version;
            packageInDB.method = argResults!['method'];
            packageInDB.channel = argResults!['channel'];
            await db.packages.put(packageInDB);
          }
        });

        // Log the result of the installation.
        if (error != null) {
          Logger.error(error);
        } else {
          Logger.success('Successfully installed "$packageRequested".');
        }
      }
    }
  }
  sharedStdIn.terminate();
}