Homebrewでのバージョン管理
Homebrewでは以前はHomebrew-versionsというtapが存在し、古いバージョンのインストールが出来たりしました。
現在はそれもなくなり、基本的に最新バージョンのものしかインストールできない仕様になっています。
一部、Pythonなど複数のよく使われるメジャーバージョンがある場合のみ、[email protected]
のような@
付きの名前で
違うバージョンがインストールできるようになってはいます。(@
なしがいずれかに対応するようになっている。)
普通のFormulaはちょっと前のバージョンを入れたい、と思っても 公式でやる方法は用意されていません。
なのでちょっと手動で色々とやる必要があります。
awscliのエラー
追記: 2023/01/20
以下のエラーはどうもawscli自体に問題があったというより、環境(恐らくPythonの)がおかしな状態になっていたようです。
別件でHomebrewを入れ直してawscliを入れたところ問題なく動きました。
2.9.1まで遡って入れ直して試してみましたがやはりエラーは起きませんでした。
追記ここまで
今回awscliでエラーが出て前のバージョンを使わなくてはならなくなったのが発端です。
最新の2.9.1にアップグレードすると
$ aws --version
Traceback (most recent call last):
File “/opt/homebrew/bin/aws”, line 19, in <module>
import awscli.clidriver
File “/opt/homebrew/Cellar/awscli/2.9.1/libexec/lib/python3.11/site-packages/awscli/clidriver.py”, line 43, in <module>
from awscli.help import ProviderHelpCommand
File “/opt/homebrew/Cellar/awscli/2.9.1/libexec/lib/python3.11/site-packages/awscli/help.py”, line 20, in <module>
from docutils.core import publish_string
ModuleNotFoundError: No module named ‘docutils’
といったエラーが出て使えなくなってしまいました。
問題が起こっているのはmacOSの環境で、M1 Macですが、Rosetta2を使ったx86_64の環境でも同じエラーが出ました。
WindowsのWSL環境では出なかったのでmacOSでの問題のようです。
毎日brew upgrade
をかけていますが、どうやら2.9.1に変更が入ったあたりが問題っぽい。
いくつか試してみたところ、
のcommitの前までならエラーが出ませんでした。
2.9.0でも上のcommit以降では同様のエラーが出ました。
上のエラーでもdocutilsに関して文句を言っているのでおそらくこの変更が原因。
まだIssueなどに上がってないことから、もしかしたら自分の環境固有の問題かもしれませんが、まだFormulaがアップデートされたばかりなので、今後同じようなエラーが出て問題が発覚するかもしれません。
とりあえず使えないと困るのでなんとかしようと。
Homebrewで古いバージョンのインストール
上にも書いたように、現状のHomebrewでは常に最新バージョンを常に使うことを想定して古いバージョンを使う方法は公式には用意されていません。
また、以前はFormulaのURLをを直接指定してのインストールなどもできましたが、現在は
$ brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/b72dc5a4db9c20cbda5c50a8e196943cca34d8f6/Formula/awscli.rb
Error: Installation of awscli from a GitHub commit URL is unsupported! `brew extract awscli` to a stable tap on GitHub instead.
といった感じでダメです。
さらに、ローカルにダウンロードして直接指定しても
$ brew install ./awscli.rb scli.rb
Warning: No available formula with the name “./awscli.rb”. Did you mean awscli?
==> Searching for similarly named formulae...
This similarly named formula was found:
awscli
To install it, run:
brew install awscli
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
となってできなくなっています。
したがってきちんとTapした形でFormulaを用意しないといけません。
すごく簡単には/opt/homebrew/Library/Taps/homebrew/homebrew-core/Formulaの中のawscli.rbを以前のものと置き換えて上げてbrew install
とかすれば古いバージョンがインストールできます。
ですが、これだとbrew update
などがうまくいかなくなります。
別途自分でTapレポジトリを作ってawsclimod.rbみたいな自分用のFormulaを作ることも考えられますが結構手間です。
なので、一旦古いFormulaを取り出して、元にもどすような事を考えます。
TapはGitのレポジトリとして管理されているので
$ brew rm awscli # 一旦現バージョンを削除
$ cd /opt/homebrew/Library/Taps/homebrew/homebrew-core
$ git log Formula/awscli.log # 必要なcommitを探す
$ git checkout b72dc5a4db9c20cbda5c50a8e196943cca34d8f6 # 必要なcommitの状態に移行
$ brew install awscli # 古いバージョンをインストール
$ aws --version
aws-cli/2.9.0 Python/3.11.0 Darwin/21.6.0 source/arm64 prompt/off
とすることで古いFormulaを取り出してインストールすることができます。
ただ、このままだとbrew update
などがうまくいななくなるので元のmaster
ブランチに戻す必要があります。
そのまま戻してしまうとbrew upgrade
で2.9.1になってしまいます。
とどめておくには以下の2つの方法があります。
ピンどめする
Homebrewにはbrew pin
というコマンドがあり、現在インストールされているパッケージを、アップデートされたバージョンがあってもそのまま留めておく、という機能があります。
これを使い、上の状態で、
$ brew pin awscli
$ git checkout master
とすることで、今後awscliを2.9.0のまま保つことができます。
この状態でupdate
/upgrade
してみると
$ brew update
Updated 2 taps (homebrew/core and homebrew/cask).
==> Outdated Formulae
awscli
You have 1 outdated formula installed.
You can upgrade it with brew upgrade
or list it with brew outdated.
$ brew upgrade
Error: Not upgrading 1 pinned package:
awscli 2.9.1
==> No packages to upgrade
みたいな感じでエラーにはなりますが、awscliに関してはバージョンを保ったままにできます。
もし問題が治ったバージョンがリリースされたらunpin
コマンドを使って、
$ brew unpin awscli
$ brew update && brew upgrade
で最新バージョンにすることができます。
古いバージョンを残して直接使う
上の方法だとbrew update
などでエラー終了になるのがちょっと気持ち悪いところです。
また、最新バージョンを試そうと思うと一旦unpin
してインストールした後、だめだったら
再び最初の方法で古いバージョンを入れ直す必要があります。
そこで、別の方法として、古いバージョンを残しておき、それを直接使う方法を考えます。
Homebrewではパッケージのバージョンごとに別のディレクトリを作りインストールを行い、そこから/opt/bin/などへのシンボリックリンクをはっています。
awscliであれば/opt/homebrew/Cellar/awscli/2.9.0にbin/awsなどがあります。
ただし、現在のHomebrewではパッケージの新しいバージョンがインストールされると古いバージョンは即座に消されるようになっています。
したがって上のようなエラーに気づいてから古いバージョンを使おうと思ってもすでに消されています。
これに関しては
$ export HOMEBREW_NO_INSTALL_CLEANUP=1
をしてからbrew
コマンドを使うことで古いバージョンを消さないようにできます。
これを使って、まず上の方法に従って2.9.0をインストールした後、
$ git checkout master
$ export HOMEBREW_NO_INSTALL_CLEANUP=1
$ brew update & brew upgrade
とすると /opt/homebrew/Cellar/awscli/に2.9.0と2.9.1が残ったままになります。
/opt/homebrew/bin/awsは2.9.1のものになってしまいますが、 2.9.0の実行ファイルも/opt/homebrew/Cellar/awscli/2.9.0/bin/awsに残っています。
そこで
$ export PATH=/opt/homebrew/Cellar/awscli/2.9.0/bin:$PATH
とすればaws
と呼ぶことで2.9.0の方を使えるようになります。
この方法であればbrew update
/brew upgrade
は問題なく行えますし、
最新のawscliも
$ /opt/homebrew/bin/aws --version
とすればすぐに使えるのでチェックも簡単にできます。
厳密には/opt/homebrew/Cellar/awscli/2.9.0/etcの下に補完用のファイルがあったりして このあたりも使えるようにしたほうが良いかもしれませんが、 最新バージョンとマイナーバージョンまで同じものでもあり大きな違いはなさそうなのでとりあえず実行ファイルだけ2.9.0を直接指定して動かすようにしています。
上の設定を毎回やるのは面倒なので、.bashrcなどに
export HOMEBREW_NO_INSTALL_CLEANUP=1
export PATH=/opt/homebrew/Cellar/awscli/2.9.0/bin:$PATH
を追記しておきます。
特にHOMEBREW_NO_INSTALL_CLEANUP
の設定は忘れると2.9.0のディレクトリがbrew upgrade
などで消えてしまうので注意。
逆に、この設定をし続けると他のFormulaも古いファイルが残り続けるのでディスクが圧迫されてる場合にはちょっと注意が必要です。
場合によっては一度HOMEBREW_NO_INSTALL_CLEANUP=0
でbrew upgrade
などを行って掃除してサイドawscliの2.9.0を入れたりする必要があるかもしれません。
ちなみに以前はbrew switch
という、古いバージョンへの切り替えコマンドがありましたが、
このコマンドも古いバージョンを即座に消すようになった流れの中で削除されていて現在は使えません。