For your review, I present 'modulereport' which generates a handy report of installed modules and produces a breakdown by section of what version numbers are currently installed vs what is current on CPAN.
Cleanup and revisions are now to the point where I'm very satisfied with the results. (I apologize for the 85char linewrapping for this one post, but it would have fudged a few lines in the code unacceptably, like the format.) I'd like to submit this to CPAN, if possible, and useful. comments welcome, but the webdragon.net addresses are currently down. re-hosting elsewhere shortly. apologies. -=- #!/usr/bin/perl # visualized and hacked by Scott R. Godin, 12/30/2000 # last update and realization of original vision May 24, 2002 # [EMAIL PROTECTED], http://www.webdragon.net/ ###### ## Command-line Options: # modulereport -r switch causes modulereport to ignore the storefile and # recheck even if it exists # modulereport -f [filename] switch causes modulereport to write output # to that file, defaults to "ModuleCheck.txt" ## I've finally gotten around to fixing the .stor file problem by ## putting it in /tmp prefaced with the user's name. No more overlap, ## or multiple files. :-) Also got the pretty printing version via ## format STDOUT finished and working the way I want. I intend to ## 'nativize' the storefile location of /tmp for OS independance at ## some point with File::Temp, as this release breaks under MacPerl now ## since there is no '/tmp' on Classic MacOS. ## NOTE: the CPAN.pm shell (perl -MCPAN -e shell) must be configured ## and set up in order to use this, and Storable.pm must be installed. ## Storable is used to speed up multiple iterations of ## modulereport | less or modulereport |grep "blah" |less ## and also caches Metadata for CPAN, when used, to speed *it* up. require 5.006; use warnings; use strict; use vars qw/%opts/; use Getopt::Std; use Storable; use File::Spec; use CPAN 1.59;# preferably let's have one that groks Storable .. $| = 1; my $host = $ENV{HOSTNAME} || $ENV{HOST} || "unknown"; BEGIN { getopts('srf:', \%opts); } # sets to 0 if you don't specify -f switch to have the output # redirected to a file. use constant USE_SAVEFILE => exists($opts{'f'}) ? 1 : 0; my $savefile = File::Spec->catfile( File::Spec->curdir(), defined($opts{'f'}) ? $opts{'f'} : 'ModuleCheck.txt' ); my $storefile = File::Spec->catfile( File::Spec->rootdir(), 'tmp', "$ENV{USER}_modules.stor" ); sub checkmodule () { my %installed_modules = (); print <<EOH; Checking Modules...Please stand by -- the cursor will spin for a minute or so. GO get some coffee! You Deserve it! :-D EOH for my $mod (CPAN::Shell->expand("Module","/./")) { next unless $mod->inst_file;# skip the stuff that's not installed $installed_modules{ $mod->id } = [ (($mod->inst_version eq "undef") ? '' : $mod->inst_version), (($mod->cpan_version eq "undef") ? '' : $mod->cpan_version), ]; # "undef" = MakeMaker convention for undefined $VERSION: } store \%installed_modules, $storefile; print "Done and stored.\n\n"; } sub readstored () { my $ref = retrieve($storefile) or die "$!"; my $last = ''; ## originally did this because not enough buffer space to display ## entire list in MacPerl. left in for MacOS as there's no way to ## redirect buffer output to a file, otherwise we send to buffer and ## let user direct it to a file if they so choose, via ./modulereport -f ## [file] or usual redirect/pipe if (USE_SAVEFILE or $^O eq 'MacOS') { print "Now retrieving Module data; output sent to $savefile\n"; open STDOUT, ">$savefile" or die "$!"; } print<<"EOF"; Listing all Installed Modules and Versions where available... This is Perl $], running on host '$host' Installed Module Ins Version CPAN Version EOF my $fullbar = "-" x 80; foreach (sort {uc($a) cmp uc($b)} keys %{$ref}) { /^(\w+)\:{0,2}.*$/; my $this = $1;# current module primary tree my $bar = ""; # insert a separator if the primary module tree changed ;-) $bar = $fullbar if ($last ne $this); my($ver, $cp) = ($ref->{$_}[0], $ref->{$_}[1]); # remove all non-numeric characters from version strings $ver =~ s/[^\d._]*//g; $cp =~ s/[^\d._]*//g; my $t = ""; if ($ver && $cp) {# if both are valid strings (not "" ) no warnings "numeric"; # some authors use 1.00_00, which is fine except in strings =:P # Perl will coerce the value, but the warning is still annoying $t = 0 + $ver < 0 + $cp ? "<" : ""; # show us if we're out of date } if (($ver || $cp) && !($ver && $cp)) { #if one is valid and the other not.. $t = "?";# make us look twice at it, it's unusual } # okay, let's take this mess and make it look pretty for the nice people format STDOUT = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~ $bar @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @< @<<<<<<<<<<< $_, $ref->{$_}[0],$t, $ref->{$_}[1] . write; $last = $this; } } # back to the essential program flow... # if the storefile already exists, use it to save time # unless -r (recheck) switch is used if (-e $storefile and !$opts{'r'}) { print <<"EOD"; Using existing .stor file for brevity... Either delete '$storefile' or re-run the script with the -r switch if you wish to update it. EOD readstored; } else { checkmodule; readstored; } exit 0; print pack "H*", "4a75737420416e6f74686572204d61635065726c204861636b65722c0d"; -- Scott R. Godin | e-mail : [EMAIL PROTECTED] Laughing Dragon Services | web : http://www.webdragon.net/ It is not necessary to cc: me via e-mail unless you mean to speak off-group. I read these via nntp.perl.org, so as to get the stuff OUT of my mailbox. :-)
