| 1 | package Acme::CPANAuthors::Utils; |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use warnings; |
|---|
| 5 | use Carp; |
|---|
| 6 | use base qw( Exporter ); |
|---|
| 7 | use File::Spec; |
|---|
| 8 | |
|---|
| 9 | our $VERSION = '0.08'; # see RT #43388 |
|---|
| 10 | our @EXPORT_OK = qw( cpan_authors cpan_packages ); |
|---|
| 11 | |
|---|
| 12 | my $CPANFiles = {}; |
|---|
| 13 | |
|---|
| 14 | sub clear_cached_cpan_files () { $CPANFiles = {}; } |
|---|
| 15 | |
|---|
| 16 | sub cpan_authors () { |
|---|
| 17 | unless ( $CPANFiles->{authors} ) { |
|---|
| 18 | require Parse::CPAN::Authors; |
|---|
| 19 | $CPANFiles->{authors} = |
|---|
| 20 | Parse::CPAN::Authors->new( _cpan_authors_file() ); |
|---|
| 21 | } |
|---|
| 22 | return $CPANFiles->{authors}; |
|---|
| 23 | } |
|---|
| 24 | |
|---|
| 25 | sub cpan_packages () { |
|---|
| 26 | unless ( $CPANFiles->{packages} ) { |
|---|
| 27 | require Parse::CPAN::Packages; |
|---|
| 28 | $CPANFiles->{packages} = |
|---|
| 29 | Parse::CPAN::Packages->new( _cpan_packages_file() ); |
|---|
| 30 | } |
|---|
| 31 | return $CPANFiles->{packages}; |
|---|
| 32 | } |
|---|
| 33 | |
|---|
| 34 | sub _cpan_authors_file () { |
|---|
| 35 | _cpan_file( authors => '01mailrc.txt.gz' ); |
|---|
| 36 | } |
|---|
| 37 | |
|---|
| 38 | sub _cpan_packages_file () { |
|---|
| 39 | _cpan_file( modules => '02packages.details.txt.gz' ); |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | sub _cpan_file { |
|---|
| 43 | my ($dir, $basename) = @_; |
|---|
| 44 | |
|---|
| 45 | my $file; |
|---|
| 46 | |
|---|
| 47 | # see if CPAN is configured |
|---|
| 48 | _require_myconfig_or_config(); |
|---|
| 49 | if ( $CPAN::Config && ref $CPAN::Config eq 'HASH' ) { |
|---|
| 50 | my $source_dir = $CPAN::Config->{keep_source_where}; |
|---|
| 51 | $file = _catfile( $source_dir, $dir, $basename ); |
|---|
| 52 | unless ( -f $file ) { |
|---|
| 53 | require URI::file; |
|---|
| 54 | foreach my $url ( @{ $CPAN::Config->{urllist} || [] } ) { |
|---|
| 55 | next unless $url =~ s{^file://}{/}; |
|---|
| 56 | $file = URI::file->new(join '/', $url, $dir, $basename )->file; |
|---|
| 57 | last if -f $file; |
|---|
| 58 | } |
|---|
| 59 | } |
|---|
| 60 | unless ( -f $file ) { |
|---|
| 61 | $file = _catfile( $source_dir, $dir, "$basename.bak" ); |
|---|
| 62 | } |
|---|
| 63 | unless ( -f $file ) { |
|---|
| 64 | $file = _catfile( $source_dir, $basename ); |
|---|
| 65 | } |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | # see if CPANPLUS is configured |
|---|
| 69 | eval { require CPANPLUS::Configure }; |
|---|
| 70 | unless ($@) { |
|---|
| 71 | # XXX: should also support custom-sources directory? |
|---|
| 72 | my $source_dir = CPANPLUS::Configure->new->get_conf('base'); |
|---|
| 73 | my $cpanplus_file = _catfile( $source_dir, $basename ); |
|---|
| 74 | if ( -f $cpanplus_file ) { |
|---|
| 75 | $file ||= $cpanplus_file; |
|---|
| 76 | if ( (stat($file))[9] < (stat($cpanplus_file))[9] ) { |
|---|
| 77 | $file = $cpanplus_file; |
|---|
| 78 | } |
|---|
| 79 | } |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | croak "$file not found; You might want to configure CPAN first." unless -f $file; |
|---|
| 83 | |
|---|
| 84 | return $file; |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | sub _require_myconfig_or_config () { # from CPAN::HandleConfig |
|---|
| 88 | return if $INC{'CPAN/MyConfig.pm'}; |
|---|
| 89 | local @INC = @INC; |
|---|
| 90 | |
|---|
| 91 | eval { |
|---|
| 92 | require File::HomeDir; |
|---|
| 93 | die unless $File::HomeDir::VERSION >= 0.52; |
|---|
| 94 | }; |
|---|
| 95 | my $home = $@ ? $ENV{HOME} : File::HomeDir->my_data; |
|---|
| 96 | |
|---|
| 97 | unshift @INC, File::Spec->catdir($home, '.cpan'); |
|---|
| 98 | |
|---|
| 99 | eval { require CPAN::MyConfig }; |
|---|
| 100 | if ( $@ and $@ !~ m{Can't locate CPAN/MyConfig\.pm} ) { |
|---|
| 101 | croak "CPAN::MyConfig error: $@"; |
|---|
| 102 | } |
|---|
| 103 | unless ( $INC{'CPAN/MyConfig.pm'} ) { |
|---|
| 104 | eval { require CPAN::Config }; |
|---|
| 105 | if ( $@ and $@ !~ m{Can't locate CPAN/Config\.pm} ) { |
|---|
| 106 | croak "CPAN::Config error: $@"; |
|---|
| 107 | } |
|---|
| 108 | } |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | sub _catfile { File::Spec->canonpath( File::Spec->catfile( @_ ) ); } |
|---|
| 112 | |
|---|
| 113 | 1; |
|---|
| 114 | |
|---|
| 115 | __END__ |
|---|
| 116 | |
|---|
| 117 | =head1 NAME |
|---|
| 118 | |
|---|
| 119 | Acme::CPANAuthors::Utils |
|---|
| 120 | |
|---|
| 121 | =head1 DESCRIPTION |
|---|
| 122 | |
|---|
| 123 | This may export several utility functions to use internally. |
|---|
| 124 | |
|---|
| 125 | =head1 FUNCTIONS |
|---|
| 126 | |
|---|
| 127 | =head2 cpan_authors (exportable) |
|---|
| 128 | |
|---|
| 129 | returns a (probably cached) Parse::CPAN::Authors object. |
|---|
| 130 | |
|---|
| 131 | =head2 cpan_packages (exportable) |
|---|
| 132 | |
|---|
| 133 | returns a (probably cached) Parse::CPAN::Packages object. |
|---|
| 134 | |
|---|
| 135 | =head2 clear_cached_cpan_files |
|---|
| 136 | |
|---|
| 137 | clears cached Parse::CPAN::Authors/Packages objects. |
|---|
| 138 | |
|---|
| 139 | =head1 AUTHOR |
|---|
| 140 | |
|---|
| 141 | Kenichi Ishigaki, E<lt>ishigaki at cpan.orgE<gt> |
|---|
| 142 | |
|---|
| 143 | =head1 COPYRIGHT AND LICENSE |
|---|
| 144 | |
|---|
| 145 | Copyright (C) 2007 by Kenichi Ishigaki. |
|---|
| 146 | |
|---|
| 147 | This program is free software; you can redistribute it and/or |
|---|
| 148 | modify it under the same terms as Perl itself. |
|---|
| 149 | |
|---|
| 150 | =cut |
|---|