CPANモジュールのアンインストール(改良版)

信じられない間違いを犯していましたぁ!!(><)
aliasを書き直しました。
もし以前のaliasを持っていたら、見比べてニヤニヤしてくださいヽ(;´Д`)ノ

何かCPANPLUSでdistroprefsが使えない(CPANモジュールのオレオレパッチ - ヒルズで働く@robarioの技ログ)ので、一旦CPANに戻ってきました。

それで、CPANではアンインストールコマンドが無いので、cpan-uninstall(CPANモジュールのアンインストール - ヒルズで働く@robarioの技ログ)を使うわけなんですが、色々あってcpan-uninstallを改良しました。


コード(aliasとしてワンライナーで実装)

alias cpan-uninstall='\perl -MExtUtils::Install -MExtUtils::Installed -e "unshift@ARGV,new ExtUtils::Installed;sub a{\@ARGV};uninstall((eval{a->[0]->packlist(a->[1])}||do{require CPAN;a->[0]->packlist(CPAN::Shell->expandany(a->[1])->distribution->base_id=~m/(.*)-[^-]+$/)})->packlist_file,1,a->[2])"'


改良点

  1. ExtUtils::Installedを使って.packlistの位置を調べるようにした
  2. ディストリビューション名じゃなかったら、CPANを使ってディストリビューション名を調べるようにした
  3. cpan-uninstallの第2引数に実際のアンインストールを行なうかどうか指定できるようにした(--dry-run)。cpan-uninstall ack 1と書けばファイル一覧だけ表示して終了します(真なら何でも良いので cpan-uninstall ack -nでも良い)
  4. "$"を使わずに書いた($を使うとシェルに拾われてしまってちょっと面倒)

4番目を実現するために

unshift @ARGV, ExtUtils::Installed->new;
sub a{\@ARGV};
a->[0]->packlist(a->[1]);

というちょっとトリッキーな書き方をしています。perlでalias書くときにはちょっと便利&面白いんじゃないかなーと思います。
ARGVに関係無いデータ(ExtUtils::Installedオブジェクト)を突っ込んでるのがアレなんで、

sub a{+{ARGV=>\@ARGV,e=>new ExtUtils::Installed}};
a->{e}->packlist(a->{ARGV}->[0]);

とするのが妥当なのかもしれませんが・・・、ワンライナーなのでご勘弁^^;



最後に実行の様子でも。

# ディストリビューションを指定した場合
% sudo cpan-uninstall ack
unlink /usr/bin/ack
unlink /usr/lib/perl5/site_perl/5.10/App/Ack.pm
unlink /usr/lib/perl5/site_perl/5.10/i386-linux-thread-multi/auto/ack/.packlist

# モジュールを指定した場合(自動的にディストリビューション名を調べてくれる)
% sudo cpan-uninstall App::Ack
CPAN: File::HomeDir loaded ok (v0.80)
CPAN: Storable loaded ok (v2.18)
Going to read /var/tmp/.cpan/Metadata
  Database was generated on Sat, 23 Aug 2008 02:03:21 GMT
CPAN: YAML loaded ok (v0.66)
Going to read /var/tmp/.cpan/build/
DONE
Found no old builds, restored the state of none
unlink /usr/bin/ack
unlink /usr/lib/perl5/site_perl/5.10/App/Ack.pm
unlink /usr/lib/perl5/site_perl/5.10/i386-linux-thread-multi/auto/ack/.packlist


# おまけ:第2引数が真なら何もしない
% cpan-uninstall ack -n
unlink /usr/bin/ack
unlink /usr/lib/perl5/site_perl/5.10/App/Ack.pm
unlink /usr/lib/perl5/site_perl/5.10/i386-linux-thread-multi/auto/ack/.packlist


でもぶっちゃけrpm化した方が良いですよ。