Edited at

cpanfileから消したはずの依存がcpanfile.snapshotに残る

More than 3 years have passed since last update.

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にある。ざっくりまとめると



  1. $builder->install($env->install_path);で依存モジュールをlocal/にインストールする。


    • 内部的にはcpanmを呼び出している(Carton::Builder::installを参照)




  2. $env->snapshot->find_installs($env->install_path, $env->cpanfile->requirements);でlocal/にインストールされているモジュールを走査して$env->snapshot->save;でcpanfile.snapshotに書き出す。

という処理をしている。


関連



This document is licensed under
CC0.





  1. Cartonのドキュメントではlocal/をバージョン管理しない運用が推奨されている。