4

Given a CPAN dist file (e.g. like Acme-Chef-1.01.tar.gz), what is the algorithm to determine what module-versions are "defined" (or present) in the dist file?

For instance, in the 02packages.details.txt file, there are four lines which correspond to this dist file:

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

I basically want to know how those lines are generated.

Is the procedure something like:

  1. find all of the .pm files in the dist file
  2. load each of the .pm files and print out ${ "${pkg}::VERSION"} where $pkg is the package name corresponding to the .pm file name (i.e. if the .pm file name is Foo/Bar.pm then $pkg is Foo::Bar.)

Is there code which does this indexing procedure?

Do you really have to load the module in order to determine what its version is?

4

1 回答 1

4

为 PAUSE 执行此操作的实际代码在 GitHub 上。解析包和版本声明的子例程在 lib/PAUSE/pmfile.pm (packages_per_pmfileparse_version) 中。就使 CPAN 工作发生的事情而言,这是权威的,但它不是您想要为自己使用的代码 - PAUSE 已经有将近 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
于 2013-08-16T06:00:44.337 回答