Commit | Line | Data |
4a656c5e |
1 | #!perl |
2 | # Generates info for Module::CoreList from this perl tree |
e1018a69 |
3 | # run this from the root of a perl tree, using the perl built in that tree. |
4 | # |
5 | # Data is on STDOUT. |
6 | # |
7 | # With an optional arg specifying the root of a CPAN mirror, outputs the |
8 | # %upstream and %bug_tracker hashes too. |
9 | |
10 | use 5.010001; # needs Parse::CPAN::Meta |
4a656c5e |
11 | |
4a656c5e |
12 | use strict; |
13 | use warnings; |
14 | use File::Find; |
15 | use ExtUtils::MM_Unix; |
fb237dfd |
16 | use lib "Porting"; |
17 | use Maintainers qw(%Modules files_to_modules); |
18 | use File::Spec; |
4a656c5e |
19 | |
e1018a69 |
20 | |
59189dd7 |
21 | my %lines; |
fb237dfd |
22 | my %module_to_file; |
23 | my %modlist; |
e1018a69 |
24 | |
25 | die "usage: $0 [ cpan-mirror/ ]\n" unless @ARGV <= 1; |
fb237dfd |
26 | my $cpan = shift; |
27 | |
e1018a69 |
28 | if (! -f 'MANIFEST') { |
29 | die "Must be run from the root of a clean perl tree\n" |
30 | } |
31 | |
fb237dfd |
32 | if ($cpan) { |
33 | my $modlistfile |
34 | = File::Spec->catfile($cpan, 'modules', '02packages.details.txt'); |
35 | open my $fh, '<', $modlistfile or die "Couldn't open $modlistfile: $!"; |
36 | |
37 | { |
38 | local $/ = "\n\n"; |
39 | die "Incompatible modlist format" |
40 | unless <$fh> =~ /^Columns: +package name, version, path/m; |
41 | } |
42 | |
43 | # Converting the file to a hash is about 5 times faster than a regexp flat |
44 | # lookup. |
45 | while (<$fh>) { |
46 | next unless /^([A-Za-z_:0-9]+) +[-0-9.undefHASHVERSIONvsetwhenloadingbogus]+ +(\S+)/; |
47 | $modlist{$1} = $2; |
48 | } |
49 | } |
50 | |
4a656c5e |
51 | find(sub { |
52 | /(\.pm|_pm\.PL)$/ or return; |
d51d469b |
53 | /PPPort\.pm$/ and return; |
4a656c5e |
54 | my $module = $File::Find::name; |
d51d469b |
55 | $module =~ /\b(demo|t|private)\b/ and return; # demo or test modules |
56 | my $version = MM->parse_version($_); |
57 | defined $version or $version = 'undef'; |
4a656c5e |
58 | $version =~ /\d/ and $version = "'$version'"; |
59 | # some heuristics to figure out the module name from the file name |
4a626d91 |
60 | $module =~ s{^(lib|(win32/|vms/|symbian/)?ext)/}{} |
61 | and $1 ne 'lib' |
fb237dfd |
62 | and ( $module =~ s{\b(\w+)/\1\b}{$1}, |
dc5f10bb |
63 | $module =~ s{^B/O}{O}, |
da09dfe3 |
64 | $module =~ s{^Devel-PPPort}{Devel}, |
4a656c5e |
65 | $module =~ s{^Encode/encoding}{encoding}, |
da09dfe3 |
66 | $module =~ s{^IPC-SysV/}{IPC/}, |
67 | $module =~ s{^MIME-Base64/QuotedPrint}{MIME/QuotedPrint}, |
dc5f10bb |
68 | $module =~ s{^(?:DynaLoader|Errno|Opcode)/}{}, |
4a656c5e |
69 | ); |
70 | $module =~ s{/}{::}g; |
da09dfe3 |
71 | $module =~ s{-}{::}g; |
72 | $module =~ s{^.*::lib::}{}; |
4a656c5e |
73 | $module =~ s/(\.pm|_pm\.PL)$//; |
0fdd9e5c |
74 | $lines{$module} = $version; |
fb237dfd |
75 | $module_to_file{$module} = $File::Find::name; |
59189dd7 |
76 | }, 'lib', 'ext', 'vms/ext', 'symbian/ext'); |
77 | |
0fdd9e5c |
78 | -e 'configpm' and $lines{Config} = 'undef'; |
cc8432b2 |
79 | |
59189dd7 |
80 | if (open my $ucdv, "<", "lib/unicore/version") { |
81 | chomp (my $ucd = <$ucdv>); |
0fdd9e5c |
82 | $lines{Unicode} = "'$ucd'"; |
59189dd7 |
83 | close $ucdv; |
84 | } |
fb237dfd |
85 | |
86 | sub display_hash { |
87 | my ($hash) = @_; |
0fdd9e5c |
88 | } |
fb237dfd |
89 | |
90 | print " $] => {\n"; |
91 | printf "\t%-24s=> $lines{$_},\n", "'$_'" foreach sort keys %lines; |
4a656c5e |
92 | print " },\n"; |
fb237dfd |
93 | |
94 | exit unless %modlist; |
95 | |
96 | # We have to go through this two stage lookup, given how Maintainers.pl keys its |
97 | # data by "Module", which is really a dist. |
98 | my $file_to_M = files_to_modules(values %module_to_file); |
99 | |
100 | my %module_to_upstream; |
101 | my %module_to_dist; |
102 | my %dist_to_meta_YAML; |
103 | while (my ($module, $file) = each %module_to_file) { |
104 | my $M = $file_to_M->{$file}; |
105 | next unless $M; |
106 | next if $Modules{$M}{MAINTAINER} eq 'p5p'; |
107 | $module_to_upstream{$module} = $Modules{$M}{UPSTREAM}; |
108 | next if defined $module_to_upstream{$module} && |
109 | $module_to_upstream{$module} =~ /^(?:blead|first-come)$/; |
110 | my $dist = $modlist{$module}; |
111 | unless ($dist) { |
112 | warn "Can't find a distribution for $module"; |
113 | next; |
114 | } |
115 | $module_to_dist{$module} = $dist; |
116 | |
117 | next if exists $dist_to_meta_YAML{$dist}; |
118 | |
119 | $dist_to_meta_YAML{$dist} = undef; |
120 | |
121 | # Like it or lump it, this has to be Unix format. |
122 | my $meta_YAML_path = "$cpan/authors/id/$dist"; |
123 | $meta_YAML_path =~ s/(?:tar\.gz|zip)$/meta/ or die "$meta_YAML_path"; |
124 | unless (-e $meta_YAML_path) { |
125 | warn "$meta_YAML_path does not exist for $module"; |
126 | # I tried code to open the tarballs with Archive::Tar to find and |
127 | # extract META.yml, but only Text-Tabs+Wrap-2006.1117.tar.gz had one, |
128 | # so it's not worth including. |
129 | next; |
130 | } |
131 | require Parse::CPAN::Meta; |
132 | $dist_to_meta_YAML{$dist} = Parse::CPAN::Meta::LoadFile($meta_YAML_path); |
133 | } |
134 | |
135 | print "\n%upstream = (\n"; |
136 | foreach my $module (sort keys %module_to_upstream) { |
137 | my $upstream = defined $module_to_upstream{$module} |
138 | ? "'$module_to_upstream{$module}'" : 'undef'; |
139 | printf " %-24s=> $upstream,\n", "'$module'"; |
140 | } |
141 | print ");\n"; |
142 | |
143 | print "\n%bug_tracker = (\n"; |
144 | foreach my $module (sort keys %module_to_upstream) { |
145 | my $upstream = defined $module_to_upstream{$module}; |
146 | next if defined $upstream |
147 | and $upstream eq 'blead' || $upstream eq 'first-come'; |
148 | |
149 | my $bug_tracker; |
150 | |
151 | my $dist = $module_to_dist{$module}; |
152 | $bug_tracker = $dist_to_meta_YAML{$dist}->{resources}{bugtracker} |
153 | if $dist; |
154 | |
155 | $bug_tracker = defined $bug_tracker ? "'$bug_tracker'" : 'undef'; |
156 | next if $bug_tracker eq "'http://rt.perl.org/perlbug/'"; |
157 | printf " %-24s=> $bug_tracker,\n", "'$module'"; |
158 | } |
159 | print ");\n"; |