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

  • 3
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

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/をバージョン管理しない運用が推奨されている。