final public function parseArguments()

in src/workflow/ArcanistWorkflow.php [642:782]


  final public function parseArguments(array $args) {
    $this->passedArguments = $args;

    $spec = $this->getCompleteArgumentSpecification();

    $dict = array();

    $more_key = null;
    if (!empty($spec['*'])) {
      $more_key = $spec['*'];
      unset($spec['*']);
      $dict[$more_key] = array();
    }

    $short_to_long_map = array();
    foreach ($spec as $long => $options) {
      if (!empty($options['short'])) {
        $short_to_long_map[$options['short']] = $long;
      }
    }

    foreach ($spec as $long => $options) {
      if (!empty($options['repeat'])) {
        $dict[$long] = array();
      }
    }

    $more = array();
    $size = count($args);
    for ($ii = 0; $ii < $size; $ii++) {
      $arg = $args[$ii];
      $arg_name = null;
      $arg_key = null;
      if ($arg == '--') {
        $more = array_merge(
          $more,
          array_slice($args, $ii + 1));
        break;
      } else if (!strncmp($arg, '--', 2)) {
        $arg_key = substr($arg, 2);
        $parts = explode('=', $arg_key, 2);
        if (count($parts) == 2) {
          list($arg_key, $val) = $parts;

          array_splice($args, $ii, 1, array('--'.$arg_key, $val));
          $size++;
        }

        if (!array_key_exists($arg_key, $spec)) {
          $corrected = PhutilArgumentSpellingCorrector::newFlagCorrector()
            ->correctSpelling($arg_key, array_keys($spec));
          if (count($corrected) == 1) {
            PhutilConsole::getConsole()->writeErr(
              pht(
                "(Assuming '%s' is the British spelling of '%s'.)",
                '--'.$arg_key,
                '--'.head($corrected))."\n");
            $arg_key = head($corrected);
          } else {
            throw new ArcanistUsageException(
              pht(
                "Unknown argument '%s'. Try '%s'.",
                $arg_key,
                'arc help'));
          }
        }
      } else if (!strncmp($arg, '-', 1)) {
        $arg_key = substr($arg, 1);
        if (empty($short_to_long_map[$arg_key])) {
          throw new ArcanistUsageException(
            pht(
              "Unknown argument '%s'. Try '%s'.",
              $arg_key,
              'arc help'));
        }
        $arg_key = $short_to_long_map[$arg_key];
      } else {
        $more[] = $arg;
        continue;
      }

      $options = $spec[$arg_key];
      if (empty($options['param'])) {
        $dict[$arg_key] = true;
      } else {
        if ($ii == $size - 1) {
          throw new ArcanistUsageException(
            pht(
              "Option '%s' requires a parameter.",
              $arg));
        }
        if (!empty($options['repeat'])) {
          $dict[$arg_key][] = $args[$ii + 1];
        } else {
          $dict[$arg_key] = $args[$ii + 1];
        }
        $ii++;
      }
    }

    if ($more) {
      if ($more_key) {
        $dict[$more_key] = $more;
      } else {
        $example = reset($more);
        throw new ArcanistUsageException(
          pht(
            "Unrecognized argument '%s'. Try '%s'.",
            $example,
            'arc help'));
      }
    }

    foreach ($dict as $key => $value) {
      if (empty($spec[$key]['conflicts'])) {
        continue;
      }
      foreach ($spec[$key]['conflicts'] as $conflict => $more) {
        if (isset($dict[$conflict])) {
          if ($more) {
            $more = ': '.$more;
          } else {
            $more = '.';
          }
          // TODO: We'll always display these as long-form, when the user might
          // have typed them as short form.
          throw new ArcanistUsageException(
            pht(
              "Arguments '%s' and '%s' are mutually exclusive",
              "--{$key}",
              "--{$conflict}").$more);
        }
      }
    }

    $this->arguments = $dict;

    $this->didParseArguments();

    return $this;
  }