diff options
58 files changed, 7664 insertions, 0 deletions
diff --git a/RPM4/MANIFEST b/RPM4/MANIFEST new file mode 100644 index 0000000..9acee7e --- /dev/null +++ b/RPM4/MANIFEST @@ -0,0 +1,58 @@ +MANIFEST +Makefile.PL +README +ChangeLog +src/Makefile.PL +src/RPM4.h +src/RPM4.xs +src/RPM4sign.c +src/constant.c +src/rpmconstant.c +src/rpmconstant.h +src/rpmconstant_internal.c +src/rpmh2tbl +lib/RPM4.pm +lib/RPM4/Index.pm +lib/RPM4/Header.pm +lib/RPM4/Header/Dependencies.pm +lib/RPM4/Header/Files.pm +lib/RPM4/Header/Changelogs.pm +lib/RPM4/Transaction.pm +lib/RPM4/Transaction/Problems.pm +lib/RPM4/Spec.pm +lib/RPM4/Media.pm +t/test-rpm-1.0-1mdk.noarch.rpm +t/test-rpm-1.0-1mdk.src.rpm +t/test-rpm.spec +t/test-dep-1.0-1mdk.noarch.rpm +t/test-dep-1.0-1mdk.src.rpm +t/test-dep.spec +t/rpmmacros +t/rpmrc +src/typemap +t/01compile.t +t/02header.t +t/03rpmlib.t +t/04spec.t +t/05transaction.t +t/06sign.t +t/07dep.t +t/07files.t +t/07changelogs.t +t/09hdlist.t +t/11media.t +t/gnupg/passphrase +t/gnupg/pubring.gpg +t/gnupg/secring.gpg +t/gnupg/trustdb.gpg +t/gnupg/test-key.gpg +bin/hrpmreb +bin/rpm_produced +bin/rpmresign +examples/hdinfo +examples/hdlistq +examples/hdrpmq +examples/specwillbuild +examples/hdlist2sdb +examples/hrpmreb-macros +META.yml Module meta-data (added by MakeMaker) diff --git a/RPM4/Makefile.PL b/RPM4/Makefile.PL new file mode 100644 index 0000000..95d5d33 --- /dev/null +++ b/RPM4/Makefile.PL @@ -0,0 +1,36 @@ +# $Id$ + +# use 5.008; +use ExtUtils::MakeMaker; +use Getopt::Long; + +#- require at least rpm 4.2 +my $rpm_version = `rpm --version`; +$rpm_version =~ s/RPM version //; +$rpm_version =~ /^(?:[5-9]|\d{2}|4\.[2-9])/ + or die <<BARF; +Unable to build Hdlist with too old (or undetected) rpm version $rpm_version +BARF + +sub MY::postamble { + <<MAKECHANGELOG; +.PHONY: ChangeLog + +ChangeLog: + svn update && svn log --verbose > \$@ + +rpm: dist + rpm --rmsource --define "_sourcedir `pwd`" -ba perl-Hdlist.spec +MAKECHANGELOG +} + +WriteMakefile( + NAME => 'RPM4', + VERSION_FROM => 'lib/RPM4.pm', + DIR => [ 'src' ], + 'EXE_FILES' => [ qw(bin/rpm_produced bin/rpmresign bin/hrpmreb) ], + dist => { + COMPRESS => 'bzip2 --best', + SUFFIX => '.bz2', + }, +); diff --git a/RPM4/README b/RPM4/README new file mode 100644 index 0000000..df93b5d --- /dev/null +++ b/RPM4/README @@ -0,0 +1,10 @@ +RPM4 v0.01 +============ + +A module to manipulate hdlist and synthesis files. + +COPYRIGHT AND LICENCE + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + diff --git a/RPM4/bin/hrpmreb b/RPM4/bin/hrpmreb new file mode 100755 index 0000000..a5ea8ce --- /dev/null +++ b/RPM4/bin/hrpmreb @@ -0,0 +1,671 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +use strict; +use warnings; + +use Getopt::Long; +use POSIX (qw/nice O_WRONLY O_CREAT O_APPEND/); +my $ipcstat; + +if (($ARGV[0] || "") eq '--trap') { + shift @ARGV; + my $trap = shift(@ARGV) or die "No log file specified\n"; + $0 = "hrpmreb [trapping]"; + open (my $t, ">>", $trap) or exit(1); + printf $t "\n\nRunning: %s\n\n", join(" ", @ARGV); + my $cmd = join(" ", @ARGV); + open(my $htrap, '-|', "$cmd 2>&1") or do { + print $t "Can't run cmd $cmd: $!\n"; + exit(1); + }; + { $| = 1; my $oldfh = select($t); $| =1; select($oldfh); } + + while(<$htrap>) { + print $_; + print $t $_; + } + close($t); + exit(!close($htrap)); +} + +if (($ARGV[0] || '') eq '--stat') { + require IPC::ShareLite; + foreach my $k (1000 .. 1020) { + $ipcstat = new IPC::ShareLite ( + -key => $k, + -create => 'no', + -destroy => 'no', + ) or last; + $ipcstat->lock(); + my @ipcs = map { pack("h*", $_) } split(/ /, $ipcstat->fetch()); + printf "Building: %s for %ds\n", shift(@ipcs), time - shift(@ipcs); + $ipcstat->unlock(); + show_stat(@ipcs); + } + exit(0); +} + +=head1 NAME + +hrpmreb + +=head1 DESCRIPTION + +A very powerful rpm rebuilder using perl-Hdlist + +=head1 SYNOPSYS + +hrpmreb -m macros rpm.src.rpm + +=head1 OPTIONS + +=head2 -m|--macros macrosfile + +Read a rpm macros file and add it to rpm configuration. + +To read several macros files, use -m macro1 -m macro2 ... + +=head2 -D|--define "macro value" + +Add a new macro to rpm configuration: + +example: -D "_sourcedir /tmp" + +This option can be used several time. + +=head2 -b|--batch + +Rebuild rpms found in L<%bindir> instead of the one given on command line + +=head2 -v|--verbose LEVEL + +Set rpm verbosity level to LEVEL. + +LEVEL can be an integer value (0 to 8) or a string value like "ERR", "DEBUG" or "INFO". + +=head2 --noupload + +Don't upload rpm after build. + +This option has the same effect than defining L<%upload> to 0. + +=head2 --nochkbin + +Don't check if binary already exist + +This option has the same effect that defining L<%checkbinary> to 0. + +=head2 --noinstdep + +Don't install dependancies needed to build the rpm + +This option has the same effect than defining L<%installdep> to 0. + +=head2 --keepalllog + +Don't delete log if build was successful. + +This option has the same effect than defining L<%keepalllog> to 1. + +=head2 --nobuild + +Skip build (and upload) stage, usefull for testing + +=head2 --nosort + +Do not sort srpms by builddate. + +This option has the same effect than defining L<%sortbybuilddate> to 0. + +=head2 --livestat + +Enable livestat functionnalities, see L<%livestat>, L<--stat>. + +=head2 --stat + +Give the statistics of current hrpmreb running on the current computer if +they has been started with livestat functionnality. + +=cut + +my (@define, @with, @without); + +GetOptions( + 'm|macros=s' => \my @macros, + 'D|define=s' => \@define, + 'b|batch' => \my $batch, + 'v|verbose=s' => \my $verbose, + 'nobuild' => \my $nobuild, + 'nosort' => sub { push @define, "sortbybuilddate 0"; }, + 'noupload' => sub { push @define, "upload 0"; }, + 'nochkbin' => sub { push @define, "checkbinary 0"; }, + 'noinstdep' => sub { push @define, "installdep 0"; }, + 'keepalllog' => sub { push @define, "keepalllog 1"; }, + 'trap=s' => sub { die "--trap should be first arg and you don't have to use it...\n" }, + 'livestat' => sub { push @define, "livestat 1"; }, + 'with=s' => \@with, + 'without=s' => \@without, + 'nofork' => \my $nofork, + 'dump' => \my $dumpconfig, +); + +push @define, "_with_$_ --with-$_" foreach (@with); +push @define, "_without_$_ --without-$_" foreach (@without); + +=head1 MACROS + +=head2 %myself + +The program itself ($0) + +=head2 %checkbinary + +If set, check if binary does not exists in L<%bindir> + +=head2 %srcdir + +A list of path separated by ':' where src.rpm should be found + +=head2 %bindir + +A list of path separated by ':' where binary rpm should be found + +=head2 %installdep + +If set, try to install dependancies (see L<%installrpmcmd>) + +=head2 %installdepcmd + +The command to run to install dependancies (urpmi ...) + +=head2 %upload + +If set, run the L<%uploadcmd> command + +=head2 %uploadcmd + +The upload command to run to upload binary rpms + +=head2 %logdir + +Where logfile should be put + +=head2 %keepalllog + +Don't delete log even on build success + +=head2 %nice + +Renice the build process + +=head2 %createrpmsdir + +If set, it will try to create rpms build directory + +=head2 %sortbybuilddate + +If define, sort srpms by builddate before build + +=head2 %livestat + +if set, hrpmreb use IPC to store his status, then you'll be able +to use hrpmreb --stat to immediatelly get status of the current build. + +=cut + +require Hdlist; +Hdlist::setverbosity($verbose || "INFO"); + +my $hlog = undef; + +Hdlist::setlogcallback( + sub { + my %arg = @_; + loging("%s", $arg{msg}); + } +); + +sub loging { + my ($fmt, @var) = @_; + printf STDERR $fmt, @var; + if ($hlog) { + printf $hlog $fmt, @var; + } +} + +config_macros(); + +if (Hdlist::expandnumeric("%livestat")) { + require IPC::ShareLite; + foreach my $k (1000 .. 1020) { + $ipcstat = new IPC::ShareLite ( + -key => $k, + -create => 'yes', + -destroy => 'no', + -mode => 0644, + ) and last; + } + $ipcstat or die "no IPC availlable\n"; +} + +my %status = ( + srpmdone => 0, + srpmfailure => 0, + srpmtotal => 0, + steptime => time, + currentsrpms => 'Preparing build', + currentstep => '', +); + +my $passphrase = Hdlist::expand('%{?gpgpass}'); + +my @srcdir = split(':', Hdlist::expand('%{?srcdir}')); +print Hdlist::expand("Source dir: %{?srcdir}%{?!srcdir:(none)}\n") if ($batch); + +!@srcdir && $batch and die "No src dir, please define \%srcdir\n"; + +my @bindir = split(':', Hdlist::expand('%{?bindir}')); +if (Hdlist::expandnumeric('%checkbinary')) { + if (@bindir) { + print Hdlist::expand("Using binary dir: %{?bindir}%{?!bindir:(none)}\n"); + } else { + die "No bin dir, please define \%bindir or unset \%checkbinary\n"; + } +} + +if ($dumpconfig) { + Hdlist::dumprc(\*STDOUT); + exit 0; +} + +-d Hdlist::expand("%{?logdir}%{!?logdir:.}") or mkdir Hdlist::expand("%{?logdir}%{!?logdir:.}") + or die "Can't create logdir ". Hdlist::expand("%{?logdir}%{!?logdir:.}") . " $!\n"; + +if (Hdlist::expandnumeric('%createrpmsdir')) { + foreach my $macro (qw(%_topdir %_sourcedir %_builddir %_srpmdir %_rpmdir %_rpmdir/noarch %_rpmdir/%_target_cpu %_specdir %_tmppath)) { + -d Hdlist::expand($macro) or mkdir Hdlist::expand($macro) + or die "Can't create dir " . Hdlist::expand($macro) . "($macro): $!"; + } +} + +set_ipc_status(currentstep => "searching srpms"); + +my @srpmstobuild; +my @specstobuild; + +if($batch) { + @srpmstobuild = map { glob("$_/*.src.rpm") } @srcdir; +} + +foreach my $arg (@ARGV) { + -f $arg or do { + push(@srpmstobuild, map { glob("$_/$arg") } @srcdir); + next; + }; + if ($arg =~ /\.src\.rpm$/) { + push @srpmstobuild, $arg; + } else { + push @specstobuild, $arg; + }; +} + +$status{srpmtotal} = scalar(@srpmstobuild) + scalar(@specstobuild); + +if (! $status{srpmtotal}) { + die sprintf("Nothing to do, %s\n", $batch ? "check \%srcdir value" : "give src.rpm too rebuild or use -b"); +} + +if (Hdlist::expandnumeric("%sortbybuilddate")) { + loging("Sorting srpms by buildate\n"); + set_ipc_status(currentstep => "sorting srpms"); + @srpmstobuild = sort_srpms(@srpmstobuild); +} + +# readjusting +$status{srpmtotal} = scalar(@srpmstobuild) + scalar(@specstobuild); + +foreach my $specfile (@specstobuild) { + my $pid = fork(); + + if ($pid) { + parent_wait_child($pid); + $? and $status{srpmfailure}++; + + show_stat($status{srpmtotal}, ++$status{srpmdone}, $status{srpmfailure}); + + config_macros(); + } else { + my $oldcmd = Hdlist::expand("%___build_cmd"); + Hdlist::add_macro("___build_cmd %myself --trap %_tmppath/%name-%version-%release.build.log $oldcmd"); + exit(build_specfile($specfile)); + } +} + +foreach my $srpm (@srpmstobuild) { + my $pid = fork(); + + if ($pid) { + parent_wait_child($pid); + $? and $status{srpmfailure}++; + + show_stat($status{srpmtotal}, ++$status{srpmdone}, $status{srpmfailure}); + + config_macros(); + } else { + my $oldcmd = Hdlist::expand("%___build_cmd"); + Hdlist::add_macro("___build_cmd %myself --trap %_tmppath/%name-%version-%release.build.log $oldcmd"); + exit(build_srcrpm($srpm)); + } +} + +sub parent_wait_child { + my ($pid) = @_; + my $subdie = sub { + kill 15, $pid; + waitpid $pid, 0; + exit(1); + }; + local $SIG{'TERM'} = $subdie; + local $SIG{'INT'} = $subdie; + waitpid $pid, 0; +} + +sub show_advance { + my ($end, $total, $done) = @_; + printf(" %5d / %5d [%-50s] %3d %%%s", $done, $total, + '#' x ($total ? ($done * 50 / $total) : 0), + ($total ? ($done * 100 / $total) : 0), $end); +} + +sub show_stat { + my ($total, $done, $failure) = @_; + print "\nDone:\n"; + show_advance("\n", $total, $done); + print "Failed:\n"; + show_advance("\n\n", $done, $failure); +} + +sub set_ipc_status { + my (%val) = @_; + foreach (keys %val) { + $status{$_} = $val{$_}; + /currentsrpms/ and do { + $status{steptime} = time; + $status{currentstep} = ''; + }; + } + $ipcstat or return; + $ipcstat->lock(); + $ipcstat->store(sprintf( + "%s %s %s %s %s", + unpack("h*", "$status{currentsrpms} ($status{currentstep})"), + unpack("h*", $status{steptime}), + unpack("h*", $status{srpmtotal}), unpack("h*", $status{srpmdone}), unpack("h*", $status{srpmfailure}) + )); + $ipcstat->unlock(); +} + +sub sort_srpms { + my %s; + my $db = Hdlist::newdb(); + $db->vsflags([ qw(NOSIGNATURES NOPAYLOAD NODIGESTS) ]); + my $done = 0; + my @specs; + foreach my $src (@_) { + my $h = $db->rpm2header($src) or next; + $s{$src} = $h->tag("BUILDTIME") || 0; + show_advance("\r", scalar(@_), ++$done); + + } + print "\n"; + return sort { $s{$a} <=> $s{$b} } keys %s; +} + +sub config_macros { + Hdlist::resetmacros(); + + Hdlist::add_macro("logfileformat %name.log"); + + Hdlist::readconfig(); + + Hdlist::loadmacrosfile($_) foreach (@macros); + Hdlist::add_macro($_) foreach(@define); + + Hdlist::add_macro("myself $0"); +} + +sub checkbinary { + my ($spec) = @_; + Hdlist::expandnumeric('%checkbinary') or return 1; + my $missing = 0; + my @bin = $spec->binrpm(); + foreach my $r (@bin) { + $r =~ s!^.*/!!; + my @rfake; + if (my ($rp) = $r =~ /^(.*)(?:amd64|x86_64)\.rpm/) { + push @rfake, $rp."x86_64.rpm", $rp."amd64.rpm"; + } else { + push @rfake, $r; + } + my $ok = 0; + foreach my $rp (@rfake) { + if (grep { -f "$_/$rp" } @bindir) { + loging("$rp found\n"); + $ok = 1; + last; + } + } + if (!$ok) { + loging("$r not found (need build)\n"); + $missing++; + } + } + return 0 if ($missing == 0); + return Hdlist::expandnumeric('%checkbinary') <= ($missing == scalar(@bin) ? 2 : 1); +} + +sub build_srcrpm { + my ($srpm) = @_; + my ($specf, $cookies) = Hdlist::installsrpm($srpm) or return 1; + my $rc = 0; + + my $spec; + if ($spec = Hdlist::specnew($specf, $passphrase, "/", $cookies, 0, 0)) { + open($hlog, ">", Hdlist::expand('%{?logdir:%{logdir}/}%{logfileformat}')); + $0 = Hdlist::expand("hrpmreb [%name-%version-%release]"); + set_ipc_status(currentsrpms => Hdlist::expand("%name-%version-%release")); + $SIG{'TERM'} = sub { + $spec && $spec->build(["RMSOURCE", "RMSPEC", "RMBUILD"]); + $spec && $spec->build(["CLEAN"]); + }; + + if (checkbinary($spec)) { + $rc = build_spec($spec, $srpm); + upload_build($spec, 0) unless($rc); + } else { + loging("Found binary, skipping build\n"); + } + + if ($rc || Hdlist::expandnumeric('%keepalllog')) { + if (open(my $buildlog, "<", Hdlist::expand("%_tmppath/%name-%version-%release.build.log"))) { + while (<$buildlog>) { + print $hlog $_; + } + close($buildlog); + } + } else { + unlink(Hdlist::expand("\%{?logdir:%{logdir}/}%{logfileformat}")); + } + + close($hlog); $hlog = undef; + } else { + $rc = 1; + } + + $spec ||= Hdlist::specnew($specf, $passphrase, "/", $cookies, 1, 1); + + if ($spec) { + set_ipc_status(currentstep => "cleaning"); + loging("cleaning sources, spec\n"); + $spec && $spec->build(["RMSOURCE", "RMSPEC", "RMBUILD"]); + } + + unlink(Hdlist::expand("%_tmppath/%name-%version-%release.build.log")); + return $rc; +} + +sub build_specfile { + my ($specf) = @_; + my $rc = 0; + + my $spec; + if ($spec = Hdlist::specnew($specf, $passphrase, "/", undef, 0, 0)) { + open($hlog, ">", Hdlist::expand('%{?logdir:%{logdir}/}%{logfileformat}')); + $0 = Hdlist::expand("hrpmreb [%name-%version-%release]"); + set_ipc_status(currentsrpms => Hdlist::expand("%name-%version-%release")); + $SIG{'TERM'} = sub { + $spec && $spec->build(["RMBUILD"]); + }; + + $spec->build(["PACKAGESOURCE"]); + my $srpm = $spec->srcrpm(); + + if (checkbinary($spec)) { + $rc = build_spec($spec, $srpm); + upload_build($spec, 1) unless($rc); + } else { + loging("Found binary, skipping build\n"); + } + + if ($rc || Hdlist::expandnumeric('%keepalllog')) { + if (open(my $buildlog, "<", Hdlist::expand("%_tmppath/%name-%version-%release.build.log"))) { + while (<$buildlog>) { + print $hlog $_; + } + close($buildlog); + } + } else { + unlink(Hdlist::expand("\%{?logdir:%{logdir}/}%{logfileformat}")); + } + + close($hlog); $hlog = undef; + } else { + $rc = 1; + } + + $spec ||= Hdlist::specnew($specf, $passphrase, "/", undef, 1, 1); + + if ($spec) { + set_ipc_status(currentstep => "cleaning"); + loging("cleaning sources, spec\n"); + $spec && $spec->build(["RMBUILD"]); + } + + unlink(Hdlist::expand("%_tmppath/%name-%version-%release.build.log")); + return $rc; +} + + +sub build_spec { + my ($spec, $srpm) = @_; + my ($rc, $starttime, $chkdeptime, $installdeptime, $uploadtime, $buildtime, $endtime) = (0); + + $starttime = time; + + if (Hdlist::expandnumeric('%installdep') && $srpm) { + set_ipc_status(currentstep => "installing dep"); + runmacro("%installdepcmd", $srpm); + $installdeptime = time; + } + + nice(Hdlist::expand("%{?nice}")) if (Hdlist::expandnumeric("%{?nice:1}")); + set_ipc_status(currentstep => "checking dep"); + my @pb; + { + my $db = Hdlist::newdb(); + my $sh = $spec->srcheader(); + + $db->transadd($sh, "", 0); + $db->transcheck; + @pb = $db->transpb(); + } + $chkdeptime = time; + + if (@pb) { + loging("\nMissing dependancies:\n"); + loging("$_\n") foreach(Hdlist::format_rpmpb(@pb)); + $rc = 1; + } elsif(! $nobuild) { + set_ipc_status(currentstep => "compiling"); + $rc = $spec->build([ qw/PREP BUILD INSTALL CHECK FILECHECK PACKAGEBINARY/ ]); + $spec->build([ qw/CLEAN/ ]); + $buildtime = time; + } + $endtime = time; + + loging("\nBuild time in sec:\n"); + loging("%20s %5s\n", 'installdepcmd: ', defined($installdeptime) ? $installdeptime - $starttime : "N/A"); + loging("%20s %5s\n", 'check dep: ', $chkdeptime - ($installdeptime || $starttime)); + loging("%20s %5s\n", 'build: ', defined($buildtime) ? $buildtime - $chkdeptime : "N/A"); + loging("%20s %5s\n", 'Total: ', $endtime - $starttime); + + loging("Build exit code: $rc\n"); + + return $rc; +} + +sub upload_build { + my ($spec, $uploadsrc) = @_; + my @buildrpms = $spec->binrpm; + unshift @buildrpms, $spec->srcrpm if($uploadsrc); + + my $noexist = 0; + foreach (@buildrpms) { + if(-f $_) { + loging("%s has been built\n", $_); + } else { + loging("%s has not been built\n", $_); + $noexist++; + } + } + $noexist and return 1; + if (Hdlist::expandnumeric('%upload')) { + set_ipc_status(currentstep => "uploading"); + !runmacro("%uploadcmd", @buildrpms) and unlink @buildrpms; + } + return 0; +} + +sub runmacro { + my ($macro, @args) = @_; + my $cmd = Hdlist::expand($macro. " " . join(' ', @args)); + $cmd =~ /^\Q$macro/ and return 1; + loging("Executing(%%%s) %s\n", $macro, $cmd); + system($cmd) +} + +__END__ + +=head1 AUTHOR + +Olivier Thauvin <nanardon@mandrake.org> + +=cut diff --git a/RPM4/bin/rpm_produced b/RPM4/bin/rpm_produced new file mode 100755 index 0000000..e9fe67b --- /dev/null +++ b/RPM4/bin/rpm_produced @@ -0,0 +1,77 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use warnings; +use RPM4; +use Getopt::Long; + +my ($showsrc, $tmp, @macros) = (1, $ENV{TMP} || '/tmp'); + +GetOptions( + 'define=s' => \@macros, + 'src!' => \$showsrc, +); + +(@ARGV) or die +"$0 file1 [file2 [...]] +Give rpms filename produce by a specfile or a src.rpm + +Options: + --define \"macro value\" define a macro into rpm land + --no-src do not show the src.rpm +"; + +Hdlist::add_macro("_sourcedir $tmp"); +Hdlist::add_macro("_specdir $tmp"); + +sub set_config { + Hdlist::readconfig(); + foreach (@macros) { + Hdlist::add_macro($_); + } +} + +sub specquery { + my ($spec) = @_; + $showsrc and print $spec->srcrpm ."\n"; + foreach my $bin ($spec->binrpm) { + print "$bin\n"; + } +} + +foreach my $file (@ARGV) { + set_config(); + $file =~ m/\.src\.rpm$/ and do { + if(my ($specfile) = Hdlist::installsrpm($file)) { + if (my $spec = Hdlist::specnew($specfile, undef, undef, undef, 1, 1)) { + specquery($spec); + $spec->build([qw(RMSOURCE RMSPEC)]); + } + } + next; + }; + $file =~ m/\.spec$/ and do { + if (my $spec = Hdlist::specnew($file, undef, undef, undef, 1, 1)) { + specquery($spec); + } + next; + } +} diff --git a/RPM4/bin/rpmresign b/RPM4/bin/rpmresign new file mode 100755 index 0000000..4cce105 --- /dev/null +++ b/RPM4/bin/rpmresign @@ -0,0 +1,65 @@ +#!/usr/bin/perl + +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +use strict; +use warnings; + +use Getopt::Long; +use Hdlist::Sign; + +my ($configfile, $batch, $sigtype, $passfile, $macrofile, $fastmode, $path, $name, $keyid, $pass); +my @defines; + +GetOptions( + 'p|path=s' => \$path, + 'n|name=s' => \$name, + 'c|config=s' => \$configfile, + 'b|batch' => \$batch, + 'd|define=s' => \@defines, + 'f|fastmode' => \$fastmode, + 'passwordfile|sig-pass-file=s' => \$passfile, + 'm|macros=s' => \$macrofile, +); + +foreach (@defines) { + Hdlist::add_macro($_); +} + +if (!$passfile) { + $pass = <STDIN>; + chomp($pass); +} + +my $sign = Hdlist::Sign->new( + passphrase => $pass, + _signature => $sigtype, + path => $path, + name => $name, + checkrpms => $fastmode ? 0 : 1, + password_file => $passfile, +); + +my @files; + +while (my $f = shift(@ARGV)) { + -d $f and do { + push(@files, glob("$f/*.rpm")); + next; + }; + push(@files, $f); +} + +$sign->rpmssign(@files); diff --git a/RPM4/bin/urpm_interactive b/RPM4/bin/urpm_interactive new file mode 100755 index 0000000..7756fea --- /dev/null +++ b/RPM4/bin/urpm_interactive @@ -0,0 +1,149 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +use strict; +use warnings; + +use Hdlist::Media; +use Hdlist::Media::Solve; +use Term::ReadLine; +use Text::ParseWords; +use urpm; +use Getopt::Long; + +#Hdlist::setverbosity('DEBUG'); + +my $dbpath; + +GetOptions( + "dbpath=s" => \$dbpath, +); + + +Hdlist::add_macro("_dbpath $dbpath") if ($dbpath); + +my $s = Hdlist::Media::Solve->new( +); + +{ + my $u = urpm->new(); + $u->read_config; + foreach my $m (@{$u->{media}}) { + $m->{virtual} or next; + my $dir = $m->{url}; + $dir =~ s!file:/+!/!; + $s->addmedia( + Hdlist::Media->new( + hdlist => $m->{with_hdlist}, + rpmsdir => $dir, + ), + ); + } +} + +$s->add_system_dep('REQUIRE', "basesystem"); + +$s->load(); + +my $term = new Term::ReadLine 'Hdlist'; + +my $prompt = "urpm > "; + +while (defined (my $cmdline = $term->readline($prompt))) { + chomp($cmdline); + my $cmd; local @ARGV; + ($cmd, @ARGV) = &parse_line('\s+', 0, $cmdline); + + $cmd or next; + $term->addhistory($cmdline); + + $cmd =~ /^quit$/ and last; + + $cmd =~ /^(q|query)$/ and do { + my $tag; + my $qf; + GetOptions( + "t|tag=s" => \$tag, + "qf|queryformat=s" => \$qf, + ); + $s->traverse(db => 1, medium => undef, callback => sub { + my ($header, $id, $media) = @_; + print "$media: " . $header->queryformat($qf || $s->{short_fmt}) ."\n"; + 1; + }, tag => $tag || ($ARGV[0] ? 'NAME' : ""), tagvalue => $ARGV[0]); + next; + }; + + $cmd =~ /^sysdep$/ and do { + my $tag = 'REQUIRE'; + GetOptions( + 'c' => sub { $tag = 'CONFLICT'; }, + ); + $ARGV[0] or next; + $s->add_system_dep($tag, @ARGV); + next; + }; + + $cmd =~ /^(\+|add)$/ and do { + $s->find_and_add($ARGV[0]); + next; + }; + + $cmd =~ /^(-|remove)$/ and do { + $s->find_and_remove($ARGV[0]); + next; + }; + + $cmd =~ /^a(utoselect)?$/ and do { + $s->autoselect(); + next; + }; + + $cmd =~ /^c(heck)?$/ and do { + $s->check(); + next; + }; + + $cmd =~ /^r(un)?$/ and do { + $s->run(); + next; + }; + + $cmd =~ /^l(ist)?$/ and do { + $s->list_trans(); + next; + }; + + $cmd =~ /^d$/ and do { + $s->add_from_require(@ARGV); + next; + }; + + $cmd =~ /^clean$/ and do { + foreach (@ARGV) { + m/trans/ and $s->clean_trans(); + m/request/ and $s->clean_request(); + } + next; + }; + + print "unknow command '$cmd'\n"; +}; + diff --git a/RPM4/examples/checkhdr b/RPM4/examples/checkhdr new file mode 100755 index 0000000..c2006cb --- /dev/null +++ b/RPM4/examples/checkhdr @@ -0,0 +1,13 @@ +#!/usr/bin/perl + +# $Id$ + +use strict; +use warnings; +use RPM4; +use RPM4::Header::Checks; + +foreach (@ARGV) { + my $h = rpm2header($_); + RPM4::Header::Checks::check($h); +} diff --git a/RPM4/examples/hbuildspec b/RPM4/examples/hbuildspec new file mode 100755 index 0000000..d0204db --- /dev/null +++ b/RPM4/examples/hbuildspec @@ -0,0 +1,40 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use Hdlist; +use Getopt::Long; + +(@ARGV) or die +"$0 specfile1.spec [specfile2.spec [...]] +Give rpms filename produce by a specfile +"; + +foreach (@ARGV) { + my $spec = Hdlist::specnew($_); + my @err = $spec->check(); + if (@err) { + foreach (Hdlist::print_rpmpb(@err)) { + print "\t$_\n"; + } + } else { + + } +} diff --git a/RPM4/examples/hdinfo b/RPM4/examples/hdinfo new file mode 100755 index 0000000..3d3de25 --- /dev/null +++ b/RPM4/examples/hdinfo @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +##- trem <trem@zarb.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use Hdlist; + +my $arch = Hdlist::getarchname(); +print "arch = " . $arch . "\n"; + +my $os = Hdlist::getosname(); +print "os = " . $os . "\n"; + +my $host = Hdlist::buildhost(); +print "host = " . $host . "\n"; diff --git a/RPM4/examples/hdlist2sdb b/RPM4/examples/hdlist2sdb new file mode 100755 index 0000000..e1fe387 --- /dev/null +++ b/RPM4/examples/hdlist2sdb @@ -0,0 +1,68 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use Hdlist; +use Getopt::Long; + +GetOptions ( + 'dbpath=s' => \my $dbpath, + 'v' => \my $verbose, +) && @ARGV or die " +Usage $0 [--dbpath path] hdlist.cz [hdlist2.cz [...]] +Synch rpm found into given hdlist into a database. +Usefull to create a solve rpm database. +"; + +$dbpath ||= Hdlist::expand("%_solve_dbpath"); + +Hdlist::add_macro("_dbpath $dbpath"); + +my $db = Hdlist::newdb(1) or die "Can't open DB"; + +my %rpmlist; +my %indb; + +$db->traverse_headers( sub { + my ($hdr, $id) = @_; + $indb{$hdr->queryformat("%{PKGID}")} = 1; + }); + +foreach my $arg (@ARGV) { + print "Reading $arg\n"; + open(my $hdfh, "zcat '$arg' |") or die "Can't open $_"; + while (my $hdr = stream2header($hdfh)) { + $rpmlist{$hdr->queryformat("%{PKGID}")} = 1; + defined($indb{$hdr->queryformat("%{PKGID}")}) and next; + print "Adding " . $hdr->queryformat("%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}") . "\n"; + $db->injectheader($hdr); + } +} + +my @id2remove; + +$db->traverse_headers( sub { + my ($hdr, $id) = @_; + defined($rpmlist{$hdr->queryformat("%{PKGID}")}) or push(@id2remove, $id); + }); + +foreach (@id2remove) { + $db->deleteheader($_); +} diff --git a/RPM4/examples/hdlistq b/RPM4/examples/hdlistq new file mode 100755 index 0000000..1e2489a --- /dev/null +++ b/RPM4/examples/hdlistq @@ -0,0 +1,68 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use Hdlist; +use Getopt::Long; + +my $qf = "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n"; +my $cond = undef; + +my $go_res = GetOptions ( + "qf|queryformat=s" => \$qf, + "c|cond=s" => \$cond, + "qi" => sub { + $qf = +'Name : %-27{NAME} Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}| +Version : %-27{VERSION} Vendor: %{VENDOR} +Release : %-27{RELEASE} Build Date: %{BUILDTIME:date} +Install Date: %|INSTALLTIME?{%-27{INSTALLTIME:date}}:{(not installed) }| Build Host: %{BUILDHOST} +Group : %-27{GROUP} Source RPM: %{SOURCERPM} +Size : %-27{SIZE}%|LICENSE?{ License: %{LICENSE}}| +Signature : %|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}| +%|PACKAGER?{Packager : %{PACKAGER}\n}|%|URL?{URL : %{URL}\n}|\Summary : %{SUMMARY} +Description :\n%{DESCRIPTION} +'; + }, +); +my ($type, $name, $flag, $ENV, $dep); +if ($cond) { + my @d = split(/ +/, $cond); + $dep = Hdlist::newdep(@d); +} + +($go_res && @ARGV) or die +"$0 [--qf|--queryformat rpm_query] [--cond cond] hdlist.cz [hdlist2.cz [...]] +Do something like `rpm -q --queryformat' on each header contains in hdlist archive +--cond: show only rpm which apply to this condition: + R|C NAME [<=> VERSION], ex C rpm = 4.2.1 will show rpm providing rpm-4.2.1 +example: $0 --qf '%{NAME}\\n' hdlist.cz +"; + +foreach (@ARGV) { + open(my $hdfh, "zcat '$_' |") or die "Can't open $_"; + while (my $hdr = stream2header($hdfh)) { + if ($cond) { + $hdr->matchdep($dep, "PROVIDE") or next; + } + print $hdr->queryformat($qf); + } + close($hdfh); +} diff --git a/RPM4/examples/hdrpmq b/RPM4/examples/hdrpmq new file mode 100755 index 0000000..5d9c91e --- /dev/null +++ b/RPM4/examples/hdrpmq @@ -0,0 +1,44 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use Hdlist; +use Getopt::Long; + +my $qf = "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n"; + +my $go_res = GetOptions ( + "qf|queryformat=s" => \$qf, +); + +($go_res && @ARGV) or die +"$0 [--qf|--queryformat rpm_query] rpm1 [rpm2 [...]] +Do something like `rpm -qp --queryformat' using perl-Hdlist +example: $0 --qf '%{NAME}\\n' test-rpm-1.0-1mdk.noarch.rpm +"; + +foreach (@ARGV) { + my $hdr = rpm2header($_); + if ($hdr) { + print $hdr->queryformat($qf); + } else { + warn "Can't read $_\n"; + } +} diff --git a/RPM4/examples/hinfo b/RPM4/examples/hinfo new file mode 100644 index 0000000..29e1f77 --- /dev/null +++ b/RPM4/examples/hinfo @@ -0,0 +1,42 @@ +#!/usr/bin/perl + +##- trem <trem@zarb.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use Hdlist; + +(@ARGV) or die("$0 <rpmfilename>"); + +foreach (@ARGV) { + my $header = rpm2header($_); + if($header) { + print "tag\tnom\t\texiste\tvaleur\n"; + foreach ($header->listtag) { + print "$_\t" . Hdlist::tagName($_) . "\t\t"; + my $e; + $e = $header->hastag("$_"); + print "$e\t"; + eval { + print $header->tag($_) if($e); + }; + print "SOUCI: $@" if($@); + print "\n"; + } + } +} diff --git a/RPM4/examples/hrpmreb-macros b/RPM4/examples/hrpmreb-macros new file mode 100644 index 0000000..26346b5 --- /dev/null +++ b/RPM4/examples/hrpmreb-macros @@ -0,0 +1,31 @@ +# $id$ + +%media contrib +%basedistrib /home/root/mandrake/mdk/Mandrakelinux/ + +# A way to install dependancies, with this you need a sudo +%installdep 1 +%installdepcmd sudo -H /usr/sbin/urpmi --auto --no-verify-rpm + +# I have script to upload, made it +%upload 0 +%uploadcmd /home/users/olivier/bin/upload -d %media + +# Where are source +%srcdir %basedistrib/devel/cooker/SRPMS/%media + +# Where are binary +%checkbinary 1 +%bindir %basedistrib/devel/cooker/%_target_cpu/media/%media + +# Where to put log +%keepalllog 0 +%logdir ./%{_target_cpu}-%{media}-log + +# for speed up +%_sourcedir /tmp/ + +# If you want the build process to be niced +# %nice 10 + +%_signature %nil diff --git a/RPM4/examples/rpminstall b/RPM4/examples/rpminstall new file mode 100755 index 0000000..fef5caf --- /dev/null +++ b/RPM4/examples/rpminstall @@ -0,0 +1,96 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use Hdlist; +use Getopt::Long qw(:config pass_through); + +sub help { + die " +Usage $0 [options] [-i rpm_to_install.rpm] [-e rpm_name_to_remove] +This script mimic a simple rpm programs for installing or removing packages +options: + --dbpath path alternate path to rpmdb + --root root set rootdir for installation + --test only test, do not install pkg + --justdb only install package in the db, not on filesystem + +Notice it permit to install and to remove package in same time ! :) +"; +} + +my (@rpmi, @rpme); +my @installflags; +my ($root, $dbpath) = + (undef, undef ); + +GetOptions( + 'root=s' => \$root, + 'dbpath=s' => \$dbpath, + 'test' => sub { push(@installflags, 'TEST') }, + 'justdb' => sub { push(@installflags, 'JUSTDB') }, + 'h|help' => sub { help() }, +); + +{ + my $install = 1; + + while (my $arg = shift(@ARGV)) { + $arg =~ /^-i$/ and do { + $install = 1; + next; + }; + $arg =~ m/^-e$/ and do { + $install = 0; + next; + }; + if ($install) { + push(@rpmi, $arg); + } else { + push(@rpme, $arg); + } + } +} + +(@rpmi || @rpme) or help(); + +if (defined($dbpath)) { + Hdlist::add_macro("_dbpath $dbpath"); +} +my $db = newdb(0, $root); + +foreach my $rpm (@rpmi) { + my $hdr = rpm2header($rpm) or do { + warn "Can't get header from $rpm, skipping"; + next; + }; + $db->transadd($hdr, $rpm, 1); +} + +foreach my $rpm (@rpme) { + $db->transremove($rpm) or warn "Can't remove unknown package $rpm, skipping"; +} + +$db->transcheck(); + +my @pb = $db->transpb(); +if (@pb) { die(join('\n', map { s/^/\t/ } format_rpmpb(@pb))); } + +$db->transrun(undef, @installflags); diff --git a/RPM4/examples/specwillbuild b/RPM4/examples/specwillbuild new file mode 100755 index 0000000..7ccbbf9 --- /dev/null +++ b/RPM4/examples/specwillbuild @@ -0,0 +1,42 @@ +#!/usr/bin/perl + +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# $Id$ + +use strict; +use Hdlist; +use Getopt::Long; + +(@ARGV) or die +"$0 specfile1.spec [specfile2.spec [...]] +Give rpms filename produce by a specfile +"; + +foreach (@ARGV) { + Hdlist::readconfig(); + my $spec = Hdlist::specnew($_, undef, undef, undef, 1, 1); + defined $spec or do { + warn "unable to parse $_\n"; + next; + }; + print "$_:\n"; + print $spec->srcrpm . "\n"; + foreach my $bin ($spec->binrpm) { + print "$bin\n"; + } +} diff --git a/RPM4/lib/RPM4.pm b/RPM4/lib/RPM4.pm new file mode 100644 index 0000000..beac297 --- /dev/null +++ b/RPM4/lib/RPM4.pm @@ -0,0 +1,422 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +package RPM4; + +use strict; +use warnings; + +use DynaLoader; +use Exporter; + +use RPM4::Header; +use RPM4::Transaction; +use RPM4::Header::Dependencies; +use RPM4::Header::Files; +use RPM4::Spec; + +our $VERSION = '0.08'; +our @ISA = qw(DynaLoader Exporter); +our @EXPORT = qw(moduleinfo + readconfig querytag tagName tagValue expand rpmvercmp + stream2header rpm2header + installsrpm + setverbosity setlogcallback format_rpmpb + rpmresign + newdb parserpms); +our %EXPORT_TAGS = ( + rpmlib => [qw(getosname getarchname dumprc dumpmacros rpmvercmp setverbosity setlogcallback + rpmlog)], + macros => [qw(add_macros del_macros loadmacrosfile resetmacros)], + build => [qw(headernew)], + rpmdb => [qw(rpmdbverify rpmdbrebuild)], +); + +bootstrap RPM4; + +# I18N: +sub N { + my ($msg, @args) = @_; + sprintf($msg, @args) +} + +sub compare_evr { + my ($ae, $av, $ar) = $_[0] =~ /^(?:([^:]*):)?([^-]*)(?:-(.*))?$/; + my ($be, $bv, $br) = $_[1] =~ /^(?:([^:]*):)?([^-]*)(?:-(.*))?$/; + + my $rc = 0; + if(defined($ae) && ! defined($be)) { + return 1; + } elsif(!defined($ae) && defined($be)) { + return -1; + } else { + $rc = RPM4::rpmvercmp($ae, $be) if (defined($ae) && defined($be)); + if ($rc == 0) { + $rc = RPM4::rpmvercmp($av, $bv); + if ($rc == 0) { + if(defined($ar) && !defined($br)) { + return 1; + } elsif(!defined($ar) && defined($br)) { + return -1; + } elsif (!defined($ar) && !defined($br)) { + return 0; + } else { + return RPM4::rpmvercmp($ar, $br); + } + } else { + return $rc; + } + } else { + return $rc; + } + } +} + +# parse* function +# callback => function +# ( +# header => the header (undef on error) +# file => actual source +# ) +# files => [] +# flags => ?? + +sub parserpms { + my (%options) = @_; + my $db = newdb(); + $db->vsflags($options{checkrpms} ? [ "NOSIGNATURES" ] : [ qw(NOSIGNATURES NOPAYLOAD NODIGESTS) ]); + foreach my $rpm (@{$options{rpms} || []}) { + my $header = $db->rpm2header($options{path} ? "$options{path}/$rpm" : $rpm); + defined($options{callback}) and + $options{callback}->( + header => $header, + dir => $options{path} ? "$options{path}/" : "", + rpm => $rpm, + ); + } +} + +sub format_rpmpb { + my (@msgs) = @_; + my @ret; + foreach my $p (@msgs) { + $p->{pb} eq "BADARCH" and do { + push @ret, N('package %s is intended for a different architecture', $p->{pkg}); + next; + }; + $p->{pb} eq "BADOS" and do { + push @ret, N('package %s is intended for a different operating system', $p->{pkg}); + next; + }; + $p->{pb} eq "PKG_INSTALLED" and do { + push @ret, N('package %s is allready installed', $p->{pkg}); + next; + }; + $p->{pb} eq "BADRELOCATE" and do { + push @ret, N('path %s in package %s is not relocatable', $p->{path}, $p->{pkg}); + next; + }; + $p->{pb} eq "NEW_FILE_CONFLICT" and do { + push @ret, N('file %s conflicts between attempted installs of %s and %s', $p->{file}, $p->{pkg}, $p->{pkg2}); + next; + }; + $p->{pb} eq "FILE_CONFLICT" and do { + push @ret, N('file %s from install of %s conflicts with file from package %s', $p->{file}, $p->{pkg}, $p->{pkg2}); + next; + }; + $p->{pb} eq "OLDPACKAGE" and do { + push @ret, N('package %s (which is newer than %s) is already installed', $p->{pkg2}, $p->{pkg}); + next; + }; + $p->{pb} eq "DISKSPACE" and do { + push @ret, N('installing package %s needs %sB on the %s filesystem', $p->{pkg}, + ($p->{size} > 1024 * 1024 + ? ($p->{size} + 1024 * 1024 - 1) / (1024 * 1024) + : ($p->{size} + 1023) / 1024 ) . + ($p->{size} > 1024 * 1024 ? 'M' : 'K'), + $p->{filesystem}); + next; + }; + $p->{pb} eq "DISKNODES" and do { + push @ret, N('installing package %s needs %ld inodes on the %s filesystem', $p->{pkg}, $p->{nodes}, $p->{filesystem}); + next; + }; + $p->{pb} eq "BADPRETRANS" and do { + push @ret, N('package %s pre-transaction syscall(s): %s failed: %s', $p->{pkg}, $p->{'syscall'}, $p->{error}); + next; + }; + $p->{pb} eq "REQUIRES" and do { + push @ret, N('%s is needed by %s%s', $p->{pkg2}, + defined($p->{installed}) ? N("(installed) ") : "", + $p->{pkg}); + next; + }; + $p->{pb} eq "CONFLICT" and do { + push @ret, N('%s conflicts with %s%s', $p->{pkg2}, + defined($p->{val2}) ? N("(installed) ") : "", + $p->{pkg}); + next; + }; + }; + @ret +} + +########################## +# Alias for compatiblity # +########################## + +sub specnew { + newspec(@_); +} + +1; + +__END__ + +=head1 NAME + +RPM4 - perl module to handle hdlist and synthesis files + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +This module allow to use API functions from rpmlib, directly or trough +perl objects. + +=head1 FUNCTIONS + +=head2 readconfig($rpmrc, $target) + +Force rpmlib to re-read configuration files. If defined, $rpmrc is read. +If $target is defined, rpmlib will read config for this target. $target has +the form "CPU-VENDOR-OS". + + readconfig(); # Reread default configuration + readconfig(undef, "i386-mandrake-linux"); # Read configuration for i386 + +=head2 setverbosity($level) + +Set the rpmlib verbosity level. $level can be an integer (0 to 7) or a +verbosity level name. + + - EMERG (0) + - ALERT (1) + - CRIT (2) + - ERR (3) + - WARNING (4) + - NOTICE (5) + - INFO (6) + - DEBUG (7) + +=head2 setlogcallback(sub {}) + +Set a perl callback code for rpm logging/output system. When the callback is +set, rpm lets your code print error/information messages. The parameter passed +to the callback is a hash with log value: + C<locode> => the rpm log code (integer), + C<priority> => priority of the message (0 to 7), + C<msg> => the formated string message. + +To unset the callback function, passed an undef value as code reference. + +Ex: + setlogcallback( sub { + my %log = @_; + print "$log{priority}: $log{msg}\n"; + }); + +=head2 setlogfile(filename) + +Redirect all rpm message into this file. Data will be append to the end of the +file, the file is created if it don't already exists. The old loging file is close. + +To unset (and close) a pending loging file, passed an undef value. + +=head2 lastlogmsg + +Return an array about latest rpm log message information: + - rpm log code, + - rpm priority (0 to 7), + - string message. + +=head2 rpmlog($codelevel, $msg) + +Send a message trougth the rpmlib logging system. + - $codelevel is either an integer value between 0 and 7, or a level code string, +see setverbosity(), + - $msg is the message to send. + +=head2 format_rpmpb(@pb) + +Some functions return an array of rpm transaction problem +(RPM4::Db->transpb()), this function return an array of human readable +string for each problem. + +=head2 querytag + +Returns a hash containing the tags known by rpmlib. The hash has the form +C< TAGNAME => tagvalue >. Note that some tags are virtual and do not have +any tag value, and that some tags are alias to already existing tags, so +they have the same value. + +=head2 tagtypevalue($tagtypename) + +Return the type value of a tag type. $tagtypename can be CHAR, INT8, INT16 +INT32, STRING, ARRAY_STRING or I18NSTRING. This return value is usefull with +RPM4::Header::addtag() function. + +=head2 tagName($tagvalue) + +Returns the tag name for a given internal value. + + tagName(1000); return "NAME". + +See: L<tagValue>. + +=head2 tagValue($tagname) + +Returns the internal tag value for C<$tagname>. + + tagValue("NAME"); return 1000. + +See: L<tagName>. + +=head2 expand($string) + +Evaluate macros contained in C<$string>, like C<rpm --eval>. + + expand("%_var") return "/var". + +=head2 add_macro("_macro value") + +Define a macro into rpmlib. The macro is defined for the whole script. Ex: +C<add_macro("_macro value")>. Note that the macro name does have the prefix +"%", to prevent rpm from evaluating it. + +=head2 del_macro("_macro") + +Delete a macro from rpmlib. Exactly the reverse of add_macro(). + +=head2 loadmacrosfile($filename) + +Read a macro configuration file and load macros defined within. +Unfortunately, the function returns nothing, even when file loading failed. + +To reset macros loaded from file you have to re-read the rpm config file +with L<readconfig>. + +=head2 resetmacros + +Reset all macros defined with add_macro() functions. + +This function does not reset macros loaded with loadmacrosfile(). + +=head2 getosname + +Returns the operating system name of current rpm configuration. +Rpmlib auto-detects the system name, but you can force rpm to use +another system name with macros or using readconfig(). + +=head2 getarchname + +Returns the arch name of current rpm configuration. +Rpmlib auto-detects the architecture, but you can force rpm to use +another architecture with macros or by using readconfig(). + +=head2 buildhost + +Returns the BuildHost name of the current system, ie the value rpm will use +to set BuilHost tag in built rpm. + +=head2 dumprc(*FILE) + +Dump rpm configuration into file handle. +Ex: + dumprc(*STDOUT); + +=head2 dumpmacros(*FILE) + +Dump rpm macros into file handle. +Ex: + dumpmacros(*STDOUT); + +=head2 rpmresign($passphrase, $rpmfile) + +Resign a rpm using user settings. C<$passphrase> is the key's gpg/pgp +pass phrase. + +Return 0 on success. + +=head2 rpmvercmp(version1, version2) + +Compare two version and return 1 if left argument is highter, -1 if +rigth argument is highter, 0 if equal. +Ex: + rpmvercmp("1.1mdk", "2.1mdk"); # return -1. + +=head2 compare_evr(version1, version2) + +COmpare two rpm version in forms [epoch:]version[-release] and return +1 if left argument is highter, -1 if rigth argument is highter, 0 if +equal. +Ex: + compare_evr("1:1-1mdk", "2-2mdk"); # return 1 + +=head2 installsrpm($filename) + +Install a source rpm and return spec file path and its cookies. +Returns undef if install is impossible. + +see L<RPM4::Spec>->new() for more information about cookies. + +=head2 rpmdbinit(rootdir, permissions) + +Create an empty rpm database located into I<%{_dbpath}> (useally /var/lib/rpm). +If set, rootdir is the root directory of system where rpm db should be +create, if set, theses permissions will be applied to files, default is 0644. + +Directory I<%{_dbpath}> should exist. + +Returns 0 on success. + +Ex: + rpmdbinit(); # Create rpm database on the system + rpmdbinit("/chroot"); # Create rpm database for system located into /chroot. + +=head2 rpmdbverify($rootdir) + +Verify rpm database located into I<%{_dbpath}> (useally /var/lib/rpm). +If set, $rootdir is root directory of system to check. + +Returns 0 on success. + +=head2 rpmdbrebuild($rootdir) + +Rebuild the rpm database located into I<%{_dbpath}> (useally /var/lib/rpm). +If set, $rootdir is the root directory of system. + +Returns 0 on success. + +=head1 SEE ALSO + +L<rpm(8)>, + +This aims at replacing part of the functionality provided by URPM. + +=cut diff --git a/RPM4/lib/RPM4/Header.pm b/RPM4/lib/RPM4/Header.pm new file mode 100644 index 0000000..21f80e2 --- /dev/null +++ b/RPM4/lib/RPM4/Header.pm @@ -0,0 +1,335 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +package RPM4::Header; + +use strict; +use warnings; +use vars qw($AUTOLOAD); + +use RPM4; +use Digest::SHA1; +use Carp; + +sub new { + my ($class, $arg) = @_; + + if ($arg) { + if (ref $arg eq 'GLOB') { + return RPM4::stream2header($arg); + } elsif (-f $arg) { + return RPM4::rpm2header($arg); + } else { + croak("Invalid argument $arg"); + } + } else { + return RPM4::headernew(); + } +} + +# proxify calls to $header->tag() +sub AUTOLOAD { + my ($header) = @_; + + my $tag = $AUTOLOAD; + $tag =~ s/.*:://; + return $header->tag($tag); +} + +sub writesynthesis { + my ($header, $handle, $filestoprovides) = @_; + $handle ||= *STDOUT; + + my $sinfo = $header->synthesisinfo($filestoprovides); + + foreach my $deptag (qw(provide conflict obsolete require)) { + printf($handle '@%ss@%s'."\n", + $deptag, + join('@', @{$sinfo->{$deptag}})) if (@{$sinfo->{$deptag} || []}); + } + + printf($handle '@summary@%s'. "\n", + $sinfo->{summary}, + ); + printf($handle '@info@%s@%d@%d@%s'."\n", + $sinfo->{fullname}, + $sinfo->{epoch}, + $sinfo->{size}, + $sinfo->{group}, + ); + return 1; +} + +sub synthesisinfo { + my ($header, $filestoprovides) = @_; + my $synthinfo = { + fullname => scalar($header->fullname()), + summary => $header->tag(1004), + epoch => $header->tag(1003) || 0, + size => $header->tag(1009), + group => $header->tag(1016), + os => $header->tag('OS'), + hdrid => pack("H*",$header->tag('HDRID')), + }; + + + my @pkgfiles; + if (my $files = $header->files()) { + $files->init(); + while($files->next() >= 0) { + my $f = $files->filename(); + foreach(@{$filestoprovides}) { + $_ eq $f and do { + push @pkgfiles, "$f"; + last; + }; + } + } + } + foreach my $deptag (qw(provide conflict obsolete require)) { + my @deps; + $deptag eq 'provide' and push(@deps, @pkgfiles); + if (my $dep = $header->dep(uc($deptag . "name")) || undef) { + $dep->init(); + while ($dep->next() >= 0) { + ($dep->flags() & (1 << 24)) and next; + my @d = $dep->info(); + #$d[1] =~ /^rpmlib\(\S*\)$/ and next; + push(@deps, sprintf( + "%s%s%s", + "$d[1]", + ($dep->flags() & RPM4::flagvalue('sense', [ 'PREREQ' ])) ? '[*]' : '', + $d[2] ? '[' . ($d[2] eq '=' ? '==' : $d[2]) . " $d[3]\]" : '' )); + } + } + + { my %uniq; @uniq{@deps} = (); @deps = keys(%uniq); } + push(@{$synthinfo->{$deptag}}, @deps) if(@deps); + } + + $synthinfo; +} + +# return an array of required files +sub requiredfiles { + my ($header) = @_; + grep { m:^/: } $header->tag(1049); +} + +# is this usefull +# @keeptags can/should be reworks +sub buildlight { + my ($header, $hinfo) = @_; + + { + my @n = $hinfo->{fullname} =~ m/^(.*)-([^-]*)-([^-]*)\.([^.]*)/; + + $header->addtag(1000, 6, $n[0]); # Name + $header->addtag(1001, 6, $n[1]); # Version + $header->addtag(1002, 6, $n[2]); # Release + if ($n[3] eq 'src') { + $header->addtag(1022, 6, RPM4::getarchname()); # Arch + } else { + $header->addtag(1022, 6, $n[3]); + $header->addtag(1044, 6, "RPM4-Fake-1-1mdk.src.rpm"); + } + } + $header->addtag(1004, 6, $hinfo->{summary}); + $header->addtag(1003, 4, $hinfo->{epoch}) if ($hinfo->{epoch}); + $header->addtag(1009, 4, $hinfo->{size}); + $header->addtag(1016, 6, $hinfo->{group}); + $header->addtag("OS", 6, $hinfo->{os} ? $hinfo->{os} : RPM4::getosname()); + + foreach my $dep (qw(provide require conflict obsolete)) { + my $deptag = $dep; $deptag = uc($deptag); + foreach my $entry (@{$hinfo->{$dep} || []}) { + my ($name, $pre, $fl, $version) = $entry =~ m/([^\[]*)(\[\*\])?(?:\[(\S*)(?:\s*(\S*))?\])?/; + $fl ||= ''; + $dep eq 'provide' && substr($name, 0, 1) eq '/' and do { + $header->addtag('OLDFILENAMES', 8, $name); + next; + }; + #print "$deptag . 'NAME', 8, $name\n"; + $header->addtag($deptag . 'NAME', 8, $name); + $header->addtag($deptag . 'FLAGS', 'INT32', RPM4::flagvalue("sense", $fl || "") | ($pre ? RPM4::flagvalue("sense", [ 'PREREQ' ]) : 0)); + $header->addtag($deptag . 'VERSION', 8, $version || ""); + } + } + + if (!$hinfo->{hdrid}) { + my $sha = Digest::SHA1->new; + + foreach my $tag ($header->listtag()) { + $sha->add(join('', $header->tag($tag))); + } + + $hinfo->{hdrid} = $sha->digest; + } + + $header->addtag("HDRID", "BIN", $hinfo->{hdrid}); +} + +sub getlight { + my ($header, $reqfiles) = @_; + my $hi = RPM4::headernew(); + $hi->buildlight($header->synthesisinfo($reqfiles)); + $hi +} + +sub osscore { + my ($header) = @_; + my $os = $header->tag("OS"); + defined $os ? RPM4::osscore($os) : 1; +} + +sub archscore { + my ($header) = @_; + $header->issrc and return 0; + my $arch = $header->tag("ARCH"); + defined($arch) ? RPM4::archscore($arch) : 1; +} + +sub is_better_than { + my ($header, $h) = @_; + + if ($header->tag(1000) eq $h->tag(1000)) { + my $c = $header->compare($h); + $c != 0 and return $c; + return 1 if $header->osscore < $h->osscore; + return 1 if $header->archscore < $h->archscore; + } elsif (my $obs = $header->dep('OBSOLETENAME')) { + $obs->init(); + while ($obs->next >= 0) { + $obs->name eq $h->tag(1000) or next; + return 1 if ($obs->matchheadername($h)); + } + } + 0; +} + +sub sourcerpmname { + $_[0]->queryformat('%|SOURCERPM?{%{SOURCERPM}}:{%{NAME}-%{VERSION}-%{RELEASE}.src.rpm}|') +} + +1; + +__END__ + +=head1 NAME + +RPM4::Header + +=head1 DESCRIPTION + +The header contains informations about a rpms, this object give methods +to manipulate its. + +=head1 METHODS + +=head2 RPM4::Header->new($item) + +Create a new C<RPM4::Header> instance from: + +=over 4 + +=item a file + +if $item is an rpm file, returns the corresponding object. + +=item a file handler + +if $item is a file handler, returns an object corresponding to the next header there. + +=item nothing + +if $item is omitted, returns an empty object. + +=back + +If data are unreadable for whatever reason, returns undef. + +=head2 RPM4::Header->write(*FILE) + +Dump header data into file handle. + +Warning: Perl modifier (like PerlIO::Gzip) won't works. + +=head2 RPM4::Header->hsize() + +Returns the on-disk size of header data, in bytes. + +=head2 RPM4::Header->copy() + +Returns a RPM4::Header object copy. + +=head2 RPM4::Header->removetag(tagid) + +Remove tag 'tagid' from header. + +=head2 RPM4::Header->addtag(tagid, tagtype, value1, value2...) + +Add a tag into the header: +- tagid is the integervalue of tag +- tagtype is an integer, it identify the tag type to add (see rpmlib headers +files). Other argument are value to put in tag. + +=head2 RPM4::Header->listtag() + +Returns a list of tag id present in header. + +=head2 RPM4::Header->hastag(tagid) + +Returns true if tag 'tagid' is present in header. + +Ex: + $header->hastag(1000); # Returns true if tag 'NAME' is present. + +=head2 RPM4::Header->tagtype(tagid) + +Returns the tagtype value of tagid. Returns 0 if tagid is not found. + +=head2 RPM4::Header->tag(tagid) + +Returns array of tag value for tag 'tagid'. + + $header->tag(1000); # return the name of rpm header. + +=head2 RPM4::Header->queryformat($query) + +Make a formated query on the header, macros in I<$query> are evaluated. +This function works like C<rpm --queryformat ...> + + $header->queryformat("%{NAME}-%{VERSION}-%{RELEASE}"); + +=head2 RPM4::Header->fullname + +In scalar context return the "name-version-version.arch" of package. +In array context return (name, version, release, arch) of package. + +=head2 RPM4::Header->issrc() + +Returns true if package is a source package. + +=head2 RPM4::Header->compare(header) + +Compare the header to another, return 1 if the object is higher, -1 if +header passed as argument is better, 0 if update is not possible. + +=head1 SEE ALSO + +L<RPM4> diff --git a/RPM4/lib/RPM4/Header/Changelogs.pm b/RPM4/lib/RPM4/Header/Changelogs.pm new file mode 100644 index 0000000..be614c0 --- /dev/null +++ b/RPM4/lib/RPM4/Header/Changelogs.pm @@ -0,0 +1,73 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +package RPM4::Header::Changelogs; + +sub new { + my ($class, $header) = @_; + + my $changelogs = { + changelogtext => [ $header->tag("changelogtext") ], + changelogname => [ $header->tag("changelogname") ], + changelogtime => [ $header->tag("changelogtime") ], + _counter => -1, + }; + bless($changelogs, $class); +} + +sub init { + my ($self) = @_; + $self->{_counter} = -1; +} + +sub hasnext { + my ($self) = @_; + $self->{_counter}++; + return $self->{_counter} <= $#{$self->{changelogname}}; +} + +sub text { + my ($self) = @_; + return ${$self->{changelogtext}}[$self->{_counter}]; +} + +sub name { + my ($self) = @_; + return ${$self->{changelogname}}[$self->{_counter}]; +} + +sub time { + my ($self) = @_; + return ${$self->{changelogtime}}[$self->{_counter}]; +} + + +1; + +__END__ + +=head1 NAME + +Hdlist::Header::Changelogs - A set of changelogs + +=head1 METHODS + +=head1 SEE ALSO + +L<Hdlist> + diff --git a/RPM4/lib/RPM4/Header/Checks.pm b/RPM4/lib/RPM4/Header/Checks.pm new file mode 100644 index 0000000..0a4b0d7 --- /dev/null +++ b/RPM4/lib/RPM4/Header/Checks.pm @@ -0,0 +1,98 @@ +# $Id$ + +package RPM4::Header::Checks; + +use strict; +use warnings; + +my @tagstocheck = ( + { + tag => 'NAME', + type => 'STRING', + count => 1, + mandatory => 1, + }, + { + tag => 'VERSION', + type => 'STRING', + count => 1, + mandatory => 1, + }, + { + tag => 'RELEASE', + type => 'STRING', + count => 1, + mandatory => 1, + }, + { tag => 'EPOCH', type => 'INT32', count => 1, }, + { + tag => 'CHANGELOGTEXT', type => 'STRING_ARRAY', + countof => [ qw(CHANGELOGNAME CHANGELOGTIME) ], + }, + { tag => 'CHANGELOGNAME', type => 'STRING_ARRAY', }, + { tag => 'CHANGELOGTIME', type => 'INT32', }, + { tag => 'PACKAGER', type => 'STRING', }, + { tag => 'DISTRIBUTION', type => 'STRING', }, + { tag => 'SUMMARY', type => 'STRING', count => 1, mandatory => 1, }, + { tag => 'DESCRIPTION', type => 'STRING', count => 1, mandatory => 1, }, + +); + +sub reporterror { + printf(@_); + print "\n"; +} + +sub check { + my ($header) = @_; + foreach my $check (@tagstocheck) { + $check->{tag} or next; # buggy check + + if (!$header->hastag($check->{tag})) { + reporterror( + "tag %s not found", + $check->{tag}, + ) if($check->{mandatory}); + } elsif (defined($check->{count})) { + my @t = $header->tag($check->{tag}); + if(scalar(@t) != $check->{count}) { + reporterror( + "Wrong count for tag %s: %d, %d is expected", + $check->{tag}, + scalar(@t), + $check->{count}, + ); + } + } + + if ($check->{countof}) { + my @t = $header->tag($check->{tag}); + foreach my $co (@{$check->{countof}}) { + my @t2 = $header->tag($co); + if (scalar(@t) != scalar(@t2)) { + reporterror( + "count of tag %s is not the same than %s, %d vs %d", + $check->{tag}, + $co, + scalar(@t), + scalar(@t2), + ); + } + } + } + + $header->hastag($check->{tag}) or next; + + if ($check->{type}) { + if ($header->tagtype($check->{tag}) != RPM4::tagtypevalue($check->{type})) { + reporterror( + "Wrong tagtype for tag %s: %d, %d is expected", + $check->{tag}, + $header->tagtype($check->{tag}), + RPM4::tagtypevalue($check->{type}) + ); + } + } + } +} + diff --git a/RPM4/lib/RPM4/Header/Dependencies.pm b/RPM4/lib/RPM4/Header/Dependencies.pm new file mode 100644 index 0000000..f9a0198 --- /dev/null +++ b/RPM4/lib/RPM4/Header/Dependencies.pm @@ -0,0 +1,118 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +package RPM4::Header::Dependencies; + +sub new { + my ($class, $deptag, $initdep, @depdesc) = @_; + print "$deptag, $initdep\n"; + my $dep = RPM4::Header::Dependencies->newsingle($deptag, @$initdep) or return; + foreach (@depdesc) { + print "$_\n"; + $dep->add(@$_); + } + return $dep; +} + +1; + +__END__ + +=head1 NAME + +Hdlist::Header::Dependencies - A set of dependencies + +=head1 METHODS + +=head2 Hdlist::Header::Dependencies->new($tagtype, $dep1, [$dep2, ...]) + +Create a new arbitrary dependencies set. +$tagtype is the rpm tag {PROVIDE/REQUIRE/CONFLICT/OBSOLETE/TRIGGER}NAME. + +Next arguments are array ref for each dependancy to add in the dependencies set, +in form a name and optionnaly as sense flags and a version. + +For example: + + $d = Hdlist::Header::Dependencies->new( + "REQUIRENAME" + [ "rpm" ], + [ "rpm", 2, "4.0" ], + [ "rpm", [ qw/LESS/ ], "4.0" ] + ); + +=head2 $deps->count + +Return the number of dependencies contained by this set. + +=head2 $deps->move($index) + +Move internal index to $index (0 by default). + +=head2 $deps->init + +Reset internal index and set it to -1, see L<$deps-\\>next()> + +=head2 $deps->hasnext + +Advance to next dependency in the set. +Return FALSE if no further dependency available, TRUE otherwise. + +=head2 $deps->next + +Advance to next dependency in the set. +Return -1 if no further dependency available, next index otherwise. + +=head2 $deps->color + +Return the 'color' of the current dependency in the depencies set. + +=head2 $deps->overlap($depb) + +Compare two dependency from two dependencies set and return TRUE if match. + +=head2 $deps->info + +Return information about current dependency from dependencies set. + +=head2 $deps->tag + +Return the type of the dependencies set as a rpmtag (PROVIDENAME, REQUIRENAME, +PROVIDENAME, OBSOLETENAME of TRIGGERNAME). + +=head2 $deps->name + +Return the name of dependency from dependencies set. + +=head2 $deps->flags + +Return the sense flag of dependency from dependencies set. + +=head2 $deps->evr + +Return the version of dependency from dependencies set. + +=head2 $deps->nopromote($nopromote) + +Set or return the nopromote flags of the dependencies set. + +=head1 SEE ALSO + +L<Hdlist> +L<Hdlist::Header> + diff --git a/RPM4/lib/RPM4/Header/Files.pm b/RPM4/lib/RPM4/Header/Files.pm new file mode 100644 index 0000000..dd315d8 --- /dev/null +++ b/RPM4/lib/RPM4/Header/Files.pm @@ -0,0 +1,61 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +package RPM4::Header::Files; + +sub dircount { + $_[0]->countdir(); +} + +1; + +__END__ + +=head1 NAME + +Hdlist::Header::Files - A set of files and directories + +=head1 METHODS + +=head2 $files->count() + +Return the number of files contained by this set. + +=head2 $files->countdir() + +Return the number of directories contained by this set. + +=head2 $files->init() + +Reset internal files index and set it to -1. + +=head2 $files->initdir() + +Reset internal directories index and set it to -1. + +=head2 $deps->next() + +Set current file to the next one in the set. + +=head2 $deps->nextdir() + +Set current directory to the next one in the set. + +=head2 $files->move($index) + +Move internal file index to $index (0 by default). diff --git a/RPM4/lib/RPM4/Index.pm b/RPM4/lib/RPM4/Index.pm new file mode 100644 index 0000000..c94d0aa --- /dev/null +++ b/RPM4/lib/RPM4/Index.pm @@ -0,0 +1,163 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +package RPM4::Index; + +use strict; +use warnings; + +use RPM4; +use RPM4::Header; +use Packdrakeng; + +use File::Temp qw(tempfile); + +sub buildindex { + my (%options) = @_; + + my ($pid, $pack, $h_synthesis, $h_list); + if ($options{synthesis}) { + $pid = open($h_synthesis, "| gzip --best > '$options{synthesis}'") or return 0; + } + if ($options{hdlist}) { + $pack = Packdrakeng->new( + archive => $options{hdlist}, + comp_level => $options{complevel}, + ) or return 0; + } + if ($options{list}) { + open($h_list, ">", $options{list}) or return 0; + } + + RPM4::parserpms( + rpms => $options{rpms}, + callback => sub { + my (%res) = @_; + if(defined($options{callback})) { + $options{callback}->(%res) or return; + } + defined($res{header}) or return; + + if ($options{synthesis}) { + $res{header}->writesynthesis($h_synthesis, $options{filestoprovides}); + } + + if ($options{hdlist}) { + $res{header} or return; + # Hacking perl-URPM + my $h = $res{header}->copy(); # Get a copy to not alter original header + $h->addtag(1000000, 6, scalar($res{header}->fullname()) . '.rpm'); + $h->addtag(1000001, 4, (stat("$res{dir}$res{rpm}"))[7]); + my $fh = new File::Temp( UNLINK => 1, SUFFIX => '.header'); + $h->write($fh); + sysseek($fh, 0, 0); + $pack->add_virtual('f', scalar($res{header}->fullname()), $fh); + close($fh); + } + + if ($options{list}) { + print $h_list "$res{rpm}\n"; + } + + }, + checkrpms => $options{checkrpms}, + path => $options{path}, + + ); + + if ($options{synthesis}) { + close($h_synthesis); + waitpid $pid, 0; + } + + if($options{list}) { + close($h_list); + } + 1; +} + +sub buildsynthesis { + my (%options) = @_; + buildindex(%options); +} + +# Build only an hdlist file +sub buildhdlist { + my (%options) = @_; + buildindex(%options); +} + +sub parsehdlist { + my (%options) = @_; + my $pack = Packdrakeng->open(archive => $options{hdlist}) or return 0; + + my (undef, $files, undef) = $pack->getcontent(); + pipe(my $in, my $out); + if (my $pid = fork()) { + close($out); + stream2header($in, 0, sub { + #printf STDERR $header->fullname ."\n"; + $options{callback}->( + header => $_[0], + ); + }); + close($in); + waitpid($pid, 0); + } else { + close($in); + foreach my $h (@{$options{files} || $files || []}) { + $pack->extract_virtual($out, $h) >= 0 or die; + } + close($out); + exit; + } + 1; +} + +sub parsesynthesis { + my (%options) = @_; + + open(my $h, "cat '$options{synthesis}' | gunzip |") or return 0; + + my %hinfo = (); + while (my $line = <$h>) { + chomp($line); + my (undef, $type, $info) = split('@', $line, 3); + my @infos = split('@', $info); + if ($type =~ m/^(provides|requires|conflict|obsoletes)$/) { + @{$hinfo{$type}} = @infos; + } elsif ($type eq 'summary') { + $hinfo{summary} = $info; + } elsif ($type eq 'info') { + @hinfo{qw(fullname epoch size group)} = @infos; + + my $header = RPM4::headernew(); + $header->buildlight(\%hinfo); + $options{callback}->( + header => $header, + ); + + %hinfo = (); + } else { + } + } + close($h); + 1; +} + +1; diff --git a/RPM4/lib/RPM4/Media.pm b/RPM4/lib/RPM4/Media.pm new file mode 100644 index 0000000..5096e2b --- /dev/null +++ b/RPM4/lib/RPM4/Media.pm @@ -0,0 +1,193 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +package RPM4::Media; + +use strict; +use RPM4::Index; +use RPM4::Header; + +# $options = { +# prefixurl if need, ie real rpms locations +# type => rpms, hdlist, headers +# source => $ (hdlist,dir) or @ (rpms, headers) +sub new { + my ($class, %options) = @_; + my $media = { + hdlist => undef, + synthesis => undef, + list => 'list', + rpmsdir => undef, + + rpms => [], + + rpmn2path => {}, + id2path => {}, + + info => undef, + + hdr => [], + + use_light_header => 1, + }; + + foreach (keys %$media) { + defined($options{$_}) and $media->{$_} = $options{$_}; + } + + bless($media, $class); +} + +sub init { + my ($self, $callback) = @_; + + $self->{hdr} = []; + $self->{hdrid} = []; + my %reqfiles; + $self->{selectedhdrid} = {}; + $self->{reqfiles} = []; + + $callback ||= sub { + my (%arg) = @_; + @reqfiles{$arg{header}->requiredfiles()} = (); + 1; + }; + + if (defined(my $synthesis = $self->get_indexfile('synthesis'))) { + RPM4::Index::parsesynthesis( + synthesis => $synthesis, + callback => sub { + my %arg = @_; + $callback->(%arg) or return; + push(@{$self->{hdr}}, $arg{header}); + }, + ); + } elsif (defined(my $hdlist = $self->get_indexfile('hdlist'))) { + RPM4::Index::parsehdlist( + hdlist => $hdlist, + callback => sub { + my %arg = @_; + $callback->(%arg) or return; + $self->{selectedhdrid}{$arg{header}->tag('HDRID')} = 1; + }, + ); + } elsif (defined($self->{rpms})) { + my @rpms = grep { defined($_) } map { $self->get_rpm($_) } @{$self->{rpms}}; + RPM4::parserpms( + rpms => \@rpms, + callback => sub { + my %arg = @_; + $callback->(%arg) or return; + $self->{selectedhdrid}{$arg{header}->tag('HDRID')} = 1; + }, + ); + } + $self->{reqfiles} = [ keys %reqfiles ]; +} + +sub load { + my ($self, $reqfiles) = @_; + $reqfiles ||= $self->{reqfiles}; + + if (defined($self->get_indexfile('synthesis'))) { + # populate is done during first pass + } elsif (defined(my $hdlist = $self->get_indexfile('hdlist'))) { + RPM4::Index::parsehdlist( + hdlist => $hdlist, + callback => sub { + my %arg = @_; + $self->{selectedhdrid}{$arg{header}->tag('HDRID')} or return; + if ($self->{use_light_header}) { + my $h = $arg{header}->getlight($reqfiles); + push(@{$self->{hdr}}, $h); + } else { + push(@{$self->{hdr}}, $arg{header}); + } + }, + ); + } elsif (defined($self->{rpms})) { + my @rpms = grep { defined($_) } map { $self->get_rpm($_) } @{$self->{rpms}}; + RPM4::parserpms( + rpms => \@rpms, + callback => sub { + my %arg = @_; + $self->{selectedhdrid}{$arg{header}->tag('HDRID')} or return; + if ($self->{use_light_header}) { + my $h = $arg{header}->getlight($reqfiles); + push(@{$self->{hdr}}, $h); + } else { + push(@{$self->{hdr}}, $arg{header}); + } + $self->{id2path}{$#{$self->{hdr}}} = $arg{rpm}; + }, + ); + } + delete($self->{reqfiles}); + delete($self->{selectedhdrid}); + + if (my $listf = $self->get_indexfile('list')) { + if (open(my $lh, "<", $listf)) { + while (my $line = <$lh>) { + chomp($line); + my ($fullname) = $line =~ m,^(?:.*/)?(.*)\.rpm$,; + $self->{rpmn2path}{$fullname} = $line; + } + close($lh); + } + } +} + +sub traverse { + my ($self, $callback) = @_; + + foreach my $id (0 .. $#{$self->{hdr} || []}) { + my $header = $self->{hdr}[$id]; + $callback->($header, $id) or return; + } +} + +sub get_header { + my ($self, $id) = @_; + return $self->{hdr}[$id]; +} + +sub get_indexfile { + my ($self, $file) = @_; + defined($self->{$file}) or return undef; + my $f = + (substr($self->{$file}, 0, 1) ne '/' && defined($self->{rpmsdir}) ? "$self->{rpmsdir}/" : "") . + $self->{$file}; + -e $f ? $f : undef; +} + +sub id2rpm { + my ($self, $id) = @_; + my $rpm = $self->get_header($id)->fullname; + return exists($self->{rpmn2path}{$rpm}) ? $self->{rpmn2path}{$rpm} : + (exists($self->{id2path}{$id}) ? $self->{id2path}{$id} : "$rpm.rpm"); +} + +sub get_rpm { + my ($self, $rpm) = @_; + my $file = + (substr($rpm, 0, 1) ne '/' && defined($self->{rpmsdir}) ? "$self->{rpmsdir}/" : "") . + $rpm; + -e $file ? $file : undef; +} + +1; diff --git a/RPM4/lib/RPM4/Spec.pm b/RPM4/lib/RPM4/Spec.pm new file mode 100644 index 0000000..d6c5b29 --- /dev/null +++ b/RPM4/lib/RPM4/Spec.pm @@ -0,0 +1,195 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +package RPM4::Spec; + +use strict; +use warnings; + +use RPM4; +use RPM4::Transaction::Problems; + +sub rpmbuild { + my ($spec, $flags, %options) = @_; + + $options{db} ||= RPM4::newdb(); + + my ($f) = $flags =~ /^(?:-)?b([pcibas])/; + $f or die "Unknown build options '$flags', should be b[pciabs]\n"; + my @buildflags; + for (qw/p c i/) { + $options{shortcircuit} && $f ne $_ and next; + /^p$/ and push (@buildflags, "PREP"); + /^c$/ and push (@buildflags, "BUILD"); + /^l$/ and push (@buildflags, "FILECHECK"); + /^i$/ and push (@buildflags, qw/INSTALL CHECK/); + $f eq $_ and last; + } + for ($f) { + /^a$/ and push(@buildflags, qw/PACKAGESOURCE PACKAGEBINARY/); + /^b$/ and push(@buildflags, qw/PACKAGEBINARY/); + /^s$/ and push(@buildflags, qw/PACKAGESOURCE/); + } + $options{clean} and push(@buildflags, qw/RMBUILD RMSOURCE/); + $options{rmspec} and push(@buildflags, qw/RMSPEC/); + + + if (!$options{nodeps}) { + my $sh = $spec->srcheader() or die "Can't get source header from spec object"; # Can't happend + $options{db}->transadd($sh, "", 0); + $options{db}->transcheck; + my $pbs = RPM4::Transaction::Problems->new($options{db}); + $options{db}->transreset(); + if ($pbs) { + $pbs->print_all(\*STDERR); + return 1; + } + } + return $options{db}->specbuild($spec, [ @buildflags ]); +} + +1; + +__END__ + +=head1 NAME + +RPM4::Spec + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +Extend method availlable on RPM4::Spec objects + +=head1 METHODS + +=head2 new(file, var => value, ...) + +Create a C<RPM4::Spec> instance, only the file values is mandatory. + +=over 4 + +=item file + +The spec file from wich to create the object + +=item passphrase + +If specified, the passphrase will be used for gpg signing after build. + +=item rootdir + +If specified, root dir will be use root instead '/'. + +=item cookies + +the cookies is string rpm will put into RPMCOOKIES tag, a way to know if a rpm +has been built from a specific src. You get this value from L<installsrpm>. + +=item anyarch + +If set, you'll get a spec object even the spec can't be build on the +current %_target_cpu. Notice if you set this value, starting a build over +the spec object will works ! + +=item force + +Normally, source analyze is done during spec parsing, getting a spec object +failed if a source file is missing, else you set force value. + +TAKE CARE: if force is set, rpm will not check source type, so patch will NOT +be gunzip/bunzip... If you want to compile the spec, don't set it to 1, if you +just want run clean/packagesource stage, setting force to 1 is ok. + +=back + +By default anyarch and force are set to 0. + +=head2 RPM4::Spec->srcheader() + +Returns a RPM4::Header object like source rpm will be. +Please notice that the header is not finish and header information you'll +get can be incomplete, it depend if you call the function before or after +RPM4::Spec->build(). + +=head2 RPM4::Spec->srcrpm() + +Returns the source filename spec file will build. The function take care +about rpmlib configuration (build dir path). + +=head2 RPM4::Spec->binrpm() + +Returns files names of binaries rpms that spec will build. The function take +care about rpmlib configuration (build dir path). + +=head2 RPM4::Spec->build([ @actions ]) + +Run build process on spec file. +Each value in @actions is one or more actions to do: + + - PACKAGESOURCE: build source package, + - PREP: run prep stage, + - BUILD: run build stage, + - INSTALL: run install stage, + - CHECK: check installed files, + - FILECHECK: check installed files, + - PACKAGEBINARY: build binaries packages, + - CLEAN: run clean stage, + - RMSPEC: delete spec file, + - RMSOURCE: delete sources files, + - RMBUILD: delete build files, + +=head2 rpmbuild($flags, %options) + +Build a spec using rpm same rpm options. + +$flags should be -b[abspci] + +%options is a list of optionnal options: + +=over 4 + +=item db + +reuse an already existing RPM4::Db object (else a new one is created) + +=item clean + +if set, clean source and build tre (like rpmbuild --clean + +=item rmspec + +if set, delete the spec after build (like rpmbuild --rmspec) + +=item nodeps + +If set, don't check dependancies before build + +=item shortcircuit + +if set, run only the build stage asked, not all preceding (like rpmbuild +--short-circuit) + +=back + +=head1 SEE ALSO + +L<RPM4> + +=cut diff --git a/RPM4/lib/RPM4/Transaction.pm b/RPM4/lib/RPM4/Transaction.pm new file mode 100644 index 0000000..a62be4d --- /dev/null +++ b/RPM4/lib/RPM4/Transaction.pm @@ -0,0 +1,195 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +use strict; +use warnings; +use RPM4::Transaction::Problems; + +package RPM4::Transaction; + +sub newspec { + my ($self, $filename, %options) = @_; + $options{transaction} = $self; + RPM4::Spec->new( + $filename, + %options + ); +} + +sub transpbs { + my ($self) = @_; + return RPM4::Transaction::Problems->new($self); +} + +1; + +__END__ + +=head1 NAME + +Hdlist::Db + +=head1 DESCRIPTION + +This object allow to access to the rpm datadase and installing rpms on the +system. + +=head1 METHODS + +=head2 Hdlist::Db->traverse_headers(sub) + +Go through the rpm database and for each header run the callback passed as +argument. + +Argument passed to the callback function is the current header as a Hdlist::Header object. + +Ex: + $db->traverse_headers( sub { + my ($h) = @_; + print $h->queryformat("%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}"); + }); + + +=head2 Hdlist::Db->injectheader($header) + +Add the header into rpmdb. This is not installing a package, the function +only fill information into the rpmdb. + +Return 0 on success. + +=head2 Hdlist::Db->deleteheader($index) + +Remove header from rpmdb locate at $index. This is not uninstalling a package, +this function only delete information from rpmdb. + +Return 0 on success + +=head2 Hdlist::Db->transadd(header, filename, upgrade, relocation, force) + +Add rpm headers for next transaction. This means this rpm are going to be +installed on the system. + +- header is an Hdlist::Header object, + +- filename, if given, is the rpm file you want to install, and should +of course match the header, + +- upgrade is a boolean flag to indicate whether the rpm is going to be upgraded +(1 by default). + +Returns 0 on success. + +See: $Hdlist::Db->transcheck(), $Hdlist::Db->transrun(). + +=head2 Hdlist::Db->transremove(rpm_name) + +Add rpm to remove for next transaction. This mean the rpm will be uninstalled +from the system. + +Argument is the exact rpm name (%{NAME}) or a string as NAME(EPOCH:VERSION-RELEASE). + +Returns the number of selected rpms for this transaction. + +=head2 Hdlist::Db->transcheck() + +Check current transaction is possible. + +Returns 0 on success, 1 on error during check. + +=head2 Hdlist::Db->transorder() + +Call to rpmlib to order the transaction, aka sort rpm installation / +desintallation. + +Returns 0 on success. + +=head2 Hdlist::Db->transpb + +Return an array of problem found during L<Hdlist::Db->transcheck> or +L<Hdlist::Db->transrun> + +=head2 Hdlist::Db->transrun($callback, $flags...) + +Really run transaction and install/uninstall packages. + +$callback can be: + +- undef value, let rpm show progression with some default value. + +- array ref: each value represent a rpm command line options: + + PERCENT: show percentage of progress (--percent) + HASH: print '#' during progression (--hash) + LABEL: show rpm name (--verbose) + +- code ref: rpm is fully silent, the perl sub is called instead. Arguments +passed to the subroutine are in a hash: + + filename => opened filename + header => current header in transaction + what => current transaction process + amount => amount of transaction + total => number of transaction to do + +flags: list of flags to set for transaction (see rpm man page): + +I<From rpm Transaction flag>: + + - NOSCRIPTS: --noscripts + - JUSTDB: --justdb + - NOTRIGGERS: --notriggers + - NODOCS: --excludedocs + - ALLFILES: --allfiles + - DIRSTASH: --dirstash + - REPACKAGE: --repackage + - NOTRIGGERPREIN: --notriggerprein + - NOPRE: --nopre + - NOPOST: --nopost + - NOTRIGGERIN: --notriggerin + - NOTRIGGERUN: --notriggerun + - NOPREUN: --nopreun + - NOPOSTUN: --nopostun + - NOTRIGGERPOSTUN: --notriggerpostun + - NOSUGGEST: --nosuggest + - NOMD5: --nomd5 + - ADDINDEPS: --aid + - noscripts: Do not running any scripts, neither triggers + +I<From rpm prob filter> + + - IGNOREOS: --ignoreos + - IGNOREARCH: --ignorearch + - REPLACEPKG: --replacepkgs + - REPLACENEWFILES: --replacefiles + - REPLACEOLDFILES: --replacefiles + - OLDPACKAGES: --oldpackage + - DISKSPACE: --ignoresize + - DISKNODE: --ignoresize + +Returns 0 on success. + +=head2 $db->transpbs + +Return a Hdlist::Db::Problems object containing problem found during +rpms installation/desinstallation. + +See L<Hdlist::Db::Problems> + +=head1 SEE ALSO + +L<Hdlist> diff --git a/RPM4/lib/RPM4/Transaction/Problems.pm b/RPM4/lib/RPM4/Transaction/Problems.pm new file mode 100644 index 0000000..0266c7f --- /dev/null +++ b/RPM4/lib/RPM4/Transaction/Problems.pm @@ -0,0 +1,115 @@ +##- Nanar <nanardon@mandrake.org> +##- +##- This program is free software; you can redistribute it and/or modify +##- it under the terms of the GNU General Public License as published by +##- the Free Software Foundation; either version 2, or (at your option) +##- any later version. +##- +##- This program is distributed in the hope that it will be useful, +##- but WITHOUT ANY WARRANTY; without even the implied warranty of +##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +##- GNU General Public License for more details. +##- +##- You should have received a copy of the GNU General Public License +##- along with this program; if not, write to the Free Software +##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +use strict; +use warnings; + +use RPM4; +use RPM4::Transaction; + +package RPM4::Transaction::Problems; + +sub new { + my ($class, $ts) = @_; + my $pbs = { + _problems => $ts->_transpbs() || undef, + _counter => -1, + }; + + $pbs->{_problems} or return undef; + bless($pbs, $class); +} + +sub count { + my ($self) = @_; + return $self->{_problems}->count(); +} + +sub init { + my ($self) = @_; + $self->{_counter} = -1; +} + +sub hasnext { + my ($self) = @_; + return ++$self->{_counter} < $self->{_problems}->count(); +} + +sub problem { + my ($self) = @_; + return $self->{_problems}->fmtpb($self->{_counter}); +} + +sub is_ignore { + my ($self) = @_; + return $self->{_problems}->isignore($self->{_counter}); +} + +sub print_all { + my ($self, $handle) = @_; + $handle ||= *STDOUT; + $self->{_problems}->print($handle); +} + +1; + +__END__ + +=head1 NAME + +RPM4::Transaction::Problems + +RPM4::Transaction + +=head1 DESCRIPTION + +This module an object for a collection of problems return by the rpmlib +when trying to install or removing rpms from the system. + +=head1 METHODS + +=head2 new(ts) + +Create a new problems collection from transaction. Return undef if now +problems has been found in the transaction. + +=head2 $pbs->init + +Reset internal index and set it to -1, see L<$deps-\\>hasnext()> + +=head2 $pbs->hasnext + +Advance to next dependency in the set. +Return FALSE if no further problem availlable, TRUE otherwise. + +=head2 $pbs->problem + +Return a format string about current problem in the set + +=head2 $pbs->is_ignore + +Return True if the problem should be ignored + +=head2 $pbs->print_all($handle) + +Print all error problems into the given handle, STDOUT if not specified. + +=head1 SEE ALSO + +L<RPM4> +L<RPM4::Db> diff --git a/RPM4/patches/Makefile.PL.staticrpm.patch b/RPM4/patches/Makefile.PL.staticrpm.patch new file mode 100644 index 0000000..e63fcc0 --- /dev/null +++ b/RPM4/patches/Makefile.PL.staticrpm.patch @@ -0,0 +1,17 @@ +Index: src/Makefile.PL +=================================================================== +RCS file: /cooker/soft/perl-Hdlist/src/Makefile.PL,v +retrieving revision 1.1 +diff -r1.1 Makefile.PL +5a6,8 +> my $staticrpm = join(' ', map { "$_" } glob ("librpm/*.a")); +> print "$staticrpm\n"; +> +9c12 +< OBJECT => 'Hdlist.o Hdlistsign.o', +--- +> OBJECT => 'Hdlist.o Hdlistsign.o $staticrpm', +12c15 +< LIBS => '-lrpm -lrpmio -lrpmdb -lrpmbuild -lpopt -lz -lbz2 -lrpmconstant', +--- +> LIBS => '-lrpm -lpopt -lz -lbz2 -lrpmconstant', diff --git a/RPM4/src/Makefile.PL b/RPM4/src/Makefile.PL new file mode 100644 index 0000000..9b9a60f --- /dev/null +++ b/RPM4/src/Makefile.PL @@ -0,0 +1,48 @@ +# $Id$ + +# use 5.008; +use ExtUtils::MakeMaker; + +my ($obj, $ldd, $fl) = + -f '/usr/include/rpmconstant/rpmconstant.h' ? + ('', '-lrpmconstant', '-DHAVE_RPMCONSTANT') : + ('rpmconstant.o rpmconstant_internal.o rpmconstanttbl.o', '', ''); + +sub MY::postamble { + my $first = <<RPMCONSTTBL; + +rpmconstanttbl.c: Makefile rpmh2tbl + perl rpmh2tbl /usr/include/rpm/*.h > \$@ +RPMCONSTTBL + # This code is to reduce duplication of files + # in fact it is only usefull for the maintainers of this module + # if you get the module from CPAN, those files are allready here + # if you're building from svn, you need rpmconstant directory + my $second = ""; + if(-d '../../rpmconstant') { + $second = <<RPMCONST +rpmconstant.c: ../../rpmconstant/rpmconstant.c + cp -a \$< \$@ + +rpmconstant.h: ../../rpmconstant/rpmconstant.h + cp -a \$< \$@ + +rpmconstant_internal.c: ../../rpmconstant/rpmconstant_internal.c + cp -a \$< \$@ + +rpmh2tbl: ../../rpmconstant/rpmh2tbl + cp -a \$< \$@ +RPMCONST + } + + $first . $second +} + +WriteMakefile( + NAME => 'RPM4', + VERSION_FROM => '../lib/RPM4.pm', + OBJECT => "RPM4.o RPM4sign.o $obj", + INC => '-I/usr/include/rpm', + LIBS => "-lrpm -lrpmio -lrpmdb -lrpmbuild -lpopt -lz -lbz2 $ldd", + 'CCFLAGS' => $fl, +); diff --git a/RPM4/src/RPM4.h b/RPM4/src/RPM4.h new file mode 100644 index 0000000..fcad6b0 --- /dev/null +++ b/RPM4/src/RPM4.h @@ -0,0 +1,119 @@ +/* $Id$ */ + +#ifndef _HDLIST_H +#define _HDLIST_H + +#include "header.h" + +/* Hdlistsign.c: imported but modified functions */ + +int rpmsign(char *passphrase, const char *rpm); + +int rpmchecksig(rpmts ts, const char * filename, int flags); + +/* rpmlib does not export some usefull functions + * We Import its here + * This File should be the last included */ + +/* From rpmlead.h */ + +#ifndef _H_RPMLEAD + +rpmRC writeLead(FD_t fd, const struct rpmlead *lead); +rpmRC readLead(FD_t fd, struct rpmlead *lead); + +#endif /* _H_RPMLEAD */ + +/* From signature.h */ + +#ifndef H_SIGNATURE + +typedef enum sigType_e { + RPMSIGTYPE_HEADERSIG= 5 +} sigType; + +typedef enum pgpVersion_e { + PGP_NOTDETECTED = -1, + PGP_UNKNOWN = 0, + PGP_2 = 2, + PGP_5 = 5 +} pgpVersion; + +Header rpmNewSignature(void); + +rpmRC rpmReadSignature(FD_t fd, Header *sighp, + sigType sig_type, const char ** msg); + +int rpmWriteSignature(FD_t fd, Header h); + +int rpmAddSignature(Header sig, const char * file, + int_32 sigTag, const char * passPhrase); + +#define RPMLOOKUPSIG_QUERY 0 /*!< Lookup type in effect */ +#define RPMLOOKUPSIG_DISABLE 1 /*!< Disable (--sign was not given) */ +#define RPMLOOKUPSIG_ENABLE 2 /*!< Re-enable %_signature */ + +int rpmLookupSignatureType(int action); + +char * rpmGetPassPhrase(const char * prompt, + const int sigTag); + +const char * rpmDetectPGPVersion(pgpVersion * pgpVer); + +#endif /* H_SIGNATURE */ + +#ifndef H_HEADER_INTERNAL + +#ifdef HD_HEADER_INTERNAL +/** \ingroup header + * Description of tag data. + */ +typedef /*@abstract@*/ struct entryInfo_s * entryInfo; +struct entryInfo_s { + int_32 tag; /*!< Tag identifier. */ + int_32 type; /*!< Tag data type. */ + int_32 offset; /*!< Offset into data segment (ondisk only). */ + int_32 count; /*!< Number of tag elements. */ +}; + +/** \ingroup header + * A single tag from a Header. + */ +typedef /*@abstract@*/ struct indexEntry_s * indexEntry; +struct indexEntry_s { + struct entryInfo_s info; /*!< Description of tag data. */ +/*@owned@*/ + void * data; /*!< Location of tag data. */ + int length; /*!< No. bytes of data. */ + int rdlen; /*!< No. bytes of data in region. */ +}; + +struct headerToken_s { + /*@unused@*/ + struct HV_s hv; /*!< Header public methods. */ + /*@only@*/ /*@null@*/ + void * blob; /*!< Header region blob. */ + /*@owned@*/ + indexEntry index; /*!< Array of tags. */ + int indexUsed; /*!< Current size of tag array. */ + int indexAlloced; /*!< Allocated size of tag array. */ + int flags; +#define HEADERFLAG_SORTED (1 << 0) /*!< Are header entries sorted? */ +#define HEADERFLAG_ALLOCATED (1 << 1) /*!< Is 1st header region allocated? */ +#define HEADERFLAG_LEGACY (1 << 2) /*!< Header came from legacy source? */ +#define HEADERFLAG_DEBUG (1 << 3) /*!< Debug this header? */ + /*@refs@*/ + int nrefs; /*!< Reference count. */ +}; +#endif + +#endif /* H_HEADER_INTERNAL */ + +#ifndef H_LEGACY + +void compressFilelist(Header h); +void expandFilelist(Header h); + +#endif /* H_LEGACY */ + +#endif diff --git a/RPM4/src/RPM4.xs b/RPM4/src/RPM4.xs new file mode 100644 index 0000000..77198e7 --- /dev/null +++ b/RPM4/src/RPM4.xs @@ -0,0 +1,2832 @@ +/* Nanar <nanardon@mandrake.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* $Id$ */ + +/* PREPROSSEUR FLAGS + * HHACK: if defined, activate some functions or behaviour for expert user who + * want hacking purpose in their perl code + * HDLISTDEBUG: activate some debug code + * HDRPMDEBUG: activate rpm debug internals flags + * HDRPMMEM: print message about Free()/New on rpm + * HDEBUG: active all debug flags + */ + +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#undef Fflush +#undef Mkdir +#undef Stat + +/* copy data into rpm or use the header */ +#define O_SCAREMEM 1 /* If returning perl object */ +#define SCAREMEM 1 + +/* Pre processor flags for debugging purpose */ + +#ifdef HDEBUG + #undef HDLISTDEBUG + #define HDLISTDEBUG + #undef HDRPMDEBUG + #define HDRPMDEBUG + #undef HDRPMMEM + #define HDRPMMEM +#endif + +#ifdef HDRPMMEM + #define PRINTF_FREE(o, a, r) fprintf(stderr, "HDEBUG FREE: %s[%p], %d at %s:%d\n", (o), (a), (r), CopFILE(PL_curcop), CopLINE(PL_curcop)) + #define PRINTF_NEW(o, a, r) fprintf(stderr, "HDEBUG NEW : %s[%p], %d at %s:%d\n", (o), (a), (r), CopFILE(PL_curcop), CopLINE(PL_curcop)) +#endif + +#ifdef HDLISTDEBUG + #define PRINTF_CALL fprintf(stderr, "HDEBUG RUN: %s() at %s:%d\n", __FUNCTION__, CopFILE(PL_curcop), CopLINE(PL_curcop)) +#endif + +#if defined(HDRPMMEM) || defined(HDRPMDEBUG) + #define _RPMDS_INTERNAL + #define _RPMFI_INTERNAL + #define _RPMTS_INTERNAL + #define HD_HEADER_INTERNAL +#endif + +#include <rpm/header.h> +#include <rpm/rpmio.h> +#include <rpm/rpmdb.h> +#include <rpm/rpmts.h> +#include <rpm/rpmte.h> +#include <rpm/rpmps.h> +#include <rpm/rpmds.h> +#include <rpm/rpmfi.h> +#include <rpm/rpmpgp.h> +#include <rpm/misc.h> +#include <rpm/rpmbuild.h> +#include <rpm/rpmlib.h> +#include <rpm/rpmpgp.h> + +#ifdef HAVE_RPMCONSTANT +#include <rpmconstant/rpmconstant.h> +#else +#include "rpmconstant.h" +#endif + +#include "RPM4.h" + +static unsigned char header_magic[8] = { + 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00 +}; + +#define CHECK_RPMDS_IX(dep) if (rpmdsIx((dep)) < 0) croak("You call RPM4::Header::Dependencies method after lastest next() of before init()") + +#define bless_rpmds "RPM4::Header::Dependencies" +#define bless_rpmps "RPM4::Db::_Problems" +#define bless_rpmts "RPM4::Transaction" +#define bless_header "RPM4::Header" +#define bless_rpmfi "RPM4::Header::Files" +#define bless_spec "RPM4::Spec" + +/* The perl callback for output err messages */ +SV * log_callback_function = NULL; + +static int scalar2constant(SV * svconstant, const char * context, int * val) { + int rc = 0; + if (!svconstant || !SvOK(svconstant)) { + warn("Use of an undefined value"); + return 0; + } else if (SvIOK(svconstant)) { + *val = SvIV(svconstant); + rc = 1; + } else if (SvPOK(svconstant)) { + rc = rpmconstantFindName((char *)context, (void *) SvPV_nolen(svconstant), val, 0); + } else { + } + return rc; +} + +static int sv2constant(SV * svconstant, const char * context) { + AV * avparam; + int val = 0; + SV **tmpsv; + int i; + if (svconstant == NULL) { + return 0; + } else if (!SvOK(svconstant)) { + return 0; + } else if (SvPOK(svconstant) || SvIOK(svconstant)) { + if (!scalar2constant(svconstant, context, &val)) + warn("Unknow value '%s' in '%s'", SvPV_nolen(svconstant), context); + } else if (SvTYPE(SvRV(svconstant)) == SVt_PVAV) { + avparam = (AV*) SvRV(svconstant); + for (i = 0; i <= av_len(avparam); i++) { + tmpsv = av_fetch(avparam, i, 0); + if (!scalar2constant(*tmpsv, context, &val)) + warn("Unknow value '%s' in '%s' from array", SvPV_nolen(*tmpsv), context); + } + } else { + } + return val; +} + +/* Parse SV arg and return assossiated RPMLOG value */ +#define sv2loglevel(sv) sv2constant((sv), "rpmlog") + +#define sv2deptag(sv) sv2constant((sv), "rpmtag") + +/* compatibility */ +#define sv2sens(sv) sv2senseflags(sv) + +#define sv2vsflags(sv) sv2constant((sv), "rpmvsflags") + +#define sv2transflags(sv) sv2constant((sv), "rpmtransflags") + +static rpmTag sv2dbquerytag(SV * sv_tag) { + int val = 0; + if (!scalar2constant(sv_tag, "rpmdbi", &val) && !scalar2constant(sv_tag, "rpmtag", &val)) + croak("unknown tag value '%s'", SvPV_nolen(sv_tag)); + return val; +} + +#define sv2rpmbuildflags(sv) sv2constant((sv), "rpmbuildflags") + +#define sv2fileattr(sv) sv2constant((sv), "rpmfileattrs") + +#define sv2senseflags(sv) sv2constant((sv), "rpmsenseflags") + +#define sv2tagtype(sv) sv2constant((sv), "rpmtagtype") + +/* This function replace the standard rpmShowProgress callback + * during transaction to allow perl callback */ + +void * transCallback(const void *h, + const rpmCallbackType what, + const unsigned long amount, + const unsigned long total, + const void * pkgKey, + void * data) { + + /* The call back is used to open/close file, so we fix value, run the perl callback + * and let rpmShowProgress from rpm rpmlib doing its job. + * This unsure we'll not have to follow rpm code at each change. */ + const char * filename = (const char *)pkgKey; + const char * s_what = NULL; + dSP; + +#ifdef HDLISTDEBUG + fprintf(stderr, "HDEBUG: RPM4: running Callback transCallback()"); +#endif + + PUSHMARK(SP); + + switch (what) { + case RPMCALLBACK_UNKNOWN: + s_what = "UNKNOWN"; + break; + case RPMCALLBACK_INST_OPEN_FILE: + if (filename != NULL && filename[0] != '\0') { + XPUSHs(sv_2mortal(newSVpv("filename", 0))); + XPUSHs(sv_2mortal(newSVpv(filename, 0))); + } + s_what = "INST_OPEN_FILE"; + break; + case RPMCALLBACK_INST_CLOSE_FILE: + s_what = "INST_CLOSE_FILE"; + break; + case RPMCALLBACK_INST_PROGRESS: + s_what = "INST_PROGRESS"; + break; + case RPMCALLBACK_INST_START: + s_what = "INST_START"; + if (h) { + XPUSHs(sv_2mortal(newSVpv("header", 0))); + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, &h))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_header, &h, -1); +#endif + } + break; + case RPMCALLBACK_TRANS_PROGRESS: + s_what = "TRANS_PROGRESS"; + break; + case RPMCALLBACK_TRANS_START: + s_what = "TRANS_START"; + break; + case RPMCALLBACK_TRANS_STOP: + s_what = "TRANS_STOP"; + break; + case RPMCALLBACK_UNINST_PROGRESS: + s_what = "UNINST_PROGRESS"; + break; + case RPMCALLBACK_UNINST_START: + s_what = "UNINST_START"; + break; + case RPMCALLBACK_UNINST_STOP: + s_what = "UNINST_STOP"; + break; + case RPMCALLBACK_REPACKAGE_PROGRESS: + s_what = "REPACKAGE_PROGRESS"; + break; + case RPMCALLBACK_REPACKAGE_START: + s_what = "REPACKAGE_START"; + break; + case RPMCALLBACK_REPACKAGE_STOP: + s_what = "REPACKAGE_STOP"; + break; + case RPMCALLBACK_UNPACK_ERROR: + s_what = "UNPACKAGE_ERROR"; + break; + case RPMCALLBACK_CPIO_ERROR: + s_what = "CPIO_ERROR"; + break; + } + + XPUSHs(sv_2mortal(newSVpv("what", 0))); + XPUSHs(sv_2mortal(newSVpv(s_what, 0))); + XPUSHs(sv_2mortal(newSVpv("amount", 0))); + XPUSHs(sv_2mortal(newSViv(amount))); + XPUSHs(sv_2mortal(newSVpv("total", 0))); + XPUSHs(sv_2mortal(newSViv(total))); + PUTBACK; + call_sv((SV *) data, G_DISCARD | G_SCALAR); + SPAGAIN; + + /* Running rpmlib callback, returning its value */ + return rpmShowProgress(h, + what, + amount, + total, + pkgKey, + (long *) INSTALL_NONE /* shut up */); +} + +/* This function is called by rpm if a callback + * is set for for the logging system. + * If the callback is set, rpm does not print any message, + * and let the callback to do it */ +void logcallback(void) { + dSP; + if (log_callback_function) { + int logcode = rpmlogCode(); +#ifdef HDLISTDEBUG + fprintf(stderr, "HDEBUG: RPM4: running Callback logcallback()"); +#endif + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVpv("logcode", 0))); + XPUSHs(sv_2mortal(newSViv(logcode))); + XPUSHs(sv_2mortal(newSVpv("msg", 0))); + XPUSHs(sv_2mortal(newSVpv(rpmlogMessage(), 0))); + XPUSHs(sv_2mortal(newSVpv("priority", 0))); + XPUSHs(sv_2mortal(newSViv(RPMLOG_PRI(logcode)))); + PUTBACK; + call_sv(log_callback_function, G_DISCARD | G_SCALAR); + SPAGAIN; + } +} + +/* This callback is run during transcheck */ +int transSolveCallback(rpmts ts, rpmds Dep, const void * data) { + int rc = 0; + int count; + dSP; +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + /* Should return -1 retry, 0 ignore, 1 not found */ + rc = rpmtsSolve(ts, Dep, data); + /* PUSHMARK(SP); */ + if (ts) { + XPUSHs(sv_2mortal(newSVpv("db", 0))); + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmts, rpmtsLink(ts, "RPM4 transSolveCallback()")))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmts, ts, ts->nrefs); +#endif + + } + if (Dep) { + XPUSHs(sv_2mortal(newSVpv("dep", 0))); + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, rpmdsLink(Dep, "RPM4 transSolveCallback()")))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmds, Dep, Dep->nrefs); +#endif + } + XPUSHs(sv_2mortal(newSVpv("rc", 0))); + XPUSHs(sv_2mortal(newSViv(rc))); + PUTBACK; + count = call_sv((SV *) data, G_SCALAR); + SPAGAIN; + if (count) { + rc = POPi; + if (rc < -1 || rc > 1) + croak("Uh Oh! Your perl callback should return 1 (retry), 0 (ignore) or 1 (not found) and not %d", rc); + } else { + rc = 1; + } + return rc; +} + +/************************************************** + * Real Function rpmts function with double call * + * Aka function(arg) or RPM4::Db->function(arg) * + * This permit to reuse existing rpmts object * + **************************************************/ + +void _rpm2header(rpmts ts, char * filename, int checkmode) { + FD_t fd; + Header ret = NULL; + rpmRC rc; + dSP; +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + if ((fd = Fopen(filename, "r"))) { + rc = rpmReadPackageFile(ts, fd, filename, &ret); + if (checkmode) { + XPUSHs(sv_2mortal(newSViv(rc))); + ret = headerFree(ret); /* For checking the package, we don't keep the header */ + } else { + if (rc == 0) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)ret))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_header, ret, ret->nrefs); +#endif + } else { + XPUSHs(sv_2mortal(&PL_sv_undef)); + } + } + Fclose(fd); + } else { + XPUSHs(sv_2mortal(&PL_sv_undef)); + } + + PUTBACK; + return; +} + +void _newdep(SV * sv_deptag, char * name, SV * sv_sense, SV * sv_evr) { + rpmTag deptag = 0; + rpmsenseFlags sense = RPMSENSE_ANY; + rpmds Dep; + char * evr = NULL; + dSP; + + if (sv_deptag && SvOK(sv_deptag)) + deptag = sv2deptag(sv_deptag); + if (sv_sense && SvOK(sv_sense)) + sense = sv2sens(sv_sense); + if (sv_evr && SvOK(sv_evr)) + evr = SvPV_nolen(sv_evr); + Dep = rpmdsSingle(deptag, + name, + evr ? evr : "", sense); + if (Dep) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, Dep))); + } + PUTBACK; +} + +/* Get a new specfile */ +void _newspec(rpmts ts, char * filename, SV * svpassphrase, SV * svrootdir, SV * svcookies, SV * svanyarch, SV * svforce) { + Spec spec = NULL; + char * passphrase = NULL; + char * rootdir = NULL; + char * cookies = NULL; + int anyarch = 0; + int force = 0; + + if (svpassphrase && SvOK(svpassphrase)) + passphrase = SvPV_nolen(svpassphrase); + + if (svrootdir && SvOK(svrootdir)) + rootdir = SvPV_nolen(svrootdir); + else + rootdir = "/"; + + if (svcookies && SvOK(svcookies)) + cookies = SvPV_nolen(svcookies); + + if (svanyarch && SvOK(svanyarch)) + anyarch = SvIV(svanyarch); + + if (svforce && SvOK(svforce)) + force = SvIV(svforce); + + dSP; + if (filename) { + if (!parseSpec(ts, filename, rootdir, NULL, 0, passphrase, cookies, anyarch, force)) + spec = rpmtsSetSpec(ts, NULL); +#ifdef HHACK + } else { + spec = newSpec(); +#endif + } + if (spec) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_spec, (void *)spec))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_spec, spec, -1); +#endif + } else + XPUSHs(sv_2mortal(&PL_sv_undef)); + PUTBACK; + return; +} + +/* Building a spec file */ +int _specbuild(rpmts ts, Spec spec, SV * sv_buildflags) { + rpmBuildFlags buildflags = sv2rpmbuildflags(sv_buildflags); + if (buildflags == RPMBUILD_NONE) croak("No action given for build"); + return buildSpec(ts, spec, buildflags, 0); +} + +void _installsrpms(rpmts ts, char * filename) { + const char * specfile = NULL; + const char * cookies = NULL; + dSP; + if (rpmInstallSource( + ts, + filename, + &specfile, + &cookies) == 0) { + XPUSHs(sv_2mortal(newSVpv(specfile, 0))); + XPUSHs(sv_2mortal(newSVpv(cookies, 0))); + } + PUTBACK; +} + +int _header_vs_dep(Header h, rpmds dep, int nopromote) { + CHECK_RPMDS_IX(dep); + return rpmdsAnyMatchesDep(h, dep, nopromote); + /* return 1 if match */ +} + +int _headername_vs_dep(Header h, rpmds dep, int nopromote) { + char *name; int type; + int rc = 0; + CHECK_RPMDS_IX(dep); + headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, NULL); + if (strcmp(name, rpmdsN(dep)) != 0) + rc = 0; + else + rc = rpmdsNVRMatchesDep(h, dep, nopromote); + headerFreeData(name, type); + return rc; + /* return 1 if match */ +} + +MODULE = RPM4 PACKAGE = RPM4 + +BOOT: +if (rpmReadConfigFiles(NULL, NULL) != 0) + croak("Can't read configuration"); +#ifdef HDLISTDEBUG +rpmSetVerbosity(RPMMESS_DEBUG); +#else +rpmSetVerbosity(RPMMESS_NORMAL); +#endif +#ifdef HDRPMDEBUG +_rpmds_debug = -1; +_rpmdb_debug = -1; +_rpmts_debug = -1; +_rpmfi_debug = -1; +_rpmte_debug = -1; +#endif + +int +isdebug() + CODE: +#ifdef HDLISTDEBUG + RETVAL = 1; +#else + RETVAL = 0; +#endif + OUTPUT: + RETVAL + +void +moduleinfo() + PPCODE: + XPUSHs(sv_2mortal(newSVpv("Hack", 0))); +#ifdef HHACK + XPUSHs(sv_2mortal(newSVpv("Yes", 0))); +#else + XPUSHs(sv_2mortal(newSVpv("No", 0))); +#endif + XPUSHs(sv_2mortal(newSVpv("RPMVERSION", 0))); + XPUSHs(sv_2mortal(newSVpv("RPMVERSION", 0))); + XPUSHs(sv_2mortal(newSVpv(RPMVERSION, 0))); + XPUSHs(sv_2mortal(newSVpv("RPM4VERSION", 0))); + XPUSHs(sv_2mortal(newSVpv(VERSION, 0))); + XPUSHs(sv_2mortal(newSVpv("RPMNAME", 0))); + XPUSHs(sv_2mortal(newSVpv(rpmNAME, 0))); + XPUSHs(sv_2mortal(newSVpv("RPMEVR", 0))); + XPUSHs(sv_2mortal(newSVpv(rpmEVR, 0))); + +# Functions to control log/verbosity + +void +setverbosity(svlevel) + SV * svlevel + CODE: + rpmSetVerbosity(sv2loglevel(svlevel)); + +void +setlogcallback(function) + SV * function + CODE: + if (function == NULL || !SvOK(function)) { + rpmlogSetCallback(NULL); + } else if (SvTYPE(SvRV(function)) == SVt_PVCV) { + log_callback_function = newSVsv(function); + rpmlogSetCallback(logcallback); + } else + croak("First arg is not a code reference"); + +void +lastlogmsg() + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmlogCode()))); + XPUSHs(sv_2mortal(newSVpv(rpmlogMessage(), 0))); + +int +setlogfile(filename) + char * filename + PREINIT: + FILE * ofp = NULL; + FILE * fp = NULL; + CODE: + if (filename && *filename != 0) { + if ((fp = fopen(filename, "a+")) == NULL) { + XSprePUSH; PUSHi((IV)0); + XSRETURN(1); + } + } + if((ofp = rpmlogSetFile(fp)) != NULL) + fclose(ofp); + RETVAL=1; + OUTPUT: + RETVAL + +int +readconfig(rcfile = NULL, target = NULL) + char * rcfile + char * target + CODE: + RETVAL = rpmReadConfigFiles(rcfile, target); + OUTPUT: + RETVAL + +void +rpmlog(svcode, msg) + SV * svcode + char * msg + CODE: + rpmlog(sv2loglevel(svcode), "%s", msg); + +# Return hash of know tag +# Name => internal key (if available) + +void +querytag() + PREINIT: + int i = 0; + const struct headerSprintfExtension_s * ext = rpmHeaderFormats; + PPCODE: + for (i = 0; i < rpmTagTableSize; i++) { + XPUSHs(sv_2mortal(newSVpv(rpmTagTable[i].name + 7, 0))); + XPUSHs(sv_2mortal(newSViv(rpmTagTable[i].val))); + } + + while (ext->name != NULL) { + if (ext->type == HEADER_EXT_MORE) { + ext = ext->u.more; + continue; + } + for (i = 0; i < rpmTagTableSize; i++) { + if (!strcmp(rpmTagTable[i].name, ext->name)) + break; + } + if (i >= rpmTagTableSize && ext->type == HEADER_EXT_TAG) { + XPUSHs(sv_2mortal(newSVpv(ext->name + 7, 0))); + XPUSHs(sv_newmortal()); + } + ext++; + } + +int +tagtypevalue(svtagtype) + SV * svtagtype + CODE: + RETVAL = sv2tagtype(svtagtype); + OUTPUT: + RETVAL + +int +tagValue(tagname) + char * tagname + CODE: + RETVAL = tagValue((const char *) tagname); + OUTPUT: + RETVAL + +void +tagName(tag) + int tag + PREINIT: + const char *r = NULL; + PPCODE: + r = tagName(tag); + XPUSHs(sv_2mortal(newSVpv(r, 0))); + +void +flagvalue(flagtype, sv_value) + char * flagtype + SV * sv_value + PPCODE: + if (strcmp(flagtype, "loglevel") == 0) { + XPUSHs(sv_2mortal(newSViv(sv2constant(sv_value, "rpmlog")))); + } else if (strcmp(flagtype, "deptag") == 0) { /* Who will use this ?? */ + XPUSHs(sv_2mortal(newSViv(sv2deptag(sv_value)))); + } else if (strcmp(flagtype, "vsf") == 0) { + XPUSHs(sv_2mortal(newSViv(sv2constant(sv_value, "rpmverifyflags")))); + } else if (strcmp(flagtype, "trans") == 0) { + XPUSHs(sv_2mortal(newSViv(sv2transflags(sv_value)))); + } else if (strcmp(flagtype, "dbquery") == 0) { + XPUSHs(sv_2mortal(newSViv(sv2dbquerytag(sv_value)))); + } else if (strcmp(flagtype, "build") == 0) { + XPUSHs(sv_2mortal(newSViv(sv2rpmbuildflags(sv_value)))); + } else if (strcmp(flagtype, "fileattr") == 0) { + XPUSHs(sv_2mortal(newSViv(sv2fileattr(sv_value)))); + } else if (strcmp(flagtype, "sense") == 0) { + XPUSHs(sv_2mortal(newSViv(sv2senseflags(sv_value)))); + } else if (strcmp(flagtype, "tagtype") == 0) { + XPUSHs(sv_2mortal(newSViv(sv2tagtype(sv_value)))); + } else if (strcmp(flagtype, "list") == 0) { + XPUSHs(sv_2mortal(newSVpv("loglevel", 0))); + XPUSHs(sv_2mortal(newSVpv("deptag", 0))); + XPUSHs(sv_2mortal(newSVpv("vsf", 0))); + XPUSHs(sv_2mortal(newSVpv("trans", 0))); + XPUSHs(sv_2mortal(newSVpv("dbquery", 0))); + XPUSHs(sv_2mortal(newSVpv("build", 0))); + XPUSHs(sv_2mortal(newSVpv("fileattr", 0))); + XPUSHs(sv_2mortal(newSVpv("tagtype", 0))); + } + +# Macros functions: + +void +expand(name) + char * name + PPCODE: + const char * value = rpmExpand(name, NULL); + XPUSHs(sv_2mortal(newSVpv(value, 0))); + +void +expandnumeric(name) + char *name + PPCODE: + int value = rpmExpandNumeric(name); + XPUSHs(sv_2mortal(newSViv(value))); + +void +add_macro(macro) + char * macro + CODE: + rpmDefineMacro(NULL, macro, RMIL_DEFAULT); + +void +del_macro(name) + char * name + CODE: + delMacro(NULL, name); + +void +loadmacrosfile(filename) + char * filename + PPCODE: + rpmInitMacros(NULL, filename); + +void +resetmacros() + PPCODE: + rpmFreeMacros(NULL); + +void +resetrc() + PPCODE: + rpmFreeRpmrc(); + +void +getosname() + PREINIT: + const char *v = NULL; + PPCODE: + rpmGetOsInfo(&v, NULL); + XPUSHs(sv_2mortal(newSVpv(v, 0))); + +void +getarchname() + PREINIT: + const char *v = NULL; + PPCODE: + rpmGetArchInfo(&v, NULL); + XPUSHs(sv_2mortal(newSVpv(v, 0))); + +int +osscore(os, build = 0) + char * os + int build; + PREINIT: + int machtable; + CODE: + machtable = build ? RPM_MACHTABLE_BUILDOS : RPM_MACHTABLE_INSTOS; + RETVAL = rpmMachineScore(machtable, os); + OUTPUT: + RETVAL + +int +archscore(arch, build = 0) + char * arch + int build; + PREINIT: + int machtable; + CODE: + machtable = build ? RPM_MACHTABLE_BUILDARCH : RPM_MACHTABLE_INSTARCH; + RETVAL = rpmMachineScore(machtable, arch); + OUTPUT: + RETVAL + +void +buildhost() + PPCODE: + XPUSHs(sv_2mortal(newSVpv(buildHost(),0))); + +# Dump to file functions: +void +dumprc(fp) + FILE *fp + CODE: + rpmShowRC(fp); + +void +dumpmacros(fp) + FILE *fp + CODE: + rpmDumpMacroTable(NULL, fp); + +int +rpmvercmp(one, two) + char *one + char *two + +# create a new empty header +# Is this usefull + +void +headernew() + PREINIT: + Header h = headerNew(); + PPCODE: + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)h))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_header, h, h->nrefs); +#endif + + +# Read data from file pointer and return next header object +# Return undef if failed +# fedora use HEADER_MAGIC_NO, too bad, set no_header_magic make the function +# compatible +void +stream2header(fp, no_header_magic = 0, callback = NULL) + FILE *fp + int no_header_magic + SV * callback + PREINIT: + FD_t fd; + Header header; + PPCODE: + if (fp && (fd = fdDup(fileno(fp)))) { +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + if (callback != NULL && SvROK(callback)) { + while ((header = headerRead(fd, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES))) { + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)header))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_header, header, header->nrefs); +#endif + PUTBACK; + call_sv(callback, G_DISCARD | G_SCALAR); + SPAGAIN; + FREETMPS; + LEAVE; + } + } else { + header = headerRead(fd, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES); + if (header) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)header))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_header, header, header->nrefs); +#endif + + } +#ifdef HDLISTDEBUG + else fprintf(stderr, "HDEBUG: No header found from fp: %d\n", fileno(fp)); +#endif + } + Fclose(fd); + } + +# Read a rpm and return a Header +# Return undef if failed +void +rpm2header(filename, sv_vsflags = NULL) + char * filename + SV * sv_vsflags + PREINIT: + rpmts ts = rpmtsCreate(); + rpmVSFlags vsflags = RPMVSF_DEFAULT; + PPCODE: + if (sv_vsflags == NULL) /* Nothing has been passed, default is no signature */ + vsflags |= _RPMVSF_NOSIGNATURES; + else + vsflags = sv2vsflags(sv_vsflags); + rpmtsSetVSFlags(ts, vsflags); + _rpm2header(ts, filename, 0); + SPAGAIN; + ts = rpmtsFree(ts); + +int +rpmresign(passphrase, rpmfile) + char * passphrase + char * rpmfile + CODE: + RETVAL = rpmsign(passphrase, (const char *) rpmfile); + OUTPUT: + RETVAL + +void +installsrpm(filename, sv_vsflags = NULL) + char * filename + SV * sv_vsflags + PREINIT: + rpmts ts = rpmtsCreate(); + rpmVSFlags vsflags = RPMVSF_DEFAULT; + PPCODE: + vsflags = sv2vsflags(sv_vsflags); + rpmtsSetVSFlags(ts, vsflags); + PUTBACK; + _installsrpms(ts, filename); + SPAGAIN; + ts = rpmtsFree(ts); + +MODULE = RPM4 PACKAGE = RPM4::Header PREFIX = Header_ + +void +Header_DESTROY(h) + Header h + CODE: +#ifdef HDRPMMEM + PRINTF_FREE(bless_header, h, h->nrefs); +#endif + headerFree(h); + +# Write rpm header into file pointer +# fedora use HEADER_MAGIC_NO, too bad, set no_header_magic make the function +# compatible +int +Header_write(h, fp, no_header_magic = 0) + Header h + FILE * fp + int no_header_magic + PREINIT: + FD_t fd; + CODE: + RETVAL = 0; +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + if (h) { + if ((fd = fdDup(fileno(fp))) != NULL) { + headerWrite(fd, h, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES); + Fclose(fd); + RETVAL = 1; + } + } + OUTPUT: + RETVAL + +void +Header_hsize(h, no_header_magic = 0) + Header h + int no_header_magic + PPCODE: + XPUSHs(sv_2mortal(newSViv(headerSizeof(h, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES)))); + +void +Header_copy(h) + Header h + PREINIT: + Header hcopy; + PPCODE: + hcopy = headerCopy(h); + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)hcopy))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_header, hcopy, hcopy->nrefs); +#endif + +void +Header_string(h, no_header_magic = 0) + Header h + int no_header_magic + PREINIT: + char * string = NULL; + int offset = 0; + void * ptr = NULL; + int hsize = 0; + PPCODE: + ptr = headerUnload(h); + hsize = headerSizeof(h, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES); + string = malloc(hsize); + if (!no_header_magic) { + memcpy(string, header_magic, sizeof(header_magic)); + offset = sizeof(header_magic); + } + memcpy(string + offset, ptr, headerSizeof(h, HEADER_MAGIC_NO)); + PUSHs(sv_2mortal(newSVpv((char *)string, hsize))); + free(ptr); + + +int +Header_removetag(h, sv_tag) + Header h + SV * sv_tag + PREINIT: + rpmTag tag = -1; + CODE: + if (SvIOK(sv_tag)) { + tag = SvIV(sv_tag); + } else if (SvPOK(sv_tag)) { + tag = tagValue(SvPV_nolen(sv_tag)); + } + if (tag > 0) + RETVAL = headerRemoveEntry(h, tag); + else + RETVAL = 1; + OUTPUT: + RETVAL + +int +Header_addtag(h, sv_tag, sv_tagtype, ...) + Header h + SV * sv_tag + SV * sv_tagtype + PREINIT: + char * value; + int ivalue; + int i; + rpmTag tag = -1; + rpmTagType tagtype = RPM_NULL_TYPE; + STRLEN len; + CODE: + if (SvIOK(sv_tag)) { + tag = SvIV(sv_tag); + } else if (SvPOK(sv_tag)) { + tag = tagValue(SvPV_nolen(sv_tag)); + } + tagtype = sv2tagtype(sv_tagtype); + if (tag > 0) + RETVAL = 1; + else + RETVAL = 0; + if (tag == RPMTAG_OLDFILENAMES) + expandFilelist(h); + for (i = 3; (i < items) && RETVAL; i++) { + switch (tagtype) { + case RPM_CHAR_TYPE: + case RPM_INT8_TYPE: + case RPM_INT16_TYPE: + case RPM_INT32_TYPE: + ivalue = SvUV(ST(i)); + RETVAL = headerAddOrAppendEntry(h, tag, tagtype, &ivalue, 1); + break; + case RPM_BIN_TYPE: + value = (char *)SvPV(ST(i), len); + RETVAL = headerAddEntry(h, tag, tagtype, value, len); + break; + case RPM_STRING_ARRAY_TYPE: + value = SvPV_nolen(ST(i)); + RETVAL = headerAddOrAppendEntry(h, tag, tagtype, &value, 1); + break; + default: + value = SvPV_nolen(ST(i)); + RETVAL = headerAddOrAppendEntry(h, tag, tagtype, value, 1); + break; + } + } + if (tag == RPMTAG_OLDFILENAMES) { + compressFilelist(h); + } + OUTPUT: + RETVAL + +void +Header_listtag(h) + Header h + PREINIT: + HeaderIterator iterator; + int tag; + PPCODE: + iterator = headerInitIterator(h); + while (headerNextIterator(iterator, &tag, NULL, NULL, NULL)) { + XPUSHs(sv_2mortal(newSViv(tag))); + } + headerFreeIterator(iterator); + +int +Header_hastag(h, sv_tag) + Header h + SV * sv_tag + PREINIT: + rpmTag tag = -1; + CODE: + if (SvIOK(sv_tag)) { + tag = SvIV(sv_tag); + } else if (SvPOK(sv_tag)) { + tag = tagValue(SvPV_nolen(sv_tag)); + } + if (tag > 0) + RETVAL = headerIsEntry(h, tag); + else + RETVAL = -1; + OUTPUT: + RETVAL + +# Return the tag value in headers +void +Header_tag(h, sv_tag) + Header h + SV * sv_tag + PREINIT: + void *ret = NULL; + int type; + int n; + rpmTag tag = -1; + PPCODE: + if (SvIOK(sv_tag)) { + tag = SvIV(sv_tag); + } else if (SvPOK(sv_tag)) { + tag = tagValue(SvPV_nolen(sv_tag)); + } + if (tag > 0) + if (headerGetEntry(h, tag, &type, &ret, &n)) { + switch(type) { + case RPM_STRING_ARRAY_TYPE: + { + int i; + char **s; + + EXTEND(SP, n); + s = (char **)ret; + + for (i = 0; i < n; i++) { + PUSHs(sv_2mortal(newSVpv(s[i], 0))); + } + } + break; + case RPM_STRING_TYPE: + PUSHs(sv_2mortal(newSVpv((char *)ret, 0))); + break; + case RPM_CHAR_TYPE: + case RPM_INT8_TYPE: + case RPM_INT16_TYPE: + case RPM_INT32_TYPE: + { + int i; + int *r; + + EXTEND(SP, n); + r = (int *)ret; + + for (i = 0; i < n; i++) { + PUSHs(sv_2mortal(newSViv(r[i]))); + } + } + break; + case RPM_BIN_TYPE: + PUSHs(sv_2mortal(newSVpv((char *)ret, n))); + break; + default: + croak("unknown rpm tag type %d", type); + } + } + headerFreeTag(h, ret, type); + +int +Header_tagtype(h, sv_tag) + Header h + SV * sv_tag + PREINIT: + int type; + rpmTag tag = -1; + CODE: + if (SvIOK(sv_tag)) { + tag = SvIV(sv_tag); + } else if (SvPOK(sv_tag)) { + tag = tagValue(SvPV_nolen(sv_tag)); + } + RETVAL = RPM_NULL_TYPE; + if (tag > 0) + if (headerGetEntry(h, tag, &type, NULL, NULL)) + RETVAL = type; + OUTPUT: + RETVAL + +void +Header_queryformat(h, query) + Header h + char * query + PREINIT: + char *s = NULL; + PPCODE: + s = headerSprintf(h, query, + rpmTagTable, rpmHeaderFormats, NULL); + if (s) { + char * cs = NULL; + int len = strlen(s); + + cs = malloc(strlen(s)); /* TODO need to check return of malloc */ + memcpy(cs, s, len); + XPUSHs(sv_2mortal(newSVpv(cs, len))); + } + _free(s); + +void +Header_fullname(h) + Header h + PREINIT: + I32 gimme = GIMME_V; + char *name; + char *version; + char *release; + char *arch; + PPCODE: + if (h) { + headerGetEntry(h, RPMTAG_NAME, NULL, (void *) &name, NULL); + headerGetEntry(h, RPMTAG_VERSION, NULL, (void *) &version, NULL); + headerGetEntry(h, RPMTAG_RELEASE, NULL, (void *) &release, NULL); + headerGetEntry(h, RPMTAG_ARCH, NULL, (void *) &arch, NULL); + + if (gimme == G_SCALAR) { + XPUSHs(sv_2mortal(newSVpvf("%s-%s-%s.%s", + name, + version, + release, + headerIsEntry(h, RPMTAG_SOURCEPACKAGE) ? "src" : arch + ))); + } else if (gimme == G_ARRAY) { + EXTEND(SP, 4); + PUSHs(sv_2mortal(newSVpv(name, 0))); + PUSHs(sv_2mortal(newSVpv(version, 0))); + PUSHs(sv_2mortal(newSVpv(release, 0))); + if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) { + PUSHs(sv_2mortal(newSVpv("src", 0))); + } else { + PUSHs(sv_2mortal(newSVpv(arch, 0))); + } + } + } + headerFreeTag(h, name, RPM_STRING_TYPE); + headerFreeTag(h, version, RPM_STRING_TYPE); + headerFreeTag(h, release, RPM_STRING_TYPE); + headerFreeTag(h, arch, RPM_STRING_TYPE); + +void +Header_nevr(header) + Header header + PPCODE: + PUSHs(sv_2mortal(newSVpv(hGetNEVR(header, NULL), 0))); + +int +Header_issrc(h) + Header h + CODE: + RETVAL = headerIsEntry(h, RPMTAG_SOURCEPACKAGE); + OUTPUT: + RETVAL + +# Dependancies versions functions + +int +Header_compare(h1, h2) + Header h1 + Header h2 + CODE: + RETVAL = rpmVersionCompare(h1, h2); + OUTPUT: + RETVAL + +void +Header_dep(header, type, scaremem = O_SCAREMEM) + Header header + SV * type + int scaremem + PREINIT: + rpmds ds; + rpmTag tag; + PPCODE: + tag = sv2deptag(type); + ds = rpmdsNew(header, tag, scaremem); + ds = rpmdsInit(ds); + if (ds != NULL) + if (rpmdsNext(ds) >= 0) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, ds))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmds, ds, ds->nrefs); +#endif + + } + +void +Header_files(header, scaremem = O_SCAREMEM) + Header header + int scaremem + PREINIT: + rpmfi Files; + rpmts ts = NULL; /* setting this to NULL skip path relocation + * maybe a good deal is Header::Files(header, Dep = NULL) */ + PPCODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + Files = rpmfiNew(ts, header, RPMTAG_BASENAMES, scaremem); + if ((Files = rpmfiInit(Files, 0)) != NULL && rpmfiNext(Files) >= 0) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmfi, Files))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmfi, Files, Files->nrefs); +#endif + } + +void +Header_hchkdep(h1, h2, type) + Header h1 + Header h2 + SV * type + PREINIT: + rpmds ds = NULL; + rpmds pro = NULL; + rpmTag tag; + PPCODE: + tag = sv2deptag(type); + ds = rpmdsNew(h1, tag, SCAREMEM); + pro = rpmdsNew(h2, RPMTAG_PROVIDENAME, SCAREMEM); +#ifdef HDLISTDEBUG + fprintf(stderr, "HDEBUG: Header::hchkdep %d: %s vs %s %p\n", tag, hGetNEVR(h1, NULL), hGetNEVR(h2, NULL), ds); +#endif + if (ds != NULL) { + rpmdsInit(ds); + while (rpmdsNext(ds) >= 0) { + rpmdsInit(pro); + while (rpmdsNext(pro) >= 0) { + if (rpmdsCompare(ds,pro)) { + XPUSHs(sv_2mortal(newSVpv(rpmdsDNEVR(ds), 0))); +#ifdef HDLISTDEBUG + fprintf(stderr, "HDEBUG: Header::hchkdep match %s %s p in %s\n", rpmdsDNEVR(ds), rpmdsDNEVR(pro), hGetNEVR(h2, NULL)); +#endif + break; + } + } + } + } + pro = rpmdsFree(pro); + ds = rpmdsFree(ds); + +int +Header_matchdep(header, Dep, sv_nopromote = NULL) + Header header + SV * sv_nopromote + rpmds Dep + PREINIT: + int nopromote = 0; + CODE: + if (sv_nopromote != NULL) + nopromote = SvIV(sv_nopromote); + RETVAL = _header_vs_dep(header, Dep, nopromote); + OUTPUT: + RETVAL + +int +Header_namematchdep(header, Dep, sv_nopromote = NULL) + Header header + rpmds Dep + SV * sv_nopromote + PREINIT: + int nopromote = 0; + CODE: + if (sv_nopromote != NULL) + nopromote = SvIV(sv_nopromote); + RETVAL = _headername_vs_dep(header, Dep, nopromote); /* return 1 if match */ + OUTPUT: + RETVAL + +# DB functions +MODULE = RPM4 PACKAGE = RPM4 + +int +rpmdbinit(rootdir = NULL) + char * rootdir + PREINIT: + rpmts ts = rpmtsCreate(); + CODE: + if (rootdir) + rpmtsSetRootDir(ts, rootdir); + /* rpm{db,ts}init is deprecated, we open a database with create flags + * and close it */ + /* 0 on success */ + RETVAL = rpmtsOpenDB(ts, O_CREAT); + ts = rpmtsFree(ts); + OUTPUT: + RETVAL + +int +rpmdbverify(rootdir = NULL) + char * rootdir + PREINIT: + rpmts ts = rpmtsCreate(); + CODE: + if (rootdir) + rpmtsSetRootDir(ts, rootdir); + /* 0 on success */ + RETVAL = rpmtsVerifyDB(ts); + ts = rpmtsFree(ts); + OUTPUT: + RETVAL + +int +rpmdbrebuild(rootdir = NULL) + char * rootdir + PREINIT: + rpmts ts = rpmtsCreate(); + CODE: + if (rootdir) + rpmtsSetRootDir(ts, rootdir); + /* 0 on success */ + RETVAL = rpmtsRebuildDB(ts); + ts = rpmtsFree(ts); + OUTPUT: + RETVAL + +#ifdef HHACK +void +emptydb() + PREINIT: + rpmts ts = rpmtsCreate(); + PPCODE: + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmts, (void *)ts))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmts, ts, ts->nrefs); +#endif + + +#endif + +void +newdb(write = 0, rootdir = NULL) + int write + char * rootdir + PREINIT: + rpmts ts = rpmtsCreate(); + PPCODE: + if (rootdir) + rpmtsSetRootDir(ts, rootdir); + + rpmtsSetVSFlags(ts, RPMTRANS_FLAG_NONE); + /* is O_CREAT a good idea here ? */ + /* is the rpmtsOpenDB really need ? */ + if (rpmtsOpenDB(ts, write ? O_RDWR | O_CREAT : O_RDONLY) == 0) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmts, (void *)ts))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmts, ts, ts->nrefs); +#endif + } else { + ts = rpmtsFree(ts); + } + +MODULE = RPM4 PACKAGE = RPM4::Transaction PREFIX = Ts_ + +void +Ts_new(perlclass, rootdir = NULL) + char * perlclass + char * rootdir + PREINIT: + rpmts ts = rpmtsCreate(); + PPCODE: + if (rootdir) + rpmtsSetRootDir(ts, rootdir); + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), perlclass, (void *)ts))); + +void +Ts_DESTROY(ts) + rpmts ts + CODE: +#ifdef HDRPMMEM + PRINTF_FREE(bless_rpmts, ts, ts->nrefs); +#endif + ts = rpmtsFree(ts); + +# Function to control RPM4::Transaction behaviour + +int +Ts_vsflags(ts, sv_vsflags = NULL) + rpmts ts + SV * sv_vsflags + PREINIT: + rpmVSFlags vsflags; + CODE: + if (sv_vsflags != NULL) { + vsflags = sv2vsflags(sv_vsflags); + RETVAL = rpmtsSetVSFlags(ts, vsflags); + } else { + RETVAL = rpmtsVSFlags(ts); + } + OUTPUT: + RETVAL + +int +Ts_transflag(ts, sv_transflag = NULL) + rpmts ts + SV * sv_transflag + PREINIT: + rpmtransFlags transflags; + CODE: + if (sv_transflag != NULL) { + transflags = sv2transflags(sv_transflag); + /* Take care to rpm config (userland) */ + if (rpmExpandNumeric("%{?_repackage_all_erasures}")) + transflags |= RPMTRANS_FLAG_REPACKAGE; + RETVAL = rpmtsSetFlags(ts, transflags); + } else { + RETVAL = rpmtsFlags(ts); + } + OUTPUT: + RETVAL + +int +Ts_injectheader(db, header) + rpmts db + Header header + PREINIT: + rpmdb rdb; + CODE: + rdb = rpmtsGetRdb(db); + RETVAL = rpmdbAdd(rdb, 0, header, db, NULL); + OUTPUT: + RETVAL + +int +Ts_deleteheader(db, sv_offset) + rpmts db + SV * sv_offset + PREINIT: + rpmdb rdb; + unsigned int offset = 0; + CODE: + offset = SvUV(sv_offset); + rdb = rpmtsGetRdb(db); + if (offset) + RETVAL = rpmdbRemove(rdb, 0, offset, db, NULL); + else + RETVAL = 1; + OUTPUT: + RETVAL + +int +Ts_traverse(ts, callback = NULL, sv_tagname = NULL, sv_tagvalue = NULL, keylen = 0, sv_exclude = NULL) + rpmts ts + SV * callback + SV * sv_tagname + SV * sv_tagvalue + SV * sv_exclude + int keylen + PREINIT: + rpmTag tag; + void * value = NULL; + rpmdbMatchIterator mi; + Header header; + int rc = 1; + int count = 0; + int * exclude = NULL; + AV * av_exclude; + int i; + CODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + ts = rpmtsLink(ts, "RPM4 Db::traverse()"); + if (sv_tagname == NULL || !SvOK(sv_tagname)) { + tag = RPMDBI_PACKAGES; /* Assume search into installed packages */ + } else { + tag = sv2dbquerytag(sv_tagname); + } + if (sv_tagvalue != NULL && SvOK(sv_tagvalue)) { + switch (tag) { + case RPMDBI_PACKAGES: + i = SvIV(sv_tagvalue); + value = &i; + keylen = sizeof(i); + break; + default: + value = (void *) SvPV_nolen(sv_tagvalue); + break; + } + } + + RETVAL = 0; + if (tag >= 0) { + mi = rpmtsInitIterator(ts, tag, value, keylen); + if (sv_exclude != NULL && SvOK(sv_exclude) && SvTYPE(SvRV(sv_exclude)) == SVt_PVAV) { + av_exclude = (AV*)SvRV(sv_exclude); + exclude = malloc((av_len(av_exclude)+1) * sizeof(int)); + for (i = 0; i <= av_len(av_exclude); i++) { + SV **isv = av_fetch(av_exclude, i, 0); + exclude[i] = SvUV(*isv); + } + rpmdbPruneIterator(mi, exclude, av_len(av_exclude) + 1, 0); + } + while (rc && ((header = rpmdbNextIterator(mi)) != NULL)) { + RETVAL++; + if (callback != NULL && SvROK(callback)) { + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, headerLink(header)))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_header, header, header->nrefs); +#endif + XPUSHs(sv_2mortal(newSVuv(rpmdbGetIteratorOffset(mi)))); + PUTBACK; + count = call_sv(callback, G_SCALAR); + SPAGAIN; + if (tag == RPMDBI_PACKAGES && value != NULL) { + rc = 0; + } else if (count == 1) { + rc = POPi; + } + FREETMPS; + LEAVE; + + } + } + if (exclude != NULL) free(exclude); + rpmdbFreeIterator(mi); + } else + RETVAL = -1; + ts = rpmtsFree(ts); + OUTPUT: + RETVAL + +void +Ts_get_header(ts, off) + rpmts ts + int off + PREINIT: + rpmdbMatchIterator mi; + Header header; + PPCODE: + mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &off, sizeof(off)); + if ((header = rpmdbNextIterator(mi)) != NULL) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, headerLink(header)))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_header, header, header->nrefs); +#endif + } + rpmdbFreeIterator(mi); + +int +Ts_transadd(ts, header, key = NULL, upgrade = 1, sv_relocation = NULL, force = 0) + rpmts ts + Header header + char * key + int upgrade + SV * sv_relocation + int force + PREINIT: + rpmRelocation * relocations = NULL; + HV * hv_relocation; + HE * he_relocation; + int i = 0; + I32 len; + CODE: + + if (key != NULL) + key = strdup(key); + + /* Relocation settings */ + if (sv_relocation && SvOK(sv_relocation) && !force) { +/* if (! (headerGetEntry(eiu->h, RPMTAG_PREFIXES, &pft, + (void **) &paths, &c) && (c == 1))) { */ + if (! headerIsEntry(header, RPMTAG_PREFIXES)) { + rpmMessage(RPMMESS_ERROR, + _("package %s is not relocatable\n"), ""); + XPUSHi((IV)1); + XSRETURN(1); + } + if (SvTYPE(sv_relocation) == SVt_PV) { + /* String value, assume a prefix */ + relocations = malloc(2 * sizeof(*relocations)); + relocations[0].oldPath = NULL; + relocations[0].newPath = SvPV_nolen(sv_relocation); + relocations[1].oldPath = relocations[1].newPath = NULL; + } else if (SvTYPE(SvRV(sv_relocation)) == SVt_PVHV) { + hv_relocation = (HV*)SvRV(sv_relocation); + hv_iterinit(hv_relocation); + while ((he_relocation = hv_iternext(hv_relocation)) != NULL) { + relocations = realloc(relocations, sizeof(*relocations) * (++i)); + relocations[i-1].oldPath = NULL; + relocations[i-1].newPath = NULL; + relocations[i-1].oldPath = hv_iterkey(he_relocation, &len); + relocations[i-1].newPath = SvPV_nolen(hv_iterval(hv_relocation, he_relocation)); + } + /* latest relocation is identify by NULL setting */ + relocations = realloc(relocations, sizeof(*relocations) * (++i)); + relocations[i-1].oldPath = relocations[i-1].newPath = NULL; + } else { + croak("latest argument is set but is not an array ref or a string"); + } + } + + /* TODO fnpyKey: another value can be use... */ + RETVAL = rpmtsAddInstallElement(ts, header, (fnpyKey) key, upgrade, relocations); + OUTPUT: + RETVAL + +int +Ts_transremove(ts, recOffset, header = NULL) + rpmts ts + int recOffset + Header header + PREINIT: + rpmdbMatchIterator mi; + CODE: + RETVAL = 0; + if (header != NULL) { /* reprofit Db_traverse */ + rpmtsAddEraseElement(ts, header, recOffset); + } else { + mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset)); + if ((header = rpmdbNextIterator(mi)) != NULL) { +#ifdef HDLISTDEBUG + fprintf(stderr, "HDEBUG: Db::transremove(h, o) H: %p Off:%u\n", header, recOffset); +#endif + rpmtsAddEraseElement(ts, header, recOffset); + RETVAL = 1; + } + rpmdbFreeIterator(mi); + } + OUTPUT: + RETVAL + +int +Ts_transremove_pkg(ts, N_evr) + rpmts ts + char * N_evr + PREINIT: + rpmdbMatchIterator mi; + Header header; + int recOffset; + CODE: + RETVAL = 0; + /* N_evr is not NEVR but N(EVR), with RPMDBI_LABEL + * I want to find another way to exactly match a header + * For more flexible function, check Db_traverse / Db_transremove */ + mi = rpmtsInitIterator(ts, RPMDBI_LABEL, N_evr, 0); + while ((header = rpmdbNextIterator(mi))) { + recOffset = rpmdbGetIteratorOffset(mi); +#ifdef HDLISTDEBUG + fprintf(stderr, "HDEBUG: Db::transremove(Name) N: %s H: %p Off:%u\n", N_evr, header, recOffset); +#endif + if (recOffset != 0) { + rpmtsAddEraseElement(ts, header, recOffset); + RETVAL ++; + } + } + rpmdbFreeIterator(mi); + OUTPUT: + RETVAL + +int +Ts_traverse_transaction(ts, callback, type = 0) + rpmts ts + SV * callback + int type + PREINIT: + rpmtsi pi; + rpmte Te; + CODE: + ts = rpmtsLink(ts, "RPM4 Db::traverse_transaction()"); + pi = rpmtsiInit(ts); + RETVAL = 0; + while ((Te = rpmtsiNext(pi, type)) != NULL) { + RETVAL++; + if (callback != NULL && SvROK(callback)) { + ENTER; + SAVETMPS; + PUSHMARK(SP); +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), "RPM4::Db::Te", Te))); + PUTBACK; + call_sv(callback, G_DISCARD | G_SCALAR); + SPAGAIN; + FREETMPS; + LEAVE; + } + } + pi = rpmtsiFree(pi); + ts = rpmtsFree(ts); + OUTPUT: + RETVAL + +int +Ts_transcheck(ts, callback = NULL) + rpmts ts + SV * callback + CODE: + ts = rpmtsLink(ts, "RPM4 Db_transcheck()"); + if (callback != NULL && SvOK(callback) && SvTYPE(SvRV(callback)) == SVt_PVCV) { /* Be sure we have a code ref */ +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + rpmtsSetSolveCallback(ts, transSolveCallback, (void *) callback); + } + + RETVAL = rpmtsCheck(ts); + /* Restoring default rpm setting */ + rpmtsSetSolveCallback(ts, rpmtsSolve, NULL); + ts = rpmtsFree(ts); + OUTPUT: + RETVAL + +int +Ts_transorder(ts) + rpmts ts + CODE: + RETVAL = rpmtsOrder(ts); + OUTPUT: + RETVAL + +void +Ts_transclean(ts) + rpmts ts + PPCODE: + rpmtsClean(ts); + +int +Ts_transrun(ts, callback, ...) + rpmts ts + SV * callback + PREINIT: + int i; + rpmprobFilterFlags probFilter = RPMPROB_FILTER_NONE; + rpmInstallInterfaceFlags install_flags = INSTALL_NONE; + rpmps ps; + CODE: + ts = rpmtsLink(ts, "RPM4 Db::transrun()"); + if (!SvOK(callback)) { /* undef value */ + rpmtsSetNotifyCallback(ts, + rpmShowProgress, + (void *) ((long) INSTALL_LABEL | INSTALL_HASH | INSTALL_UPGRADE)); + } else if (SvTYPE(SvRV(callback)) == SVt_PVCV) { /* ref sub */ + rpmtsSetNotifyCallback(ts, + transCallback, (void *) callback); + } else if (SvTYPE(SvRV(callback)) == SVt_PVAV) { /* array ref */ + install_flags = sv2constant(callback, "rpminstallinterfaceflags"); + rpmtsSetNotifyCallback(ts, + rpmShowProgress, + (void *) ((long) install_flags)); + } else { + croak("Wrong parameter given"); + } + + for (i = 2; i < items; i++) + probFilter |= sv2constant(ST(i), "rpmprobfilterflags"); + + ps = rpmtsProblems(ts); + RETVAL = rpmtsRun(ts, ps, probFilter); + ps = rpmpsFree(ps); + ts = rpmtsFree(ts); + OUTPUT: + RETVAL + +# get from transaction a problem set +void +Ts__transpbs(ts) + rpmts ts + PREINIT: + rpmps ps; + PPCODE: + ps = rpmtsProblems(ts); + if (ps && ps->numProblems) /* if no problem, return undef */ + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmps, ps))); + +int +Ts_importpubkey(ts, filename) + rpmts ts + char * filename + PREINIT: + const byte * pkt = NULL; + size_t pktlen = 0; + int rc; + CODE: + rpmtsClean(ts); + + if ((rc = pgpReadPkts(filename, &pkt, &pktlen)) <= 0) { + RETVAL = 1; + } else if (rc != PGPARMOR_PUBKEY) { + RETVAL = 1; + } else if (rpmcliImportPubkey(ts, pkt, pktlen) != RPMRC_OK) { + RETVAL = 1; + } else { + RETVAL = 0; + } + pkt = _free(pkt); + OUTPUT: + RETVAL + +void +Ts_checkrpm(ts, filename, sv_vsflags = NULL) + rpmts ts + char * filename + SV * sv_vsflags + PREINIT: + rpmVSFlags vsflags = RPMVSF_DEFAULT; + rpmVSFlags oldvsflags = RPMVSF_DEFAULT; + PPCODE: + oldvsflags = rpmtsVSFlags(ts); /* keep track of old settings */ + if (sv_vsflags != NULL) { + vsflags = sv2vsflags(sv_vsflags); + rpmtsSetVSFlags(ts, vsflags); + } + PUTBACK; + _rpm2header(ts, filename, 1); /* Rpmread header is not the most usefull, + * but no other function in rpmlib allow this :( */ + SPAGAIN; + rpmtsSetVSFlags(ts, oldvsflags); /* resetting in case of change */ + +void +Ts_transreset(ts) + rpmts ts + PPCODE: + rpmtsEmpty(ts); + +# Remaping function: + +# RPM4::rpm2header(filename); # Reusing existing RPM4::Db +void +Ts_rpm2header(ts, filename) + rpmts ts + char * filename + PPCODE: + _rpm2header(ts, filename, 0); + SPAGAIN; + +# RPM4::Spec::specbuild([ buildflags ]); Reusing existing RPM4::Db +int +Ts_specbuild(ts, spec, sv_buildflags) + rpmts ts + Spec spec + SV * sv_buildflags + CODE: + RETVAL = _specbuild(ts, spec, sv_buildflags); + OUTPUT: + RETVAL + +void +Ts_installsrpm(ts, filename) + rpmts ts + char * filename + PPCODE: + PUTBACK; + _installsrpms(ts, filename); + SPAGAIN; + +MODULE = RPM4 PACKAGE = RPM4::Db::Te PREFIX = Te_ + +void +Te_DESTROY(Te) + rpmte Te + CODE: +#ifdef HDRPMMEM +/* PRINTF_FREE(RPM4::Db::Te, -1); */ +#endif + /* Don't do that ! * + Te = rpmteFree(Te); */ + +int +Te_type(Te) + rpmte Te + CODE: + RETVAL = rpmteType(Te); + OUTPUT: + RETVAL + +void +Te_name(Te) + rpmte Te + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmteN(Te), 0))); + +void +Te_version(Te) + rpmte Te + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmteV(Te), 0))); + +void +Te_release(Te) + rpmte Te + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmteR(Te), 0))); + +void +Te_epoch(Te) + rpmte Te + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmteE(Te), 0))); + +void +Te_arch(Te) + rpmte Te + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmteA(Te), 0))); + +void +Te_os(Te) + rpmte Te + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmteO(Te), 0))); + +void +Te_fullname(Te) + rpmte Te + PREINIT: + I32 gimme = GIMME_V; + PPCODE: + if (gimme == G_SCALAR) { + XPUSHs(sv_2mortal(newSVpvf("%s-%s-%s.%s", + rpmteN(Te), rpmteV(Te), rpmteR(Te), rpmteA(Te)))); + } else { + XPUSHs(sv_2mortal(newSVpv(rpmteN(Te), 0))); + XPUSHs(sv_2mortal(newSVpv(rpmteV(Te), 0))); + XPUSHs(sv_2mortal(newSVpv(rpmteR(Te), 0))); + XPUSHs(sv_2mortal(newSVpv(rpmteA(Te), 0))); + } + +void +Te_size(Te) + rpmte Te + PPCODE: + XPUSHs(sv_2mortal(newSVuv(rpmtePkgFileSize(Te)))); + +void +Te_dep(Te, type) + rpmte Te + SV * type + PREINIT: + rpmds ds; + rpmTag tag; + PPCODE: + tag = sv2deptag(type); + ds = rpmteDS(Te, tag); + if (ds != NULL) + if (rpmdsNext(ds) >= 0) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, ds))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmds, ds, ds->nrefs); +#endif + } + +void +Te_files(Te) + rpmte Te + PREINIT: + rpmfi Files; + PPCODE: + Files = rpmteFI(Te, RPMTAG_BASENAMES); + if ((Files = rpmfiInit(Files, 0)) != NULL && rpmfiNext(Files) >= 0) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmfi, Files))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmfi, Files, Files->nrefs); +#endif + } + +MODULE = RPM4 PACKAGE = RPM4 + +# Return a new Dep object +void +newdep(sv_depTag, Name, sv_sense = NULL, sv_evr = NULL) + SV * sv_depTag + char * Name + SV * sv_evr + SV * sv_sense + PPCODE: + PUTBACK; + _newdep(sv_depTag, Name, sv_sense, sv_evr); + SPAGAIN; + +void +rpmlibdep() + PREINIT: + rpmds Dep = NULL; + rpmds next; + const char ** provNames; + int * provFlags; + const char ** provVersions; + int num = 0; + int i; + PPCODE: + num = rpmGetRpmlibProvides(&provNames, &provFlags, &provVersions); + for (i = 0; i < num; i++) { +#ifdef HDLISTDEBUG + fprintf(stderr, "HDEBUG: rpmlibdep %s %s %d\n", provNames[i], provVersions[i], provFlags[i]); +#endif + next = rpmdsSingle(RPMTAG_PROVIDENAME, provNames[i], provVersions[i], provFlags[i]); + rpmdsMerge(&Dep, next); + next = rpmdsFree(next); + } + if (Dep != NULL) { + Dep = rpmdsInit(Dep); + if (rpmdsNext(Dep) >= 0) { + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, Dep))); +#ifdef HDRPMMEM + PRINTF_NEW(bless_rpmds, Dep, Dep->nrefs); +#endif + } + } + +MODULE = RPM4 PACKAGE = RPM4::Header::Dependencies PREFIX = Dep_ + +void +Dep_newsingle(perlclass, sv_tag, name, sv_sense = NULL, sv_evr = NULL) + char * perlclass + SV * sv_tag + char * name + SV * sv_sense + SV * sv_evr + PPCODE: + PUTBACK; + _newdep(sv_tag, name, sv_sense, sv_evr); + SPAGAIN; + +void +Dep_DESTROY(Dep) + rpmds Dep + CODE: +#ifdef HDRPMMEM + PRINTF_FREE(bless_rpmds, Dep, Dep->nrefs); +#endif + Dep = rpmdsFree(Dep); + +int +Dep_count(Dep) + rpmds Dep + CODE: + RETVAL = rpmdsCount(Dep); + OUTPUT: + RETVAL + +int +Dep_move(Dep, index = 0) + rpmds Dep + int index + CODE: + if (index == -1) /* -1 do nothing and give actual index */ + RETVAL = rpmdsIx(Dep); + else + RETVAL = rpmdsSetIx(Dep, index); + OUTPUT: + RETVAL + +void +Dep_init(Dep) + rpmds Dep + CODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + rpmdsInit(Dep); + +int +Dep_next(Dep) + rpmds Dep + CODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + RETVAL = rpmdsNext(Dep); + OUTPUT: + RETVAL + +int +Dep_hasnext(Dep) + rpmds Dep + CODE: + RETVAL = rpmdsNext(Dep) > -1; + OUTPUT: + RETVAL + +int +Dep_color(Dep) + rpmds Dep + CODE: + RETVAL = rpmdsColor(Dep); + OUTPUT: + RETVAL + +int +Dep_find(Dep, depb) + rpmds Dep + rpmds depb + CODE: + RETVAL = rpmdsFind(Dep, depb); + OUTPUT: + RETVAL + +int +Dep_merge(Dep, depb) + rpmds Dep + rpmds depb + CODE: + RETVAL = rpmdsMerge(&Dep, depb); + OUTPUT: + RETVAL + +int +Dep_overlap(Dep1, Dep2) + rpmds Dep1 + rpmds Dep2 + CODE: + CHECK_RPMDS_IX(Dep1); + CHECK_RPMDS_IX(Dep2); + RETVAL = rpmdsCompare(Dep1, Dep2); + OUTPUT: + RETVAL + +void +Dep_info(Dep) + rpmds Dep + PREINIT: + rpmsenseFlags flag; + I32 gimme = GIMME_V; + PPCODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + CHECK_RPMDS_IX(Dep); + if (gimme == G_SCALAR) { + XPUSHs(sv_2mortal(newSVpv(rpmdsDNEVR(Dep), 0))); + } else { + switch (rpmdsTagN(Dep)) { + case RPMTAG_PROVIDENAME: + XPUSHs(sv_2mortal(newSVpv("P", 0))); + break; + case RPMTAG_REQUIRENAME: + XPUSHs(sv_2mortal(newSVpv("R", 0))); + break; + case RPMTAG_CONFLICTNAME: + XPUSHs(sv_2mortal(newSVpv("C", 0))); + break; + case RPMTAG_OBSOLETENAME: + XPUSHs(sv_2mortal(newSVpv("O", 0))); + break; + case RPMTAG_TRIGGERNAME: + XPUSHs(sv_2mortal(newSVpv("T", 0))); + break; + default: + break; + } + XPUSHs(sv_2mortal(newSVpv(rpmdsN(Dep), 0))); + flag = rpmdsFlags(Dep); + XPUSHs(sv_2mortal(newSVpvf("%s%s%s", + flag & RPMSENSE_LESS ? "<" : "", + flag & RPMSENSE_GREATER ? ">" : "", + flag & RPMSENSE_EQUAL ? "=" : ""))); + XPUSHs(sv_2mortal(newSVpv(rpmdsEVR(Dep), 0))); + } + +void +Dep_tag(Dep) + rpmds Dep + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmdsTagN(Dep)))); + +void +Dep_name(Dep) + rpmds Dep + PPCODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + CHECK_RPMDS_IX(Dep); + XPUSHs(sv_2mortal(newSVpv(rpmdsN(Dep), 0))); + +void +Dep_flags(Dep) + rpmds Dep + PPCODE: + CHECK_RPMDS_IX(Dep); + XPUSHs(sv_2mortal(newSViv(rpmdsFlags(Dep)))); + +void +Dep_evr(Dep) + rpmds Dep + PPCODE: + CHECK_RPMDS_IX(Dep); + XPUSHs(sv_2mortal(newSVpv(rpmdsEVR(Dep), 0))); + +int +Dep_nopromote(Dep, sv_nopromote = NULL) + rpmds Dep + SV * sv_nopromote + CODE: + if (sv_nopromote == NULL) { + RETVAL = rpmdsNoPromote(Dep); + } else { + RETVAL = rpmdsSetNoPromote(Dep, SvIV(sv_nopromote)); + } + OUTPUT: + RETVAL + + +int +Dep_add(Dep, name, sv_sense = NULL, sv_evr = NULL) + rpmds Dep + char * name + SV * sv_evr + SV * sv_sense + PREINIT: + rpmsenseFlags sense = RPMSENSE_ANY; + rpmds Deptoadd; + char * evr = NULL; + CODE: + RETVAL = 0; + if (sv_sense && SvOK(sv_sense)) + sense = sv2sens(sv_sense); + if (sv_evr && SvOK(sv_evr)) + evr = SvPV_nolen(sv_evr); + Deptoadd = rpmdsSingle(rpmdsTagN(Dep), name, + evr ? evr : "", sense); + if (Deptoadd) { + rpmdsMerge(&Dep, Deptoadd); + Deptoadd = rpmdsFree(Deptoadd); + RETVAL = 1; + } + OUTPUT: + RETVAL + +int +Dep_matchheader(Dep, header, sv_nopromote = NULL) + Header header + SV * sv_nopromote + rpmds Dep + PREINIT: + int nopromote = 0; + CODE: + if (sv_nopromote != NULL) + nopromote = SvIV(sv_nopromote); + RETVAL = _header_vs_dep(header, Dep, nopromote); + OUTPUT: + RETVAL + +int +Dep_matchheadername(Dep, header, sv_nopromote = NULL) + rpmds Dep + Header header + SV * sv_nopromote + PREINIT: + int nopromote = 0; + CODE: + if (sv_nopromote != NULL) + nopromote = SvIV(sv_nopromote); + RETVAL = _headername_vs_dep(header, Dep, nopromote); + OUTPUT: + RETVAL + +MODULE = RPM4 PACKAGE = RPM4::Header::Files PREFIX = Files_ + +void +Files_DESTROY(Files) + rpmfi Files + PPCODE: +#ifdef HDRPMMEM + PRINTF_FREE(bless_rpmfi, Files, Files->nrefs); +#endif + Files = rpmfiFree(Files); + +int +Files_compare(Files, Fb) + rpmfi Files + rpmfi Fb + CODE: + RETVAL = rpmfiCompare(Files, Fb); + OUTPUT: + RETVAL + +int +Files_move(Files, index = 0) + rpmfi Files; + int index + PREINIT: + int i; + CODE: + index ++; /* keeping same behaviour than Header::Dep */ + rpmfiInit(Files, 0); + RETVAL = 0; + for (i=-1; i < index && (RETVAL = rpmfiNext(Files)) >= 0; i++) {} + if (RETVAL == -1) { + rpmfiInit(Files, 0); + rpmfiNext(Files); + } + OUTPUT: + RETVAL + +int +Files_count(Files) + rpmfi Files + CODE: + RETVAL = rpmfiFC(Files); + OUTPUT: + RETVAL + +int +Files_countdir(Files) + rpmfi Files + CODE: + RETVAL = rpmfiDC(Files); + OUTPUT: + RETVAL + +void +Files_init(Files) + rpmfi Files + CODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + rpmfiInit(Files, 0); + +void +Files_initdir(Files) + rpmfi Files + CODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + rpmfiInitD(Files, 0); + +int +Files_next(Files) + rpmfi Files + CODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + RETVAL = rpmfiNext(Files); + OUTPUT: + RETVAL + +int +Files_hasnext(Files) + rpmfi Files + CODE: + RETVAL = rpmfiNext(Files) > -1; + OUTPUT: + RETVAL + +int +Files_nextdir(Files) + rpmfi Files + CODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; +#endif + RETVAL = rpmfiNextD(Files); + OUTPUT: + RETVAL + +void +Files_filename(Files) + rpmfi Files + PPCODE: +#ifdef HDLISTDEBUG + PRINTF_CALL; + fprintf(stderr, "File %s", rpmfiFN(Files)); +#endif + XPUSHs(sv_2mortal(newSVpv(rpmfiFN(Files), 0))); + +void +Files_dirname(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmfiDN(Files), 0))); + +void +Files_basename(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmfiBN(Files), 0))); + +void +Files_fflags(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmfiFFlags(Files)))); + +void +Files_mode(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmfiFMode(Files)))); + +void +Files_md5(Files) + rpmfi Files + PREINIT: + const byte * md5; + char * fmd5 = malloc((char) 33); + PPCODE: + if ((md5 = rpmfiMD5(Files)) != NULL && *md5 != 0 /* return undef if empty */) { + (void) pgpHexCvt(fmd5, md5, 16); + XPUSHs(sv_2mortal(newSVpv(fmd5, 0))); + } + _free(fmd5); + +void +Files_link(Files) + rpmfi Files + PREINIT: + const char * link; + PPCODE: + if ((link = rpmfiFLink(Files)) != NULL && *link != 0 /* return undef if empty */) { + XPUSHs(sv_2mortal(newSVpv(link, 0))); + } + +void +Files_user(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmfiFUser(Files), 0))); + +void +Files_group(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSVpv(rpmfiFGroup(Files), 0))); + +void +Files_inode(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmfiFInode(Files)))); + +void +Files_size(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmfiFSize(Files)))); + +void +Files_dev(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmfiFRdev(Files)))); + +void +Files_color(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmfiFColor(Files)))); + +void +Files_class(Files) + rpmfi Files + PREINIT: + const char * class; + PPCODE: + if ((class = rpmfiFClass(Files)) != NULL) + XPUSHs(sv_2mortal(newSVpv(rpmfiFClass(Files), 0))); + +void +Files_mtime(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmfiFMtime(Files)))); + +void +Files_nlink(Files) + rpmfi Files + PPCODE: + XPUSHs(sv_2mortal(newSViv(rpmfiFNlink(Files)))); + +MODULE = RPM4 PACKAGE = RPM4 + +void +newspec(filename = NULL, passphrase = NULL, rootdir = NULL, cookies = NULL, anyarch = NULL, force = NULL) + char * filename + SV * passphrase + SV * rootdir + SV * cookies + SV * anyarch + SV * force + PREINIT: + rpmts ts = rpmtsCreate(); + PPCODE: + PUTBACK; + _newspec(ts, filename, passphrase, rootdir, cookies, anyarch, force); + ts = rpmtsFree(ts); + SPAGAIN; + +MODULE = RPM4 PACKAGE = RPM4::Spec PREFIX = Spec_ + +void +Spec_new(perlclass, specfile = NULL, ...) + char * perlclass + char * specfile + PREINIT: + rpmts ts = NULL; + SV * passphrase = NULL; + SV * rootdir = NULL; + SV * cookies = NULL; + SV * anyarch = 0; + SV * force = 0; + int i; + PPCODE: + for(i=2; i < items; i++) { + if(strcmp(SvPV_nolen(ST(i)), "transaction") == 0) { + i++; + if (sv_isobject(ST(i)) && (SvTYPE(SvRV(ST(i))) == SVt_PVMG)) { + ts = (rpmts)SvIV((SV*)SvRV(ST(i))); + ts = rpmtsLink(ts, bless_spec); + } else { + croak( "transaction is not a blessed SV reference" ); + XSRETURN_UNDEF; + } + } else if (strcmp(SvPV_nolen(ST(i)), "force") == 0) { + i++; + force = ST(i); + } else if (strcmp(SvPV_nolen(ST(i)), "anyarch") == 0) { + i++; + anyarch = ST(i); + } else if (strcmp(SvPV_nolen(ST(i)), "passphrase") == 0) { + i++; + passphrase = ST(i); + } else if (strcmp(SvPV_nolen(ST(i)), "root") == 0) { + i++; + rootdir = ST(i); + } else { + warn("Unknown value in " bless_spec "->new, ignored"); + i++; + } + } + if (!ts) + ts = rpmtsCreate(); + PUTBACK; + _newspec(ts, specfile, passphrase, rootdir, cookies, anyarch, force); + SPAGAIN; + ts = rpmtsFree(ts); + +void +Spec_DESTROY(spec) + Spec spec + CODE: +#ifdef HDRPMMEM + PRINTF_FREE(bless_spec, spec, -1); +#endif + freeSpec(spec); + +void +Spec_srcheader(spec) + Spec spec + PPCODE: + if ( ! spec->sourceHeader) + initSourceHeader(spec); + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)headerLink(spec->sourceHeader)))); + +void +Spec_binheader(spec) + Spec spec + PREINIT: + Package pkg; + PPCODE: + for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)headerLink(pkg->header)))); + +void +Spec_srcrpm(spec) + Spec spec + PREINIT: + const char *name, *version, *release; + PPCODE: + (void) headerNVR(spec->packages->header, &name, &version, &release); + XPUSHs(sv_2mortal(newSVpvf("%s/%s-%s-%s.%ssrc.rpm", + rpmGetPath("%{_srcrpmdir}", NULL), + name, version, release, + spec->noSource ? "no" : "" + ))); + headerFreeTag(spec->packages->header, name, RPM_STRING_TYPE); + headerFreeTag(spec->packages->header, version, RPM_STRING_TYPE); + headerFreeTag(spec->packages->header, release, RPM_STRING_TYPE); + +void +Spec_binrpm(spec) + Spec spec + PREINIT: + Package pkg; + const char * binFormat; + char * binRpm; + PPCODE: + for(pkg = spec->packages; pkg != NULL; pkg = pkg->next) { + if (pkg->fileList == NULL) + continue; + /* headerCopyTags(h, pkg->header, copyTags); */ + binFormat = rpmGetPath("%{_rpmfilename}", NULL); + binRpm = headerSprintf(pkg->header, binFormat, rpmTagTable, + rpmHeaderFormats, NULL); + _free(binFormat); + XPUSHs(sv_2mortal(newSVpv(rpmGetPath("%{_rpmdir}/", binRpm, NULL), 0))); + _free(binRpm); + } + +void +Spec_check(spec, ts = NULL) + Spec spec + PREINIT: + int rc; + rpmts ts = rpmtsCreate(); + rpmps ps; + PPCODE: + PUTBACK; + if (ts) + ts = rpmtsLink(ts, "Spec_check"); + else + ts = rpmtsCreate(); + + if ( ! spec->sourceHeader) + initSourceHeader(spec); + + if (!headerIsEntry(spec->sourceHeader, RPMTAG_REQUIRENAME) + && !headerIsEntry(spec->sourceHeader, RPMTAG_CONFLICTNAME)) + /* XSRETURN_UNDEF; */ + return; + + (void) rpmtsAddInstallElement(ts, spec->sourceHeader, NULL, 0, NULL); + + if(rpmtsCheck(ts)) + croak("Can't check rpmts"); /* any better idea ? */ + + ps = rpmtsProblems(ts); + if (ps && ps->numProblems) /* if no problem, return undef */ + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmps, ps))); + ts = rpmtsFree(ts); + SPAGAIN; + + +int +Spec_build(spec, sv_buildflags) + Spec spec + SV * sv_buildflags + PREINIT: + rpmts ts = rpmtsCreate(); + CODE: + RETVAL = _specbuild(ts, spec, sv_buildflags); + ts = rpmtsFree(ts); + OUTPUT: + RETVAL + +const char * +Spec_specfile(spec) + Spec spec + CODE: + RETVAL = spec->specFile; + OUTPUT: + RETVAL + +void +Spec_sources(spec, is = 0) + Spec spec + int is + PREINIT: + struct Source *srcPtr; + PPCODE: + for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) { + char * dest = NULL; + int len; + if (is && !(srcPtr->flags & is)) + continue; + len = strlen(srcPtr->source); + dest = malloc(len); + memcpy(dest, srcPtr->source, len); + XPUSHs(sv_2mortal(newSVpv(dest, len))); + } + +void +Spec_sources_url(spec, is = 0) + Spec spec + int is + PREINIT: + struct Source * srcPtr; + PPCODE: + for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) { + char * dest = NULL; + int len; + if (is && !(srcPtr->flags & is)) + continue; + len = strlen(srcPtr->fullSource); + dest = malloc(len); + memcpy(dest, srcPtr->fullSource, len); + XPUSHs(sv_2mortal(newSVpv(dest, len))); + } + + +MODULE = RPM4 PACKAGE = RPM4::Db::_Problems PREFIX = ps_ + +void +ps_new(perlclass, ts) + char * perlclass + rpmts ts + PREINIT: + rpmps ps; + PPCODE: + ps = rpmtsProblems(ts); + if (ps && ps->numProblems) /* if no problem, return undef */ + XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmps, ps))); + +void +ps_DESTROY(ps) + rpmps ps + PPCODE: + ps = rpmpsFree(ps); + +int +ps_count(ps) + rpmps ps + CODE: + RETVAL = rpmpsNumProblems(ps); + OUTPUT: + RETVAL + +void +ps_print(ps, fp) + rpmps ps + FILE *fp + PPCODE: + rpmpsPrint(fp, ps); + +int +ps_isignore(ps, numpb) + rpmps ps + int numpb + PREINIT: + rpmProblem p; + CODE: + if (ps->numProblems < numpb) + RETVAL = 0; /* croak here ? */ + else { + p = ps->probs + numpb; + RETVAL = p->ignoreProblem; + } + OUTPUT: + RETVAL + +const char * +ps_fmtpb(ps, numpb) + rpmps ps + int numpb + PREINIT: + rpmProblem p; + CODE: + if (ps->numProblems < numpb) + RETVAL = NULL; + else { + p = ps->probs + numpb; + RETVAL = rpmProblemString(p); + } + OUTPUT: + RETVAL + diff --git a/RPM4/src/RPM4sign.c b/RPM4/src/RPM4sign.c new file mode 100644 index 0000000..04bb60f --- /dev/null +++ b/RPM4/src/RPM4sign.c @@ -0,0 +1,28 @@ +/* $Id$ */ + +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#undef Fflush +#undef Mkdir +#undef Stat + +#include <rpm/rpmcli.h> + +#include "RPM4.h" + +/* Hight level function */ +int rpmsign(char *passphrase, const char *rpm) { + QVA_t qva = &rpmQVKArgs; + const char * file[2]; + + file[0] = rpm; + file[1] = NULL; + + qva->qva_mode = RPMSIGN_ADD_SIGNATURE; + qva->passPhrase = passphrase; + + return rpmcliSign(NULL, qva, file); +} + diff --git a/RPM4/src/typemap b/RPM4/src/typemap new file mode 100644 index 0000000..1889a0a --- /dev/null +++ b/RPM4/src/typemap @@ -0,0 +1,21 @@ +TYPEMAP +Header O_OBJECT +Spec O_OBJECT +rpmts O_OBJECT +rpmds O_OBJECT +rpmfi O_OBJECT +rpmte O_OBJECT +rpmps O_OBJECT + +INPUT +O_OBJECT + if (sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG)) + $var = ($type)SvIV((SV*)SvRV( $arg )); + else { + warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" ); + XSRETURN_UNDEF; + } + +OUTPUT +O_OBJECT + sv_setref_pv( $arg, (char *)CLASS, (void*)$var ); diff --git a/RPM4/t/01compile.t b/RPM4/t/01compile.t new file mode 100644 index 0000000..568a258 --- /dev/null +++ b/RPM4/t/01compile.t @@ -0,0 +1,12 @@ +# $Id$ + +use Test::More tests => 3; + +use_ok('RPM4'); +can_ok('RPM4', qw/rpm2header stream2header dumprc dumpmacros newdb/); + +#Header + +# Db +can_ok('RPM4::Transaction', qw/traverse transadd transremove transcheck transorder transrun + importpubkey checkrpm transreset/); diff --git a/RPM4/t/02header.t b/RPM4/t/02header.t new file mode 100644 index 0000000..7bba1a4 --- /dev/null +++ b/RPM4/t/02header.t @@ -0,0 +1,78 @@ +# $Id$ + +use strict; +use Test::More tests => 40; +use FindBin qw($Bin); +use RPM4; + +my $headerfile; + +{ +my $hdr = RPM4::Header->new(); +isa_ok($hdr, "RPM4::Header", "Creating empty header works"); +ok(! defined $hdr->tag(1000), "empty tag return nothings"); +} + +{ +my $hdr = RPM4::Header->new("$Bin/test-rpm-1.0-1mdk.src.rpm"); +isa_ok($hdr, "RPM4::Header", "instanciating an header from a source rpm works"); +ok($hdr->hastag(1000) eq 1, "Has tag 1000 (NAME), yes"); +ok($hdr->hastag("NAME") eq 1, "Has 'NAME', yes"); +ok($hdr->hastag(1106) eq 1, "Has tag 1106 (SOURCEPACKAGE), yes"); +ok($hdr->listtag(), "can list tag"); +is($hdr->tag(1000), "test-rpm", "accessing tag by id works"); +is($hdr->tag("NAME"), "test-rpm", "accessing tag by name works"); +is($hdr->NAME(), "test-rpm", "accessing tag directly works"); +ok($hdr->queryformat("%{NAME}-%{VERSION}-%{RELEASE}") eq "test-rpm-1.0-1mdk", "Queryformat is ok"); +ok($hdr->nevr() eq "test-rpm-1.0-1mdk", "header->nevr works"); +ok(scalar($hdr->fullname) eq "test-rpm-1.0-1mdk.src", "scalar fullname works"); +ok(join(",", $hdr->fullname) eq "test-rpm,1.0,1mdk,src", "wantarray fullname works"); +ok($hdr->issrc == 1, "Is a src, Yes !"); +ok($hdr->sourcerpmname eq "test-rpm-1.0-1mdk.src.rpm", "sourcerpmname works"); +ok($hdr->removetag(1000) == 0, "Removing a tag"); +ok(! defined $hdr->tag(1000), "tag is not present"); +ok($hdr->addtag(1000, 6, "new name") == 1, "Adding a tag (string type)"); +ok($hdr->tag(1000) eq "new name", "Added tag return good value"); +} + +{ +my $hdr = RPM4::Header->new("$Bin/test-rpm-1.0-1mdk.noarch.rpm"); +isa_ok($hdr, "RPM4::Header", "instanciating an header from a binary rpm works"); +ok($hdr->hastag(1000) eq 1, "Has tag 1000 (NAME), yes"); +ok($hdr->tagtype(1000) eq RPM4::tagtypevalue("STRING"), "can get type of a tag"); +ok($hdr->hastag(1106) eq 0, "Has tag 1106 (SOURCEPACKAGE), no"); +ok($hdr->listtag(), "can list tag"); +is($hdr->tag(1000), "test-rpm", "accessing tag by id works"); +is($hdr->tag("NAME"), "test-rpm", "accessing tag by name works"); +is($hdr->NAME(), "test-rpm", "accessing tag directly works"); +ok($hdr->queryformat("%{NAME}-%{VERSION}-%{RELEASE}") eq "test-rpm-1.0-1mdk", "Queryformat is ok"); +ok(scalar($hdr->fullname) eq "test-rpm-1.0-1mdk.noarch", "scalar fullname works"); +ok(join(",", $hdr->fullname) eq "test-rpm,1.0,1mdk,noarch", "wantarray fullname works"); +ok($hdr->issrc == 0, "Is a src, No !"); +ok($hdr->sourcerpmname eq "test-rpm-1.0-1mdk.src.rpm", "sourcerpmname works"); +$headerfile = scalar($hdr->fullname).".hdr"; + + +my $hdrcopy = $hdr->copy(); +ok(defined $hdrcopy, "copy works"); +ok($hdrcopy->tag(1000) eq 'test-rpm', "tag 1000 (NAME) from copy works"); + +open(my $hdfh, ">", $headerfile); +ok($hdr->write($hdfh), "Write the header works"); +close($hdfh); + +my $size = $hdr->hsize; +ok($size != 0, "Header size works"); +ok($size == (stat($headerfile))[7], "file size is same than in memory"); +} + +{ +open(my $hdfh, "< $headerfile"); +my $hdr2 = RPM4::Header->new($hdfh); +isa_ok($hdr2, "RPM4::Header", "instanciating an header from a stream works"); +close $hdfh; +unlink($headerfile); +ok($hdr2->tag(1000) eq 'test-rpm', "tag 1000 from header file works"); +} + + diff --git a/RPM4/t/03rpmlib.t b/RPM4/t/03rpmlib.t new file mode 100755 index 0000000..24681bb --- /dev/null +++ b/RPM4/t/03rpmlib.t @@ -0,0 +1,86 @@ +# $Id$ + +use strict; +use Test::More tests => 52; +use FindBin qw($Bin); +use RPM4; + +ok(! defined(RPM4::setverbosity("DEBUG")), "Set verbosity works"); +{ +my $marker = 0; +ok(! defined(RPM4::setlogcallback(sub { my %m = @_; $marker = 1; print "$m{priority}: $m{msg}\n" } )), + "Setting log callback function works"); +ok(!defined(RPM4::rpmlog("ERR", "This is a rpm debug message")), "rpmlog function works"); +ok($marker == 1, "rpmlogcallback has been called"); +} +ok(! defined(RPM4::setlogcallback(undef)), "remove callback function"); +ok(RPM4::setlogfile("logfile"), "set a log file"); +ok(!defined(RPM4::rpmlog(7, "This is a rpm debug message")), "rpmlog function works"); +ok(RPM4::setlogfile(undef), "set a log file"); +unlink("logfile"); + +# Generic query: +open(my $null, ">", "/dev/null"); +ok(!RPM4::dumprc($null), "Can dumprc"); +ok(!RPM4::dumpmacros($null), "Can dumpmacros"); +close($null); +ok(length(RPM4::getosname), "Return OS name"); +ok(length(RPM4::getarchname), "Return arch name"); +ok(length(RPM4::buildhost), "Return buildhost"); + +# Playing with macros +my $target_cpu = RPM4::expand("%_target_cpu"); +ok(($target_cpu !~ /^\%/), "Getting _target_cpu macro"); +# setting test_macro to test +ok(RPM4::expand("%test_macro") eq "%test_macro", "\%test_macro is no set"); +RPM4::add_macro("test_macro test"); +ok(RPM4::expand("%test_macro") eq "test", "add_macro works"); +RPM4::del_macro("test_macro"); +ok(RPM4::expand("%test_macro") eq "%test_macro", "del_macro works"); +RPM4::add_macro("test_macro test"); +ok(RPM4::expand("%test_macro") eq "test", "add_macro works"); +ok(!RPM4::resetmacros(), "Reset macro works"); +ok(!RPM4::resetrc(), "Reset rc works"); +ok(RPM4::expand("%test_macro") eq "%test_macro", "resetmacros works"); +RPM4::loadmacrosfile("$Bin/rpmmacros"); +ok(RPM4::expand("%RPM4") eq "perl-RPM4", "Checking macros define in our rpmmacros"); +ok(!RPM4::add_macro("_numeric 1"), "Add numeric macro"); +ok(RPM4::expandnumeric("%_numeric"), "expandnumeric works"); + +ok(RPM4::readconfig("t/rpmrc") == 0, "Reading alternate config file"); +ok(RPM4::readconfig(undef, "xtentas-MandrakeSoft-osf1") == 0, "Reading conf for xtentas-MandrakeSoft-osf1"); +ok(RPM4::expand("%_target_cpu") eq "xtentas", "the conf is properly load"); +ok(RPM4::readconfig() == 0, "Re-Reading the conf, reset to default"); +ok(RPM4::expand("%_target_cpu") eq $target_cpu, "the conf is properly load"); + + +ok(RPM4::tagName(1000) eq "Name", "tagName works"); +ok(RPM4::tagValue("NAME") == 1000, "tagValue works"); +ok(RPM4::tagtypevalue("STRING"), "Get tage type value"); + +# Version comparison +ok(RPM4::rpmvercmp("1mdk", "1mdk") == 0, "rpmvercmp with ="); +ok(RPM4::rpmvercmp("1mdk", "2mdk") == -1, "rpmvercmp with <"); +ok(RPM4::rpmvercmp("2mdk", "1mdk") == 1, "rpmvercmp with >"); + +ok(RPM4::compare_evr("1", "1") == 0, "comparing version only, equal"); +ok(RPM4::compare_evr("2", "1") == 1, "comparing version only, higther"); +ok(RPM4::compare_evr("1", "2") == -1, "comparing version only, lesser"); +ok(RPM4::compare_evr("1-1mdk", "1-1mdk") == 0, "comparing version-release only, equal"); +ok(RPM4::compare_evr("2-1mdk", "1-1mdk") == 1, "comparing version-release only, higther"); +ok(RPM4::compare_evr("1-1mdk", "2-1mdk") == -1, "comparing version-release only, lesser"); +ok(RPM4::compare_evr("1:1-1mdk", "1:1-1mdk") == 0, "comparing epoch:version-release only, equal"); +ok(RPM4::compare_evr("2:1-1mdk", "1:1-1mdk") == 1, "comparing epoch:version-release only, higther"); +ok(RPM4::compare_evr("1:1-1mdk", "2:1-1mdk") == -1, "comparing epoch:version-release only, lesser"); + +ok(RPM4::compare_evr("0:1-1mdk", "1-1mdk") == 1, "comparing epoch 0 vs no epoch"); +ok(RPM4::compare_evr("1:1-1mdk", "1-1mdk") == 1, "comparing epoch 1 vs no epoch"); +ok(RPM4::compare_evr("1.0-1mdk", "1.0") == 1, "comparing version-release vs version only"); +ok(RPM4::compare_evr("0:1-1mdk", "1.0") == 1, "comparing epoch:version-release vs no version"); + +ok(RPM4::osscore("osf1") == 0, "get os score"); +ok(RPM4::osscore("osf1", 1) == 0, "get build os score"); + +ok(RPM4::archscore("noarch") != 0, "get arch score"); +ok(RPM4::archscore("noarch", 1) != 0, "get arch score"); + diff --git a/RPM4/t/04spec.t b/RPM4/t/04spec.t new file mode 100644 index 0000000..b1019eb --- /dev/null +++ b/RPM4/t/04spec.t @@ -0,0 +1,62 @@ +# $Id$ + +use strict; +use Test::More tests => 23; +use FindBin qw($Bin); +use File::Temp qw(tempdir); +use RPM4; + +my %info = RPM4::moduleinfo(); + +my $testdir = tempdir( CLEANUP => 1 ); +mkdir("$testdir/$_") foreach (qw(BUILD RPMS RPMS/noarch SRPMS)); + +my $passphrase = "RPM4"; + +RPM4::add_macro("_tmppath $testdir"); +RPM4::add_macro("_builddir $testdir"); +RPM4::add_macro("_topdir $testdir"); +RPM4::add_macro("_signature gpg"); +RPM4::add_macro("_gpg_name RPM4 test key"); +RPM4::add_macro("_gpg_path $Bin/gnupg"); + +ok((RPM4::installsrpm("$Bin/test-rpm-1.0-1mdk.src.rpm"))[0] =~ m/test-rpm\.spec$/, "installsrpms works"); +ok(!RPM4::installsrpm("$Bin/test-rpm-1.0-1mdk.noarch.rpm"), "installsrpms works"); + +my $spec; +if ($info{Hack} eq "Yes") { + ok( defined(RPM4::Spec->new()), "Create an empty spec object"); +} else { + ok(! defined(RPM4::Spec->new()), "Create an empty spec object don't works"); +} +ok(!defined($spec = RPM4::Spec->new("$Bin/test-rpm-1.0-1mdk.noarch.rpm")), "Loading a bad spec file"); +ok($spec = RPM4::Spec->new("$Bin/test-rpm.spec", passphrase => $passphrase), "Loading a spec file"); + +my @rpms = $spec->binrpm; +ok(@rpms == 1, "Can find binary package"); +ok($rpms[0] =~ m!noarch/test-rpm-1.0-1mdk.noarch.rpm$!, "binrpm return good value"); + +ok($spec->srcrpm =~ m!SRPMS/test-rpm-1.0-1mdk.src.rpm$!, "srcrpm return good value"); + +ok(!defined($spec->check()), "Running spec::check"); + +my $h; +ok(defined($h = $spec->srcheader()), "Geting source header before build"); +ok($h->queryformat("%{NAME}") eq "test-rpm", "can querying header give by spec"); + +ok($spec->build([ qw(PREP) ]) == 0, "simulate rpm -bp (check prep)"); +ok($spec->build([ qw(BUILD) ]) == 0, "simulate rpm -bc"); +ok($spec->build([ qw(INSTALL CHECK) ]) == 0, "simulate rpm -bi"); +ok($spec->build([ qw(FILECHECK) ]) == 0, "simulate rpm -bl"); +ok($spec->build([ qw(PACKAGEBINARY CLEAN) ]) == 0, "simulate rpm -bb (binary, clean)"); +ok($spec->build([ qw(PACKAGESOURCE) ]) == 0, "simulate rpm -bs"); +ok($spec->rpmbuild("bb") == 0, "testing spec->rpmbuild(-bb)"); +ok($spec->build([ qw(RMBUILD RMSOURCE) ]) == 0, "simulate cleaning spec, source, build"); + +ok(defined($h = $spec->srcheader()), "Geting source header after build"); +ok($h->queryformat("%{NAME}") eq "test-rpm", "can querying header give by spec"); + +my ($bh) = $spec->binheader(); +ok(defined($bh), "Can get binary header from spec"); +ok($bh->queryformat("%{NAME}") eq "test-rpm", "can querying header give by spec"); + diff --git a/RPM4/t/05transaction.t b/RPM4/t/05transaction.t new file mode 100644 index 0000000..8ee1f44 --- /dev/null +++ b/RPM4/t/05transaction.t @@ -0,0 +1,147 @@ +# $Id$ + +use strict; +use Test::More tests => 50; +use FindBin qw($Bin); +use File::Path; +use File::Temp qw/tempdir/; +use RPM4; +use RPM4::Transaction::Problems; + +# Test on wrong db +RPM4::add_macro("_dbpath /dev/null"); +ok(RPM4::rpmdbverify() != 0, "Verify non existing database (get error)"); + +my $tempdir = tempdir(); +rmtree($tempdir) if $tempdir; +my $testdir = "$tempdir/testdb"; +mkdir $testdir; + +RPM4::add_macro("_dbpath $testdir"); + +ok(RPM4::rpmdbinit() == 0, "initdb works"); +ok(RPM4::rpmdbrebuild() == 0, "rebuild database"); +ok(RPM4::rpmdbverify() == 0, "Verify empty"); + +my $ts; +ok($ts = RPM4::Transaction->new(), "Open a new database"); +ok($ts->traverse(sub { print STDERR $_->tag(1000) . "\n"; }) != -1, "db->traverse()"); + +ok($ts->importpubkey("$Bin/gnupg/test-key.gpg") == 0, "Importing a public key"); + +my $hd = RPM4::rpm2header("$Bin/test-dep-1.0-1mdk.noarch.rpm"); +ok($hd, "Reading the header works"); + +ok($ts->transadd($hd, "$Bin/test-dep-1.0-1mdk.noarch.rpm") == 0, "Adding a package to transaction works"); +ok($ts->transcheck() == 0, "Checking transaction works"); +ok($ts->transorder() == 0, "Run transaction order"); + +if (0){ +my $pbs = RPM4::Transaction::Problems->new($ts); +isa_ok( + $pbs, + 'RPM4::Db::Problems', + 'Can retrieve pb from transaction' +); + +ok($pbs->count, "Can get number of problems"); + +ok($pbs->init() || 1, "Resetting problems counter"); +my $strpb; +while($pbs->hasnext()) { + $strpb .= $pbs->problem(); +} +ok($strpb, "Can get problem description"); +} + +ok(defined($ts->transflag([qw(TEST)])), "Set transflags"); +ok($ts->transrun([ qw(LABEL PERCENT) ]) == 0, "Running transaction justdb"); +ok(!defined($ts->transreset()), "Resetting transaction"); + +my $h = RPM4::rpm2header("$Bin/test-rpm-1.0-1mdk.noarch.rpm"); +ok($h, "Reading the header works"); + +ok($ts->transadd($h, "$Bin/test-rpm-1.0-1mdk.noarch.rpm") == 0, "Adding a package to transaction works"); +ok($ts->traverse_transaction(sub { + ok($_[0]->fullname, "Can get name from te"); + ok($_[0]->type, "Can get type from te"); +}), "traverse_transaction works"); + +ok($ts->transcheck() == 0, "Checking transaction works"); +ok($ts->transorder() == 0, "Run transaction order"); + +ok(defined($ts->transflag([qw(JUSTDB)])), "Set transflags"); +ok($ts->transrun( sub { my %a = @_; print STDERR "$a{what} $a{filename} $a{amount} / $a{total}\n"; }) == 0, "Running transaction justdb"); + +ok($ts->injectheader($hd) == 0, "Injecting header in a db"); + +my $found = 0; +my ($rhf, $roffset); +ok($ts->traverse( sub { + my ($hf, $offset) = @_; + scalar($hf->fullname()) eq "test-dep-1.0-1mdk.noarch" and do { + $found++; + ($rhf, $roffset) = ($hf, $offset); + }; + 1; + }), "Running traverse"); + +ok($found, "Can find heaer in db"); +ok($ts->deleteheader($roffset) == 0, "Removing header from db"); + +$ts = undef; # explicitely calling DESTROY to close database + +ok($ts = RPM4::newdb(1), "Open existing database"); +$found = 0; + +($rhf, $roffset) = (undef, undef); +ok($ts->traverse( sub { + my ($hf, $offset) = @_; + scalar($hf->fullname()) eq "test-rpm-1.0-1mdk.noarch" and do { + $found++; + ($rhf, $roffset) = ($hf, $offset); + } + }), "Running traverse"); + +ok($found == 1, "The previously installed rpm is found"); +ok($roffset > 0, "Retrieve offset db"); + +ok($ts->transremove_pkg("test-rpm(1.0-1mdk)") == 1, "Try to remove a rpm"); +ok($ts->transcheck() == 0, "Checking transaction works"); +ok(!defined($ts->transreset()), "Reseting current transaction"); + +ok($ts->transremove($roffset), "Removing pkg from header and offset"); +ok($ts->transorder() == 0, "Run transaction order"); +ok($ts->transcheck() == 0, "Checking transaction works"); +ok(defined($ts->transflag([qw(JUSTDB)])), "Set transflags"); +ok($ts->transrun([ qw(LABEL PERCENT) ]) == 0, "Running transaction justdb"); + +$found = 0; + +ok($ts->traverse( sub { + my ($hf, $offset) = @_; + scalar($hf->fullname()) eq "test-rpm-1.0-1mdk.noarch" and do { + $found++; + ($rhf, $roffset) = ($hf, $offset); + } + }), "Running traverse"); + +ok($found == 0, "The previously removed rpm is not found"); + +ok($ts->transadd($h, "test-rpm-1.0-1mdk.noarch.rpm", 1, "/usr", 1) == 0, "Adding a package to transaction with prefix"); +ok($ts->transorder() == 0, "Run transaction order"); +ok($ts->transcheck() == 0, "Checking transaction works"); +ok(!defined($ts->transreset()), "Reseting current transaction"); + +ok($ts->transadd($h, "test-rpm-1.0-1mdk.noarch.rpm", 1, {"/etc" => "/usr" }, 1) == 0, "Adding a package to transaction with relocation works"); +ok($ts->transorder() == 0, "Run transaction order"); +ok($ts->transcheck() == 0, "Checking transaction works"); +ok(!defined($ts->transreset()), "Reseting current transaction"); + +{ +my $spec = $ts->newspec("$Bin/test-rpm.spec"); +isa_ok($spec, 'RPM4::Spec', 'ts->newspec'); +} + +$ts = undef; # explicitely calling DESTROY to close database +rmtree($tempdir); diff --git a/RPM4/t/06sign.t b/RPM4/t/06sign.t new file mode 100644 index 0000000..5dd0c02 --- /dev/null +++ b/RPM4/t/06sign.t @@ -0,0 +1,33 @@ +# $Id$ + +use strict; +use Test::More tests => 6; +use FindBin qw($Bin); +use File::Temp qw(tempdir); +use File::Copy; +use RPM4; + +my $passphrase = "RPM4"; + +my $testdir = tempdir( CLEANUP => 1 ); + +RPM4::add_macro("_dbpath $testdir"); + +copy("$Bin/test-rpm-1.0-1mdk.noarch.rpm", "$testdir"); + +RPM4::add_macro("_signature gpg"); +RPM4::add_macro("_gpg_name RPM4 test key"); +RPM4::add_macro("_gpg_path $Bin/gnupg"); + +ok(RPM4::rpmresign($passphrase, "$testdir/test-rpm-1.0-1mdk.noarch.rpm") == 0, "can resign a rpm"); + +ok(my $db = RPM4::newdb(1), "Open a new database"); + +ok($db->checkrpm("$testdir/test-rpm-1.0-1mdk.noarch.rpm") != 0, "checking a rpm, key is missing"); +ok($db->checkrpm("$testdir/test-rpm-1.0-1mdk.noarch.rpm", [ "NOSIGNATURES" ]) == 0, "checking a rpm, no checking the key"); + +ok($db->importpubkey("$Bin/gnupg/test-key.gpg") == 0, "Importing a public key"); + +ok($db->checkrpm("$testdir/test-rpm-1.0-1mdk.noarch.rpm") == 0, "checking a rpm file"); + +$db = undef; diff --git a/RPM4/t/07changelogs.t b/RPM4/t/07changelogs.t new file mode 100644 index 0000000..d2c2555 --- /dev/null +++ b/RPM4/t/07changelogs.t @@ -0,0 +1,18 @@ +# $Id$ + +use strict; +use Test::More tests => 1; +use FindBin qw($Bin); +use RPM4; +use RPM4::Header::Changelogs; + +my $htest = RPM4::Header->new("$Bin/test-rpm-1.0-1mdk.noarch.rpm"); + +my $ch = RPM4::Header::Changelogs->new($htest); + +isa_ok( + $ch, + 'RPM4::Header::Changelogs', + 'Get changelogs object' +); + diff --git a/RPM4/t/07dep.t b/RPM4/t/07dep.t new file mode 100644 index 0000000..e51327e --- /dev/null +++ b/RPM4/t/07dep.t @@ -0,0 +1,97 @@ +# $Id$ + +use strict; +use Test::More tests => 43; +use FindBin qw($Bin); +use RPM4; +use RPM4::Header::Dependencies; + +isa_ok( + RPM4::rpmlibdep(), + 'RPM4::Header::Dependencies', + "Can get a dep for rpmlib" +); + +my $htest = RPM4::Header->new("$Bin/test-rpm-1.0-1mdk.noarch.rpm"); +my $hdep = RPM4::Header->new("$Bin/test-dep-1.0-1mdk.noarch.rpm"); +isa_ok($htest, 'RPM4::Header', '$htest'); +isa_ok($hdep, 'RPM4::Header' , '$hdep'); + +isa_ok( + $hdep->dep("CONFLICTNAME"), + 'RPM4::Header::Dependencies', + '$hdep->dep("CONFLICTNAME")' +); +isa_ok( + $hdep->dep("REQUIRENAME"), + 'RPM4::Header::Dependencies', + '$hdep->dep("REQUIRENAME")' +); +isa_ok( + $hdep->dep("OBSOLETENAME"), + 'RPM4::Header::Dependencies', + '$hdep->dep("OBSOLETENAME")' +); +isa_ok( + $hdep->dep("PROVIDENAME"), + 'RPM4::Header::Dependencies', + '$hdep->dep("PROVIDENAME")' +); +ok( + ! defined $hdep->dep("TRIGGERNAME"), + "fetching triggers returns undef" +); + +ok($htest->compare($hdep) == 0, "Compare two header"); +ok($hdep->compare($htest) == 0, "Compare two header"); + +ok(! defined($htest->hchkdep($hdep, "REQUIRENAME")), "test-rpm requires test-dep, no"); +ok( defined($hdep->hchkdep($htest, "REQUIRENAME")), "test-dep requires test-rpm, yes"); +ok(! defined($htest->hchkdep($hdep, "OBSOLETENAME")), "test-rpm obsoletes test-dep, no"); +ok( defined($hdep->hchkdep($htest, "OBSOLETENAME")), "test-dep obsoletes test-rpm, yes"); +ok(! defined($htest->hchkdep($hdep, "CONFLICTNAME")), "test-rpm conflics test-dep, no"); +ok( defined($hdep->hchkdep($htest, "CONFLICTNAME")), "test-dep conflicts test-rpm, yes"); +ok(! defined($htest->hchkdep($hdep, "TRIGGERNAME")), "test-rpm trigger test-dep, no"); +ok(! defined($hdep->hchkdep($htest, "TRIGGERNAME")), "test-dep trigger test-rpm, no"); +ok(! defined($htest->hchkdep($hdep, "PROVIDENAME")), "test-rpm provide test-dep, no"); +ok(! defined($hdep->hchkdep($htest, "PROVIDENAME")), "test-dep provide test-rpm, no"); + +ok( $hdep->is_better_than($htest), "test-dep better than test-rpm: yes"); +ok(! $htest->is_better_than($hdep), "test-rpm better than test-dep: no"); + +my ($dep1, $dep2, $dep3); +isa_ok( + RPM4::Header::Dependencies->new("REQUIRENAME", + [ "test-rpm", [ qw/LESS EQUAL/ ], "1.0-1mdk" ] + ), + 'RPM4::Header::Dependencies', + 'New REQUIRENAME dependencies' +); + +ok($dep1 = RPM4::newdep("REQUIRENAME", "test-rpm", [ qw/LESS EQUAL/ ], "1.0-1mdk"), "Build a new dep"); +ok($dep2 = RPM4::newdep("REQUIRENAME", "test-rpm", [ qw/GREATER EQUAL/ ], "1.0-1mdk"), "Build a new dep"); +ok($dep3 = RPM4::newdep("REQUIRENAME", "test-rpm", [ "GREATER" ], "1.0-1mdk"), "Build a new dep"); + +is($dep1->count(), 1, "dependencies number"); +ok(defined($dep1->move()), "Can move into dep"); +ok($dep1->next() == -1, "no further dependency"); + +ok($dep1->add("test-dep", [ qw/LESS EQUAL/ ], "1.0-1mdk"), "Add a dep entry into existing dep"); + +ok(scalar($dep1->info()) eq "R test-rpm <= 1.0-1mdk", "Can get info from RPM4::Header::Dep"); +ok(($dep1->info())[3] eq "1.0-1mdk", "Can get info from RPM4::Header::Dep"); +ok($dep1->name() eq 'test-rpm', "Get dep name from RPM4::Header::Dep"); +ok($dep1->flags(), "Get dep flags from RPM4::Header::Dep"); +ok($dep1->evr() eq '1.0-1mdk', "Get dep evr from RPM4::Header::Dep"); + +ok($dep1->overlap($dep2), "compare two dep"); +ok($dep1->overlap($dep3) == 0, "compare two dep"); + +ok($htest->matchdep($dep1), "Test single dep PROVIDE"); +ok($htest->matchdep($dep3) == 0, "Test single dep REQUIRE"); + +ok($hdep->matchdep($dep1) == 0, "Test single dep PROVIDE"); +ok($htest->matchdep($dep2), "Test single dep REQUIRE"); + +ok( $dep1->matchheadername($htest), "Dependancy match header name: yes"); +ok(! $dep1->matchheadername($hdep), "Dependancy match header name: no"); diff --git a/RPM4/t/07files.t b/RPM4/t/07files.t new file mode 100644 index 0000000..ee5388f --- /dev/null +++ b/RPM4/t/07files.t @@ -0,0 +1,37 @@ +# $Id$ + +use strict; +use Test::More tests => 10; +use FindBin qw($Bin); +use RPM4; + +my $htest = RPM4::Header->new("$Bin/test-rpm-1.0-1mdk.noarch.rpm"); +isa_ok($htest, 'RPM4::Header', '$htest'); + +my $files = $htest->files(); +isa_ok($files, 'RPM4::Header::Files', '$files'); + +is( + $files->count(), + 1, + "files count OK" +); +like( + $files->filename(), + qr!^/!, + "filename OK" +); +like( + $files->dirname(), + qr!^/!, + "dirname OK" +); +ok(defined($files->basename()), "Can get Files::basename()"); +ok(defined($files->fflags()), "Can get Files::fflags()"); +is( + $files->md5(), + "b9cb4e3dc1b8007e5c9678d1acecac47", + "md5 is OK" +); +ok(!defined($files->link()), "Can get Files::link()"); +ok(defined($files->mode()), "Can get Files::mode()"); diff --git a/RPM4/t/09hdlist.t b/RPM4/t/09hdlist.t new file mode 100644 index 0000000..17d32f4 --- /dev/null +++ b/RPM4/t/09hdlist.t @@ -0,0 +1,27 @@ +# $Id$ + +use strict; +use Test::More tests => 6; +use FindBin qw($Bin); +use File::Temp qw(tempdir); +use File::Glob; + +my $testdir = tempdir( CLEANUP => 1 ); + +use_ok('RPM4'); +use_ok('RPM4::Index'); + +my @headers; +my $callback = sub { my %arg = @_; defined($arg{header}) and push(@headers, $arg{header}); }; + +my @rpms = <$Bin/*.rpm>; + +RPM4::parserpms(callback => $callback, rpms => [ @rpms ]); +ok(scalar(@headers) == 4, "RPM4::parserpms works"); + +ok(RPM4::Index::buildhdlist(hdlist => "$testdir/hdlist.cz", rpms => [ @rpms ]), + "Creating a hdlist"); +ok(RPM4::Index::buildsynthesis(synthesis => "$testdir/synthesis.hdlist.cz", rpms => [ @rpms ]), + "Creating a synthesis"); +ok(RPM4::Index::buildindex(list => "$testdir/list", rpms => [ @rpms ]), + "Creating a list file"); diff --git a/RPM4/t/11media.t b/RPM4/t/11media.t new file mode 100644 index 0000000..6df34bf --- /dev/null +++ b/RPM4/t/11media.t @@ -0,0 +1,11 @@ +# $Id$ + +use strict; +use Test::More tests => 1; + +use_ok('RPM4::Media'); + + + + + diff --git a/RPM4/t/gnupg/passphrase b/RPM4/t/gnupg/passphrase new file mode 100644 index 0000000..0bff4aa --- /dev/null +++ b/RPM4/t/gnupg/passphrase @@ -0,0 +1,6 @@ +RPM4 + +# $Id$ +# This is key passphrase, this key is here only for testing. +# Do not use it for signing/crypting. +# Do not trust it. diff --git a/RPM4/t/gnupg/pubring.gpg b/RPM4/t/gnupg/pubring.gpg Binary files differnew file mode 100644 index 0000000..77672f4 --- /dev/null +++ b/RPM4/t/gnupg/pubring.gpg diff --git a/RPM4/t/gnupg/secring.gpg b/RPM4/t/gnupg/secring.gpg Binary files differnew file mode 100644 index 0000000..35d1b0a --- /dev/null +++ b/RPM4/t/gnupg/secring.gpg diff --git a/RPM4/t/gnupg/test-key.gpg b/RPM4/t/gnupg/test-key.gpg new file mode 100644 index 0000000..f016987 --- /dev/null +++ b/RPM4/t/gnupg/test-key.gpg @@ -0,0 +1,26 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.4 (GNU/Linux) + +mQGiBEDpJpERBACs+drbbg4K8tPXhyTZdgwDDmejQrBFxqiPwu4CSrpx8qvjEieU +JRGmwrv1pCSgag6bOF+04cnjaHT/FwUQpokDWRFWrHlJoFFHaP32I1n+nj/bv5Bg +pUKgF5ZU8Jd8OeG9TZzzZUQ/EF9/QvpCN7ZdqkMoTRTzj8O8Pa6L5x/+EwCgpwA2 +1ULjab5DlcODWeBOltLtiGUD/jFBKDvOq+XxeRi4k8gEvI3UPs4utMir/e2hw1yC +N6G3TZpOJHx+iMuy1LoqrBcwz3pZb1MwucA+QlF/imBBWurirFblOcGuw3Un6+Ef +AeQ0kqX/76WN161xu6FAYkfIg7XUvdlEMM4svDl0jm7NbzBJHsw3Z84/jusPmCGJ +hRCzBACTopdtD8FBzvihiCL7Fql4Vqu1U/kt2+fMXPDSduzUe8c0lgI2Irk0DBsH +w3in1FaZrtai5f521v4b8Xqazcq7lcPVZFTrhPD8b1h21STKi4aB8QwZHZSLbP0A +0kGLFqhyuBQ0sBRRQXNrjSufIuTto+BOplQ9srYX9dR9nssdB7R9SGRsaXN0IHRl +c3Qga2V5IChUaGlzIGtleSBpcyBvbmx5IGZvciB0ZXN0aW5nIHJwbSBzaWduaW5n +IHNvZnR3YXJlLCBETyBOT1QgVVNFUyBJVCwgRE8gTk9UIFRSVVNUIElUKSA8ZGV2 +ZWxAbWFuZHJha2Vzb2Z0LmNvbT6IXgQTEQIAHgUCQOkmkQIbAwYLCQgHAwIDFQID +AxYCAQIeAQIXgAAKCRAqlxaKod9cSNLHAJ4xiVz5RIwpilxIszS+lOfs72ldFgCd +HUFDq3t/xU+J/YdyOC2U6ojrbLy5AQ0EQOkmkRAEAMNv7Re/vT+jARIqrbbEyHjv +vgqKiDEiBwowXOO7e3JVhGUG/vZqRFFUkPXxaXFIfosgbWFqNiKwPwTs5Avtm5gc +U0BsxaeHsy9O4lCpyPaFc62qtDiqukRCGTRCrK0TmAJULgJmYh90fxAX11KL8fUi +05qcI/mdM317kC6jYErjAAMFA/9WmDbkYlMAPlrU8oKSduXeFFBLTdG+5XNtf62E +c+VKDcZKzRohEUYG/FLlzoLKp7nqGEnTaCldqIUIvJvC+5fuAVfhiae3SyAqHNxZ +lTgIzAqjsaYOdVk2xZQZMiSM+UqTH15oXv/MgK4t/5Muwq5S6feqo/+tqJBFZ+cF +EU0Yx4hJBBgRAgAJBQJA6SaRAhsMAAoJECqXFoqh31xISlAAn1kzaAaSc20WfhEl +2uM8BV2NJNICAJ9o75o/N0GbzHxqZacdGVWncQv+PQ== +=QAx/ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/RPM4/t/gnupg/trustdb.gpg b/RPM4/t/gnupg/trustdb.gpg Binary files differnew file mode 100644 index 0000000..199a2f2 --- /dev/null +++ b/RPM4/t/gnupg/trustdb.gpg diff --git a/RPM4/t/rpmmacros b/RPM4/t/rpmmacros new file mode 100644 index 0000000..ae2aeed --- /dev/null +++ b/RPM4/t/rpmmacros @@ -0,0 +1,8 @@ +# rpmmacros test file for perl-RPM4 +# $Id$ + +%RPM4 perl-RPM4 + +%_tmppath %(pwd)/testdir +%_builddir %(pwd)/testdir +%_topdir %(pwd)/testdir diff --git a/RPM4/t/rpmrc b/RPM4/t/rpmrc new file mode 100644 index 0000000..5ee28ee --- /dev/null +++ b/RPM4/t/rpmrc @@ -0,0 +1,369 @@ +#/*! \page config_rpmrc Default configuration: /usr/lib/rpm/rpmrc +# \verbatim +# +# $Id$ +# +# This is a global RPM configuration file. All changes made here will +# be lost when the rpm package is upgraded. Any per-system configuration +# should be added to /etc/rpmrc, while per-user configuration should +# be added to ~/.rpmrc. +# +############################################################# +# Values for RPM_OPT_FLAGS for various platforms + +optflags: i386 -O2 -fomit-frame-pointer -pipe -march=i386 %{debugcflags} +optflags: i486 -O2 -fomit-frame-pointer -pipe -march=i486 %{debugcflags} +optflags: k6 -O2 -fomit-frame-pointer -pipe -march=k6 %{debugcflags} +optflags: i586 -O2 -fomit-frame-pointer -pipe -march=i586 -mcpu=pentiumpro %{debugcflags} +optflags: i686 -O2 -fomit-frame-pointer -pipe -march=i686 %{debugcflags} +optflags: athlon -O2 -fomit-frame-pointer -pipe -march=athlon %{debugcflags} +optflags: ia64 -O2 -pipe %{debugcflags} +optflags: x86_64 -O2 -pipe %{debugcflags} +optflags: amd64 -O2 -pipe %{debugcflags} + + # XXX Please note that -mieee has been added in rpm-3.0.5. +optflags: alpha -O2 -mieee -mcpu=ev5 -pipe %{debugcflags} +optflags: alphaev5 -O2 -mieee -mcpu=ev5 -pipe %{debugcflags} +optflags: alphaev56 -O2 -mieee -mcpu=ev56 -pipe %{debugcflags} +optflags: alphapca56 -O2 -mieee -mcpu=pca56 -pipe %{debugcflags} +optflags: alphaev6 -O2 -mieee -mcpu=ev6 -pipe %{debugcflags} +optflags: alphaev67 -O2 -mieee -mcpu=ev67 -pipe %{debugcflags} + +optflags: sparc -O2 -m32 -mtune=ultrasparc %{debugcflags} +optflags: sparcv9 -O2 -m32 -mcpu=ultrasparc %{debugcflags} +optflags: sparc64 -O2 -m64 -mcpu=ultrasparc %{debugcflags} + +optflags: m68k -O2 %{debugcflags} -fomit-frame-pointer + +optflags: ppc -O2 -fsigned-char -frename-registers -mcpu=750 -mtune=7450 -pipe %{debugcflags} +optflags: ppciseries -O2 %{debugcflags} -fsigned-char +optflags: ppcpseries -O2 %{debugcflags} -fsigned-char +optflags: ppc64 -O2 %{debugcflags} -fsigned-char + +optflags: parisc -O2 %{debugcflags} -mpa-risc-1-0 +optflags: hppa1.0 -O2 %{debugcflags} -mpa-risc-1-0 +optflags: hppa1.1 -O2 %{debugcflags} -mpa-risc-1-0 +optflags: hppa1.2 -O2 %{debugcflags} -mpa-risc-1-0 +optflags: hppa2.0 -O2 %{debugcflags} -mpa-risc-1-0 + +optflags: mips -O2 %{debugcflags} +optflags: mipsel -O2 %{debugcflags} + +optflags: armv3l -O2 %{debugcflags} -fsigned-char -fomit-frame-pointer -march=armv3 +optflags: armv4b -O2 %{debugcflags} -fsigned-char -fomit-frame-pointer -march=armv4 +optflags: armv4l -O2 %{debugcflags} -fsigned-char -fomit-frame-pointer -march=armv4 + +optflags: atarist -O2 %{debugcflags} -fomit-frame-pointer +optflags: atariste -O2 %{debugcflags} -fomit-frame-pointer +optflags: ataritt -O2 %{debugcflags} -fomit-frame-pointer +optflags: falcon -O2 %{debugcflags} -fomit-frame-pointer +optflags: atariclone -O2 %{debugcflags} -fomit-frame-pointer +optflags: milan -O2 %{debugcflags} -fomit-frame-pointer +optflags: hades -O2 %{debugcflags} -fomit-frame-pointer + +optflags: s390 -O2 %{debugcflags} +optflags: s390x -O2 %{debugcflags} + +############################################################# +# Canonical arch names and numbers + +arch_canon: athlon: athlon 1 +arch_canon: i686: i686 1 +arch_canon: i586: i586 1 +arch_canon: k6: k6 1 +arch_canon: i486: i486 1 +arch_canon: i386: i386 1 + +arch_canon: alpha: alpha 2 +arch_canon: alphaev5: alphaev5 2 +arch_canon: alphaev56: alphaev56 2 +arch_canon: alphapca56:alphapca56 2 +arch_canon: alphaev6: alphaev6 2 +arch_canon: alphaev67: alphaev67 2 + +arch_canon: sparc: sparc 3 +arch_canon: sun4: sparc 3 +arch_canon: sun4m: sparc 3 +arch_canon: sun4c: sparc 3 +arch_canon: sun4d: sparc 3 +arch_canon: sparcv9: sparcv9 3 +# This is really a place holder for MIPS. +arch_canon: mips: mips 4 + +arch_canon: ppc: ppc 5 +arch_canon: ppciseries: ppciseries 5 +arch_canon: ppcpseries: ppcpseries 5 + +arch_canon: m68k: m68k 6 +arch_canon: IP: sgi 7 +arch_canon: rs6000: rs6000 8 +arch_canon: ia64: ia64 9 + +arch_canon: sparc64:sparc64 10 +arch_canon: sun4u: sparc64 10 +arch_canon: mipsel: mipsel 11 + +arch_canon: armv3l: armv3l 12 +arch_canon: armv4b: armv4b 12 +arch_canon: armv4l: armv4l 12 + +arch_canon: m68kmint: m68kmint 13 +arch_canon: atarist: m68kmint 13 +arch_canon: atariste: m68kmint 13 +arch_canon: ataritt: m68kmint 13 +arch_canon: falcon: m68kmint 13 +arch_canon: atariclone: m68kmint 13 +arch_canon: milan: m68kmint 13 +arch_canon: hades: m68kmint 13 + +arch_canon: s390: s390 14 +arch_canon: i370: i370 14 +arch_canon: s390x: s390x 15 + +arch_canon: ppc64: ppc64 16 + +arch_canon: sh: sh 17 +arch_canon: xtensa: xtensa 18 + +arch_canon: amd64: amd64 19 +arch_canon: x86_64: x86_64 19 + +############################################################# +# Canonical OS names and numbers + +os_canon: Linux: Linux 1 +os_canon: IRIX: Irix 2 +# This is wrong +os_canon: SunOS5: solaris 3 +os_canon: SunOS4: SunOS 4 + +os_canon: AmigaOS: AmigaOS 5 +os_canon: AIX: AIX 5 +os_canon: HP-UX: hpux10 6 +os_canon: OSF1: osf1 7 +os_canon: osf4.0: osf1 7 +os_canon: osf3.2: osf1 7 +os_canon: FreeBSD: FreeBSD 8 +os_canon: SCO_SV: SCO_SV3.2v5.0.2 9 +os_canon: IRIX64: Irix64 10 +os_canon: NEXTSTEP: NextStep 11 +os_canon: BSD_OS: bsdi 12 +os_canon: machten: machten 13 +os_canon: CYGWIN32_NT: cygwin32 14 +os_canon: CYGWIN32_95: cygwin32 15 +os_canon: UNIX_SV: MP_RAS: 16 +os_canon: MiNT: FreeMiNT 17 +os_canon: OS/390: OS/390 18 +os_canon: VM/ESA: VM/ESA 19 +os_canon: Linux/390: OS/390 20 +os_canon: Linux/ESA: VM/ESA 20 + +############################################################# +# For a given uname().machine, the default build arch + +buildarchtranslate: osfmach3_i686: i386 +buildarchtranslate: osfmach3_i586: i386 +buildarchtranslate: osfmach3_i486: i386 +buildarchtranslate: osfmach3_i386: i386 + +buildarchtranslate: athlon: i586 +buildarchtranslate: i686: i586 +buildarchtranslate: k6: i586 +buildarchtranslate: i586: i586 +buildarchtranslate: i486: i486 +buildarchtranslate: i386: i386 + +buildarchtranslate: alphaev5: alpha +buildarchtranslate: alphaev56: alpha +buildarchtranslate: alphapca56: alpha +buildarchtranslate: alphaev6: alpha +buildarchtranslate: alphaev67: alpha + +buildarchtranslate: sun4c: sparc +buildarchtranslate: sun4d: sparc +buildarchtranslate: sun4m: sparc +buildarchtranslate: sparcv9: sparc +buildarchtranslate: sun4u: sparc64 + +buildarchtranslate: osfmach3_ppc: ppc +buildarchtranslate: powerpc: ppc +buildarchtranslate: powerppc: ppc +buildarchtranslate: ppciseries: ppc +buildarchtranslate: ppcpseries: ppc + +buildarchtranslate: atarist: m68kmint +buildarchtranslate: atariste: m68kmint +buildarchtranslate: ataritt: m68kmint +buildarchtranslate: falcon: m68kmint +buildarchtranslate: atariclone: m68kmint +buildarchtranslate: milan: m68kmint +buildarchtranslate: hades: m68kmint + +buildarchtranslate: s390: s390 +buildarchtranslate: s390x: s390x + +buildarchtranslate: ia64: ia64 + +buildarchtranslate: amd64: amd64 +buildarchtranslate: x86_64: amd64 + +############################################################# +# Architecture compatibility + +arch_compat: alphaev67: alphaev6 +arch_compat: alphaev6: alphapca56 +arch_compat: alphapca56: alphaev56 +arch_compat: alphaev56: alphaev5 +arch_compat: alphaev5: alpha +arch_compat: alpha: axp noarch + +arch_compat: athlon: i686 +arch_compat: i686: i586 +arch_compat: k6: i586 +arch_compat: i586: i486 +arch_compat: i486: i386 +arch_compat: i386: noarch + +arch_compat: osfmach3_i686: i686 osfmach3_i586 +arch_compat: osfmach3_i586: i586 osfmach3_i486 +arch_compat: osfmach3_i486: i486 osfmach3_i386 +arch_compat: osfmach3_i386: i486 + +arch_compat: osfmach3_ppc: ppc +arch_compat: powerpc: ppc +arch_compat: powerppc: ppc +arch_compat: ppciseries: ppc +arch_compat: ppcpseries: ppc +arch_compat: ppc64: ppc +arch_compat: ppc: rs6000 +arch_compat: rs6000: noarch + +arch_compat: sun4c: sparc +arch_compat: sun4d: sparc +arch_compat: sun4m: sparc +arch_compat: sun4u: sparc64 +arch_compat: sparc64: sparcv9 +arch_compat: sparcv9: sparc +arch_compat: sparc: noarch + +arch_compat: mips: noarch +arch_compat: mipsel: noarch + +arch_compat: hppa2.0: hppa1.2 +arch_compat: hppa1.2: hppa1.1 +arch_compat: hppa1.1: hppa1.0 +arch_compat: hppa1.0: parisc +arch_compat: parisc: noarch + +arch_compat: armv4b: noarch +arch_compat: armv4l: armv3l +arch_compat: armv3l: noarch + +arch_compat: atarist: m68kmint noarch +arch_compat: atariste: m68kmint noarch +arch_compat: ataritt: m68kmint noarch +arch_compat: falcon: m68kmint noarch +arch_compat: atariclone: m68kmint noarch +arch_compat: milan: m68kmint noarch +arch_compat: hades: m68kmint noarch + +arch_compat: i370: noarch +arch_compat: s390: noarch +arch_compat: s390x: s390 noarch + +arch_compat: ia64: i686 noarch + +arch_compat: amd64: x86_64 +arch_compat: x86_64: athlon noarch + +os_compat: IRIX64: IRIX +os_compat: solaris2.7: solaris2.3 solaris2.4 solaris2.5 solaris2.6 +os_compat: solaris2.6: solaris2.3 solaris2.4 solaris2.5 +os_compat: solaris2.5: solaris2.3 solaris2.4 +os_compat: solaris2.4: solaris2.3 + +os_compat: hpux11.00: hpux10.30 +os_compat: hpux10.30: hpux10.20 +os_compat: hpux10.20: hpux10.10 +os_compat: hpux10.10: hpux10.01 +os_compat: hpux10.01: hpux10.00 +os_compat: hpux10.00: hpux9.07 +os_compat: hpux9.07: hpux9.05 +os_compat: hpux9.05: hpux9.04 + +os_compat: osf4.0: osf3.2 osf1 + +os_compat: ncr-sysv4.3: ncr-sysv4.2 + +os_compat: FreeMiNT: mint MiNT TOS +os_compat: MiNT: FreeMiNT mint TOS +os_compat: mint: FreeMiNT MiNT TOS +os_compat: TOS: FreeMiNT MiNT mint + +os_compat: BSD_OS: bsdi +os_compat: bsdi4.0: bsdi + +buildarch_compat: ia64: noarch + +buildarch_compat: athlon: i686 +buildarch_compat: i686: i586 +buildarch_compat: k6: i486 +buildarch_compat: i586: i486 +buildarch_compat: i486: i386 +buildarch_compat: i386: noarch + +buildarch_compat: sun4c: noarch +buildarch_compat: sun4d: noarch +buildarch_compat: sun4m: noarch +buildarch_compat: sun4u: noarch +buildarch_compat: sparc64: noarch +buildarch_compat: sparcv9: sparc +buildarch_compat: sparc: noarch + +buildarch_compat: alphaev67: alphaev6 +buildarch_compat: alphaev6: alphapca56 +buildarch_compat: alphapca56: alphaev56 +buildarch_compat: alphaev56: alphaev5 +buildarch_compat: alphaev5: alpha +buildarch_compat: alpha: noarch + +buildarch_compat: m68k: noarch + +buildarch_compat: ppciseries: noarch +buildarch_compat: ppcpseries: noarch +buildarch_compat: ppc: noarch +buildarch_compat: ppc64: noarch + +buildarch_compat: mips: noarch +buildarch_compat: mipsel: noarch + +buildarch_compat: armv3l: noarch +buildarch_compat: armv4b: noarch +buildarch_compat: armv4l: noarch + +buildarch_compat: hppa2.0: hppa1.2 +buildarch_compat: hppa1.2: hppa1.1 +buildarch_compat: hppa1.1: hppa1.0 +buildarch_compat: hppa1.0: parisc +buildarch_compat: parisc: noarch + +buildarch_compat: atarist: m68kmint noarch +buildarch_compat: atariste: m68kmint noarch +buildarch_compat: ataritt: m68kmint noarch +buildarch_compat: falcon: m68kmint noarch +buildarch_compat: atariclone: m68kmint noarch +buildarch_compat: milan: m68kmint noarch +buildarch_compat: hades: m68kmint noarch + +buildarch_compat: s390: noarch +buildarch_compat: s390x: noarch + +buildarch_compat: ia64: noarch + +buildarch_compat: amd64: noarch +buildarch_compat: x86_64: noarch + +macrofiles: /usr/lib/rpm/macros:/usr/lib/rpm/%{_target}/macros:/etc/rpm/macros.specspo:/etc/rpm/macros.prelink:/etc/rpm/macros.solve:/etc/rpm/macros.up2date:/etc/rpm/macros:/etc/rpm/%{_target}/macros:~/.rpmmacros + +# \endverbatim +#*/ diff --git a/RPM4/t/test-dep-1.0-1mdk.noarch.rpm b/RPM4/t/test-dep-1.0-1mdk.noarch.rpm Binary files differnew file mode 100644 index 0000000..1e36db6 --- /dev/null +++ b/RPM4/t/test-dep-1.0-1mdk.noarch.rpm diff --git a/RPM4/t/test-dep-1.0-1mdk.src.rpm b/RPM4/t/test-dep-1.0-1mdk.src.rpm Binary files differnew file mode 100644 index 0000000..8b09d78 --- /dev/null +++ b/RPM4/t/test-dep-1.0-1mdk.src.rpm diff --git a/RPM4/t/test-dep.spec b/RPM4/t/test-dep.spec new file mode 100644 index 0000000..8cfb060 --- /dev/null +++ b/RPM4/t/test-dep.spec @@ -0,0 +1,38 @@ +# $Id$ +Summary: test rpm dependencies for perl-URPM test suite +BuildArch: noarch +Name: test-dep +Version: 1.0 +Release: 1mdk +License: GPL +Group: Application/Development +BuildRoot: %{_tmppath}/%{name}-root +Requires: test-rpm +Conflicts: test-rpm +Obsoletes: test-rpm + +%description +test rpm for dependencies + +%prep + +%build + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT%_sysconfdir + +date >> $RPM_BUILD_ROOT%_sysconfdir/%name + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%config(noreplace) %_sysconfdir/%name + +%changelog +* Thu Apr 22 2004 Olivier Thauvin <thauvin@aerov.jussieu.fr> 1-1mdk +- initial build + + diff --git a/RPM4/t/test-rpm-1.0-1mdk.noarch.rpm b/RPM4/t/test-rpm-1.0-1mdk.noarch.rpm Binary files differnew file mode 100644 index 0000000..6087dd2 --- /dev/null +++ b/RPM4/t/test-rpm-1.0-1mdk.noarch.rpm diff --git a/RPM4/t/test-rpm-1.0-1mdk.src.rpm b/RPM4/t/test-rpm-1.0-1mdk.src.rpm Binary files differnew file mode 100644 index 0000000..8f3730a --- /dev/null +++ b/RPM4/t/test-rpm-1.0-1mdk.src.rpm diff --git a/RPM4/t/test-rpm.spec b/RPM4/t/test-rpm.spec new file mode 100644 index 0000000..bbd60f1 --- /dev/null +++ b/RPM4/t/test-rpm.spec @@ -0,0 +1,35 @@ +# $Id$ +Summary: test rpm for perl-URPM test suite +BuildArch: noarch +Name: test-rpm +Version: 1.0 +Release: 1mdk +License: GPL +Group: Application/Development +BuildRoot: %{_tmppath}/%{name}-root + +%description +test rpm + +%prep + +%build + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT%_sysconfdir + +date >> $RPM_BUILD_ROOT%_sysconfdir/%name + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%config(noreplace) %_sysconfdir/%name + +%changelog +* Thu Apr 22 2004 Olivier Thauvin <thauvin@aerov.jussieu.fr> 1-1mdk +- initial build + + |