private async function mainImplAsync()

in src/__Private/MigrationCLI.hack [374:475]


  private async function mainImplAsync(): Awaitable<int> {
    $err = $this->getStderr();
    if (C\is_empty($this->migrations)) {
      await $err->writeAllAsync("You must specify at least one migration!\n\n");
      $this->displayHelp($err);
      return 1;
    }

    $args = $this->getArguments();
    if (C\is_empty($args)) {
      await $err->writeAllAsync("You must specify at least one path!\n\n");
      $this->displayHelp($err);
      return 1;
    }

    $all_config_options = dict[];
    foreach ($this->migrations as $migration) {
      $min_version = $migration::getMinimumHHVMVersion();
      if (
        $min_version is nonnull &&
        \version_compare(\HHVM_VERSION, $min_version, '<')
      ) {
        /* HHAST_IGNORE_ERROR[DontAwaitInALoop]
           This statement is followed by a return statement and will therefore only execute once
           */
        await $err->writeAllAsync(Str\format(
          "Migration %s requires HHVM version %s or newer.\n",
          $migration,
          $min_version,
        ));
        return 1;
      }

      $config_options = $migration::getRequiredHHConfigOptions();
      $all_config_options = Dict\merge($config_options, $all_config_options);
      foreach ($config_options as $option => $value) {
        if ($all_config_options[$option] !== $value) {
          /* HHAST_IGNORE_ERROR[DontAwaitInALoop]
             This statement is followed by a return statement and will therefore only execute once
             */
          await $err->writeAllAsync(Str\format(
            'Migration %s requires .hhconfig option %s=%s which conflicts '.
            "with another migration.\n",
            $migration,
            $option,
            $value,
          ));
          return 1;
        }
      }
    }

    try {
      // Restart hh_server for each path (some or all of these may be the same
      // hh_server instance) with the correct .hhconfig options.
      if (!C\is_empty($all_config_options)) {
        foreach ($args as $path) {
          /* HHAST_IGNORE_ERROR[DontAwaitInALoop]
             these shouldn't run concurrently
             */
          await execute_async(
            'hh_client',
            'restart',
            '--config',
            $all_config_options
              |> Vec\map_with_key($$, ($option, $value) ==> $option.'='.$value)
              |> Str\join($$, ','),
            $path,
          );
        }
      }

      foreach ($args as $path) {
        $migrations = Vec\map($this->migrations, $class ==> new $class($path));
        if (\is_file($path)) {
          $this->migrateFile($migrations, $path);
          continue;
        }
        if (\is_dir($path)) {
          $this->migrateDirectory($migrations, $path);
          continue;
        }

        /* HHAST_IGNORE_ERROR[DontAwaitInALoop] */
        await $err->writeAllAsync(
          Str\format("Don't know how to process path: %s\n", $path),
        );
        return 1;
      }
      return 0;
    } finally {
      // Restart hh_server to get rid of the overridden .hhconfig options.
      if (!C\is_empty($all_config_options)) {
        foreach ($args as $path) {
          /* HHAST_IGNORE_ERROR[DontAwaitInALoop]
             these shouldn't run concurrently
             */
          await execute_async('hh_client', 'restart', $path);
        }
      }
    }
  }