package only::install; $VERSION = '0.26'; @EXPORT_OK = qw(install); use strict; use 5.006001; use base 'Exporter'; use only; use File::Spec; use Config; use Carp; sub install { my %args = @_; check_env(); my ($dist_name, $dist_ver) = get_meta(); my $versionlib = $args{versionlib} || &only::config::versionlib; my $version = $args{version} || $dist_ver; if ($version !~ /^\d+(\.\d+)?$/) { croak <catdir(qw(blib lib)); mkdir($lib, 0777) unless -d $lib; my $arch = File::Spec->catdir(qw(blib arch)); mkdir($arch, 0777) unless -d $arch; my $install_lib = File::Spec->catdir( $versionlib, $version, ); my $install_arch = File::Spec->catdir( $versionlib, $Config{archname}, $version, ); my $install_map = { $lib => $install_lib, $arch => $install_arch, read => '', }; { # 5.6.1 has a warning bug. :( local $^W = 0; require ExtUtils::Install; } ExtUtils::Install::install($install_map, 1, 0); my @lib_pm_files = map trim_dir($_), find_pm($lib); my @arch_pm_files = map trim_dir($_), find_pm($arch); my $meta = <splitdir($file); $meta .= " - $pm_file\n"; } install_meta($meta, $install_lib, $_) for @lib_pm_files; install_meta($meta, $install_arch, $_) for @arch_pm_files; } sub install_meta { my ($meta, $base, $module) = @_; my $meta_file = File::Spec->catfile($base, $module); $meta_file =~ s/\.pm$/\.yaml/ or croak; my $old_meta = ''; if (-f $meta_file) { open META, $meta_file or croak "Can't open $meta_file for input\n"; $old_meta = do {local $/; }; close META; } if ($meta eq $old_meta) { print "Skipping $meta_file (unchanged)\n"; } else { print "Installing $meta_file\n"; open META, '>', $meta_file or croak "Can't open $meta_file for output\n"; print META $meta; close META; } } sub trim_dir { my ($path) = @_; my ($vol, $dir, $file) = File::Spec->splitpath($path); my @dirs = File::Spec->splitdir($dir); pop @dirs unless $dirs[-1]; splice(@dirs, 0, 2); $dir = scalar(@dirs) ? File::Spec->catdir(@dirs) : ''; $dir ? File::Spec->catfile($dir, $file) : $file } sub find_pm { my ($path, $base) = (@_, ''); croak unless $path; my (@pm_files); $path = File::Spec->catdir($base, $path) if $base; local *DIR; opendir(DIR, $path) or croak "Can't open directory '$path':\n$!"; while (my $file = readdir(DIR)) { next if $file =~ /^\./; my $file_path = File::Spec->catfile($path, $file); my $dir_path = File::Spec->catdir($path, $file); if ($file =~ /^\w+\.pm$/) { push @pm_files, $file_path; } elsif (-d $dir_path) { push @pm_files, find_pm($file, $path); } } return @pm_files; } sub check_env { my $lib = File::Spec->catdir(qw(blib lib)); my $arch = File::Spec->catdir(qw(blib arch)); return 1 if -d 'blib' and (-d $lib or -d $arch); if (-f 'Build.PL') { croak <; close META; if ($meta =~ /^name\s*:\s+(\S+)$/m) { $dist_name = $1; } if ($meta =~ /^version\s*:\s+(\S+)$/m) { $dist_ver = $1; } } else { if (-f 'Makefile') { open MAKEFILE, "Makefile" or croak "Can't open Makefile for input:\n$!\n"; local $/; my $makefile = ; close MAKEFILE; if ($makefile =~ /^DISTNAME\s*=\s*(\S+)$/m) { $dist_name = $1; } if ($makefile =~ /^VERSION\s*=\s*(\S+)$/m) { $dist_ver = $1; } } } croak < 1.23, versionlib => '/my/version/lib', ); =head1 DESCRIPTION This module provides the programmer's API for installing multiple versions of a module. There is only one exportable function: C. In order to install, you must be chdir()ed into a valid module distribution directory, and C or C<./Build> must already have been run. More specifically, there must be a C directory and either a C or a C file. =head1 ARGUMENTS =over 4 =item * version The version parameter tells C which version to install the distribution modules under. You normally don't need this, since C can extrapolate the vaule from the Makefile or from the META.yml file. =item * versionlib The versionlib parameter tells where to install the distribution contents. The default is stored in C. =back =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2003. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut