cpanfileにCPANモジュールを追加してcarton install
したとする。追加したモジュールをcpanfileから削除して、もう一度carton install
を実行したとき、最初に追加したCPANモジュールの依存がcpanfile.snapshot
に残ったままになるという現象が起きた。
理由
cpanfile.snapshotはlocal/にインストールされているモジュールから生成されるが、cpanfileからモジュールを外してもlocal/からは削除されないから。
対処方法
- local/を消してから
carton install
する。 -
cpanm --local-lib-contained local --uninstall Module::Name
でlocal/からモジュールを削除してからcarton install
する。(※ドキュメントでは--uninstall
はEXPERIMENTALと表示されていることに注意) -
Re: Cartonで不要になったモジュールをcpanfile.snapshotから削除したい - skaji's blog
- cpanfileに登録されたモジュールを起点に再帰的に依存モジュールを取得してcpanfile.snapshotに書き出しているらしい。
- 依存から外れたモジュールをlocal/から削除する機能はないので、
carton install
を実行すると、削除したモジュールがcpanfile.snapshotに再び追加される。carton install
を実行したらregen-cpanfile-snapshot.pl
を再実行すること。
VCSのブランチ間でlocal/が食い違う問題
「ブランチAでモジュールXを追加したが、ブランチBでは追加していない」という場合、local/をVCSで管理していないと1、ブランチBでもlocal/にモジュールXがインストールされた状態になるので、carton install
を実行するとcpanfile.snapshotにモジュールXが追加されてしまう。
gitのpost-checkout hookでlocal/を入れ替えるなどの対策が考えられる(→vzvu3k6k/carton-local-stash · GitHub)。
再現コード
mkdir tmp && cd tmp
echo "requires 'Nothing::Tiny';" > cpanfile
carton install
mv cpanfile.snapshot cpanfile.snapshot.0 # cpanfile.snapshotを外して
echo > cpanfile # cpanfileを空にする
carton install # cpanfile.snapshotには何の依存もない状態になってほしいが……
diff -sq cpanfile.snapshot cpanfile.snapshot.0 # cpanfile.snapshot.0と同じ内容になる
rm -rf local
rm cpanfile.snapshot
carton install # 一度local/を消すと、cpanfileの指定通りのcpanfile.snapshotが生成される
diff -sq cpanfile.snapshot cpanfile.snapshot.0
内部処理
carton install
の処理の実体はCarton::CLI::cmd_installにある。ざっくりまとめると
-
$builder->install($env->install_path);
で依存モジュールをlocal/にインストールする。
- 内部的にはcpanmを呼び出している(Carton::Builder::installを参照)
-
$env->snapshot->find_installs($env->install_path, $env->cpanfile->requirements);
でlocal/にインストールされているモジュールを走査して$env->snapshot->save;
でcpanfile.snapshotに書き出す。
という処理をしている。
関連
- Remove modules in local that can't be reached from cpanfile · Issue #127 · perl-carton/carton
-
carton-uninstall - uninstall modules from your local environment - metacpan.org:
carton uninstall
というコマンドがあったが、削除された。
This document is licensed under CC0.
-
Cartonのドキュメントではlocal/をバージョン管理しない運用が推奨されている。 ↩