App-Sqitch
view release on metacpan or search on metacpan
lib/App/Sqitch/Command/add.pm view on Meta::CPAN
},
);
has open_editor => (
is => 'ro',
isa => Bool,
lazy => 1,
default => sub {
shift->sqitch->config->get(
key => 'add.open_editor',
as => 'bool',
) // 0;
},
);
sub _check_script($) {
my $file = file shift;
hurl add => __x(
'Template {template} does not exist',
template => $file,
) unless -e $file;
hurl add => __x(
'Template {template} is not a file',
template => $file,
) unless -f $file;
return $file;
}
sub _config_templates {
my ($self, $config) = @_;
my $tmpl = $config->get_section( section => 'add.templates' );
$_ = _check_script $_ for values %{ $tmpl };
return $tmpl;
}
sub all_templates {
my ($self, $name) = @_;
my $config = $self->sqitch->config;
my $tmpl = { %{ $self->templates } };
# Read all the template directories.
for my $dir (
$self->template_directory,
$config->user_dir->subdir('templates'),
$config->system_dir->subdir('templates'),
) {
next unless $dir && -d $dir;
for my $subdir($dir->children) {
next unless $subdir->is_dir;
next if $tmpl->{my $script = $subdir->basename};
my $file = $subdir->file("$name.tmpl");
$tmpl->{$script} = $file if -f $file
}
}
# Make sure we have core templates.
my $with = $self->with_scripts;
for my $script (qw(deploy revert verify)) {
hurl add => __x(
'Cannot find {script} template',
script => $script,
) if !$tmpl->{$script} && ($with->{$script} || !exists $with->{$script});
}
return $tmpl;
}
sub options {
return qw(
change-name|change|c=s
requires|r=s@
conflicts|x=s@
note|n|m=s@
all|a!
template-name|template|t=s
template-directory=s
with=s@
without=s@
use=s%
open-editor|edit|e!
);
}
# Override to convert multiple vars to an array.
sub _parse_opts {
my ( $class, $args ) = @_;
my (%opts, %vars);
Getopt::Long::Configure(qw(bundling no_pass_through));
Getopt::Long::GetOptionsFromArray(
$args, \%opts,
$class->options,
'set|s=s%' => sub {
my ($opt, $key, $val) = @_;
if (exists $vars{$key}) {
$vars{$key} = [$vars{$key}] unless ref $vars{$key};
push @{ $vars{$key} } => $val;
} else {
$vars{$key} = $val;
}
}
) or $class->usage;
$opts{set} = \%vars if %vars;
# Convert dashes to underscores.
for my $k (keys %opts) {
next unless ( my $nk = $k ) =~ s/-/_/g;
$opts{$nk} = delete $opts{$k};
}
# Merge with and without.
$opts{with_scripts} = {
( map { $_ => 1 } qw(deploy revert verify) ),
( map { $_ => 1 } @{ delete $opts{with} || [] } ),
( map { $_ => 0 } @{ delete $opts{without} || [] } ),
};
return \%opts;
}
sub configure {
my ( $class, $config, $opt ) = @_;
my %params = (
requires => $opt->{requires} || [],
conflicts => $opt->{conflicts} || [],
note => $opt->{note} || [],
);
for my $key (qw(with_scripts change_name)) {
$params{$key} = $opt->{$key} if $opt->{$key};
}
if (
my $dir = $opt->{template_directory}
|| $config->get( key => 'add.template_directory' )
) {
$dir = $params{template_directory} = dir $dir;
hurl add => __x(
'Directory "{dir}" does not exist',
dir => $dir,
) unless -e $dir;
hurl add => __x(
'"{dir}" is not a directory',
dir => $dir,
) unless -d $dir;
}
if (
my $name = $opt->{template_name}
|| $config->get( key => 'add.template_name' )
) {
$params{template_name} = $name;
}
# Merge variables.
if ( my $vars = $opt->{set} ) {
$params{variables} = {
%{ $config->get_section( section => 'add.variables' ) },
%{ $vars },
};
}
# Merge template info.
my $tmpl = $class->_config_templates($config);
if ( my $use = delete $opt->{use} ) {
while (my ($k, $v) = each %{ $use }) {
$tmpl->{$k} = _check_script $v;
}
}
$params{templates} = $tmpl if %{ $tmpl };
# Copy other options.
lib/App/Sqitch/Command/add.pm view on Meta::CPAN
if (eval 'use Template; 1') {
my $tt = Template->new;
$tt->process( $self->_slurp($tmpl), $vars, $fh ) or hurl add => __x(
'Error executing {template}: {error}',
template => $tmpl,
error => $tt->error,
);
} else {
eval 'use Template::Tiny 0.11; 1' or die $@;
my $output = '';
Template::Tiny->new->process( $self->_slurp($tmpl), $vars, \$output );
print $fh $output;
}
close $fh or hurl add => __x(
'Error closing {file}: {error}',
file => $file,
error => $!
);
# Warn if the file name has a double extension
if ($file =~ m/\.(\w+)\.\1+$/) {
my $ext = $1;
$self->warn(__x(
'File {file} has a double extension of {ext}',
file => $file,
ext => $ext,
));
}
$self->info(__x 'Created {file}', file => $file);
}
sub _slurp {
my ( $self, $tmpl ) = @_;
open my $fh, "<:utf8_strict", $tmpl or hurl add => __x(
'Cannot open {file}: {error}',
file => $tmpl,
error => $!
);
local $/;
return \<$fh>;
}
1;
__END__
=head1 Name
App::Sqitch::Command::add - Add a new change to Sqitch plans
=head1 Synopsis
my $cmd = App::Sqitch::Command::add->new(%params);
$cmd->execute;
=head1 Description
Adds a new deployment change. This will result in the creation of a scripts in
the deploy, revert, and verify directories. The scripts are based on
L<Template::Tiny> templates in F<~/.sqitch/templates/> or
C<$(prefix)/etc/sqitch/templates> (call C<sqitch --etc-path> to find out
where, exactly (e.g., C<$(sqitch --etc-path)/sqitch.conf>).
=head1 Interface
=head2 Class Methods
=head3 C<options>
my @opts = App::Sqitch::Command::add->options;
Returns a list of L<Getopt::Long> option specifications for the command-line
options for the C<add> command.
=head3 C<configure>
my $params = App::Sqitch::Command::add->configure(
$config,
$options,
);
Processes the configuration and command options and returns a hash suitable
for the constructor.
=head2 Attributes
=head3 C<change_name>
The name of the change to be added.
=head3 C<note>
Text of the change note.
=head3 C<requires>
List of required changes.
=head3 C<conflicts>
List of conflicting changes.
=head3 C<all>
Boolean indicating whether or not to run the command against all plans in the
project.
=head3 C<template_name>
The name of the templates to use when generating scripts. Defaults to the
engine for which the scripts are being generated.
=head3 C<template_directory>
Directory in which to find the change script templates.
=head3 C<with_scripts>
Hash reference indicating which scripts to create.
( run in 1.059 second using v1.01-cache-2.11-cpan-5a3173703d6 )