App-Sqitch
view release on metacpan or search on metacpan
inc/Module/Build/Sqitch.pm view on Meta::CPAN
package Module::Build::Sqitch;
use strict;
use warnings;
use Module::Build 0.35;
use base 'Module::Build';
use IO::File ();
use File::Spec ();
use Config ();
use File::Path ();
use File::Copy ();
__PACKAGE__->add_property($_) for qw(etcdir installed_etcdir);
# List one more more engines to include in a bundle install.
# --with postgres --with mysql
__PACKAGE__->add_property(with => []);
# Set dual_life to true to force dual-life modules such as Pod::Simple to be
# included in the bundle directory.
# --dual_life 1
__PACKAGE__->add_property(dual_life => 0);
sub new {
my ( $class, %p ) = @_;
if ($^O eq 'MSWin32') {
my $recs = $p{recommends} ||= {};
$recs->{$_} = 0 for qw(
Win32
Win32::Console::ANSI
Win32API::Net
);
$p{requires}{'Win32::Locale'} = 0;
$p{requires}{'Win32::ShellQuote'} = 0;
$p{requires}{'DateTime::TimeZone::Local::Win32'} = 0;
}
if (eval { require Hash::Merge; 1 } && $Hash::Merge::VERSION eq '0.298') {
warn join "\n", (
'**************************************************************',
'* You have Hash::Merge $Hash::Merge::VERSION, which is broken.',
"**************************************************************\n",
);
$p{requires}{'Hash::Merge'} = '0.299';
}
my $self = $class->SUPER::new(%p);
$self->add_build_element('etc');
$self->add_build_element('mo');
$self->add_build_element('sql');
return $self;
}
sub _getetc {
my $self = shift;
my $prefix;
if ($self->installdirs eq 'site') {
$prefix = $Config::Config{siteprefix} // $Config::Config{prefix};
} elsif ($self->installdirs eq 'vendor') {
$prefix = $Config::Config{vendorprefix} // $Config::Config{siteprefix} // $Config::Config{prefix};
} else {
$prefix = $Config::Config{prefix};
}
# Prefer the user-specified directory.
if (my $etc = $self->etcdir) {
return $etc;
}
# Use a directory under the install base (or prefix).
my @subdirs = qw(etc sqitch);
if ( my $dir = $self->install_base || $self->prefix ) {
return File::Spec->catdir( $dir, @subdirs );
}
# Go under Perl's prefix.
return File::Spec->catdir( $prefix, @subdirs );
}
sub ACTION_move_old_templates {
my $self = shift;
$self->depends_on('build');
# First, rename existing etc dir templates; They were moved in v0.980.
my $notify = 0;
my $tmpl_dir = File::Spec->catdir(
( $self->destdir ? $self->destdir : ()),
$self->_getetc,
'templates'
);
if (-e $tmpl_dir && -d _) {
# Scan for old templates, but only if we can read the directory.
if (opendir my $dh, $tmpl_dir) {
while (my $bn = readdir $dh) {
next unless $bn =~ /^(deploy|verify|revert)[.]tmpl([.]default)?$/;
my ($action, $default) = ($1, $2);
my $file = File::Spec->catfile($tmpl_dir, $bn);
if ($default) {
$self->log_verbose("Unlinking $file\n");
# Just unlink default files.
unlink $file;
next;
}
# Move action templates to $action/pg.tmpl and $action/sqlite.tmpl.
my $action_dir = File::Spec->catdir($tmpl_dir, $action);
File::Path::mkpath($action_dir) or die;
for my $engine (qw(pg sqlite)) {
my $dest = File::Spec->catdir($action_dir, "$engine.tmpl");
$self->log_info("Copying old $bn to $dest\n");
File::Copy::copy($file, $dest)
or die "Cannot copy('$file', '$dest'): $!\n";
}
$self->log_verbose("Unlinking $file\n");
unlink $file;
$notify = 1;
}
}
}
# If we moved any files, nofify the user that custom templates will need
# to be updated, too.
if ($notify) {
$self->log_warn(q{
#################################################################
# WARNING #
# #
# As of v0.980, the location of script templates has changed. #
# The system-wide templates have been moved to their new #
# locations as described above. However, user-specific #
# templates have not been moved. #
# #
# Please inform all users that any custom Sqitch templates in #
# their ~/.sqitch/templates directories must be moved into #
# subdirectories using the appropriate engine name (pg, sqlite, #
# or oracle) as follows: #
# #
# deploy.tmpl -> deploy/$engine.tmpl #
# revert.tmpl -> revert/$engine.tmpl #
# verify.tmpl -> verify/$engine.tmpl #
# #
#################################################################
} . "\n");
}
}
sub ACTION_install {
my ($self, @params) = @_;
$self->depends_on('move_old_templates');
$self->SUPER::ACTION_install(@_);
}
sub process_etc_files {
my $self = shift;
my $etc = $self->_getetc;
$self->install_path( etc => $etc );
if (my $ddir = $self->destdir) {
# Need to search the final destination directory.
$etc = File::Spec->catdir($ddir, $etc);
}
for my $file ( @{ $self->rscan_dir( 'etc', sub { -f && !/\.\#/ } ) } ) {
$file = $self->localize_file_path($file);
# Remove leading `etc/` to get path relative to $etc.
my ($vol, $dirs, $fn) = File::Spec->splitpath($file);
my (undef, @segs) = File::Spec->splitdir($dirs);
my $rel = File::Spec->catpath($vol, File::Spec->catdir(@segs), $fn);
my $dest = $file;
# Append .default if file already exists at its ultimate destination
# or if it exists with an old name (to be moved by move_old_templates).
if ( -e File::Spec->catfile($etc, $rel) || (
$segs[0] eq 'templates'
&& $fn =~ /^(?:pg|sqlite)[.]tmpl$/
&& -e File::Spec->catfile($etc, 'templates', "$segs[1].tmpl")
) ) {
$dest .= '.default';
}
$self->copy_if_modified(
from => $file,
to => File::Spec->catfile( $self->blib, $dest )
);
}
}
sub process_pm_files {
my $self = shift;
my $ret = $self->SUPER::process_pm_files(@_);
my $pm = File::Spec->catfile(qw(blib lib App Sqitch Config.pm));
my $etc = $self->installed_etcdir || $self->_getetc;
$self->do_system(
$self->perl, '-i.bak', '-pe',
qq{s{my \\\$SYSTEM_DIR = undef}{my \\\$SYSTEM_DIR = q{\Q$etc\E}}},
$pm,
);
unlink "$pm.bak";
return $ret;
}
sub fix_shebang_line {
my $self = shift;
# Noting to do after 5.10.0.
return $self->SUPER::fix_shebang_line(@_) if $] > 5.010000;
# Remove -C from the shebang line.
for my $file (@_) {
my $FIXIN = IO::File->new($file) or die "Can't process '$file': $!";
local $/ = "\n";
chomp(my $line = <$FIXIN>);
next unless $line =~ s/^\s*\#!\s*//; # Not a shebang file.
my ($cmd, $arg) = (split(' ', $line, 2), '');
next unless $cmd =~ /perl/i && $arg =~ s/ -C\w+//;
# We removed -C; write the file out.
my $FIXOUT = IO::File->new(">$file.new")
or die "Can't create new $file: $!\n";
local $\;
undef $/; # Was localized above
print $FIXOUT "#!$cmd $arg", <$FIXIN>;
close $FIXIN;
close $FIXOUT;
rename($file, "$file.bak")
or die "Can't rename $file to $file.bak: $!";
rename("$file.new", $file)
or die "Can't rename $file.new to $file: $!";
$self->delete_filetree("$file.bak")
or $self->log_warn("Couldn't clean up $file.bak, leaving it there");
}
# Back at it now.
return $self->SUPER::fix_shebang_line(@_);
}
sub ACTION_bundle {
my ($self, @params) = @_;
my $base = $self->install_base or die "No --install_base specified\n";
# XXX Consider replacing with a Carton or Carmel-based solution?
SHHH: {
local $SIG{__WARN__} = sub {}; # Menlo has noisy warnings.
local $ENV{PERL_CPANM_OPT}; # Override cpanm options.
require Menlo::Sqitch;
my $feat = $self->with || [];
$feat = [$feat] unless ref $feat;
my $app = Menlo::Sqitch->new(
quiet => $self->quiet,
verbose => $self->verbose,
notest => 1,
self_contained => 1,
skip_installed => 0,
install_types => [qw(requires recommends)],
local_lib => File::Spec->rel2abs($base),
pod2man => undef,
features => { map { $_ => 1 } @{ $feat } },
);
if ($self->dual_life) {
# Force Install dual-life modules.
$app->{argv} = [qw(
File::Temp Scalar::Util Pod::Usage Digest::SHA Pod::Escapes
Pod::Find Getopt::Long Time::HiRes File::Path List::Util
Encode Pod::Simple Time::Local parent IO::File if
Term::ANSIColor
)];
die "Error installing modules: $@\n" if $app->run;
}
# Install required modules, but not Sqitch itself.
$app->{argv} = ['.'];
$app->{installdeps} = 1;
die "Error installing modules: $@\n" if $app->run;
# Remove unneeded build-time dependencies.
die "Error removing build modules: $@\n"
unless $app->remove_build_dependencies;
}
# Install Sqitch. Required to intall man pages.
$self->depends_on('install');
# Delete unneeded files.
$self->delete_filetree(File::Spec->catdir($base, qw(lib perl5 Test)));
$self->delete_filetree(File::Spec->catdir($base, qw(bin)));
for my $file (@{ $self->rscan_dir($base, qr/[.](?:meta|packlist)$/) }) {
$self->delete_filetree($file);
}
# Install sqitch script using FindBin.
$self->_copy_findbin_script;
# Delete empty directories.
( run in 0.446 second using v1.01-cache-2.11-cpan-5a3173703d6 )