OpenPKG CVS Repository
http://cvs.openpkg.org/
____________________________________________________________________________
Server: cvs.openpkg.org Name: Ralf S. Engelschall
Root: /e/openpkg/cvs Email: [EMAIL PROTECTED]
Module: openpkg-web, openpkg-src Date: 26-Nov-2002 20:54:12
Branch: HEAD Handle: 2002112619541101
Added files:
openpkg-src/openpkg-tool Makefile openpkg-build.pl openpkg-index.pl
openpkg-tool.spec openpkg.1 openpkg.pod openpkg.sh
Modified files:
openpkg-web news.txt
Log:
new package: openpkg-tool 20021126 (OpenPKG Tool)
Summary:
Revision Changes Path
1.1 +4 -0 openpkg-src/openpkg-tool/Makefile
1.1 +1291 -0 openpkg-src/openpkg-tool/openpkg-build.pl
1.1 +866 -0 openpkg-src/openpkg-tool/openpkg-index.pl
1.1 +89 -0 openpkg-src/openpkg-tool/openpkg-tool.spec
1.1 +327 -0 openpkg-src/openpkg-tool/openpkg.1
1.1 +265 -0 openpkg-src/openpkg-tool/openpkg.pod
1.1 +90 -0 openpkg-src/openpkg-tool/openpkg.sh
1.2118 +1 -0 openpkg-web/news.txt
____________________________________________________________________________
Index: openpkg-src/openpkg-tool/Makefile
============================================================
$ cvs update -p -r1.1 Makefile
openpkg.1: openpkg.pod
pod2man --section=1 --quotes=none --release="openpkg-tool" --center="OpenPKG
Maintainance" openpkg.pod >openpkg.1
Index: openpkg-src/openpkg-tool/openpkg-build.pl
============================================================
$ cvs update -p -r1.1 openpkg-build.pl
##
## openpkg-build -- create build scripts from package index
##
## Copyright (c) 2000-2002 Cable & Wireless Deutschland GmbH
## Copyright (c) 2000-2002 The OpenPKG Project <http://www.openpkg.org/>
## Copyright (c) 2000-2002 Ralf S. Engelschall <[EMAIL PROTECTED]>
##
## Permission to use, copy, modify, and distribute this software for
## any purpose with or without fee is hereby granted, provided that
## the above copyright notice and this permission notice appear in all
## copies.
##
## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
require 5;
$|=1; # autoflush
use strict;
use vars qw/$opt_R $opt_r $opt_f $opt_u $opt_U $opt_a $opt_A $opt_z $opt_Z $opt_P
$opt_N $opt_E $opt_i $opt_D $opt_p $opt_q/;
getopts('R:r:f:uUaAzZP:N:E:iD:p:q');
##########################################################################
sub getopts ($) {
my($opts) = @_;
my(%optf) = map { /(\w)/; $1 => $_ } $opts =~ /(\w:|\w)/g;
my(%opts,@argv,$optarg);
foreach (@ARGV) {
if (@argv) {
push @argv, $_;
} elsif (defined $optarg) {
if (exists $opts{$optarg}) {
$opts{$optarg} .= " $_";
} else {
$opts{$optarg} = $_;
}
$optarg = undef;
} elsif (!/^[-]/) {
push @argv, $_;
} else {
while (/^\-(\w)(.*)/) {
if (exists $optf{$1}) {
if (length($optf{$1}) > 1) {
if ($2 ne '') {
if (exists $opts{$1}) {
$opts{$1} .= " $2";
} else {
$opts{$1} = $2;
}
} else {
$optarg = $1;
}
last;
} else {
$opts{$1} = 1;
}
} else {
warn "warning: unknown option $_\n";
}
$_ = "-$2";
}
}
}
if (defined $optarg) {
warn "warning: option $optarg requires an argument\n";
}
foreach (keys %opts) {
eval '$opt_'.$_.' = "'.quotemeta($opts{$_}).'";';
}
@ARGV = @argv;
}
my(%env) = ( '' => { } );
if (open(FH, "< $ENV{'HOME'}/.openpkg/build")) {
my($env) = $env{''};
while (<FH>) {
if (/^\s*\[([^\]]*)\]/) {
$env{$1} = { } unless $env{$1};
$env = $env{$1};
} elsif (my($opt,$val) = /^\-([RfruUaAzPN])\s*(.*?)\s*$/) {
$val = 1 unless defined $val;
$env->{$opt} = $val;
}
}
close(FH);
}
die "openpkg:build:USAGE: $0 [-R rpm] [-r repository] [-f index.rdf] [-uUzZiq] [-P
priv-cmd] [-N non-priv-cmd] [-p platform] [-Dwith ...] [-Ename ...] ( [-aA] |
patternlist )\n"
unless $#ARGV >= 0 || ($#ARGV == -1 && ($opt_a || $opt_A));
##########################################################################
sub conditional ($$) {
my($cond,$with) = @_;
my(@s,$res);
return 1 if $cond eq '';
foreach (split(/\s+/,$cond)) {
if ($_ eq '+') {
die "FATAL: stack underflow in: $cond\n" if scalar(@s)<2;
my($a) = pop @s;
my($b) = pop @s;
push @s, $a && $b;
} elsif ($_ eq '|') {
die "FATAL: stack underflow in: $cond\n" if scalar(@s)<2;
my($a) = pop @s;
my($b) = pop @s;
push @s, $a && $b;
} elsif ($_ eq '!') {
die "FATAL: stack underflow in: $cond\n" if scalar(@s)<1;
my($a) = pop @s;
push @s, !$a;
} else {
push @s, $with->{$_} eq 'yes';
}
}
die "FATAL: stack underflow in: $cond\n" if scalar(@s)<1;
$res = pop @s;
die "FATAL: stack not empty in: $cond\n" if scalar(@s)>0;
return $res;
}
##########################################################################
my($RPM,$RPM_PRIV,$RPM_NPRIV,$CURL,$PROG);
$RPM = $opt_R || $env{''}->{opt}->{'R'} || 'rpm';
$RPM = (`which $RPM` =~ m{^(/.*)})[0];
die "FATAL: cannot locate rpm in path\n" unless $RPM =~ m{^/};
# augment command line parameters
foreach my $env (sort { $a cmp $b } grep { $RPM =~ /^\Q$_\E/ } keys %env) {
while (my($opt,$val) = each %{$env{$env}}) {
eval "\$opt_$opt = '$val' unless defined \$opt_$opt;";
}
}
$RPM_PRIV = ($opt_P ? $opt_P." ".$RPM : $RPM);
$RPM_NPRIV = ($opt_N ? $opt_N." ".$RPM : $RPM);
$CURL = $RPM;
$CURL =~ s/bin\/rpm$/lib\/openpkg\/curl/
or die "FATAL: cannot deduce curl path from $RPM\n";
($PROG) = $0 =~ /(?:.*\/)?(.*)/;
sub version_cmp ($$) {
my($a,$b) = @_;
my(@a,@b,$c);
my($ax,$bx);
@a = split(/\./, $a);
@b = split(/\./, $b);
while (@a && @b) {
if ($a[0] =~ /^\d+$/ && $b[0] =~ /^\d+$/) {
$c = $a[0] <=> $b[0];
} elsif ((($a,$ax) = $a[0] =~ /^(\d+)(.*)$/) &&
(($b,$bx) = $b[0] =~ /^(\d+)(.*)$/)) {
$c = $a <=> $b;
$c = $ax cmp $bx unless $c;
} else {
$c = $a[0] cmp $b[0];
}
return $c if $c;
shift @a;
shift @b;
}
$c = scalar(@a) <=> scalar(@b);
return $c;
}
sub release_cmp ($$) {
my($a,$b) = @_;
return $a cmp $b;
}
sub vcmp ($$) {
my($a,$b) = @_;
my($av,$ar) = $a =~ /^(.*?)(?:\-([\d\.]+))?$/;
my($bv,$br) = $b =~ /^(.*?)(?:\-([\d\.]+))?$/;
my($c);
if ((defined $ar) && (defined $br)) {
$c = release_cmp($ar,$br);
return $c if $c;
}
if ((defined $av) && (defined $bv)) {
$c = version_cmp($av,$bv);
return $c if $c;
}
return 0;
}
sub vs ($) {
my($t) = @_;
return "$t->{version}-$t->{release}";
}
sub vsn ($) {
my($t) = @_;
return "$t->{name}-$t->{version}-$t->{release}";
}
##########################################################################
sub get_config ()
{
my($c,@q);
$c = `$RPM_NPRIV --eval '%{_rpmdir} %{_rpmfilename} %{_target_os} %{_target_cpu}
%{_target_platform} %{_prefix}'`;
chomp($c);
(@q) = split(/\s+/,$c);
$q[1] =~ s/%{OS}/$q[2]/;
$q[1] =~ s/%{ARCH}/$q[3]/;
return {
rpmdir => $q[0],
template => $q[1],
platform => $q[4],
prefix => $q[5]
};
}
sub get_release () {
my($rel,$url);
($rel) =`$RPM_NPRIV -qi openpkg` =~ /Version:\s*(\S+)/m;
if ($rel =~ /^\d+$/) {
print "# $PROG current($rel)\n";
print "# using '$RPM_NPRIV' (build) and '$RPM_PRIV' (install)\n";
$url = "ftp://ftp.openpkg.org/current/";
} elsif ($rel =~ /^(\d+\.\d+)/) {
$rel = $1;
print "# $PROG release($rel)\n";
$url = "ftp://ftp.openpkg.org/release/$rel/";
} else {
die "FATAL: don't know how to handle this release\n";
}
return $url;
}
sub get_installed () {
my(%map);
my(@l) = `$RPM_NPRIV --provides -qa`;
foreach (@l) {
/^(\S+)\s*(?:=\s*([^\s\-]+)-(\S+))?$/;
push(@{$map{$1}->{"$2-$3"}}, {
name => $1,
version => (defined $2 ? $2 : '*'),
release => (defined $3 ? $3 : '*')
});
}
return \%map;
}
sub revdep ($$$) {
my($rev,$t,$name) = @_;
return 1 if $name eq $t->{name};
foreach (@{$rev->{$_}}) {
return 1 if revdep($rev,$t,$_->{name});
}
return -1;
}
sub get_revdep ($) {
my($env) = @_;
my($i) = $env->{'installed'};
my($r) = $env->{'repository'};
my($pkg, %rev);
my(@vers,$t,@names);
print "# computing reverse dependencies\n";
foreach $pkg (keys %$i) {
unless ($r->{$pkg}) {
print "# ATTENTION: $pkg has no upgrade path\n";
next;
}
@vers = get_versions($r->{$pkg}, sub { 1; });
foreach (@vers) {
foreach $t (@{$r->{$pkg}->{$_}}) {
next unless $i->{$t->{name}};
next unless $t->{depends};
@names = grep { $_ ne '' }
map { /^(\S+)/ }
@{$t->{depends}};
next unless @names;
push @{$rev{$_}}, $t foreach @names;
}
}
}
foreach $pkg (keys %rev) {
$rev{$pkg} = [
sort {
revdep(\%rev, $b, $a->{name});
} @{$rev{$pkg}}
];
}
return \%rev;
}
sub parse_options ($) {
my($l) = @_;
$l = [ split(/\n+/, $l) ] unless ref $l;
my(%with) = map { /--define\s*'(\S+)\s+(\S+?)'/ } @$l;
return unless %with;
return \%with;
}
sub override_options ($$) {
my($old, $new) = @_;
while (my ($k,$v) = each %$new) {
$old->{$k} = $v if exists $old->{$k};
}
}
sub get_with ($;$) {
my($t,$fn) = @_;
my(@l,%with);
unless ($t->{OPTIONS}) {
if (defined $fn) {
@l = `$RPM_NPRIV -qi -p $fn`;
} else {
@l = `$RPM_NPRIV -qi $t->{name}`;
}
$t->{OPTIONS} = parse_options(\@l);
}
return $t->{OPTIONS};
}
sub relurl ($$$) {
my($url,$fn,$suburl) = @_;
my($subfn,$submap);
unless ($suburl =~ /^\w+:\/\// || $suburl =~ /^\//) {
if (defined $fn) {
$subfn = $fn;
$subfn =~ s/\/[^\/]*$//;
$subfn .= '/' unless $subfn =~ /\/$/;
$subfn .= $suburl;
$suburl = $subfn;
} else {
$subfn = $url;
$subfn =~ s/\/[^\/]*$//;
$subfn .= '/' unless $subfn =~ /\/$/;
$suburl = "$subfn$suburl";
$subfn = undef;
}
}
return ($suburl, $subfn);
}
sub xel($) {
my($a) = @_;
my($l) = $a->[0];
return '' if ref $l;
return $l;
}
sub get_index ($$$) {
my($url,$fn,$with) = @_;
my($ua,$req,$res,$rdf);
my($bzip2,$path);
my(%map,@include);
my($fetch);
$fetch = defined $fn ? $fn : $url;
$bzip2 = $RPM;
$bzip2 =~ s/bin\/rpm$/lib\/openpkg\/bzip2/
or die "FATAL: cannot deduce bzip2 path from $RPM\n";
$fetch !~ /\.bz2$/ || -x $bzip2
or die "FATAL: $bzip2 not found\n";
if ($fetch =~ /^\w+:/) { # looks like URL scheme
print "# curling index $fetch\n";
if ($fetch =~ /\.bz2$/) {
$path = "$CURL -q -s -o - \"$fetch\" | $bzip2 -dc |";
} else {
$path = "$CURL -q -s -o - \"$fetch\" |";
}
} else {
print "# reading index file $fn\n";
if ($fetch =~ /\.bz2$/) {
$path = "$bzip2 -dc $fetch |";
} else {
$path = "< $fetch";
}
}
open(RFH, $path) or
die "FATAL: cannot open '$fetch' ($!)\n";
eval {
require XML::Simple;
};
if ($@) {
print "# using simple text parser\n";
my($section);
my($name,$version);
my($href,$release,$desc);
my(@prereq,@bprereq);
my(@provides,@conflicts);
my($platform,$prefix);
my($rec);
my($tag,$cond,$body);
my($useit);
while (<RFH>) {
s/>/>/g;
s/</</g;
if (!(defined $href) && /<rdf:Description.*?href="([^"]*)"/) {
$href = $1;
$section = undef;
$name = undef;
$release = undef;
$desc = '';
$platform = undef;
$prefix = undef;
@prereq = ();
@bprereq = ();
@provides = ();
@conflicts = ();
}
if (!(defined $href) && /<Repository.*?href="([^"]*)"/) {
push(@include, $1);
next;
}
next unless defined $href;
($tag,$cond,$body) = /<(\/?[\w:]+)\s*(?:cond="([^"]+)")?>([^<]*)/;
$useit = conditional($cond,$with);
if ($tag eq 'Description') {
$section = 'description';
} elsif ($tag eq '/Description') {
$section = undef;
} elsif ($section eq 'description') {
$desc .= $_;
} elsif ($tag eq 'PreReq') {
$section = 'prereq' if $useit;
} elsif ($tag eq '/PreReq') {
$section = undef;
} elsif ($tag eq 'BuildPreReq') {
$section = 'bprereq' if $useit;
} elsif ($tag eq '/BuildPreReq') {
$section = undef;
} elsif ($tag eq 'Provides') {
$section = 'provides' if $useit;
} elsif ($tag eq '/Provides') {
$section = undef;
} elsif ($tag eq 'Conflicts') {
$section = 'conflicts' if $useit;
} elsif ($tag eq '/Conflicts') {
$section = undef;
} elsif ($tag eq 'Name') {
$name = $body;
} elsif ($tag eq 'Version') {
$version = $body;
} elsif ($tag eq 'Release') {
$release = $body;
} elsif ($tag eq 'Platform') {
$platform = $body;
} elsif ($tag eq 'Prefixes') {
$prefix = $body;
} elsif ($tag eq 'rdf:li') {
if ($section eq 'prereq') {
push(@prereq, $body);
} elsif ($section eq 'bprereq') {
push(@bprereq, $body);
} elsif ($section eq 'provides') {
push(@provides, $body);
} elsif ($section eq 'conflicts') {
push(@conflicts, $body);
}
} elsif ($tag eq '/rdf:Description') {
if (defined $href &&
defined $name &&
defined $version &&
defined $release) {
@provides = map {
/(\S+)\s*(?:=\s*(\S+?)\-(\S+))?$/;
{
name => $1,
version => $2,
release => $3
}
} @provides;
unless (grep($_->{name} eq $name, @provides)) {
push(@provides, {
name => $name,
version => $version,
release => $release
});
}
$rec = {
href => (relurl($url, undef, $href))[0],
name => $name,
version => $version,
release => $release,
depends => [ @bprereq ],
keeps => [ @prereq ],
conflicts => [ @conflicts ],
desc => $desc,
platform => $platform,
prefix => $prefix
};
$rec->{OPTIONS} = parse_options($rec->{desc});
foreach (@provides) {
push(@{$map{$_->{name}}->{vs($_)}}, $rec);
}
}
$href = undef;
}
}
} else {
print "# using XML parser\n";
my($xml) = XML::Simple::XMLin(\*RFH, forcearray => 1);
my($desc) = $xml->{'Repository'}->[0]->{'rdf:Description'};
my($sub) = $xml->{'Repository'}->[0]->{'Repository'};
my($provides,@provides,$rec);
my($href,$name,$version,$release);
foreach (@$desc) {
$href = $_->{'href'};
$name = xel($_->{'Name'});
$version = xel($_->{'Version'});
$release = xel($_->{'Release'});
next unless defined $href &&
defined $name &&
defined $version &&
defined $release;
$provides = $_->{'Provides'}->[0]->{'rdf:bag'}->[0]->{'rdf:li'};
@provides = map {
/(\S+)\s*(?:=\s*(\S+?)\-(\S+))?$/;
{
name => $1,
version => $2,
release => $3
}
} @$provides;
unless (grep($_->{name} eq $name, @provides)) {
push(@provides, {
name => $name,
version => $version,
release => $release
});
}
$rec = {
href => (relurl($url, undef, $href))[0],
name => $name,
version => $version,
release => $release,
platform => xel($_->{'Platform'}),
prefix => xel($_->{'Prefixes'}),
depends =>
( $_->{'BuildPreReq'}->[0]->{'rdf:bag'}->[0]->{'rdf:li'}
|| [] ),
keeps =>
( $_->{'PreReq'}->[0]->{'rdf:bag'}->[0]->{'rdf:li'}
|| [] ),
desc => xel($_->{'Description'})
};
$rec->{OPTIONS} = parse_options($rec->{desc});
foreach (@provides) {
push(@{$map{$_->{name}}->{vs($_)}}, $rec);
}
}
if ($sub) {
@include = map { $_->{href} } @$sub;
}
}
close(RFH)
or die "FATAL: an I/O error occured\n";
#
# cannot do real recursions on file handles, so we simply append
# all sub-RDFs, the result is flattend into a big hash anyway
#
foreach (@include) {
my($submap);
my($suburl,$subfn) = relurl($url,$fn,$_);
$submap = get_index($suburl,$subfn,$with);
while (my($name,$vmap) = each %$submap) {
while (my($vs,$recs) = each %$vmap) {
push @{$map{$name}->{$vs}}, @$recs;
}
}
}
return \%map;
}
#
# grep all versions of a name that
# satisfy a condition
#
sub get_versions ($$) {
my($relmap, $cond) = @_;
return grep { $cond->($_); }
sort { vcmp($a,$b); } keys %$relmap;
}
#
# there can be multiple sources for a target release
#
sub chose_source ($$@) {
my($env, $name, $vmap, @vers) = @_;
my(@recs,@nrecs,$rec);
return unless @vers;
@recs = grep {
$env->{sourceonly} ? (
!(defined $_->{'platform'})
) : (
!(defined $_->{'platform'}) || (
defined $_->{'prefix'} &&
$_->{'platform'} eq $env->{config}->{platform} &&
$_->{'prefix'} eq $env->{config}->{prefix}
)
)
} map { @{$vmap->{$_}} } @vers;
return unless @recs;
if (scalar(@recs) > 1) {
@nrecs = grep {
$env->{built}->{$_->{name}} ||
$env->{installed}->{$_->{name}}
} @recs;
@recs = @nrecs if @nrecs;
}
if (scalar(@recs) > 1 && !$env->{sourceonly}) {
@nrecs = grep {
defined $_->{'platform'}
} @recs;
@recs = @nrecs if @nrecs;
}
if (scalar(@recs) > 1) {
print "# ambigous sources for $name\n";
my($i) = 0;
foreach (@recs) {
print "# $i: ".vsn($_)." = $_->{href}\n";
$i++;
}
die "ERROR: ambigous dependency\n";
} else {
if ($env->{upgrade}) {
$rec = $recs[-1];
} else {
$rec = $recs[0];
}
}
print "# source for $name is ".vsn($rec)."\n";
return $rec;
}
#
# see wether target is in map
#
sub target_exists ($$) {
my($target, $map) = @_;
my($vmap) = $map->{$target->{name}};
return unless $vmap;
return !defined $target->{version} ||
defined $vmap->{vs($target)};
}
#
# find target in map
#
sub find_target ($$) {
my($name, $map) = @_;
my($vmap) = $map->{$name};
my(@vs);
return unless $vmap;
@vs = sort { vcmp($b,$a) } keys %$vmap;
return $vmap->{$vs[0]}->[-1];
}
#
# see wether target has conflicts in map
#
sub target_conflicts ($$) {
my($target, $map) = @_;
my($t);
foreach (@{$target->{conflicts}}) {
$t = find_target($_, $map);
return $t if $t;
}
return;
}
#
# retrieve build dependencies for target in map
#
sub target_depends ($$) {
my($target, $map) = @_;
my($vmap,$vers);
die "FATAL: ",vsn($target)," not in depend map\n"
unless
( $vmap = $map->{$target->{name}} ) &&
( defined $target->{version} ) &&
( $vers = $vmap->{vs($target)} ) &&
@$vers;
return $vers->[0]->{depends};
}
#
# retrieve runtime dependencies for target in map
#
sub target_keeps ($$) {
my($target, $map) = @_;
my($vmap,$vers);
die "FATAL: ",vsn($target)," not in keep map\n"
unless
( $vmap = $map->{$target->{name}} ) &&
( defined $target->{version} ) &&
( $vers = $vmap->{vs($target)} ) &&
@$vers;
return $vers->[0]->{keeps};
}
#
# test wether target could be upgraded
#
sub target_newer ($$) {
my($target, $map) = @_;
my($vs) = vs($target);
my($vmap) = $map->{$target->{name}};
return 1 unless $vmap;
return !grep { vcmp($vs, $_) <= 0; } keys %$vmap;
}
#
# check wether installed package matches
# build options
#
sub target_suitable ($$) {
my($target, $with) = @_;
my($iwith);
my($k,$v);
$iwith = $target->{OPTIONS};
while (($k,$v) = each %$with) {
if (exists $iwith->{$k}) {
return 0 if $iwith->{$k} ne $with->{$k};
}
}
return 1;
}
#
# report options that are not used for
#
sub warn_about_options ($$) {
my($target, $with) = @_;
my($iwith) = $target->{OPTIONS};
my($k,$v);
return unless defined $iwith;
while (($k,$v) = each %$with) {
if (!exists $iwith->{$k}) {
print "# ATTENTION: $target->{name} ignores option '$k'\n";
}
}
}
#
# locate target for a dependency
#
sub dep2target ($$) {
my($dep, $env) = @_;
my($name,@vers);
my($i,$r,$b,$cond,$version);
my($t);
$dep =~ s/(\S+)\s*//;
$name = $1;
$i = $env->{installed}->{$name};
$r = $env->{repository}->{$name};
$b = $env->{built}->{$name};
return unless $i || $r || $b;
if ($dep =~ /^>=\s*(\S+)$/) {
$version = $1;
$cond = sub { vcmp($_[0],$version) >= 0; };
} elsif ($dep =~ /^=\s*(\S+)$/) {
$version = $1;
$cond = sub { vcmp($_[0],$version) == 0; };
} elsif ($dep =~ /^\s*$/) {
$cond = sub { 1; };
} else {
die "FATAL: don't know how to handle PreReq: $name $dep\n";
}
if ($i && (@vers = get_versions($i, $cond))) {
foreach (@vers) {
$t = $i->{$_}->[0];
if (get_with($t), target_suitable($t, $env->{with})) {
if (!$env->{upgrade}) {
return ($t, 1);
}
}
}
}
if ($b && (@vers = get_versions($b, $cond))) {
return ($b->{$vers[0]}->[0], 1);
}
return (chose_source($env, $name, $r, get_versions($r, $cond)), 0);
}
sub make_dep ($$$$$) {
my($target,$depth,$env,$list,$blist) = @_;
my($d,$k,%d,%k,$t,$old);
if (target_exists($target, $env->{built})) {
print "# $target->{name} is already in list\n";
return;
}
if ($t = target_conflicts($target, $env->{installed})) {
print "# $target->{name} conflicts with ",vsn($t),"\n";
return;
}
if ($t = target_conflicts($target, $env->{built})) {
print "# $target->{name} conflicts with ",vsn($t),"\n";
return;
}
#
# see if a target is already installed and requires a rebuild
#
if ($t = find_target($target->{name}, $env->{installed})) {
if (exists $env->{exclude}->{$target->{name}}) {
print "# excluding $target->{name} (no upgrade allowed)\n";
return;
}
get_with($t);
if ($target->{REBUILD}) {
print "# rebuilding $target->{name} (dependency)\n";
} elsif ($env->{zero}) {
print "# rebuilding $target->{name} (zero)\n";
} elsif ($env->{upgrade} && target_newer($target, $env->{installed})) {
print "# rebuilding $target->{name} (upgrade)\n";
} elsif (!target_suitable($t, $env->{with})) {
print "# rebuilding $target->{name} (parameter mismatch)\n";
} else {
print "# $target->{name} is already installed\n";
return;
}
# use options from installed base
override_options($target->{OPTIONS}, $t->{OPTIONS});
$target->{REBUILD} = 1;
}
if (exists $env->{exclude}->{$target->{name}}) {
die "FATAL: target ".vsn($target)." is forbidden\n";
}
# mark this as a target before reverse dependencies trigger
# it again
push(@{$env->{built}->{$target->{name}}->{vs($target)}}, $target);
$d = target_depends($target, $env->{repository});
$k = target_keeps($target, $env->{repository});
#
# recurse over dependencies
#
if (@$d || @$k) {
%d = map { $_ => 1 } @$d, @$k;
%k = map { $_ => 1 } @$k;
foreach (keys %d) {
# old index misses a OpenPKG provider in the index... skip it
next if $_ eq 'OpenPKG';
($t,$old) = dep2target($_, $env);
if ($t) {
if ($old) {
print "# $target->{name} uses ".vsn($t)." for $_\n";
next;
}
# record which targets to keep in blist
if ($k{$_}) {
push(@$blist,$t);
print "# $target->{name} installs ".vsn($t)." for $_\n";
} else {
print "# $target->{name} requires ".vsn($t)." for $_\n";
}
make_dep($t,$depth+1,$env,$list,$blist);
} else {
die "FATAL: $target->{name} searches for a frood called '$_'\n";
}
}
}
print "# adding ".vsn($target)." to list\n";
push(@$list, $target);
if (!$env->{quick} &&
$target->{name} ne 'openpkg' &&
$target->{REBUILD}) {
unless ($env->{revdep}) {
$env->{revdep} = get_revdep($env);
}
foreach $t (@{$env->{revdep}->{$target->{name}}}) {
# this is a rebuild, triggering further revdeps
$t->{REBUILD} = 1;
# this is a rebuild, keep this installed
push(@$blist, $t);
print "# rebuilding revdep ".vsn($t)."\n";
make_dep($t,$depth+1,$env,$list,$blist);
}
}
}
sub remove_list ($$$) {
my($targets, $keeps, $installed) = @_;
my(%keep);
%keep = map { $_ => 1 } @$keeps;
return [ grep {
!$keep{$_} && !$installed->{$_->{name}}->{vs($_)};
} @$targets
];
}
sub build_list ($$) {
my($pattern, $env) = @_;
my(@goals,@targets,@keeps,$bonly,$t);
my($name,$r,$i,@vers);
my(@todo);
if (defined $pattern) {
@todo = ();
foreach (split(/\s+/,$pattern)) {
next unless /\S/;
if (s/\*+$//) {
push @todo, '^'.quotemeta($_).'';
} else {
push @todo, '^'.quotemeta($_).'$';
}
}
$pattern = join('|',@todo);
@todo = grep(/$pattern/, keys %{$env->{repository}});
} else {
@todo = grep {
my($n) = $_;
(ref $env->{installed}->{$n}) &&
grep { $_ ne '-' } keys %{$env->{installed}->{$n}}
} keys %{$env->{repository}};
}
#
# chose sources for goals from repository
#
foreach $name (@todo) {
$t = undef;
#
# keeping installed packages for goals is ugly
# -> we currently do not support installed source RPMs
# -> source RPMs might already have expired from repository
#
# consequence:
# -> goals are always upgraded to repository versions
#
#unless ($env->{upgrade}) {
# $i = $env->{installed}->{$name};
# if (@vers = get_versions($i, sub { 1; })) {
# $t = chose_source($env, $name, $i, @vers);
# }
#}
unless ($t) {
$r = $env->{repository}->{$name};
if (@vers = get_versions($r, sub { 1; })) {
$t = chose_source($env, $name, $r, @vers);
}
}
die "FATAL: no known source found for '$name'\n" unless $t;
warn_about_options($t, $env->{with});
push(@goals, $t);
}
return unless @goals;
@targets = ();
@keeps = @goals;
foreach $t (@goals) {
print "# recursing over dependencies for ".vsn($t)."\n";
make_dep($t,0,$env,\@targets,\@keeps);
}
$bonly = remove_list(\@targets, \@keeps, $env->{installed});
return (\@targets, $bonly);
}
#######################################################################
sub target2rpm ($$) {
my($target,$c) = @_;
my($tmpl) = $c->{template};
$tmpl =~ s/%{NAME}/$target->{name}/;
$tmpl =~ s/%{VERSION}/$target->{version}/;
$tmpl =~ s/%{RELEASE}/$target->{release}/;
return $c->{rpmdir}.'/'.$tmpl;
}
#######################################################################
sub binary_target ($$) {
my($t, $fn) = @_;
my(%target) = %$t;
get_with(\%target, $fn);
return \%target;
}
sub make_defines ($$) {
my($old, $new) = @_;
my($with);
#
# override old parameters with new parameters
# drop new parameters that do not exist in old set
#
# if there is no old set at all (which happens if there
# is no template and no installed package), just use the
# new parameters and assume these are useful.
#
if ($old) {
$old = { %$old };
override_options($old, $new);
} else {
$old = $new;
}
#
# convert parameters to --define command line options
# skip parameter templates from index
#
$with = join(' ',map { "--define '$_ $old->{$_}'" }
grep { $old->{$_} !~ /^%/ } keys %$old);
$with = ' '.$with if $with ne '';
return $with;
}
sub print_list1 ($$$@$) {
my($list,$c,$uncond,$with,$ignore) = @_;
my($spkg,$bpkg);
my($opt);
my($cmd1, $cmd2, $mark);
$mark = '::::';
foreach (@$list) {
$spkg = $_->{href};
$bpkg = target2rpm($_, $c);
#
# rebuild binary package IF
#
# 'unconditional' option
# OR there is no binary package
# OR dependency check found that installed package is not suitable
# OR existing binary package doesn't satisfy wanted options
#
$cmd1 = undef;
if ($uncond || !-f $bpkg || $_->{REBUILD} ||
!target_suitable(binary_target($_, $bpkg),$with)) {
$opt = make_defines($_->{OPTIONS}, $with);
#
# someone preferred a binary from the repository
# just copy it to the local store
#
if (defined $_->{platform}) {
$cmd1 = "$CURL -q -s -o $bpkg $spkg";
} else {
$cmd1 = "$RPM_NPRIV$opt --rebuild $spkg";
}
}
#
# if package exist force rpm to copy over new files
# better than erasing everything and losing configuration
# files
#
$opt = $_->{REBUILD} ? ' --force' : '';
$cmd2 = "$RPM_PRIV$opt -Uvh $bpkg";
if ($ignore) {
$cmd2 = "$cmd1 && \\\n$cmd2" if defined $cmd1;
} else {
if (defined $cmd1) {
$cmd2 = "$cmd1 || exit \$?\n$cmd2 || exit \$?"
} else {
$cmd2 = "$cmd2 || exit \$?";
}
}
print "echo $mark $spkg $mark\n$cmd2\necho $mark $spkg = \$? $mark\n";
}
}
sub print_list2 ($$) {
my($list,$c) = @_;
my($pkg);
foreach (@$list) {
$pkg = "$_->{name}-$_->{version}-$_->{release}";
print "$RPM_PRIV -e $pkg\n";
}
}
#######################################################################
my($config,$url,$repository,$installed,$list,$bonly);
my($pattern,%with,%exclude);
if ($opt_a) {
$pattern = undef;
} else {
$pattern = join(' ', @ARGV);
}
if ($opt_A) {
$pattern = '*';
}
%with = map {
/([^\s=]+)(?:\=(\S+))?/
? ($1 => (defined $2 ? $2 : 'yes'))
: ()
} split(/\s+/, $opt_D);
%exclude = map { $_ => 1 } split(/\s+/, $opt_E);
$config = get_config();
if (defined $opt_p) {
$config->{platform} = $opt_p;
}
if (defined $opt_r) {
$url = $opt_r;
$url .= '/' unless $url =~ /\/$/;
} else {
$url = get_release();
}
#
# if we read the index from a file we can no longer deduce
# repository paths from index paths. For now lets assume
# that everything is below SRC/ to be compatible with
# existing file indexes.
#
if (defined $opt_f && !defined $opt_r) {
$url .= 'SRC/';
}
$installed = $opt_Z ? {} : get_installed();
$repository = get_index($url.'00INDEX.rdf',$opt_f,\%with);
($list,$bonly) = build_list($pattern, {
config => $config,
installed => $installed,
repository => $repository,
built => {},
revdep => undef,
with => \%with,
exclude => \%exclude,
upgrade => ($opt_a || $opt_U),
zero => ($opt_z || $opt_Z),
quick => $opt_q,
sourceonly => (
$opt_u ||
$opt_U ||
$opt_z ||
$opt_Z ||
scalar(%with) > 0 )
});
die "FATAL: cannot find package\n" unless defined $list;
print_list1($list,$config,$opt_a || $opt_u || $opt_U,\%with,$opt_i);
print_list2($bonly,$config);
Index: openpkg-src/openpkg-tool/openpkg-index.pl
============================================================
$ cvs update -p -r1.1 openpkg-index.pl
##
## openpkg-index -- create index from spec files
##
## Copyright (c) 2000-2002 Cable & Wireless Deutschland GmbH
## Copyright (c) 2000-2002 The OpenPKG Project <http://www.openpkg.org/>
## Copyright (c) 2000-2002 Ralf S. Engelschall <[EMAIL PROTECTED]>
##
## Permission to use, copy, modify, and distribute this software for
## any purpose with or without fee is hereby granted, provided that
## the above copyright notice and this permission notice appear in all
## copies.
##
## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
require 5;
use strict;
use Getopt::Std;
getopts('r:p:C:o:ci');
use vars qw/$opt_r $opt_p $opt_C $opt_o $opt_c $opt_i/;
use FileHandle;
use DirHandle;
my $RPM = 'rpm';
my $R2C = 'rpm2cpio';
my $BZ = 'bzip2 -9';
#########################################################################
#
# escape XML special characters for output in RDF file
#
# remove trailing whitespace
# remove common leading whitespace
#
sub e ($) {
my($s) = @_;
my($i);
$s =~ s/\n+$//sg;
$s =~ s/\s+$//mg;
$i = undef;
while ($s =~ /^(\s+)/mg) {
$i = $1 if !defined $i || length($1) < length($i);
}
$s =~ s/^\Q$i\E//mg if defined $i;
$s =~ s/&/&/sg;
$s =~ s/</</sg;
$s =~ s/>/>/sg;
return $s;
}
sub commasep ($$) {
my($k,$v) = @_;
if ($k =~ /^(PreReq|BuildPreReq|Provides|Conflicts)$/) {
return split(/\s*,\s*/, $v);
}
return $v;
}
sub vsub ($$) {
my($var,$v) = @_;
$v =~ s/\%\{([^}]+)\}/exists $var->{$1} ? $var->{$1} : '%{'.$1.'}'/emg;
return $v;
}
sub upn ($) {
my($t) = @_;
my(@tok) = $t =~ /(\(|\)|\&\&|\|\||\!|\S+)/g;
my(@out,$op,$o);
my(@save);
$op = [];
foreach (@tok) {
if ($_ eq '(') {
push @save, $op;
$op = [];
} elsif ($_ eq ')') {
die "FATAL: unresolved operators in: @tok\n" if @$op;
$op = pop @save
or die "FATAL: parenthesis stack underflow in: @tok\n";
while ($o = pop @$op) {
push @out, $o->[0];
last if $o->[1];
}
} elsif ($_ eq '&&') {
push @$op, [ '+', 1 ] ;
} elsif ($_ eq '||') {
push @$op, [ '|', 1 ] ;
} elsif ($_ eq '!') {
push @$op, [ '!', 0 ];
} elsif (/^\%\{(\S*?)\}$/) {
push @out, $1;
while ($o = pop @$op) {
push @out, $o->[0];
last if $o->[1]; # binop
}
}
}
return join (' ',@out);
}
#
# deduce external variables from description
#
sub find_options ($) {
my($descr) = @_;
my(%evar);
%evar = map {
$1 => '%{'.$1.'}'
} $descr =~ /--define\s*'(\S+)\s*\%\{\1\}'/;
return \%evar;
}
#
# translate default section from spec-file
# into a hash
# %if/%ifdef/%define... are translated to #if/#ifdef/#define
#
# #defines are interpolated (correct ?)
#
# #if/#ifdef/... sections are stripped
# result is the same as if all conditions evaluate false (!)
#
# all attributes are of the form key: value
# repeated attributes are coalesced into a list
#
sub package2data ($$) {
my($s,$evar) = @_;
my(%var);
my(@term, $term);
my(%attr);
my($l, $v, $cond, $d, $p);
my($re,@defs);
# combine multilines
$s =~ s/\\\n/ /sg;
#
# map conditional variable macros
#
$s =~ s/^#\{\!\?([^:]*):\s*%(.*?)\s*\}\s*$/#ifndef $1\n#$2\n#endif/mg;
$s =~ s/^#\{\!\?([^:]*):\s*(.*?)\s*\}\s*$/#ifndef $1\n$2\n#endif/mg;
#
# guess more external parameters by scanning for "default" sections.
#
$re = '^\#ifndef\s+[\w\_]+\s*\n((?:\#define\s+[\w\_]+\s.*\n)+)\#endif\n';
@defs = $s =~ /$re/gm;
foreach (@defs) {
while (/^\#define\s+([\w\_]+)\s(.*?)\s*$/mg) {
$evar->{$1} = '%{'.$1.'}';
}
}
$s =~ s/$re//gm;
#
# add everything looking like a with_ variable
#
$re = '%{(with\_[\w\_]+)}';
@defs = $s =~ /$re/gm;
foreach (@defs) {
$evar->{$1} = '%{'.$1.'}';
}
#
# extract all conditional sections
#
@term = ();
%var = ();
$cond = '';
foreach $l (split(/\n/, $s)) {
$v = vsub(\%var,$l);
if (($p) = $v =~ /^\#if\s+(.*?)\s*$/) {
#
# normalize #if expressions
# "%{variable}" == "yes"
# "%{variable}" == "no"
# operators ! && ||
#
$term = '';
while ($p =~
/(!=)|(\!|\|\||\&\&|\(|\))|"\%\{([^}]+)\}"\s*==\s*"(yes|no)"|(\S+)/g) {
if (defined $1) {
warn "WARNING: unknown token '$1':\n< $l\n> $v\n";
} elsif (defined $5) {
warn "WARNING: unknown token '$5':\n< $l\n> $v\n";
} elsif (defined $2) {
$term .= " $2 ";
} elsif (exists $evar->{$3}) {
$term .= ($4 eq 'no' ? '! ' : '').vsub($evar,'%{'.$3.'}');
} else {
warn "WARNING: unknown conditional '$2':\n< $l\n> $v\n";
}
}
#
# join with previous conditions for this #if/#endif block
#
if ($term ne '') {
push @term, "( $term )";
$cond = join(' && ', grep { $_ ne '' } @term).'';
} else {
push @term, '';
}
} elsif ($v =~ /^\#else\s*$/) {
#
# reverse last condition
#
if (@term) {
$term[-1] = ' ! '.$term[-1];
$cond = join(' && ', grep { $_ ne '' } @term).'';
} else {
die "FATAL: else without if\n";
}
} elsif ($v =~ /^\#endif\s*$/) {
#
# unwind last #if expression
#
pop @term;
$cond = join(' && ', grep { $_ ne '' } @term).'';
} elsif ($v =~ /^\#(?:define)\s*(\S+)\s*(.*?)\s*$/) {
#
# define conditional variables
# truth-value becomes current condition
#
# define internal variables
# -> store for subsequent substitution
#
if (exists $evar->{$1}) {
if ($2 eq 'yes') {
$evar->{$1} = "( \%\{$1\} || ( $cond ) )";
} elsif ($2 eq 'no') {
$evar->{$1} = "( %\{$1\} && ! ( $cond ) )";
} else {
warn "WARNING: logic too complex for '$1':\n< $l\n> $v\n";
}
} else {
$var{$1} = $2;
}
} elsif ($v =~ /^\s*([^\#]\S*)\s*:\s*(.*?)\s*$/) {
#
# store attribute=value for current condition
#
push @{$attr{$1}->{$cond}}, commasep($1,$2);
}
}
return \%attr;
}
#
# split spec file into sections starting with a %word
#
# concatenate extended lines
# strip comment lines
# map %command to #command
# split sections
#
# return package2data from default section.
#
sub spec2data ($) {
my($s) = @_;
my(%map);
my($a,$o);
# remove comments
$s =~ s/^\s*#.*?\n//mg;
# map commands
$s =~ s/^%(ifdef|ifndef|if|define|else|endif|\{)/#$1/mg;
# split sections
foreach (split(/^(?=%\w+\s*\n)/m, $s)) {
if (/^%(\w+)\s*\n/) {
$map{$1} .= $';
} else {
$map{'*'} .= $_;
}
}
$o = find_options($map{'description'});
$a = package2data($map{'*'}, $o);
if (exists $map{'description'}) {
$a->{'Description'} = { '' => [ $map{'description'} ] };
}
return $a;
}
##########################################################################
#
# start of XML file
#
sub xml_head ($$) {
my($fh,$res) = @_;
print $fh <<EOFEOF;
<?xml version="1.0" encoding="iso-8859-1"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.openpkg.org/xml-rdf-index/0.9">
<Repository rdf:resource="$res">
EOFEOF
}
#
# end of XML file, corresponds with start tags
#
sub xml_foot ($) {
my($fh) = @_;
print $fh <<EOFEOF;
</Repository>
</rdf:RDF>
EOFEOF
}
sub n($$) {
my($a,$k) = @_;
return unless $a->{$k};
return unless $a->{$k}->{''};
return $a->{$k}->{''}->[0];
}
#
# send out $a->{$k} as text-style tag
#
sub xml_text ($$$;$) {
my($i,$a,$k,$tag) = @_;
my($out);
return "" unless exists $a->{$k};
$tag = $k unless defined $tag;
$i = ' ' x $i;
$out = e(n($a,$k));
return if $out eq '';
return "$i<$tag>\n$out\n$i</$tag>\n";
}
#
# send out @{$a->{$k}} as body of an XML tag
# $k is the name of the tag unless overridden by $tag
# $i denotes the depth of indentation to form nicely
# looking files.
#
# all data from the list is flattened into a single
# body, separated by LF and escaped for XML metachars.
#
sub xml_tag ($$$;$) {
my($i,$a,$k,$tag) = @_;
my($out,$cond,$upn);
return "" unless exists $a->{$k};
$tag = $k unless defined $tag;
$out = '';
$i = ' ' x $i;
foreach $cond (sort keys %{$a->{$k}}) {
$upn = e(upn($cond));
$out .= $i.
($cond ne '' ? "<$tag cond=\"$upn\">" : "<$tag>").
join("\n", map { e($_) } @{$a->{$k}->{$cond}}).
"</$tag>\n";
}
return $out;
}
#
# send out @{$a->{$k}} as a rdf:bag
# $k is the name of the outer tag unless overriden by $tag
# $i denotes the depth of indentation, inner tags are indented
# 2 or 4 more character positions.
#
sub xml_bag ($$$;$) {
my($i,$a,$k,$tag) = @_;
my($out,$cond,$upn);
return "" unless exists $a->{$k};
$tag = $k unless defined $tag;
$out = '';
$i = ' ' x $i;
foreach $cond (sort keys %{$a->{$k}}) {
$upn = e(upn($cond));
$out .= $i.
($cond ne '' ? "<$tag cond=\"$upn\">\n" : "<$tag>\n").
"$i <rdf:bag>\n".
join("",
map { "$i <rdf:li>".e($_)."</rdf:li>\n" }
@{$a->{$k}->{$cond}}).
"$i </rdf:bag>\n".
"$i</$tag>\n";
}
return $out;
}
#
# send out reference to another RDF
#
sub xml_reference ($$$) {
my($fh, $res, $href) = @_;
print $fh <<EOFEOF;
<Repository rdf:resource="$res" href="$href"/>
EOFEOF
}
#
# translate attributes from %$a as generated by package2data
# into XML and write to file $fh
#
sub xml_record ($$$) {
my($fh, $a, $href) = @_;
my($maj,$min,$rel,$about);
$about =
n($a,'Name').'-'.
n($a,'Version').'-'.
n($a,'Release');
unless (defined $href) {
# guess location from Information in Specfile
$href = "$about.src.rpm";
($maj,$min,$rel) = n($a,'Release') =~ /^(\d+)\.(\d+)\.(\d+)/;
if (defined $min) {
if ($maj > 1 || ($maj == 1 && $min > 0)) {
# 1.1 or later
if (n($a,'Distribution') =~ /\[PLUS\]/) {
$href = 'PLUS/'.$href;
}
}
if ($maj > 1 || ($maj == 1 && $min >= 0)) {
# 1.0 or later
if ($rel > 0) {
$href = 'UPD/'.$href;
}
}
} else {
# current
}
}
print $fh <<EOFEOF;
<rdf:Description about="$about" href="$href">
EOFEOF
# fake Source attribute from Source\d attribtutes
# XXX only default conditional
$a->{'Source'} = { '' => [
map {
s/\Q%{name}\E/n($a,'Name')/esg;
s/\Q%{version}\E/n($a,'Version')/esg;
s/\Q%{release}\E/n($a,'Release')/esg;
s/.*\///;
$_;
}
map {
$a->{$_}->{''} ? @{$a->{$_}->{''}} : ()
}
sort {
my($x) = $a =~ /^(\d*)$/;
my($y) = $b =~ /^(\d*)$/;
return $x <=> $y;
}
grep {
/^Source\d*$/
} keys %$a
]};
delete $a->{'Source'} unless @{$a->{'Source'}->{''}};
print $fh
xml_tag(6, $a, 'Name'),
xml_tag(6, $a, 'Version'),
xml_tag(6, $a, 'Release'),
xml_tag(6, $a, 'Distribution'),
xml_tag(6, $a, 'Group'),
xml_tag(6, $a, 'License'),
xml_tag(6, $a, 'Packager'),
xml_tag(6, $a, 'Summary'),
xml_tag(6, $a, 'URL'),
xml_tag(6, $a, 'Vendor'),
xml_tag(6, $a, 'SourceRPM'),
xml_tag(6, $a, 'Arch'),
xml_tag(6, $a, 'Os'),
xml_tag(6, $a, 'BuildRoot'),
xml_tag(6, $a, 'BuildHost'),
xml_tag(6, $a, 'BuildSystem'),
xml_tag(6, $a, 'BuildTime'),
xml_tag(6, $a, 'Relocations'),
xml_tag(6, $a, 'Size'),
xml_tag(6, $a, 'Prefixes'),
xml_tag(6, $a, 'Platform'),
xml_tag(6, $a, 'SigSize'),
xml_tag(6, $a, 'SigMD5'),
xml_tag(6, $a, 'SigPGP'),
xml_tag(6, $a, 'SigGPG'),
xml_bag(6, $a, 'BuildPreReq'),
xml_bag(6, $a, 'PreReq'),
xml_bag(6, $a, 'Provides'),
xml_bag(6, $a, 'Conflicts'),
xml_bag(6, $a, 'Source'),
xml_bag(6, $a, 'Filenames'),
xml_text(6, $a, 'Description');
print $fh <<EOFEOF;
</rdf:Description>
EOFEOF
}
#####################################################################
sub rpm2spec ($) {
my($fn) = @_;
my($pipe) = new FileHandle "$R2C '$fn' |"
or die "FATAL: cannot read '$fn' ($!)\n";
my($buf,@hdr,$n,$m,$name,$step);
my($spec);
while (read($pipe,$buf,110) == 110) {
@hdr = unpack('a6a8a8a8a8a8a8a8a8a8a8a8a8a8',$buf);
$n = hex($hdr[12]); # filename length
$m = int(($n+5)/4)*4-2; # filename size (padded)
last unless read($pipe,$buf,$m) == $m;
$name = substr($buf,0,$n-1);
$n = hex($hdr[7]); # file length
$m = int(($n+3)/4)*4; # file size (padded)
if ($name !~ /.spec$/) {
while ($m > 0) {
$step = $m > 8192 ? 8192 : $m;
last unless read($pipe,$buf,$step);
$m -= length($buf);
}
} else {
if (read($pipe,$buf,$n) == $n) {
$spec = $buf;
}
last;
}
}
$pipe->close;
return $spec;
}
#####################################################################
sub rpm2data ($$) {
my($fn,$platform) = @_;
my($q,$pipe,%a);
my($t,$v);
$q = <<EOFEOF;
Name %{Name}
Version %{Version}
Release %{Release}
URL %{URL}
Summary %{Summary}
Copyright %{Copyright}
License %{License}
Distribution %{Distribution}
Vendor %{Vendor}
Group %{Group}
Packager %{Packager}
Prefixes %{Prefixes}
BuildRoot %{BuildRoot}
BuildHost %{BuildHost}
BuildTime %{BuildTime}
Arch %{Arch}
Os %{Os}
Size %{Size}
SigSize %{SigSize}
SigMD5 %{SigMD5}
SigPGP %{SigPGP}
SigGPG %{SigGPG}
SourceRPM %{SourceRPM}
[Patch %{Patch}
]
[Source %{Source}
]
[Filenames %{Filenames}
]
[Conflicts %{CONFLICTNAME} %|CONFLICTFLAGS?{%{CONFLICTFLAGS:depflags}
%{CONFLICTVERSION}}:{}|
]
[PreReq %{REQUIRENAME} %|REQUIREFLAGS?{%{REQUIREFLAGS:depflags}
%{REQUIREVERSION}}:{}|
]
[Provides %{PROVIDENAME} %|PROVIDEFLAGS?{%{PROVIDEFLAGS:depflags}
%{PROVIDEVERSION}}:{}|
]
Description %{Description}
EOFEOF
$pipe = new FileHandle "$RPM -qp --qf '$q' '$fn' |"
or die "FATAL: cannot read '$fn' ($!)\n";
while (<$pipe>) {
if (/^(\S+)\s+(.*?)\s*$/) {
$t = $1;
$v = $2;
} elsif (/^(\s+.+?)\s*$/) {
next unless defined $t;
$v = $1;
} else {
$t = undef;
next;
}
if (exists $a{$t}) {
$a{$t} .= "\n$v";
} else {
$a{$t} = $v;
}
}
$pipe->close;
%a = map { $_ => $a{$_} }
grep { $a{$_} ne '(none)' }
keys %a;
if ($a{'Relocations'} eq '(non relocatable)') {
delete $a{'Relocations'};
}
if ($a{'SigMD5'} eq '(unknown type)') {
delete $a{'SigMD5'};
}
$a{'Platform'} = "$a{'Arch'}-$platform-$a{'Os'}";
$a{'PreReq'} =~ s/^rpmlib\(.*$//mg;
$a{'Description'} = [ $a{'Description'} ];
return { map {
$_ => { '' => (ref $a{$_} ? $a{$_} : [ split(/\n+/, $a{$_}) ]) }
} keys %a };
}
#####################################################################
sub getindex ($) {
my($dir) = @_;
my(@idx) = sort { -M $a <=> -M $b; }
grep { -f $_ }
( <$dir/00INDEX.rdf>, <$dir/00INDEX.rdf.*> );
return unless @idx;
return $idx[0];
}
sub list_specdir ($) {
my($dir) = @_;
my($dh,$d,$path);
my(@list);
$dh = new DirHandle($dir);
while ($d = $dh->read) {
next if $d =~ /^\./;
$path = "$dir/$d/$d.spec";
push @list, $path if -f $path;
}
return \@list;
}
sub list_rpmdir ($) {
my($dir) = @_;
my($dh,$d,$path);
my(@list,$idx,$sub);
$dh = new DirHandle($dir);
while ($d = $dh->read) {
next if $d =~ /^\./;
$path = "$dir/$d";
if (-d $path) {
$idx = getindex($path);
if (defined $idx) {
push @list, $idx;
} else {
$sub = list_rpmdir($path);
push @list, @$sub;
undef $sub;
}
} else {
next unless $d =~ /\.rpm$/ && -f $path;
push @list, $path;
}
}
return \@list;
}
#####################################################################
sub readfile ($) {
my($fn) = @_;
my($fh) = new FileHandle "< $fn"
or die "FATAL: cannot read '$fn' ($!)\n";
my(@l) = <$fh>;
$fh->close;
return join('',@l);
}
sub relpath ($$) {
my($prefix,$path) = @_;
$path =~ s/^\Q$prefix\E\///s;
return $path;
}
sub dirname ($) {
my($path) = @_;
$path =~ s/\/[^\/]*$//s;
return $path.'/';
}
sub getresource ($) {
my($fn) = @_;
my($fh, $buf);
if ($fn =~ /\.bz2$/) {
$fh = new FileHandle "$BZ -dc $fn |"
or die "FATAL: cannot read '$fn' ($!)\n";
} else {
$fh = new FileHandle "< $fn"
or die "FATAL: cannot read '$fn' ($!)\n";
}
$fh->read($buf, 1024);
$fh->close;
if ($buf =~ /<Repository.*?rdf:resource="([^"]+)"/) {
return $1;
}
return undef;
}
#####################################################################
sub write_index ($$$$$$) {
my($fh,$prefix,$resource,$platform,$list,$cache) = @_;
my($a,$h,$r,$spec);
my($mtime);
foreach (@$list) {
$a = undef;
$h = undef;
$r = undef;
if (/\.spec$/) {
$spec = readfile($_);
$a = spec2data($spec);
} elsif (/([^\/]+\.src\.rpm)$/) {
$h = relpath($prefix, $_);
if ($cache) {
$mtime = (stat $_)[9];
if (exists $cache->{"M$_"} &&
$cache->{"M$_"} == $mtime) {
$spec = $cache->{"S$_"};
} else {
$spec = rpm2spec($_);
$cache->{"S$_"} = $spec;
$cache->{"M$_"} = $mtime;
}
} else {
$spec = rpm2spec($_);
}
$a = spec2data($spec);
} elsif (/([^\/]+\.rpm)$/) {
$h = relpath($prefix, $_);
$a = rpm2data($_, $platform);
} elsif (/([^\/]+\.rdf[^\/]*)$/) {
$h = relpath($prefix, $_);
$r = getresource($_) || $resource.dirname($h);
}
if ($a) {
xml_record($fh, $a, $h);
} elsif ($r) {
xml_reference($fh, $r, $h);
} else {
warn "ERROR: cannot process $_\n";
}
}
}
#####################################################################
my($prefix,$list,$fh,%cache,$tmpo);
if ($#ARGV < 0) {
print "openpkg:index:USAGE: $0 [-r resource] [-p platform] [-C cache.db] [-o
index.rdf] [-c] [-i] dir ...\n";
die "\n";
}
if ($opt_C) {
require DB_File;
tie %cache, 'DB_File', $opt_C, O_CREAT|O_RDWR, 0666, $DB_File::DB_HASH
or die "FATAL: cannot tie cache '$opt_C' ($!)\n";
}
$opt_r = 'OpenPKG-CURRENT/Source/' unless defined $opt_r;
$opt_p = 'unknown' unless defined $opt_p;
if (defined $opt_o) {
$tmpo = $opt_o . '.tmp';
if ($opt_c) {
$fh = new FileHandle "| $BZ -c > '$tmpo'"
or die "FATAL: cannot write '$tmpo' ($!)\n";
} else {
$fh = new FileHandle "> $tmpo"
or die "FATAL: cannot write '$tmpo' ($!)\n";
}
} else {
if ($opt_c) {
$fh = new FileHandle "| $BZ -c"
or die "FATAL: cannot write to stdout ($!)\n";
} else {
$fh = new FileHandle ">&=1"
or die "FATAL: cannot write to stdout ($!)\n";
}
}
xml_head($fh, $opt_r);
foreach $prefix (@ARGV) {
die "FATAL: $prefix is not a directory\n" unless -d $prefix;
if ($opt_i) {
$list = list_rpmdir($prefix);
} else {
$list = list_specdir($prefix);
}
write_index($fh, $prefix, $opt_r, $opt_p, $list, $opt_C ? \%cache : undef);
}
xml_foot($fh);
$fh->close
or die "FATAL: write error on output ($!)\n";
if (defined $tmpo) {
rename $tmpo,$opt_o
or die "FATAL: cannot rename $tmpo to $opt_o ($!)\n";
}
Index: openpkg-src/openpkg-tool/openpkg-tool.spec
============================================================
$ cvs update -p -r1.1 openpkg-tool.spec
##
## openpkg-tool.spec -- OpenPKG RPM Specification
## Copyright (c) 2000-2002 Cable & Wireless Deutschland GmbH
## Copyright (c) 2000-2002 The OpenPKG Project <http://www.openpkg.org/>
## Copyright (c) 2000-2002 Ralf S. Engelschall <[EMAIL PROTECTED]>
##
## Permission to use, copy, modify, and distribute this software for
## any purpose with or without fee is hereby granted, provided that
## the above copyright notice and this permission notice appear in all
## copies.
##
## THIS SOFTWARE IS PROVIDED AS IS'' AND ANY EXPRESSED OR IMPLIED
## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
# package information
Name: openpkg-tool
Summary: OpenPKG Tool
URL: http://www.openpkg.org/
Vendor: The OpenPKG Project
Packager: The OpenPKG Project
Distribution: OpenPKG [EVAL]
Group: Bootstrapping
License: GPL
Version: 20021126
Release: 20021126
# list of sources
Source0: openpkg.sh
Source1: openpkg-index.pl
Source2: openpkg-build.pl
Source3: openpkg.pod
Source4: openpkg.1
Source5: Makefile
# build information
Prefix: %{l_prefix}
BuildRoot: %{l_buildroot}
BuildPreReq: OpenPKG, openpkg >= 20020206
PreReq: OpenPKG, openpkg >= 20020206
AutoReq: no
AutoReqProv: no
%description
The OpenPKG tool is a helper utility for managing an OpenPKG instance.
%prep
%build
%install
rm -rf $RPM_BUILD_ROOT
%{l_shtool} mkdir -f -p -m 755 \
$RPM_BUILD_ROOT%{l_prefix}/bin \
$RPM_BUILD_ROOT%{l_prefix}/lib/openpkg \
$RPM_BUILD_ROOT%{l_prefix}/man/man1
%{l_shtool} install -c -m 755 \
-e 's;@l_prefix@;%{l_prefix};g' \
-e 's;@version@;%{version};g' \
%{SOURCE openpkg.sh} $RPM_BUILD_ROOT%{l_prefix}/bin/openpkg
%{l_shtool} install -c -m 644 \
-e 's;@l_prefix@;%{l_prefix};g' \
-e 's;@version@;%{version};g' \
%{SOURCE openpkg.1} $RPM_BUILD_ROOT%{l_prefix}/man/man1/
%{l_shtool} install -c -m 755 \
%{SOURCE openpkg-index.pl} \
$RPM_BUILD_ROOT%{l_prefix}/lib/openpkg/
%{l_shtool} install -c -m 755 \
%{SOURCE openpkg-build.pl} \
$RPM_BUILD_ROOT%{l_prefix}/lib/openpkg/
%{l_rpmtool} files -v -ofiles -r$RPM_BUILD_ROOT \
%{l_files_std} \
'%not %dir %{l_prefix}/lib/openpkg'
%files -f files
%clean
rm -rf $RPM_BUILD_ROOT
Index: openpkg-src/openpkg-tool/openpkg.1
============================================================
$ cvs update -p -r1.1 openpkg.1
.\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. | will give a
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
.\" expand to `' in nroff, nothing in troff, for use with C<>.
.tr \(*W-|\(bv\*(Tr
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C`
. ds C'
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.\"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds :
\\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "OPENPKG 1"
.TH OPENPKG 1 "2002-11-26" "openpkg-tool" "OpenPKG Maintainance"
.SH "NAME"
\&\fBopenpkg\fR \- \fBOpenPKG\fR maintainance utility
.SH "VERSION"
.IX Header "VERSION"
openpkg-tool \f(CW@version\fR@
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBopenpkg\fR
\&\fBindex\fR
[\fB\-r\fR \fIresource\fR]
[\fB\-p\fR \fIplatform\fR]
[\fB\-C\fR \fIcache.db\fR]
[\fB\-o\fR \fIindex.rdf\fR]
[\fB\-c\fR]
[\fB\-i\fR]
\&\fIdir\fR ...
.PP
\&\fBopenpkg\fR
\&\fBbuild\fR
[\fB\-R\fR \fIrpm\fR]
[\fB\-r\fR \fIrepository\fR]
[\fB\-f\fR \fIindex.rdf\fR]
[\fB\-u\fR]
[\fB\-U\fR]
[\fB\-z\fR]
[\fB\-Z\fR]
[\fB\-i\fR]
[\fB\-q\fR]
[\fB\-P\fR \fIpriv-cmd\fR]
[\fB\-N\fR \fInon-priv-cmd\fR]
[\fB\-p\fR \fIplatform\fR]
[\fB\-D\fR\fIvar\fR=\fIval\fR ...]
[\fB\-E\fR \fIname\fR ...]
([\fB\-a\fR] [\fB\-A\fR] | \fIpatternlist\fR)
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBopenpkg\fR is a frontend utility for maintaining an \fBOpenPKG\fR instance.
It currenty provides indexing of \s-1RPM\s0 files (\fBopenpkg index\fR) and
automated recursive from-scratch installation and updating of existing
\&\s-1RPM\s0 packages (\fBopenpkg build\fR).
.SH "COMMANDS"
.IX Header "COMMANDS"
.Sh "\s-1OPENPKG\s0 \s-1INDEX\s0"
.IX Subsection "OPENPKG INDEX"
\&\fBopenpkg-index\fR creates an \s-1XML/RDF\s0 based resource index for \s-1RPM\s0
\&\fI.spec\fR files in a source tree or from an \s-1RPM\s0 package repository. The
index holds enough information to support an automated build process by
\&\fBopenpkg build\fR.
.PP
The following command line options exist:
.IP "\fB\-r\fR \fIresource\fR" 4
.IX Item "-r resource"
The name of the resource stored in the index. The default is
"\f(CW\*(C`OpenPKG\-CURRENT/Source/\*(C'\fR".
.IP "\fB\-p\fR \fIplatform\fR" 4
.IX Item "-p platform"
\&\fBopenpkg index\fR adds a platform attribute for binary RPMs. The
attribute is built as
\fI%{arch}\fR\f(CW\*(C`\-\*(C'\fR\fIplatform\fR\f(CW\*(C`\-\*(C'\fR\fI%{os}\fR where
\&\fI%{arch}\fR and \fI%{os}\fR are taken from the \s-1RPM\s0 header and
\fIplatform\fR is
the value of the \fB\-p\fR option. The default value is "\f(CW\*(C`unkown\*(C'\fR".
This
must be used to distinguish between platforms that support the same
Architecture and \s-1OS\s0 name like various Linux distributions.
.IP "\fB\-C\fR \fIcache.db\fR" 4
.IX Item "-C cache.db"
Cache all \fI.spec\fR files into this Berkeley-DB file when indexing source
RPMs. The cache is refreshed automatically when the source RPMs are more
recent than the cache entry.
.IP "\fB\-o\fR \fIindex.rdf\fR" 4
.IX Item "-o index.rdf"
Name of the output \s-1XML/RDF\s0 file, default is to write to \fIstdout\fR.
.IP "\fB\-c\fR" 4
.IX Item "-c"
Compress output with \f(CW\*(C`bzip2\*(C'\fR. Use the \fB\-o\fR option to specify a
\fI.bz2\fR
suffix.
.IP "\fB\-i\fR" 4
.IX Item "-i"
The specified directories are \s-1RPM\s0 repositories. Build index over
all \fI.rpm\fR files in these directories and all subdirectories.
If a subdirectory already contains a \f(CW\*(C`00INDEX.rdf\*(C'\fR or
\f(CW\*(C`00INDEX.rdf.*\*(C'\fR
file then skip scanning the subdirectory, instead add a reference
to the index file into the new index.
.Sp
Without this option the directories are source trees with a subdirectory
per package and a \fIpackage\fR\f(CW\*(C`.spec\*(C'\fR file inside each subdirectory.
.Sh "\s-1OPENPKG\s0 \s-1BUILD\s0"
.IX Subsection "OPENPKG BUILD"
\&\fBopenpkg build\fR writes a shell script to standard output that installs
or upgrades software packages including all dependencies. Packages that
are upgraded automatically trigger rebuilds of all packages that depend
on the upgraded package (\*(L"reverse dependencies\*(R"). The dependency
information is read from an index generated by \fBopenpkg index\fR.
.PP
The following command line options exist:
.IP "\fB\-R\fR \fIrpm\fR" 4
.IX Item "-R rpm"
Specify a path to the installed \fBOpenPKG\fR \f(CW\*(C`rpm\*(C'\fR executable.
Several
other internal paths are deduced from the \fIrpm\fR path, so this should be
something like \fI%{l_prefix}\fR\f(CW\*(C`/bin/rpm\*(C'\fR.
.IP "\fB\-r\fR \fIrepository\fR" 4
.IX Item "-r repository"
Specify a path to an \s-1RPM\s0 repository, this can be a \s-1URL\s0 or a directory
path. The name of the package file is appended to this path.
The default is to use a \s-1URL\s0 pointing to the \fBOpenPKG\fR \s-1FTP\s0 server.
.IP "\fB\-f\fR \fIindex.rdf\fR" 4
.IX Item "-f index.rdf"
Specify a path to the primary \s-1XML/RDF\s0 index, this can be a \s-1URL\s0 or a
file path. If the index contains references to aother indexes these are
included automatically. The default is to use a \s-1URL\s0 pointing to the
\&\fBOpenPKG\fR \s-1FTP\s0 server for the \fBOpenPKG\fR release you are using.
.IP "\fB\-u\fR" 4
.IX Item "-u"
The generated script will ignore binary RPMs that are stored on
your system. Instead it will either fetch binary RPMs or rebuild
from source RPMs fetched from the repository.
.IP "\fB\-U\fR" 4
.IX Item "-U"
The generated script will try to upgrade all selected packages
including their dependencies to the most recent version.
.IP "\fB\-z\fR" 4
.IX Item "-z"
The generated script will rebuild all selected packages
including their dependencies even when the most recent version
is already installed.
.IP "\fB\-Z\fR" 4
.IX Item "-Z"
\&\fBopenpkg build\fR ignores a installed packages, the
script will rebuild all selected packages from scratch.
Note that this doesn't work together with the \fB\-a\fR option.
.IP "\fB\-i\fR" 4
.IX Item "-i"
The generated script will ignore errors. However, if a build
phase fails the install phase is still skipped.
.IP "\fB\-q\fR" 4
.IX Item "-q"
Ignore all reverse dependencies.
\&\fI\s-1ATTENTION:\s0 this might break already installed packages!\fR
.IP "\fB\-P\fR \fIpriv-cmd\fR" 4
.IX Item "-P priv-cmd"
Command prefix to use for install commands that require elevated
privileges. The most common tool for this is \fIsudo\fR\|(1).
.IP "\fB\-N\fR \fInon-priv-cmd\fR" 4
.IX Item "-N non-priv-cmd"
Command prefix to use for install commands that do not require elevated
privileges. The most common tool for this is \fIsudo\fR\|(1).
.IP "\fB\-p\fR \fIplatform\fR" 4
.IX Item "-p platform"
The platform string that is matched against the index for binary
packages. Default is to use the \fI%{_target_platform}\fR variable.
.IP "\fB\-D\fR\fIvar\fR=\fIval\fR" 4
.IX Item "-Dvar=val"
Specify configuration options for all selected packages. This can be
either \fB\-D\fR\f(CW\*(C`with_\*(C'\fR\fIxxx\fR\f(CW\*(C`=\*(C'\fR\fIyyy\fR or just
\fB\-D\fR\f(CW\*(C`with_\*(C'\fR\fIxxx\fR, the
latter is equivalent to a
\fB\-D\fR\f(CW\*(C`with_\*(C'\fR\fIxxx\fR\f(CW\*(C`=\*(C'\fR\f(CW\*(C`yes\*(C'\fR. The
parameters
are matched against selected packages that are already installed. If
they do indicate a change the package is rebuild. There can be multiple
\&\fB\-D\fR options.
.IP "\fB\-E\fR \fIname\fR" 4
.IX Item "-E name"
Ignore a package with the specified \fIname\fR. This can be used to avoid
upgrading to a broken package in the repository. There can be multiple
\&\fB\-E\fR options.
.IP "\fB\-a\fR" 4
.IX Item "-a"
Select all installed packages. Do not specify a pattern list together
with the \fB\-a\fR option.
.IP "\fB\-A\fR" 4
.IX Item "-A"
Select all packages in the repository. Do not specify a pattern list together
with the \fB\-a\fR option.
.SH "CONFIGURATION"
.IX Header "CONFIGURATION"
\&\fBopenpkg build\fR reads the configuration file \fI$HOME/.openpkg/build\fR.
The file lists default options, one option per line and section tags
of the form \f(CW\*(C`[\*(C'\fR\fIprefix\fR\f(CW\*(C`]\*(C'\fR. Options following
such a tag are only
evaluated if the selected \s-1RPM\s0 path matches the prefix so that you can
define default options for multiple \fBOpenPKG\fR hierarchies.
.SH "CAVEATS"
.IX Header "CAVEATS"
Parallel execution of \fBopenpkg build\fR causes undefined effects.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fIrpm\fR\|(1), \fIsudo\fR\|(1)
.SH "HISTORY"
.IX Header "HISTORY"
The \fBopenpkg index\fR and \fBopenpkg build\fR command
was invented in November 2002 by \fIMichael van Elst\fR
<[EMAIL PROTECTED]> under contract with \fICable & Wireless
Germany\fR <http://www.cw.com/de> for use inside the \fBOpenPKG\fR
project <http://www.openpkg.org/>.
.SH "AUTHORS"
.IX Header "AUTHORS"
.Vb 2
\& Michael van Elst
\& [EMAIL PROTECTED]
.Ve
Index: openpkg-src/openpkg-tool/openpkg.pod
============================================================
$ cvs update -p -r1.1 openpkg.pod
##
## openpkg.pod -- OpenPKG maintainance utility (frontend manual page)
##
## Copyright (c) 2000-2002 Cable & Wireless Deutschland GmbH
## Copyright (c) 2000-2002 The OpenPKG Project <http://www.openpkg.org/>
## Copyright (c) 2000-2002 Ralf S. Engelschall <[EMAIL PROTECTED]>
##
## Permission to use, copy, modify, and distribute this software for
## any purpose with or without fee is hereby granted, provided that
## the above copyright notice and this permission notice appear in all
## copies.
##
## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
=pod
=head1 NAME
B<openpkg> - B<OpenPKG> maintainance utility
=head1 VERSION
openpkg-tool @version@
=head1 SYNOPSIS
B<openpkg>
B<index>
[B<-r> I<resource>]
[B<-p> I<platform>]
[B<-C> I<cache.db>]
[B<-o> I<index.rdf>]
[B<-c>]
[B<-i>]
I<dir> ...
B<openpkg>
B<build>
[B<-R> I<rpm>]
[B<-r> I<repository>]
[B<-f> I<index.rdf>]
[B<-u>]
[B<-U>]
[B<-z>]
[B<-Z>]
[B<-i>]
[B<-q>]
[B<-P> I<priv-cmd>]
[B<-N> I<non-priv-cmd>]
[B<-p> I<platform>]
[B<-D>I<var>=I<val> ...]
[B<-E> I<name> ...]
([B<-a>] [B<-A>] | I<patternlist>)
=head1 DESCRIPTION
B<openpkg> is a frontend utility for maintaining an B<OpenPKG> instance.
It currenty provides indexing of RPM files (B<openpkg index>) and
automated recursive from-scratch installation and updating of existing
RPM packages (B<openpkg build>).
=head1 COMMANDS
=head2 OPENPKG INDEX
B<openpkg-index> creates an XML/RDF based resource index for RPM
F<.spec> files in a source tree or from an RPM package repository. The
index holds enough information to support an automated build process by
B<openpkg build>.
The following command line options exist:
=over 4
=item B<-r> I<resource>
The name of the resource stored in the index. The default is
"C<OpenPKG-CURRENT/Source/>".
=item B<-p> I<platform>
B<openpkg index> adds a platform attribute for binary RPMs. The
attribute is built as I<%{arch}>C<->I<platform>C<->I<%{os}> where
I<%{arch}> and I<%{os}> are taken from the RPM header and I<platform> is
the value of the B<-p> option. The default value is "C<unkown>". This
must be used to distinguish between platforms that support the same
Architecture and OS name like various Linux distributions.
=item B<-C> I<cache.db>
Cache all F<.spec> files into this Berkeley-DB file when indexing source
RPMs. The cache is refreshed automatically when the source RPMs are more
recent than the cache entry.
=item B<-o> I<index.rdf>
Name of the output XML/RDF file, default is to write to F<stdout>.
=item B<-c>
Compress output with C<bzip2>. Use the B<-o> option to specify a F<.bz2>
suffix.
=item B<-i>
The specified directories are RPM repositories. Build index over
all F<.rpm> files in these directories and all subdirectories.
If a subdirectory already contains a C<00INDEX.rdf> or C<00INDEX.rdf.*>
file then skip scanning the subdirectory, instead add a reference
to the index file into the new index.
Without this option the directories are source trees with a subdirectory
per package and a I<package>C<.spec> file inside each subdirectory.
=back
=head2 OPENPKG BUILD
B<openpkg build> writes a shell script to standard output that installs
or upgrades software packages including all dependencies. Packages that
are upgraded automatically trigger rebuilds of all packages that depend
on the upgraded package ("reverse dependencies"). The dependency
information is read from an index generated by B<openpkg index>.
The following command line options exist:
=over 4
=item B<-R> I<rpm>
Specify a path to the installed B<OpenPKG> C<rpm> executable. Several
other internal paths are deduced from the I<rpm> path, so this should be
something like I<%{l_prefix}>C</bin/rpm>.
=item B<-r> I<repository>
Specify a path to an RPM repository, this can be a URL or a directory
path. The name of the package file is appended to this path.
The default is to use a URL pointing to the B<OpenPKG> FTP server.
=item B<-f> I<index.rdf>
Specify a path to the primary XML/RDF index, this can be a URL or a
file path. If the index contains references to aother indexes these are
included automatically. The default is to use a URL pointing to the
B<OpenPKG> FTP server for the B<OpenPKG> release you are using.
=item B<-u>
The generated script will ignore binary RPMs that are stored on
your system. Instead it will either fetch binary RPMs or rebuild
from source RPMs fetched from the repository.
=item B<-U>
The generated script will try to upgrade all selected packages
including their dependencies to the most recent version.
=item B<-z>
The generated script will rebuild all selected packages
including their dependencies even when the most recent version
is already installed.
=item B<-Z>
B<openpkg build> ignores a installed packages, the
script will rebuild all selected packages from scratch.
Note that this doesn't work together with the B<-a> option.
=item B<-i>
The generated script will ignore errors. However, if a build
phase fails the install phase is still skipped.
=item B<-q>
Ignore all reverse dependencies.
I<ATTENTION: this might break already installed packages!>
=item B<-P> I<priv-cmd>
Command prefix to use for install commands that require elevated
privileges. The most common tool for this is sudo(1).
=item B<-N> I<non-priv-cmd>
Command prefix to use for install commands that do not require elevated
privileges. The most common tool for this is sudo(1).
=item B<-p> I<platform>
The platform string that is matched against the index for binary
packages. Default is to use the I<%{_target_platform}> variable.
=item B<-D>I<var>=I<val>
Specify configuration options for all selected packages. This can be
either B<-D>C<with_>I<xxx>C<=>I<yyy> or just B<-D>C<with_>I<xxx>, the
latter is equivalent to a B<-D>C<with_>I<xxx>C<=>C<yes>. The parameters
are matched against selected packages that are already installed. If
they do indicate a change the package is rebuild. There can be multiple
B<-D> options.
=item B<-E> I<name>
Ignore a package with the specified I<name>. This can be used to avoid
upgrading to a broken package in the repository. There can be multiple
B<-E> options.
=item B<-a>
Select all installed packages. Do not specify a pattern list together
with the B<-a> option.
=item B<-A>
Select all packages in the repository. Do not specify a pattern list together
with the B<-a> option.
=back
=head1 CONFIGURATION
B<openpkg build> reads the configuration file I<$HOME/.openpkg/build>.
The file lists default options, one option per line and section tags
of the form C<[>I<prefix>C<]>. Options following such a tag are only
evaluated if the selected RPM path matches the prefix so that you can
define default options for multiple B<OpenPKG> hierarchies.
=head1 CAVEATS
Parallel execution of B<openpkg build> causes undefined effects.
=head1 SEE ALSO
rpm(1), sudo(1)
=head1 HISTORY
The B<openpkg index> and B<openpkg build> command
was invented in November 2002 by I<Michael van Elst>
E<lt>[EMAIL PROTECTED]<gt> under contract with I<Cable & Wireless
Germany> E<lt>http://www.cw.com/deE<gt> for use inside the B<OpenPKG>
project E<lt>http://www.openpkg.org/E<gt>.
=head1 AUTHORS
Michael van Elst
[EMAIL PROTECTED]
=cut
Index: openpkg-src/openpkg-tool/openpkg.sh
============================================================
$ cvs update -p -r1.1 openpkg.sh
#!@l_prefix@/lib/openpkg/bash
##
## openpkg.sh -- OpenPKG maintainance utility (frontend)
##
## Copyright (c) 2000-2002 Cable & Wireless Deutschland GmbH
## Copyright (c) 2000-2002 The OpenPKG Project <http://www.openpkg.org/>
## Copyright (c) 2000-2002 Ralf S. Engelschall <[EMAIL PROTECTED]>
##
## Permission to use, copy, modify, and distribute this software for
## any purpose with or without fee is hereby granted, provided that
## the above copyright notice and this permission notice appear in all
## copies.
##
## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
# program information
progname="openpkg"
progvers="@version@"
l_prefix="@l_prefix@"
# try to determine Perl interpreter
perl=""
for dir in $l_prefix/bin `echo $PATH | sed -e 's;:; ;g'` /bin /usr/bin
/usr/local/bin; do
if [ -f "$dir/perl" ]; then
perl="$dir/perl"
break
fi
done
# command line option parsing
if [ $# -eq 0 ]; then
echo "$progname:USAGE: $progname index|build [options]"
exit 0
fi
while [ ".$1" != . ]; do
case "$1" in
-h )
echo "$progname:USAGE: $progname index|build [options]"
exit 0
;;
-v )
echo "$progname $progvers (OpenPKG instance: $l_prefix)"
exit 0
;;
-* )
echo "$progname:ERROR: invalid option \"$1\"" 1>&2
exit 1
;;
* )
break
;;
esac
done
# command dispatching
case "$1" in
index )
if [ ".$perl" = . ]; then
echo "$progname:ERROR: \"index\" command requires a Perl interpreter"
1>&2
exit 1
fi
shift
exec $perl ${l_prefix}/lib/openpkg/openpkg-index.pl ${1+"$@"}
;;
build )
if [ ".$perl" = . ]; then
echo "$progname:ERROR: \"build\" command requires a Perl interpreter"
1>&2
exit 1
fi
shift
exec $perl ${l_prefix}/lib/openpkg/openpkg-build.pl ${1+"$@"}
;;
* )
echo "$progname:ERROR: invalid command \"$1\"" 1>&2
exit 1
;;
esac
Index: openpkg-web/news.txt
============================================================
$ cvs diff -u -r1.2117 -r1.2118 news.txt
--- openpkg-web/news.txt 26 Nov 2002 18:34:49 -0000 1.2117
+++ openpkg-web/news.txt 26 Nov 2002 19:54:11 -0000 1.2118
@@ -1,3 +1,4 @@
+26-Nov-2002: New package: P<openpkg-tool-20021126-20021126>
26-Nov-2002: Upgraded package: P<w3m-0.3.2.1-20021126>
26-Nov-2002: Upgraded package: P<samba-2.2.7-20021126>
26-Nov-2002: Upgraded package: P<gd-2.0.8-20021126>
______________________________________________________________________
The OpenPKG Project www.openpkg.org
CVS Repository Commit List [EMAIL PROTECTED]