| Youri-Package documentation | Contained in the Youri-Package distribution. |
Youri::Package::RPM::URPM - URPM-based rpm package implementation
This is an URPM-based Youri::Package implementation for rpm.
It is merely a wrapper over URPM::Package class, with a more structured interface.
Creates and returns a new Youri::Package::RPM::URPM object.
Specific parameters:
Path of file to use for creating this package.
URPM::Package object to use for creating this package.
Copyright (C) 2002-2006, YOURI project
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Youri-Package documentation | Contained in the Youri-Package distribution. |
# $Id: URPM.pm 2288 2011-01-22 11:33:51Z guillomovitch $ package Youri::Package::RPM::URPM;
use strict; use warnings; use Carp; use URPM; use File::Spec; use Expect; use Scalar::Util qw/refaddr blessed/; use Youri::Package::Relationship; use Youri::Package::File; use Youri::Package::Change; use base 'Youri::Package::RPM'; use overload '""' => 'as_string', '0+' => '_to_number', fallback => 1;
sub _init { my ($self, %options) = @_; my $header; HEADER: { if (exists $options{header}) { croak "undefined header" unless $options{header}; croak "invalid header" unless $options{header}->isa('URPM::Package'); $header = $options{header}; last HEADER; } if (exists $options{file}) { croak "undefined file" unless $options{file}; croak "non-existing file $options{file}" unless -f $options{file}; croak "non-readable file $options{file}" unless -r $options{file}; my $urpm = URPM->new(); $urpm->parse_rpm($options{file}, keep_all_tags => 1); $header = $urpm->{depslist}->[0]; croak "non-rpm file $options{file}" unless $header; last HEADER; } croak "no way to extract header from arguments"; } $self->{_header} = $header; $self->{_file} = File::Spec->rel2abs($options{file}); } sub compare_revisions { my ($class, $revision1, $revision2) = @_; return URPM::rpmvercmp($revision1, $revision2); } sub check_ranges_compatibility { my ($class, $range1, $range2) = @_; return URPM::ranges_overlap($range1, $range2); } sub get_name { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->name(); } sub get_version { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->version(); } sub get_release { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->release(); } sub get_revision { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->queryformat('%|EPOCH?{%{EPOCH}:}:{}|%{VERSION}-%{RELEASE}'); } sub get_file_name { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->filename(); } sub get_arch { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->arch(); } sub get_url { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->url(); } sub get_summary { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->summary(); } sub get_description { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->description(); } sub get_packager { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->packager(); } sub is_source { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->arch() eq 'src'; } sub is_binary { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->arch() ne 'src'; } sub get_type { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->arch() eq 'src' ? "source" : "binary"; } sub get_age { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->buildtime(); } sub get_source_package { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->sourcerpm(); } sub get_canonical_name { my ($self) = @_; croak "Not a class method" unless ref $self; if ($self->{_header}->arch() eq 'src') { return $self->{_header}->name(); } else { $self->{_header}->sourcerpm() =~ /^(\S+)-[^-]+-[^-]+\.src\.rpm$/; return $1; } } sub get_canonical_revision { my ($self) = @_; croak "Not a class method" unless ref $self; if ($self->{_header}->arch() eq 'src') { return $self->{_header}->get_revision(); } else { $self->{_header}->sourcerpm() =~ /^\S+-([^-]+-[^-]+)\.src\.rpm$/; return $1; } } sub get_tag { my ($self, $tag) = @_; croak "Not a class method" unless ref $self; croak "invalid tag $tag" unless $self->{_header}->can($tag); return $self->{_header}->$tag(); } sub get_requires { my ($self) = @_; croak "Not a class method" unless ref $self; my $pattern = qr/^([^[]+)(?:\[\*\])?(?:\[(.+)\])?$/; return map { $_ =~ $pattern; Youri::Package::Relationship->new($1, $2) } $self->{_header}->requires(); } sub get_provides { my ($self) = @_; croak "Not a class method" unless ref $self; my $pattern = qr/^([^[]+)(?:\[(.+)\])?$/; return map { $_ =~ /$pattern/; Youri::Package::Relationship->new($1, $2 && $2 ne '*' ? $2 : undef) } $self->{_header}->provides(); } sub get_obsoletes { my ($self) = @_; croak "Not a class method" unless ref $self; my $pattern = qr/^([^[]+)(?:\[(.+)\])?$/; return map { $_ =~ $pattern; Youri::Package::Relationship->new($1, $2 && $2 ne '*' ? $2 : undef) } $self->{_header}->obsoletes(); } sub get_conflicts { my ($self) = @_; croak "Not a class method" unless ref $self; my $pattern = qr/^([^[]+)(?:\[(.+)\])?$/; return map { $_ =~ $pattern; Youri::Package::Relationship->new($1, $2 && $2 ne '*' ? $2 : undef) } return $self->{_header}->conflicts(); } sub get_files { my ($self) = @_; croak "Not a class method" unless ref $self; my @modes = $self->{_header}->files_mode(); my @digests = version->parse($URPM::VERSION) < version->parse("4.0.0") ? $self->{_header}->files_md5sum() : $self->{_header}->files_digest() ; return map { Youri::Package::File->new($_, shift @modes, shift @digests) } $self->{_header}->files(); } sub get_gpg_key { my ($self) = @_; croak "Not a class method" unless ref $self; my $signature = $self->{_header}->queryformat('%{DSAHEADER:pgpsig}'); return if $signature eq '(not a blob)'; my $key_id = (split(/\s+/, $signature))[-1]; return substr($key_id, 8); } sub get_changes { my ($self) = @_; croak "Not a class method" unless ref $self; my @times = $self->{_header}->changelog_time(); my @texts = $self->{_header}->changelog_text(); return map { Youri::Package::Change->new($_, shift @times, shift @texts) } $self->{_header}->changelog_name(); } sub get_last_change { my ($self) = @_; croak "Not a class method" unless ref $self; my $text = ($self->{_header}->changelog_text())[0]; my $name = ($self->{_header}->changelog_name())[0]; my $time = ($self->{_header}->changelog_time())[0]; return $text ? Youri::Package::Change->new($name, $time, $text) : undef; } sub as_string { my ($self) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->fullname(); } sub as_formated_string { my ($self, $format) = @_; croak "Not a class method" unless ref $self; return $self->{_header}->queryformat($format); } sub _to_number { return refaddr($_[0]); } sub compare { my ($self, $package) = @_; croak "Not a class method" unless ref $self; croak "Not a __PACKAGE__ object" unless blessed $package && $package->isa(__PACKAGE__); return $self->{_header}->compare_pkg($package->{_header}); } sub satisfy_range { my ($self, $range) = @_; croak "Not a class method" unless ref $self; return $self->check_ranges_compatibility( '== ' . $self->get_revision(), $range ); } sub sign { my ($self, $name, $path, $passphrase) = @_; croak "Not a class method" unless ref $self; # check if parent directory is writable my $parent = (File::Spec->splitpath($self->{_file}))[1]; croak "Unsignable package, parent directory is read-only" unless -w $parent; my $command = 'LC_ALL=C rpm --resign ' . $self->{_file} . ' --define "_signature gpg"' . ' --define "_gpg_name ' . $name . '"' . ' --define "_gpg_path ' . $path . '"'; my $expect = Expect->spawn($command) or croak "Couldn't spawn command $command: $!\n"; my @log; $expect->log_stdout(0); $expect->log_file(sub { push(@log, $_[0]); }); $expect->expect(10, 'Enter pass phrase:') or croak "Unexpected output: $log[-1]\n"; $expect->send("$passphrase\n"); $expect->soft_close(); croak "Signature error: " . $log[-1] if $expect->exitstatus(); } sub extract { my ($self) = @_; croak "Not a class method" unless ref $self; system("rpm2cpio $self->{_file} | cpio -id >/dev/null 2>&1"); }
1;