从CPAN dist文件中获取“已定义”的模块?

时间:2013-08-16 02:09:37

标签: perl cpan

给定CPAN dist文件(例如像Acme-Chef-1.01.tar.gz),确定dist文件中“定义”(或存在)的模块版本的算法是什么?

例如,在02packages.details.txt文件中,有四行与此dist文件对应:

Acme::Chef                         1.01  S/SM/SMUELLER/Acme-Chef-1.01.tar.gz
Acme::Chef::Container              1.00  S/SM/SMUELLER/Acme-Chef-1.01.tar.gz
Acme::Chef::Ingredient             1.00  S/SM/SMUELLER/Acme-Chef-1.01.tar.gz
Acme::Chef::Recipe                 1.00  S/SM/SMUELLER/Acme-Chef-1.01.tar.gz

我基本上想知道这些行是如何生成的。

程序是这样的:

  1. 查找dist文件中的所有.pm个文件
  2. 加载每个.pm文件并打印出${ "${pkg}::VERSION"},其中$pkg是与.pm文件名对应的包名称(即.pm文件名为Foo/Bar.pm$pkgFoo::Bar。)
  3. 是否有代码执行此索引过程?

    你真的必须加载模块才能确定它的版本是什么吗?

1 个答案:

答案 0 :(得分:4)

为PAUSE执行此操作的实际代码是on GitHub here。解析包和版本声明的子例程位于lib / PAUSE / pmfile.pm(packages_per_pmfileparse_version)中。这对于使CPAN工作的情况具有权威性,但它不是你想要自己使用的代码 - 暂停已经差不多20年了,甚至在最近的一些清理工作之后仍然非常严重。

相反,请查看Module::Metadata。你给它一个文件,它提供了一个非常简单的接口来发现该文件中的包的名称以及它们的版本。

这很简单:

my $mm = Module::Metadata->new_from_file("My/Module.pm");
for my $package ($mm->packages_inside) {
    print "$package: ", $mm->version($package), "\n";
}

事实上,这种“单线”有效:

find Acme-Chef-1.01 -name \*.pm \
| perl -MModule::Metadata -ln \
-e 'my $mm = Module::Metadata->new_from_file($_); ' \
-e 'print "$_: ", $mm->version($_) for $mm->packages_inside' \
| sort

和输出:

Acme::Chef: 1.01
Acme::Chef::Container: 1.00
Acme::Chef::Ingredient: 1.00
Acme::Chef::Recipe: 1.00