Dist-Zilla-Plugin-RPM

 view release on metacpan or  search on metacpan

lib/Dist/Zilla/Plugin/RPM.pm  view on Meta::CPAN


our $VERSION = '0.016'; # VERSION

with 'Dist::Zilla::Role::Releaser',
     'Dist::Zilla::Role::FilePruner';

has spec_file => (
    is      => 'ro',
    isa     => 'Str',
    default => 'build/dist.spec',
);

has build => (
    is      => 'ro',
    isa     => enum([qw/source all/]),
    default => 'all',
);

has sign => (
    is      => 'ro',
    isa     => 'Bool',
    default => 0,
);

has ignore_build_deps => (
    is      => 'ro',
    isa     => 'Bool',
    default => 0,
);

has push_packages => ( is => 'ro', isa => 'Bool', default => 0 );
has push_command => ( is => 'ro', isa => 'Str', default => 'rhnpush -s' );

use constant _CoercedRegexp => do {
    my $tc = subtype as 'RegexpRef';
    coerce $tc, from 'Str', via { qr/$_/ };
    $tc;
};

has push_ignore_packages => (
    is      => 'ro', isa => _CoercedRegexp, coerce => 1, default => '.src.rpm$' );

use Carp;
use File::Temp ();
use Path::Class qw(dir);
use Text::Template ();
use IPC::Run;

sub prune_files {
    my($self) = @_;
    my $spec = $self->spec_file;
    for my $file ($self->zilla->files->flatten) {
        if ($file->name eq $self->spec_file) {
            $self->zilla->prune_file($file);
        }
    }
    return;
}

has '_rpmbuild_options' => (
  is => 'ro', isa => 'ArrayRef[Str]', lazy => 1,
  default => sub {
    my $self = shift;
    return( [
      $self->sign ? '--sign' : (),
      $self->ignore_build_deps ? '--nodeps' : (),
    ] );
  },
);

has '_rpmbuild_stage' => (
  is => 'ro', isa => 'Str', lazy => 1,
  default => sub {
    my $self = shift;

    if ($self->build eq 'source') {
      return('-bs');
    } elsif ($self->build eq 'all') {
      return('-ba');
    }

    $self->log_fatal(q{invalid build type }.$self->build);
  },
);

has '_rpmbuild_command' => (
  is => 'ro',
  isa => 'ArrayRef[Str]',
  lazy => 1,
  default => sub {
    my $self = shift;
    return( [
      'rpmbuild',
      $self->_rpmbuild_stage,
      @{$self->_rpmbuild_options},
      $self->_tmpspecfile->stringify,
    ] );
  },
);

has '_tmpdir' => (
  is => 'ro', isa => 'File::Temp::Dir', lazy => 1,
  default => sub {
    my $self = shift;
    return File::Temp->newdir();
  },
);

has '_tmpspecfile' => (
  is => 'ro', isa => 'Path::Class::File', lazy => 1,
  default => sub {
    my $self = shift;
        return dir($self->_tmpdir)->file($self->zilla->name . '.spec');
  },
);

sub _write_spec {
  my ($self, $archive) = @_;
  my $fh = $self->_tmpspecfile->openw();
  $fh->print($self->mk_spec($archive));
  $fh->flush;
  $fh->close;
  return;
}

has '_sourcedir' => (
  is => 'ro', isa => 'Str', lazy => 1,
  default => sub {
    my $self = shift;
    my $sourcedir = qx/rpm --eval '%{_sourcedir}'/
      or $self->log_fatal(q{couldn't determine RPM sourcedir});
    $sourcedir =~ s/[\r\n]+$//;
    $sourcedir .= '/';

    unless( -d $sourcedir) {
        $sourcedir = "$self->_tmpdir";
    }

    return($sourcedir);
  },
);

sub release {
    my($self,$archive) = @_;

    $self->_write_spec($archive);

    if(! -f $archive ) {
      $self->log_fatal('archive '.$archive.' does not exist!');
    }

    system('cp',$archive,$self->_sourcedir)
        && $self->log_fatal('cp failed');

    if ($ENV{DZIL_PLUGIN_RPM_TEST}) {
        $self->log("test: would have executed ".join(' ', @{$self->_rpmbuild_command}));
        return;
    }

    $self->_execute_rpmbuild;
    $self->log('RPMs build: '.join(', ', @{$self->_packages_build} ));

    if( $self->push_packages ) {
        $self->_execute_push_command;
    }

    return;
}

has '_packages_build' => ( is => 'ro', isa => 'ArrayRef[Str]', lazy => 1,
  default => sub { [] }
);

sub _execute_rpmbuild {
  my $self = shift;
  my ($in, $out, $err);
  my $lang = $ENV{'LANG'};
  $ENV{'LANG'} = 'C';
  $self->log('building RPM...');
  IPC::Run::run( $self->_rpmbuild_command, \$in, \$out, \$err )
    or $self->log_fatal('rpmbuild failed: '.$err);
  foreach my $line ( split(/\n/, $out ) ) {
    if( $line =~ m/^Wrote: (.*)$/) {
      push(@{$self->_packages_build}, $1);
    }
  }
  $ENV{'LANG'} = $lang;
  return;
}

has _packages_to_push => (
  is => 'ro', isa => 'ArrayRef[Str]', lazy => 1,
  default => sub {
    my $self = shift;
    my $regex = $self->push_ignore_packages;
    return( [ grep { $_ !~ m/$regex/ } @{$self->_packages_build} ] );
  },
);

has _push_command => (
  is => 'ro', isa => 'ArrayRef', lazy => 1,
  default => sub {
    my $self = shift;
    return( [ split(/ /, $self->push_command) ] );
  },
);

sub _execute_push_command {
  my $self = shift;
  my ($in, $out, $err);

  $in = join("\n", @{$self->_packages_to_push});

  $self->log('pushing packages: '.join(', ', @{$self->_packages_to_push}));
  IPC::Run::run( $self->_push_command, \$in, \$out, \$err )
    or $self->log_fatal('push command failed: '.$err);

  return;
}

sub mk_spec {
    my($self,$archive) = @_;
    my $t = Text::Template->new(
        TYPE       => 'FILE',
        SOURCE     => path($self->zilla->root)->child($self->spec_file),
        DELIMITERS => [ '<%', '%>' ],
    ) || $self->log_fatal($Text::Template::ERROR);
    return $t->fill_in(
        HASH => {
            zilla   => \($self->zilla),
            archive => \$archive,
        },
    ) || $self->log_fatal($Text::Template::ERROR);
}

__PACKAGE__->meta->make_immutable;


1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Dist::Zilla::Plugin::RPM - Build an RPM from your Dist::Zilla release

=head1 VERSION

version 0.016

=head1 SYNOPSIS

In your dist.ini:

    [RPM]
    spec_file = build/dist.spec
    sign = 1



( run in 0.826 second using v1.01-cache-2.11-cpan-39bf76dae61 )