1 |
Author: cab |
2 |
Date: 2005-05-10 23:19:46 +0200 (Tue, 10 May 2005) |
3 |
New Revision: 1 |
4 |
|
5 |
Added: |
6 |
g-cpan.pl |
7 |
Log: |
8 |
|
9 |
|
10 |
Added: g-cpan.pl |
11 |
=================================================================== |
12 |
--- g-cpan.pl 2005-05-10 21:07:00 UTC (rev 0) |
13 |
+++ g-cpan.pl 2005-05-10 21:19:46 UTC (rev 1) |
14 |
@@ -0,0 +1,824 @@ |
15 |
+#!/usr/bin/perl -w |
16 |
+# Copyright 1999-2004 Gentoo Foundation |
17 |
+# Distributed under the terms of the GNU General Public License v2 |
18 |
+# $Header: $ |
19 |
+# |
20 |
+ |
21 |
+# modules to use - these will need to be marked as |
22 |
+# dependencies, and installable by portage |
23 |
+use strict; |
24 |
+use diagnostics; |
25 |
+use File::Spec; |
26 |
+use File::Path; |
27 |
+use List::Util qw(first); |
28 |
+ |
29 |
+sub printbig; |
30 |
+ |
31 |
+# Do we need to generate a config ? |
32 |
+eval 'use CPAN::Config;'; |
33 |
+my $needs_cpan_stub = $@ ? 1 : 0; |
34 |
+ |
35 |
+# Test Replacement - ((A&B)or(C&B)) should be the same as ((A or C) and B) |
36 |
+if (( ($needs_cpan_stub) || ( $> > 0 ) ) && ( !-f "$ENV{HOME}/.cpan/CPAN/MyConfig.pm" ) ) { |
37 |
+ # In case match comes from the UID test |
38 |
+ $needs_cpan_stub = 1; |
39 |
+ |
40 |
+ # Generate a fake config for CPAN |
41 |
+ cpan_stub(); |
42 |
+} |
43 |
+else { |
44 |
+ $needs_cpan_stub = 0; |
45 |
+} |
46 |
+ |
47 |
+use CPAN; |
48 |
+ |
49 |
+use Getopt::Long; |
50 |
+Getopt::Long::Configure("bundling"); |
51 |
+ |
52 |
+use Digest::MD5; |
53 |
+ |
54 |
+my $VERSION = "0.13"; |
55 |
+ |
56 |
+my @perl_dirs = ( |
57 |
+ "dev-perl", "perl-core", "perl-gcpan", "perl-text", |
58 |
+ "perl-tools", "perl-xml", "perl-dev" |
59 |
+); |
60 |
+ |
61 |
+############################### |
62 |
+# Command line interpretation # |
63 |
+############################### |
64 |
+ |
65 |
+# Init all options |
66 |
+my ( $verbose, $search, $install, $upgrade, $list ) = (0,0,0,0,0); |
67 |
+ |
68 |
+#Get & Parse them |
69 |
+GetOptions( |
70 |
+ 'verbose|v' => \$verbose, |
71 |
+ 'search|s' => \$search, |
72 |
+ 'install|i' => \$install, |
73 |
+ 'upgrade|u' => \$upgrade, |
74 |
+ 'list|l' => \$list, |
75 |
+ 'help|h' => sub { exit_usage(); } |
76 |
+ ) |
77 |
+ or exit_usage(); |
78 |
+ |
79 |
+# Output error if more than one switch is activated |
80 |
+if ($search + $list + $install + $upgrade > 1) { |
81 |
+ print "You can't combine search, list, install or upgrade with each other. Pick up one !\n\n"; |
82 |
+ exit_usage(); |
83 |
+} |
84 |
+ |
85 |
+# Output error if no arguments |
86 |
+if ( !( defined( $ARGV[0] ) ) and (!($upgrade) or !($list)) ) { |
87 |
+ print "Not even one module name or expression given !\n\n"; |
88 |
+ exit_usage(); |
89 |
+} |
90 |
+ |
91 |
+ |
92 |
+########## |
93 |
+# main() # |
94 |
+########## |
95 |
+ |
96 |
+# Taking care of Searches. This has to be improved a lot, since it uses a call to |
97 |
+# CPAN Shell to do the job, thus making it impossible to have a clean output.. |
98 |
+if ($search) { |
99 |
+ foreach my $expr (@ARGV) { |
100 |
+ |
101 |
+ # Assume they gave us module-name instead of module::name |
102 |
+ if ( $expr !~ m|::| ) { |
103 |
+ $expr =~ s/-/::/g; |
104 |
+ } |
105 |
+ print "Searching for $expr on CPAN\n\n"; |
106 |
+ CPAN::Shell->m("/$expr/"); |
107 |
+ } |
108 |
+ |
109 |
+ clean_the_mess(); |
110 |
+ exit; |
111 |
+} |
112 |
+ |
113 |
+ |
114 |
+# Take care of List requests. This should return all the ebuilds managed by g-cpan |
115 |
+if ( $list ) { |
116 |
+ print "List function not implemented yet.\n"; |
117 |
+ exit_usage(); |
118 |
+} |
119 |
+ |
120 |
+# Set our temporary overlay directory for the scope of this run. |
121 |
+# By setting an overlay directory, we bypass the predefined portage |
122 |
+# directory and allow portage to build a package outside of its |
123 |
+# normal tree. |
124 |
+my $tmp_overlay_dir; |
125 |
+if ( $ENV{TMPDIR} ) { $tmp_overlay_dir = "$ENV{TMPDIR}/perl-modules_$$" } |
126 |
+else { $tmp_overlay_dir = "/tmp/perl-modules_$$" } |
127 |
+ |
128 |
+my @ebuild_list; |
129 |
+ |
130 |
+# Set up global paths |
131 |
+# my $TMP_DEV_PERL_DIR = '/var/db/pkg/dev-perl'; |
132 |
+my $MAKECONF = '/etc/make.conf'; |
133 |
+my ( $PORTAGE_DISTDIR, $PORTAGE_DIR, @OVERLAYS ) = get_globals(); |
134 |
+ |
135 |
+my @OVERLAY_PERLS; |
136 |
+my @PORTAGE_DEV_PERL; |
137 |
+my @TMP_DEV_PERL_DIRS; |
138 |
+ |
139 |
+foreach my $pdir (@perl_dirs) { |
140 |
+ my $tmp_dir = File::Spec->catdir( $PORTAGE_DIR, $pdir ); |
141 |
+ push @PORTAGE_DEV_PERL, $tmp_dir; |
142 |
+ foreach my $odir (@OVERLAYS) { |
143 |
+ my $otmp = File::Spec->catdir( $odir, $pdir ); |
144 |
+ push @OVERLAY_PERLS, $otmp; |
145 |
+ } |
146 |
+ my $vtmp_dir = File::Spec->catdir( '/var/db/pkg/dev-perl', $pdir ); |
147 |
+ push @TMP_DEV_PERL_DIRS, $vtmp_dir; |
148 |
+} |
149 |
+ |
150 |
+# Create the ebuild in PORTDIR_OVERLAY, if it is defined and exists |
151 |
+if ( $OVERLAYS[0] ) { |
152 |
+ $tmp_overlay_dir = $OVERLAYS[0]; |
153 |
+ if ($verbose) { |
154 |
+ print |
155 |
+ "Setting $tmp_overlay_dir as the PORTDIR_OVERLAY for this session.\n"; |
156 |
+ } |
157 |
+} |
158 |
+ |
159 |
+my $arches = |
160 |
+ join( ' ', map { chomp; $_ } `cat $PORTAGE_DIR/profiles/arch.list` ); |
161 |
+ |
162 |
+#this should never find the dir, but just to be safe |
163 |
+unless ( -d $tmp_overlay_dir ) { |
164 |
+ mkpath( [$tmp_overlay_dir], 1, 0755 ) |
165 |
+ or die "Couldn't create '$tmp_overlay_dir': $|"; |
166 |
+} |
167 |
+ |
168 |
+# Now we cat our dev-perl directory onto our overlay directory. |
169 |
+# This is done so that portage records the appropriate path |
170 |
+#i.e. dev-perl/package |
171 |
+my $perldev_overlay = File::Spec->catfile( $tmp_overlay_dir, 'perl-gcpan' ); |
172 |
+ |
173 |
+unless ( -d $perldev_overlay ) { |
174 |
+ |
175 |
+ # create perldev overlay dir if not present |
176 |
+ mkpath( [$perldev_overlay], 1, 0755 ) |
177 |
+ or die "Couldn't create '$perldev_overlay': $|"; |
178 |
+} |
179 |
+ |
180 |
+# Now we export our overlay directory into the session's env vars |
181 |
+$ENV{'PORTDIR_OVERLAY'} = $tmp_overlay_dir; |
182 |
+ |
183 |
+# sub main.. well, sort of ;p |
184 |
+if ($install) { |
185 |
+ install_module($_) for (@ARGV); |
186 |
+ emerge_module($_) for (@ARGV); |
187 |
+} |
188 |
+if ($upgrade) { |
189 |
+ if (@ARGV) { |
190 |
+ upgrade_module($_) for (@ARGV); |
191 |
+ emerge_up_module($_) for (@ARGV); |
192 |
+ } |
193 |
+ else { |
194 |
+ my @GLIST = get_gcpans(); |
195 |
+ upgrade_module($_) for (@GLIST); |
196 |
+ emerge_up_module(@GLIST); |
197 |
+ } |
198 |
+ |
199 |
+} |
200 |
+if ( $install or $upgrade ) { clean_up() } |
201 |
+exit; |
202 |
+ |
203 |
+########## |
204 |
+# subs ! # |
205 |
+########## |
206 |
+ |
207 |
+# jrray printing functions |
208 |
+sub printbig { |
209 |
+ print '*' x 72, "\n"; |
210 |
+ print '*', "\n"; |
211 |
+ print '*', "\n"; |
212 |
+ print '* ', @_; |
213 |
+ print '*', "\n"; |
214 |
+ print '*', "\n"; |
215 |
+ print '*' x 72, "\n"; |
216 |
+} |
217 |
+ |
218 |
+sub ebuild_exists { |
219 |
+ my ($dir) = @_; |
220 |
+ |
221 |
+ # need to try harder here - see &portage_dir comments. |
222 |
+ # should return an ebuild name from this, as case matters. |
223 |
+ |
224 |
+ # see if an ebuild for $dir exists already. If so, return its name. |
225 |
+ my $found = ''; |
226 |
+ |
227 |
+ foreach my $sdir ( |
228 |
+ grep { -d $_ } ( |
229 |
+ @PORTAGE_DEV_PERL, @OVERLAY_PERLS, |
230 |
+ $perldev_overlay, @TMP_DEV_PERL_DIRS |
231 |
+ ) |
232 |
+ ) |
233 |
+ { |
234 |
+ opendir PDIR, $sdir; |
235 |
+ my @dirs = readdir(PDIR); |
236 |
+ closedir PDIR; |
237 |
+ $found ||= first { lc($_) eq lc($dir) }(@dirs); |
238 |
+ if ( ($found) && ($verbose) ) { |
239 |
+ print "$0: Looking for ebuilds in $sdir, found $found so far.\n"; |
240 |
+ } |
241 |
+ } |
242 |
+ |
243 |
+ # check for ebuilds that have been created by g-cpan.pl |
244 |
+ for my $ebuild (@ebuild_list) { |
245 |
+ $found = $ebuild if ( $ebuild eq $dir ); |
246 |
+ } |
247 |
+ |
248 |
+ return $found; |
249 |
+} |
250 |
+ |
251 |
+sub get_gcpans { |
252 |
+ my @g_list; |
253 |
+ foreach my $sdir ( grep { -d $_ } ( @PORTAGE_DEV_PERL, @OVERLAY_PERLS ) ) { |
254 |
+ if ( $sdir =~ m/perl-gcpan/ ) { |
255 |
+ opendir PDIR, $sdir; |
256 |
+ my @dirs = readdir(PDIR); |
257 |
+ closedir PDIR; |
258 |
+ foreach my $dir (@dirs) { |
259 |
+ push @g_list, $dir |
260 |
+ unless ( ( $dir eq "." ) or ( $dir eq ".." ) ); |
261 |
+ } |
262 |
+ |
263 |
+ } |
264 |
+ } |
265 |
+ return @g_list; |
266 |
+} |
267 |
+ |
268 |
+sub build_catdep { |
269 |
+ |
270 |
+# Needed a way to add category to the dependancy instead of hardcoding dev-perl :/ |
271 |
+# On the upside, at this point we know the ebuild exists *somewhere* so we just need to locate it |
272 |
+ my ($dir) = @_; |
273 |
+ |
274 |
+ my $found = ''; |
275 |
+ |
276 |
+ foreach my $sdir ( |
277 |
+ grep { -d $_ } ( |
278 |
+ @PORTAGE_DEV_PERL, @OVERLAY_PERLS, |
279 |
+ $perldev_overlay, @TMP_DEV_PERL_DIRS |
280 |
+ ) |
281 |
+ ) |
282 |
+ { |
283 |
+ opendir PDIR, $sdir; |
284 |
+ my @dirs = readdir(PDIR); |
285 |
+ closedir PDIR; |
286 |
+ $found ||= first { lc($_) eq lc($dir) }(@dirs); |
287 |
+ if ($found) { |
288 |
+ $sdir =~ s/.*\///; |
289 |
+ $found = "$sdir/$found"; |
290 |
+ return $found; |
291 |
+ } |
292 |
+ } |
293 |
+ |
294 |
+} |
295 |
+ |
296 |
+sub module_check { |
297 |
+ |
298 |
+# module_check evaluates whether a module can be loaded from @INC. |
299 |
+# This allows us to assure that if a module has been manually installed, we know about it. |
300 |
+ my $check = shift; |
301 |
+ eval "use $check;"; |
302 |
+ return $@ ? 0 : 1; |
303 |
+} |
304 |
+ |
305 |
+sub portage_dir { |
306 |
+ my $obj = shift; |
307 |
+ my $file = $obj->cpan_file; |
308 |
+ |
309 |
+ # need to try harder here than before (bugs 64403 74149 69464 23951 +more?) |
310 |
+ |
311 |
+ # remove ebuild-incompatible characters |
312 |
+ $file =~ tr/a-zA-Z0-9\.\//-/c; |
313 |
+ |
314 |
+ $file =~ s/\.pm//; # e.g. CGI.pm |
315 |
+ |
316 |
+ # turn this into a directory name suitable for portage tree |
317 |
+ # at least one module omits the hyphen between name and version. |
318 |
+ # these two regexps are 'better' matches than previously. |
319 |
+ if ( $file =~ m|.*/(.*)-[0-9]+\.| ) { return $1; } |
320 |
+ if ( $file =~ m|.*/([a-zA-Z-]*)[0-9]+\.| ) { return $1; } |
321 |
+ if ( $file =~ m|.*/([^.]*)\.| ) { return $1; } |
322 |
+ |
323 |
+ warn "$0: Unable to coerce $file into a portage dir name"; |
324 |
+ return; |
325 |
+} |
326 |
+ |
327 |
+sub create_ebuild { |
328 |
+ my ( $module, $dir, $file, $build_dir, $prereq_pm, $md5 ) = @_; |
329 |
+ |
330 |
+ # First, make the directory |
331 |
+ my $fulldir = File::Spec->catdir( $perldev_overlay, $dir ); |
332 |
+ my $filesdir = File::Spec->catdir( $fulldir, 'files' ); |
333 |
+ unless ( -d $fulldir ) { |
334 |
+ mkdir $fulldir, 0755 or die "Couldn't create '$fulldir': $!"; |
335 |
+ } |
336 |
+ unless ( -d $filesdir ) { |
337 |
+ mkdir $filesdir, 0755 or die "Couldn't create '$filesdir': $!"; |
338 |
+ } |
339 |
+ |
340 |
+ unless ( -d $fulldir ) { die "$fulldir not created!!\n" } |
341 |
+ unless ( -d $filesdir ) { die "$fulldir not created!!\n" } |
342 |
+ |
343 |
+ # What to call this ebuild? |
344 |
+ # CGI::Builder's '1.26+' version breaks portage |
345 |
+ unless ( $file =~ m/(.*)\/(.*?)(-?)([0-9\.]+).*\.(?:tar|tgz|zip|bz2|gz)/ ) { |
346 |
+ warn("Couldn't turn '$file' into an ebuild name\n"); |
347 |
+ return; |
348 |
+ } |
349 |
+ |
350 |
+ my ( $modpath, $filename, $filenamever ) = ( $1, $2, $4 ); |
351 |
+ |
352 |
+ # remove underscores |
353 |
+ $filename =~ tr/A-Za-z0-9\./-/c; |
354 |
+ $filename =~ s/\.pm//; # e.g. CGI.pm |
355 |
+ |
356 |
+ # Remove double .'s - happens on occasion with odd packages |
357 |
+ $filenamever =~ s/\.$//; |
358 |
+ |
359 |
+ my $ebuild = |
360 |
+ File::Spec->catdir( $fulldir, "$filename-$filenamever.ebuild" ); |
361 |
+ my $digest = |
362 |
+ File::Spec->catdir( $filesdir, "digest-$filename-$filenamever" ); |
363 |
+ |
364 |
+ my $desc = $module->description || 'No description available.'; |
365 |
+ |
366 |
+ print "Writing to $ebuild\n" if ($verbose); |
367 |
+ open EBUILD, ">$ebuild" or die "Could not write to '$ebuild': $!"; |
368 |
+ print EBUILD <<"HERE"; |
369 |
+ |
370 |
+# Copyright 1999-2004 Gentoo Foundation |
371 |
+# Distributed under the terms of the GNU General Public License v2 |
372 |
+ |
373 |
+inherit perl-module |
374 |
+ |
375 |
+S=\${WORKDIR}/$build_dir |
376 |
+DESCRIPTION="$desc" |
377 |
+SRC_URI="mirror://cpan/authors/id/$file" |
378 |
+HOMEPAGE="http://www.cpan.org/modules/by-authors/id/$modpath/\${P}.readme" |
379 |
+ |
380 |
+IUSE="" |
381 |
+ |
382 |
+SLOT="0" |
383 |
+LICENSE="|| ( Artistic GPL-2 )" |
384 |
+KEYWORDS="$arches" |
385 |
+ |
386 |
+HERE |
387 |
+ |
388 |
+ if ( $prereq_pm && keys %$prereq_pm ) { |
389 |
+ |
390 |
+ print EBUILD q|DEPEND="|; |
391 |
+ |
392 |
+ my $first = 1; |
393 |
+ my %dup_check; |
394 |
+ for ( keys %$prereq_pm ) { |
395 |
+ my $obj = CPAN::Shell->expandany($_); |
396 |
+ my $dir = portage_dir($obj); |
397 |
+ if ( $dir =~ m/Module-Build/ ) { |
398 |
+ $dir =~ s/Module-Build/module-build/; |
399 |
+ } |
400 |
+ if ( $dir =~ m/PathTools/i ) { |
401 |
+ $dir = ">=dev-perl/File-Spec-3.01"; |
402 |
+ } # Will need to fix once File-Spec is moved to perl-core - mcummings |
403 |
+ next if $dir eq "perl"; |
404 |
+ if ( ( !$dup_check{$dir} ) && ( !module_check($dir) ) ) { |
405 |
+ $dup_check{$dir} = 1; |
406 |
+ |
407 |
+ # remove trailing .pm to fix emerge breakage. |
408 |
+ $dir =~ s/.pm$//; |
409 |
+ $dir = build_catdep($dir); |
410 |
+ print EBUILD "\n\t" unless $first; |
411 |
+ print EBUILD "$dir"; |
412 |
+ } |
413 |
+ $first = 0; |
414 |
+ } |
415 |
+ print EBUILD qq|"\n\n|; |
416 |
+ } |
417 |
+ |
418 |
+ close EBUILD; |
419 |
+ |
420 |
+ # write the digest too |
421 |
+ open DIGEST, ">$digest" or die "Could not write to '$digest': $!"; |
422 |
+ print DIGEST $md5, "\n"; |
423 |
+ close DIGEST; |
424 |
+} |
425 |
+ |
426 |
+sub install_module { |
427 |
+ my ( $module_name, $recursive ) = @_; |
428 |
+ if ( $module_name !~ m|::| ) { |
429 |
+ $module_name =~ s/-/::/g; |
430 |
+ } # Assume they gave us module-name instead of module::name |
431 |
+ |
432 |
+ my $obj = CPAN::Shell->expandany($module_name); |
433 |
+ unless ( ( ref $obj eq "CPAN::Module" ) || ( ref $obj eq "CPAN::Bundle" ) ) |
434 |
+ { |
435 |
+ warn("Don't know what '$module_name' is\n"); |
436 |
+ return; |
437 |
+ } |
438 |
+ |
439 |
+ my $file = $obj->cpan_file; |
440 |
+ my $dir = portage_dir($obj); |
441 |
+ print "$0: portage_dir returned $dir\n" if ($verbose); |
442 |
+ unless ($dir) { |
443 |
+ warn("Couldn't turn '$file' into a directory name\n"); |
444 |
+ return; |
445 |
+ } |
446 |
+ |
447 |
+ if ( ebuild_exists($dir) ) { |
448 |
+ printbig "Ebuild already exists for '$module_name': " |
449 |
+ . &ebuild_exists($dir) . "\n"; |
450 |
+ return; |
451 |
+ } |
452 |
+ elsif ( !defined $recursive && module_check($module_name) ) { |
453 |
+ printbig "Module already installed for '$module_name'\n"; |
454 |
+ return; |
455 |
+ } |
456 |
+ elsif ( $dir eq 'perl' ) { |
457 |
+ printbig "Module '$module_name' is part of the base perl install\n"; |
458 |
+ return; |
459 |
+ } |
460 |
+ |
461 |
+ printbig "Need to create ebuild for '$module_name': $dir\n"; |
462 |
+ |
463 |
+ # check depends ... with CPAN have to make the module |
464 |
+ # before it can tell us what the depends are, this stinks |
465 |
+ |
466 |
+ $CPAN::Config->{prerequisites_policy} = ""; |
467 |
+ $CPAN::Config->{inactivity_timeout} = 30; |
468 |
+ |
469 |
+ my $pack = $CPAN::META->instance( 'CPAN::Distribution', $file ); |
470 |
+ $pack->called_for( $obj->id ); |
471 |
+ $pack->make; |
472 |
+ |
473 |
+ # A cheap ploy, but this lets us add module-build as needed |
474 |
+ # instead of forcing it on everyone |
475 |
+ my $add_mb = 0; |
476 |
+ if ( -f "Build.PL" ) { $add_mb = 1 } |
477 |
+ $pack->unforce if $pack->can("unforce") && exists $obj->{'force_update'}; |
478 |
+ delete $obj->{'force_update'}; |
479 |
+ |
480 |
+ # grab the MD5 checksum for the source file now |
481 |
+ |
482 |
+ my $localfile = $pack->{localfile}; |
483 |
+ ( my $base = $file ) =~ s/.*\/(.*)/$1/; |
484 |
+ |
485 |
+ my $md5digest; |
486 |
+ open( DIGIFILE, $localfile ) or die "Can't open '$file': $!"; |
487 |
+ binmode(DIGIFILE); |
488 |
+ $md5digest = Digest::MD5->new->addfile(*DIGIFILE)->hexdigest; |
489 |
+ close(DIGIFILE); |
490 |
+ |
491 |
+ my $md5string = sprintf "MD5 %s %s %d", $md5digest, $base, -s $localfile; |
492 |
+ |
493 |
+ # make ebuilds for all the prereqs |
494 |
+ my $prereq_pm = $pack->prereq_pm; |
495 |
+ if ($add_mb) { $prereq_pm->{'Module::Build'} = "0" } |
496 |
+ install_module( $_, 1 ) for ( keys %$prereq_pm ); |
497 |
+ |
498 |
+ # get the build dir from CPAN, this will tell us definitively |
499 |
+ # what we should set S to in the ebuild |
500 |
+ # strip off the path element |
501 |
+ ( my $build_dir = $pack->{build_dir} ) =~ s|.*/||; |
502 |
+ |
503 |
+ create_ebuild( $obj, $dir, $file, $build_dir, $prereq_pm, $md5string ); |
504 |
+ |
505 |
+ system( '/bin/mv', '-f', $localfile, $PORTAGE_DISTDIR ); |
506 |
+ |
507 |
+ push @ebuild_list, "perl-gcpan/$dir"; |
508 |
+} |
509 |
+ |
510 |
+sub upgrade_module { |
511 |
+ |
512 |
+# My counter intuituve function - this time we *want* there to be an ebuild, because we want to track versions to make sure the ebuild is >= the module on cpan |
513 |
+ my ( $module_name, $recursive ) = @_; |
514 |
+ if ( $module_name !~ m|::| ) { |
515 |
+ $module_name =~ s/-/::/g; |
516 |
+ } # Assume they gave us module-name instead of module::name |
517 |
+ print "Looking for $module_name...\n"; |
518 |
+ my $obj = CPAN::Shell->expandany($module_name); |
519 |
+ unless ( ( ref $obj eq "CPAN::Module" ) || ( ref $obj eq "CPAN::Bundle" ) ) |
520 |
+ { |
521 |
+ warn("Don't know what '$module_name' is\n"); |
522 |
+ return; |
523 |
+ } |
524 |
+ |
525 |
+ my $file = $obj->cpan_file; |
526 |
+ my $dir = portage_dir($obj); |
527 |
+ print "$0: portage_dir returned $dir\n" if ($verbose); |
528 |
+ unless ($dir) { |
529 |
+ warn("Couldn't turn '$file' into a directory name\n"); |
530 |
+ return; |
531 |
+ } |
532 |
+ |
533 |
+ unless ( ebuild_exists($dir) ) { |
534 |
+ printbig "No ebuild available for '$module_name': " |
535 |
+ . &ebuild_exists($dir) . "\n"; |
536 |
+ return; |
537 |
+ } |
538 |
+ elsif ( defined $recursive && !module_check($module_name) ) { |
539 |
+ printbig "No module installed for '$module_name'\n"; |
540 |
+ return; |
541 |
+ } |
542 |
+ elsif ( $dir eq 'perl' ) { |
543 |
+ printbig |
544 |
+"Module '$module_name' is part of the base perl install - we don't touch perl here\n"; |
545 |
+ return; |
546 |
+ } |
547 |
+ |
548 |
+ printbig "Checking ebuild for '$module_name': $dir\n"; |
549 |
+ |
550 |
+ # check depends ... with CPAN have to make the module |
551 |
+ # before it can tell us what the depends are, this stinks |
552 |
+ |
553 |
+ $CPAN::Config->{prerequisites_policy} = ""; |
554 |
+ $CPAN::Config->{inactivity_timeout} = 30; |
555 |
+ |
556 |
+ my $pack = $CPAN::META->instance( 'CPAN::Distribution', $file ); |
557 |
+ $pack->called_for( $obj->id ); |
558 |
+ $pack->make; |
559 |
+ |
560 |
+ # A cheap ploy, but this lets us add module-build as needed |
561 |
+ # instead of forcing it on everyone |
562 |
+ my $add_mb = 0; |
563 |
+ if ( -f "Build.PL" ) { $add_mb = 1 } |
564 |
+ $pack->unforce if $pack->can("unforce") && exists $obj->{'force_update'}; |
565 |
+ delete $obj->{'force_update'}; |
566 |
+ |
567 |
+ # grab the MD5 checksum for the source file now |
568 |
+ |
569 |
+ my $localfile = $pack->{localfile}; |
570 |
+ ( my $base = $file ) =~ s/.*\/(.*)/$1/; |
571 |
+ |
572 |
+ my $md5digest; |
573 |
+ open( DIGIFILE, $localfile ) or die "Can't open '$file': $!"; |
574 |
+ binmode(DIGIFILE); |
575 |
+ $md5digest = Digest::MD5->new->addfile(*DIGIFILE)->hexdigest; |
576 |
+ close(DIGIFILE); |
577 |
+ |
578 |
+ my $md5string = sprintf "MD5 %s %s %d", $md5digest, $base, -s $localfile; |
579 |
+ |
580 |
+ # make ebuilds for all the prereqs |
581 |
+ my $prereq_pm = $pack->prereq_pm; |
582 |
+ if ($add_mb) { $prereq_pm->{'Module::Build'} = "0" } |
583 |
+ install_module( $_, 1 ) for ( keys %$prereq_pm ); |
584 |
+ |
585 |
+ # get the build dir from CPAN, this will tell us definitively |
586 |
+ # what we should set S to in the ebuild |
587 |
+ # strip off the path element |
588 |
+ ( my $build_dir = $pack->{build_dir} ) =~ s|.*/||; |
589 |
+ |
590 |
+ create_ebuild( $obj, $dir, $file, $build_dir, $prereq_pm, $md5string ); |
591 |
+ unless ( -f "$PORTAGE_DISTDIR/$localfile" ) { |
592 |
+ system( '/bin/mv', '-f', $localfile, $PORTAGE_DISTDIR ); |
593 |
+ push @ebuild_list, "perl-gcpan/$dir"; |
594 |
+ } |
595 |
+} |
596 |
+ |
597 |
+sub clean_up { |
598 |
+ |
599 |
+ #Probably don't need to do this, but for sanity's sake, we reset this var |
600 |
+ # $ENV{'PORTDIR_OVERLAY'} = $OVERLAYS[0]; |
601 |
+ |
602 |
+ if ($needs_cpan_stub) { unlink "$ENV{HOME}/.cpan/CPAN/MyConfig.pm" } |
603 |
+ |
604 |
+ #Clean out the /tmp tree we were using |
605 |
+ rmtree( ["$tmp_overlay_dir"] ) if ( !$OVERLAYS[0] ); |
606 |
+} |
607 |
+ |
608 |
+sub emerge_module { |
609 |
+ foreach my $ebuild_name (@ebuild_list) { |
610 |
+ $ebuild_name =~ m/.*\/(.*)-[^-]+\./; |
611 |
+ print "$0: emerging $ebuild_name\n"; |
612 |
+ system( "emerge", "--oneshot", "--digest", $ebuild_name ); |
613 |
+ } |
614 |
+} |
615 |
+ |
616 |
+sub emerge_up_module { |
617 |
+ |
618 |
+ #my @e_list = @_; |
619 |
+ print "\n\n"; |
620 |
+ foreach my $ebuild_name (@ebuild_list) { |
621 |
+ $ebuild_name =~ m/.*\/(.*)-[^-]+\./; |
622 |
+ print "* Upgrade available for $ebuild_name\n"; |
623 |
+ } |
624 |
+ print "\nContinue with upgrade? (Y|N) "; |
625 |
+ my $answer = <STDIN>; |
626 |
+ chomp($answer); |
627 |
+ if ( $answer =~ m|y|i ) { |
628 |
+ foreach my $ebuild_name (@ebuild_list) { |
629 |
+ system( "emerge", "--oneshot", "--digest", $ebuild_name ); |
630 |
+ } |
631 |
+ } |
632 |
+ return; |
633 |
+ |
634 |
+} |
635 |
+ |
636 |
+sub get_globals { |
637 |
+ |
638 |
+ # Setting default configs |
639 |
+ my %conf; |
640 |
+ $conf{PORTDIR} = "/usr/portage"; |
641 |
+ $conf{DISTDIR} = "/usr/portage/distfiles"; |
642 |
+ my @OVERLAYS = (); |
643 |
+ |
644 |
+ # Opening make.conf to find real user settings |
645 |
+ open CONF, "<$MAKECONF" or die "Open $MAKECONF failed : $!"; |
646 |
+ |
647 |
+ # And parsing it :) |
648 |
+ while ( defined( my $line = <CONF> ) ) { |
649 |
+ |
650 |
+ # Improving speed by ignoring comments |
651 |
+ next if ( substr( $line, 0, 1 ) eq '#' ); |
652 |
+ chomp $line; |
653 |
+ |
654 |
+ $line =~ tr/"'//d; # Remove quotes to be safe |
655 |
+ |
656 |
+ # Now replacing defaults, if other values are set |
657 |
+ if ( $line =~ m/^PORTDIR\s*=\s*(.+)$/ ) { |
658 |
+ $conf{PORTDIR} = $1; |
659 |
+ } |
660 |
+ if ( $line =~ m/^DISTDIR\s*=\s*(.+)$/ ) { |
661 |
+ $conf{DISTDIR} = $1; |
662 |
+ } |
663 |
+ if ( $line =~ m/^PORTDIR_OVERLAY\s*=\s*(.+)$/ ) { |
664 |
+ my $hold_overlay = $1; |
665 |
+ if ( $hold_overlay =~ |
666 |
+ m/\b\s*/ ) # make.conf contains multiple overlay options |
667 |
+ { |
668 |
+ my @hold_ov = split( ' ', $hold_overlay ); |
669 |
+ foreach my $hold_o (@hold_ov) { push @OVERLAYS, $hold_o } |
670 |
+ } |
671 |
+ else { |
672 |
+ push @OVERLAYS, $hold_overlay; |
673 |
+ } |
674 |
+ } |
675 |
+ } |
676 |
+ close CONF; |
677 |
+ |
678 |
+ # If the PORTDIR_OVERLAY is an env var, test to see if it is multiples are not |
679 |
+ if ( $ENV{PORTDIR_OVERLAY} ) { |
680 |
+ if ( $ENV{PORTDIR_OVERLAY} =~ m/\b\s*/ ) # At least 2, space seperated |
681 |
+ { |
682 |
+ my @tmp_overlays = split( ' ', $ENV{PORTDIR_OVERLAY} ); |
683 |
+ foreach my $tmp_o (@tmp_overlays) { |
684 |
+ if ( $tmp_o =~ m/\w+/ ) { push @OVERLAYS, $tmp_o } |
685 |
+ } |
686 |
+ } |
687 |
+ else { |
688 |
+ push @OVERLAYS, $ENV{PORTDIR_OVERLAY}; |
689 |
+ } |
690 |
+ } |
691 |
+ |
692 |
+ $conf{DISTDIR} = clean_vars( $conf{DISTDIR}, %conf ); |
693 |
+ my $count_o = @OVERLAYS; |
694 |
+ for ( my $i = 0 ; $i < $count_o ; $i++ ) { |
695 |
+ $OVERLAYS[$i] = clean_vars( $OVERLAYS[$i], %conf ); |
696 |
+ } |
697 |
+ |
698 |
+ return ( $conf{DISTDIR}, $conf{PORTDIR}, @OVERLAYS ); |
699 |
+} |
700 |
+ |
701 |
+sub clean_vars { |
702 |
+ |
703 |
+ # In order to parse strange but allowed constructions, |
704 |
+ # (i.e. DISTDIR=${PORTDIR}/disfiles), we are cycling some times |
705 |
+ # (3 should be enough) on DISTDIR and PORTDIR_OVERLAY settings, |
706 |
+ # using a nice regexp (thx Sniper - sniper@×××××××××.net) |
707 |
+ my ( $toclean, %conf ) = @_; |
708 |
+ foreach my $i ( 1 .. 3 ) { $toclean =~ s/\$\{ ( [^}]+ ) \}/$conf{$1}/egx } |
709 |
+ return ($toclean); |
710 |
+} |
711 |
+ |
712 |
+sub cpan_stub { |
713 |
+ printbig |
714 |
+"No CPAN Config found, auto-generating a basic one in $ENV{HOME}/.cpan/CPAN\n"; |
715 |
+ unless ( -d "$ENV{HOME}/.cpan" ) { |
716 |
+ mkpath( "$ENV{HOME}/.cpan", 1, 0755 ) |
717 |
+ or die "Couldn't create $ENV{HOME}/.cpan: $|"; |
718 |
+ } |
719 |
+ unless ( -d "$ENV{HOME}/.cpan/CPAN" ) { |
720 |
+ mkpath( "$ENV{HOME}/.cpan/CPAN", 1, 0755 ) |
721 |
+ or die "Couldn't create $ENV{HOME}/.cpan/CPAN: $|"; |
722 |
+ } |
723 |
+ |
724 |
+ my ( |
725 |
+ $tmp_dir, $ftp_prog, $gpg_prog, $gzip_prog, |
726 |
+ $lynx_prog, $make_prog, $ncftpget_prog, $less_prog, |
727 |
+ $tar_prog, $unzip_prog, $wget_prog, $ftp_proxy, |
728 |
+ $http_proxy, $user_shell |
729 |
+ ); |
730 |
+ if ( $ENV{TMPDIR} ) { $tmp_dir = $ENV{TMPDIR} } |
731 |
+ else { $tmp_dir = "$ENV{HOME}" } |
732 |
+ if ( -f "/usr/bin/ftp" ) { $ftp_prog = "/usr/bin/ftp" } |
733 |
+ else { $ftp_prog = "" } |
734 |
+ if ( -f "/usr/bin/gpg" ) { $gpg_prog = "/usr/bin/gpg" } |
735 |
+ else { $gpg_prog = "" } |
736 |
+ if ( -f "/bin/gzip" ) { $gzip_prog = "/bin/gzip" } |
737 |
+ else { $gzip_prog = "" } |
738 |
+ if ( -f "/usr/bin/lynx" ) { $lynx_prog = "/usr/bin/lynx" } |
739 |
+ else { $lynx_prog = "" } |
740 |
+ if ( -f "/usr/bin/make" ) { $make_prog = "/usr/bin/make" } |
741 |
+ else { $make_prog = "" } |
742 |
+ if ( -f "/usr/bin/ncftpget" ) { $ncftpget_prog = "/usr/bin/ncftpget" } |
743 |
+ else { $ncftpget_prog = "" } |
744 |
+ if ( -f "/usr/bin/less" ) { $less_prog = "/usr/bin/less" } |
745 |
+ else { $less_prog = "" } |
746 |
+ if ( -f "/bin/tar" ) { $tar_prog = "/bin/tar" } |
747 |
+ else { $tar_prog = "" } |
748 |
+ if ( -f "/usr/bin/unzip" ) { $unzip_prog = "/usr/bin/unzip" } |
749 |
+ else { $unzip_prog = "" } |
750 |
+ if ( -f "/usr/bin/wget" ) { $wget_prog = "/usr/bin/wget" } |
751 |
+ else { $wget_prog = "" } |
752 |
+ if ( $ENV{ftp_proxy} ) { $ftp_proxy = $ENV{ftp_proxy} } |
753 |
+ else { $ftp_proxy = "" } |
754 |
+ if ( $ENV{http_proxy} ) { $http_proxy = $ENV{http_proxy} } |
755 |
+ else { $http_proxy = "" } |
756 |
+ if ( $ENV{SHELL} ) { $user_shell = $ENV{SHELL} } |
757 |
+ else { $user_shell = "/bin/bash" } |
758 |
+ open( CPANCONF, ">$ENV{HOME}/.cpan/CPAN/MyConfig.pm" ); |
759 |
+ print CPANCONF <<"SHERE"; |
760 |
+ |
761 |
+# This is CPAN.pm's systemwide configuration file. This file provides |
762 |
+# defaults for users, and the values can be changed in a per-user |
763 |
+# configuration file. The user-config file is being looked for as |
764 |
+# ~/.cpan/CPAN/MyConfig\.pm. This was generated by g-cpan for temporary usage |
765 |
+ |
766 |
+\$CPAN::Config = { |
767 |
+ 'build_cache' => q[10], |
768 |
+ 'build_dir' => q[$tmp_dir/.cpan/build], |
769 |
+ 'cache_metadata' => q[1], |
770 |
+ 'cpan_home' => q[$tmp_dir/.cpan], |
771 |
+ 'dontload_hash' => { }, |
772 |
+ 'ftp' => q[$ftp_prog], |
773 |
+ 'ftp_proxy' => q[$ftp_proxy], |
774 |
+ 'getcwd' => q[cwd], |
775 |
+ 'gpg' => q[$gpg_prog], |
776 |
+ 'gzip' => q[$gzip_prog], |
777 |
+ 'histfile' => q[$tmp_dir/.cpan/histfile], |
778 |
+ 'histsize' => q[100], |
779 |
+ 'http_proxy' => q[$http_proxy], |
780 |
+ 'inactivity_timeout' => q[0], |
781 |
+ 'index_expire' => q[1], |
782 |
+ 'inhibit_startup_message' => q[0], |
783 |
+ 'keep_source_where' => q[$tmp_dir/.cpan/sources], |
784 |
+ 'lynx' => q[$lynx_prog], |
785 |
+ 'make' => q[$make_prog], |
786 |
+ 'make_arg' => q[], |
787 |
+ 'make_install_arg' => q[], |
788 |
+ 'makepl_arg' => q[], |
789 |
+ 'ncftpget' => q[$ncftpget_prog], |
790 |
+ 'no_proxy' => q[], |
791 |
+ 'pager' => q[$less_prog], |
792 |
+ 'prerequisites_policy' => q[follow], |
793 |
+ 'scan_cache' => q[atstart], |
794 |
+ 'shell' => q[$user_shell], |
795 |
+ 'tar' => q[$tar_prog], |
796 |
+ 'term_is_latin' => q[1], |
797 |
+ 'unzip' => q[$unzip_prog], |
798 |
+ 'urllist' => [q[http://search.cpan.org/CPAN],], |
799 |
+ 'wget' => q[$wget_prog], |
800 |
+}; |
801 |
+1; |
802 |
+__END__ |
803 |
+ |
804 |
+ |
805 |
+SHERE |
806 |
+ |
807 |
+ close(CPANCONF); |
808 |
+ |
809 |
+} |
810 |
+ |
811 |
+sub clean_the_mess { |
812 |
+ if ($verbose) { |
813 |
+ print "Now cleaning up the system of all the junk we put in !\n"; |
814 |
+ } |
815 |
+ if ($needs_cpan_stub) { |
816 |
+ unlink "$ENV{HOME}/.cpan/CPAN/MyConfig.pm"; |
817 |
+ #add something here to take care of the .cpan dir, if not empty |
818 |
+ } |
819 |
+} |
820 |
+ |
821 |
+sub exit_usage { |
822 |
+ print <<"USAGE"; |
823 |
+Usage : $0 [-i|--install] [-s|--search] [-v|--verbose] Module Name(s) |
824 |
+ |
825 |
+--install,-i Try to generate ebuild for the given module name |
826 |
+ and, if successful, emerge it. Important : installation |
827 |
+ requires exact CPAN Module Name. |
828 |
+ |
829 |
+--search,-s Search CPAN for the given expression (similar to |
830 |
+ the "m /EXPR/" from the CPAN Shell). Searches are |
831 |
+ case insensitive. |
832 |
+ |
833 |
+--verbose,-v Enable (some) verbose output. |
834 |
+ |
835 |
+USAGE |
836 |
+ |
837 |
+ exit; |
838 |
+} |
839 |
|
840 |
|
841 |
Property changes on: g-cpan.pl |
842 |
___________________________________________________________________ |
843 |
Name: svn:executable |
844 |
+ * |
845 |
|
846 |
|
847 |
-- |
848 |
gentoo-perl@g.o mailing list |