public final function selectWorkflow(&$command, array &$args, ArcanistConfigurationManager $configuration_manager, PhutilConsole $console) { // First, try to build a workflow with the exact name provided. We always // pick an exact match, and do not allow aliases to override it. $workflow = $this->buildWorkflow($command); if ($workflow) { return $workflow; } // If the user has an alias, like 'arc alias dhelp diff help', look it up // and substitute it. We do this only after trying to resolve the workflow // normally to prevent you from doing silly things like aliasing 'alias' // to something else. $aliases = ArcanistAliasWorkflow::getAliases($configuration_manager); list($new_command, $args) = ArcanistAliasWorkflow::resolveAliases($command, $this, $args, $configuration_manager); $full_alias = idx($aliases, $command, array()); $full_alias = implode(' ', $full_alias); // Run shell command aliases. if (ArcanistAliasWorkflow::isShellCommandAlias($new_command)) { $shell_cmd = substr($full_alias, 1); $console->writeLog("[%s: 'arc %s' -> \$ %s]", pht('alias'), $command, $shell_cmd); if ($args) { $err = phutil_passthru('%C %Ls', $shell_cmd, $args); } else { $err = phutil_passthru('%C', $shell_cmd); } exit($err); } // Run arc command aliases. if ($new_command) { $workflow = $this->buildWorkflow($new_command); if ($workflow) { $console->writeLog("[%s: 'arc %s' -> 'arc %s']\n", pht('alias'), $command, $full_alias); $command = $new_command; return $workflow; } } $all = array_keys($this->buildAllWorkflows()); // We haven't found a real command or an alias, so try to locate a command // by unique prefix. $prefixes = $this->expandCommandPrefix($command, $all); if (count($prefixes) == 1) { $command = head($prefixes); return $this->buildWorkflow($command); } else { if (count($prefixes) > 1) { $this->raiseUnknownCommand($command, $prefixes); } } // We haven't found a real command, alias, or unique prefix. Try similar // spellings. $corrected = self::correctCommandSpelling($command, $all, 2); if (count($corrected) == 1) { $console->writeErr(pht("(Assuming '%s' is the British spelling of '%s'.)", $command, head($corrected)) . "\n"); $command = head($corrected); return $this->buildWorkflow($command); } else { if (count($corrected) > 1) { $this->raiseUnknownCommand($command, $corrected); } } $this->raiseUnknownCommand($command); }
/** * NOTE: SPOOKY BLACK MAGIC * * When arc is run in a copy of arcanist other than itself, or a copy of * libphutil other than the one we loaded, reenter the script and force it * to use the current working directory instead of the default. * * In the case of execution inside arcanist/, we force execution of the local * arc binary. * * In the case of execution inside libphutil/, we force the local copy to load * instead of the one selected by default rules. * * @param PhutilConsole Console. * @param ArcanistWorkingCopyIdentity The current working copy. * @param array Original arc arguments. * @return void */ function reenter_if_this_is_arcanist_or_libphutil(PhutilConsole $console, ArcanistWorkingCopyIdentity $working_copy, array $original_argv) { $project_id = $working_copy->getProjectID(); if ($project_id != 'arcanist' && $project_id != 'libphutil') { // We're not in a copy of arcanist or libphutil. return; } $library_names = array('arcanist' => 'arcanist', 'libphutil' => 'phutil'); $library_root = phutil_get_library_root($library_names[$project_id]); $project_root = $working_copy->getProjectRoot(); if (Filesystem::isDescendant($library_root, $project_root)) { // We're in a copy of arcanist or libphutil, but already loaded the correct // copy. Continue execution normally. return; } if ($project_id == 'libphutil') { $console->writeLog("This is libphutil! Forcing this copy to load...\n"); $original_argv[0] = dirname(phutil_get_library_root('arcanist')) . '/bin/arc'; $libphutil_path = $project_root; } else { $console->writeLog("This is arcanist! Forcing this copy to run...\n"); $original_argv[0] = $project_root . '/bin/arc'; $libphutil_path = dirname(phutil_get_library_root('phutil')); } if (phutil_is_windows()) { $err = phutil_passthru('set ARC_PHUTIL_PATH=%s & %Ls', $libphutil_path, $original_argv); } else { $err = phutil_passthru('ARC_PHUTIL_PATH=%s %Ls', $libphutil_path, $original_argv); } exit($err); }