private InstallResult installAppleBundleForSimulator()

in src/com/facebook/buck/cli/InstallCommand.java [932:1110]


  private InstallResult installAppleBundleForSimulator(
      CommandRunnerParams params,
      AppleBundle appleBundle,
      SourcePathResolverAdapter pathResolver,
      ProjectFilesystem projectFilesystem,
      ProcessExecutor processExecutor)
      throws IOException, InterruptedException {

    AppleConfig appleConfig = params.getBuckConfig().getView(AppleConfig.class);
    Optional<Path> xcodeDeveloperPath =
        appleConfig.getAppleDeveloperDirectorySupplier(processExecutor).get();
    if (!xcodeDeveloperPath.isPresent()) {
      params
          .getConsole()
          .printBuildFailure(
              String.format(
                  "Cannot install %s (Xcode not found)", appleBundle.getFullyQualifiedName()));
      return FAILURE;
    }

    UnixUserIdFetcher userIdFetcher = new UnixUserIdFetcher();
    AppleCoreSimulatorServiceController appleCoreSimulatorServiceController =
        new AppleCoreSimulatorServiceController(processExecutor);

    Optional<Path> coreSimulatorServicePath =
        appleCoreSimulatorServiceController.getCoreSimulatorServicePath(userIdFetcher);

    boolean shouldWaitForSimulatorsToShutdown = false;

    if (!coreSimulatorServicePath.isPresent()
        || !coreSimulatorServicePath
            .get()
            .toRealPath()
            .startsWith(xcodeDeveloperPath.get().toRealPath())) {
      LOG.warn(
          "Core simulator service path %s does not match developer directory %s, "
              + "killing all simulators.",
          coreSimulatorServicePath, xcodeDeveloperPath.get());
      if (!appleCoreSimulatorServiceController.killSimulatorProcesses()) {
        params.getConsole().printBuildFailure("Could not kill running simulator processes.");
        return FAILURE;
      }

      shouldWaitForSimulatorsToShutdown = true;
    }

    Path simctlPath = xcodeDeveloperPath.get().resolve("usr/bin/simctl");
    Optional<AppleSimulator> appleSimulator =
        getAppleSimulatorForBundle(appleBundle, processExecutor, simctlPath);

    if (!appleSimulator.isPresent()) {
      params
          .getConsole()
          .printBuildFailure(
              String.format(
                  "Cannot install %s (no appropriate simulator found)",
                  appleBundle.getFullyQualifiedName()));
      return FAILURE;
    }

    Path iosSimulatorPath = null;
    Path xcodeApplicationsPath = xcodeDeveloperPath.get().resolve("Applications");
    for (String simulatorApp : APPLE_SIMULATOR_APPS) {
      Path resolvedSimulatorPath = xcodeApplicationsPath.resolve(simulatorApp);
      if (projectFilesystem.isDirectory(resolvedSimulatorPath)) {
        iosSimulatorPath = resolvedSimulatorPath;
        break;
      }
    }

    if (iosSimulatorPath == null) {
      params
          .getConsole()
          .printBuildFailure(
              String.format(
                  "Cannot install %s (could not find simulator under %s, checked %s)",
                  appleBundle.getFullyQualifiedName(),
                  xcodeApplicationsPath,
                  APPLE_SIMULATOR_APPS));
      return FAILURE;
    }

    AppleSimulatorController appleSimulatorController =
        new AppleSimulatorController(processExecutor, simctlPath, iosSimulatorPath);

    if (!appleSimulatorController.canStartSimulator(appleSimulator.get().getUdid())) {
      LOG.info("Cannot start simulator %s, killing simulators and trying again.");
      if (!appleCoreSimulatorServiceController.killSimulatorProcesses()) {
        params.getConsole().printBuildFailure("Could not kill running simulator processes.");
        return FAILURE;
      }

      shouldWaitForSimulatorsToShutdown = true;

      // Killing the simulator can cause the UDIDs to change, so we need to fetch them again.
      appleSimulator = getAppleSimulatorForBundle(appleBundle, processExecutor, simctlPath);
      if (!appleSimulator.isPresent()) {
        params
            .getConsole()
            .printBuildFailure(
                String.format(
                    "Cannot install %s (no appropriate simulator found)",
                    appleBundle.getFullyQualifiedName()));
        return FAILURE;
      }
    }

    long remainingMillis = APPLE_SIMULATOR_WAIT_MILLIS;
    if (shouldWaitForSimulatorsToShutdown) {
      Optional<Long> shutdownMillis =
          appleSimulatorController.waitForSimulatorsToShutdown(remainingMillis);
      if (!shutdownMillis.isPresent()) {
        params
            .getConsole()
            .printBuildFailure(
                String.format(
                    "Cannot install %s (simulators did not shut down within %d ms).",
                    appleBundle.getFullyQualifiedName(), APPLE_SIMULATOR_WAIT_MILLIS));
        return FAILURE;
      }

      LOG.debug("Simulators shut down in %d millis.", shutdownMillis.get());
      remainingMillis -= shutdownMillis.get();
    }

    LOG.debug("Starting up simulator %s", appleSimulator.get());

    Optional<Long> startMillis =
        appleSimulatorController.startSimulator(appleSimulator.get().getUdid(), remainingMillis);

    if (!startMillis.isPresent()) {
      params
          .getConsole()
          .printBuildFailure(
              String.format(
                  "Cannot install %s (could not start simulator %s within %d ms)",
                  appleBundle.getFullyQualifiedName(),
                  appleSimulator.get().getName(),
                  APPLE_SIMULATOR_WAIT_MILLIS));
      return FAILURE;
    }

    LOG.debug(
        "Simulator started in %d ms. Installing Apple bundle %s in simulator %s",
        startMillis.get(), appleBundle, appleSimulator.get());

    if (!appleSimulatorController.installBundleInSimulator(
        appleSimulator.get().getUdid(),
        pathResolver.getAbsolutePath(
            Objects.requireNonNull(appleBundle.getSourcePathToOutput())))) {
      params
          .getConsole()
          .printBuildFailure(
              String.format(
                  "Cannot install %s (could not install bundle %s in simulator %s)",
                  appleBundle.getFullyQualifiedName(),
                  pathResolver.getAbsolutePath(appleBundle.getSourcePathToOutput()),
                  appleSimulator.get().getName()));
      return FAILURE;
    }

    if (run) {
      return launchAppleBundle(
          params, appleBundle, appleSimulatorController, projectFilesystem, appleSimulator.get());
    } else {
      params
          .getBuckEventBus()
          .post(
              ConsoleEvent.info(
                  params
                      .getConsole()
                      .getAnsi()
                      .asHighlightedSuccessText(
                          "Successfully installed %s. (Use `buck install -r %s` to run.)"),
                  getArguments().get(0),
                  getArguments().get(0)));
      return ImmutableInstallResult.of(ExitCode.SUCCESS, Optional.empty());
    }
  }