要するに
-
composer updaとかの中途半端なコマンドでもupdateと解釈してくれる - symfony が前方一致で探索してくれているおかげ
ことの始まり
[higa@local]$ composer upda
あらー。 update としたいところ、間違えて upda って打っちゃったー。
これはコマンド失敗でしょうねー。
[higa@local]$ composer upda
Loading composer repositories with package information
へ?
[higa@local]$ composer upda
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 1 update, 0 removals
# 以下略
ほ?
普段の update と同じ出力が流れ始めたんですがー。
# もちろん成功
composer update
# もちろん成功 (公式でエイリアスを用意している)
composer u
# updateコマンドとして処理してくれる
composer updat
# 同上
composer upda
# 同上
composer upd
# 同上
composer up
どういうことー?
composer のマニュアル
マニュアルやコードによると、アップデートできるコマンドは update。
エイリアスとして u, upgrade を用意しています。
他の、途切れた文字列は未定義です。
[higa@local]$ composer
______
/ ____/___ ____ ___ ____ ____ ________ _____
/ / / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
/_/
Composer version 2.2.1
Usage:
command [options] [arguments]
Available commands:
u Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
update Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
upgrade Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
https://github.com/composer/composer/blob/2.2.1/src/Composer/Command/UpdateCommand.php#L48
class UpdateCommand extends BaseCommand
{
/**
* @return void
*/
protected function configure()
{
$this
->setName('update')
->setAliases(array('u', 'upgrade'))
symfony のコード
composer は symfony/console などのライブラリを使っています。
下記は Application::find() の一部です。この下で、引数が ambiguous かどうかを判断しますが、composer では u から始まるコマンド・エイリアスが、たまたま update 1種類しかありません。
そのため、右文字がいかに削れようとも、無事に update コマンドと解釈して処理するようです。
https://github.com/symfony/console/blob/v2.8.52/Application.php#L493
public function find(string $name)
{
// 中略
$allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
// 引数 (composerのコマンド) が、途中で切れた `upda` であったとき、
// $expr = 'upda[^:]*[^:]*';
// になる。
$commands = preg_grep('{^'.$expr.'}', $allCommands);
// 正規表現で前方一致探索してくれるので、
// $commands = ['update'];
// を選定する。
おわりに
この記事では composer update コマンドが途中で切れていても動作する理由を探りました。
原因の箇所が vendor ディレクトリ配下にあるので、「composer の案内と違うけどなー?」と、しばらく混乱したのでした。
それではごきげんよう。