mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-13 02:12:41 +01:00
678efa44c6
Summary: We shove alias parameters onto the front of the arg list so if you make an alias like "qdiff" = "diff x y z" and then run "qdiff a b c", we end up with "diff x y z a b c". However, currently we reverse alias parameters, so you actually get "diff z y x a b c". This is a problem for `arc alias bdiff -- diff --background 1`, which evaluates to `arc diff 1 --background` and fails. Test Plan: Created a `bdiff` alias and ran it successfully. Reviewers: vrana, btrahan Reviewed By: btrahan CC: aran Differential Revision: https://secure.phabricator.com/D3196
183 lines
5.4 KiB
PHP
183 lines
5.4 KiB
PHP
<?php
|
|
|
|
/*
|
|
* Copyright 2012 Facebook, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* Manages aliases for commands with options.
|
|
*
|
|
* @group workflow
|
|
*/
|
|
final class ArcanistAliasWorkflow extends ArcanistBaseWorkflow {
|
|
|
|
public function getCommandSynopses() {
|
|
return phutil_console_format(<<<EOTEXT
|
|
**alias**
|
|
**alias** __command__
|
|
**alias** __command__ __target__ -- [__options__]
|
|
EOTEXT
|
|
);
|
|
}
|
|
|
|
public function getCommandHelp() {
|
|
return phutil_console_format(<<<EOTEXT
|
|
Supports: cli
|
|
Create an alias from __command__ to __target__ (optionally, with
|
|
__options__). For example:
|
|
|
|
arc alias fpatch patch -- --force
|
|
|
|
...will create a new 'arc' command, 'arc fpatch', which invokes
|
|
'arc patch --force ...' when run. NOTE: use "--" before specifying
|
|
options!
|
|
|
|
If you start an alias with "!", the remainder of the alias will be
|
|
invoked as a shell command. For example, if you want to implement
|
|
'arc ls', you can do so like this:
|
|
|
|
arc alias ls '!ls'
|
|
|
|
You can now run "arc ls" and it will behave like "ls". Of course, this
|
|
example is silly and would make your life worse.
|
|
|
|
You can not overwrite builtins, including 'alias' itself. The builtin
|
|
will always execute, even if it was added after your alias.
|
|
|
|
To remove an alias, run:
|
|
|
|
arc alias fpatch
|
|
|
|
Without any arguments, 'arc alias' will list aliases.
|
|
EOTEXT
|
|
);
|
|
}
|
|
|
|
public function getArguments() {
|
|
return array(
|
|
'*' => 'argv',
|
|
);
|
|
}
|
|
|
|
public static function getAliases($working_copy) {
|
|
$working_copy_config_aliases = $working_copy->getConfig('aliases');
|
|
if (!$working_copy_config_aliases) {
|
|
$working_copy_config_aliases = array();
|
|
}
|
|
$user_config_aliases =
|
|
idx(self::readUserConfigurationFile(), 'aliases', array());
|
|
return $user_config_aliases + $working_copy_config_aliases;
|
|
}
|
|
|
|
private function writeAliases(array $aliases) {
|
|
$config = self::readUserConfigurationFile();
|
|
$config['aliases'] = $aliases;
|
|
self::writeUserConfigurationFile($config);
|
|
}
|
|
|
|
public function run() {
|
|
// We might not be in a working directory, so we don't want to require a
|
|
// working copy identity here.
|
|
$working_copy = ArcanistWorkingCopyIdentity::newFromPath(getcwd());
|
|
$aliases = self::getAliases($working_copy);
|
|
|
|
$argv = $this->getArgument('argv');
|
|
if (count($argv) == 0) {
|
|
if ($aliases) {
|
|
foreach ($aliases as $alias => $binding) {
|
|
echo phutil_console_format(
|
|
"**%s** %s\n",
|
|
$alias,
|
|
implode(' ' , $binding));
|
|
}
|
|
} else {
|
|
echo "You haven't defined any aliases yet.\n";
|
|
}
|
|
} else if (count($argv) == 1) {
|
|
if (empty($aliases[$argv[0]])) {
|
|
echo "No alias '{$argv[0]}' to remove.\n";
|
|
} else {
|
|
echo phutil_console_format(
|
|
"'**arc %s**' is currently aliased to '**arc %s**'.",
|
|
$argv[0],
|
|
implode(' ', $aliases[$argv[0]]));
|
|
$ok = phutil_console_confirm('Delete this alias?');
|
|
if ($ok) {
|
|
$was = implode(' ', $aliases[$argv[0]]);
|
|
unset($aliases[$argv[0]]);
|
|
$this->writeAliases($aliases);
|
|
echo "Unaliased '{$argv[0]}' (was '{$was}').\n";
|
|
} else {
|
|
throw new ArcanistUserAbortException();
|
|
}
|
|
}
|
|
} else {
|
|
$arc_config = $this->getArcanistConfiguration();
|
|
|
|
if ($arc_config->buildWorkflow($argv[0])) {
|
|
throw new ArcanistUsageException(
|
|
"You can not create an alias for '{$argv[0]}' because it is a ".
|
|
"builtin command. 'arc alias' can only create new commands.");
|
|
}
|
|
|
|
$aliases[$argv[0]] = array_slice($argv, 1);
|
|
echo phutil_console_format(
|
|
"Aliased '**arc %s**' to '**arc %s**'.\n",
|
|
$argv[0],
|
|
implode(' ', $aliases[$argv[0]]));
|
|
|
|
$this->writeAliases($aliases);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static function isShellCommandAlias($command) {
|
|
return preg_match('/^!/', $command);
|
|
}
|
|
|
|
public static function resolveAliases(
|
|
$command,
|
|
ArcanistConfiguration $config,
|
|
array $argv,
|
|
ArcanistWorkingCopyIdentity $working_copy) {
|
|
|
|
$aliases = ArcanistAliasWorkflow::getAliases($working_copy);
|
|
if (!isset($aliases[$command])) {
|
|
return array(null, $argv);
|
|
}
|
|
|
|
$new_command = head($aliases[$command]);
|
|
|
|
if (self::isShellCommandAlias($new_command)) {
|
|
return array($new_command, $argv);
|
|
}
|
|
|
|
$workflow = $config->buildWorkflow($new_command);
|
|
if (!$workflow) {
|
|
return array(null, $argv);
|
|
}
|
|
|
|
$alias_argv = array_slice($aliases[$command], 1);
|
|
foreach (array_reverse($alias_argv) as $alias_arg) {
|
|
if (!in_array($alias_arg, $argv)) {
|
|
array_unshift($argv, $alias_arg);
|
|
}
|
|
}
|
|
|
|
return array($new_command, $argv);
|
|
}
|
|
|
|
}
|