Dist-Zilla-Plugin-RPM-Push

 view release on metacpan or  search on metacpan

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


our $VERSION = '0.010'; # 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 .= '/';
		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_PUSH_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     => $self->zilla->root->file($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;

=head1 NAME

Dist::Zilla::Plugin::RPM::Push - Dist::Zilla plugin to build RPMs and push them into a repository

=head1 SYNOPSIS

In your dist.ini:

    [RPM::Push]
    spec_file = build/dist.spec
    sign = 1
    ignore_build_deps = 0

    push_packages = 0
    push_command = rhnpush -s
    push_ignore_packages = .src.rpm$
    
=head1 DESCRIPTION

This plugin is a Releaser for Dist::Zilla that builds an RPM of your
distribution.
It keeps track of build RPM files and can be used to push generated
packages into a repository.



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