OpenPKG CVS Repository
  http://cvs.openpkg.org/
  ____________________________________________________________________________

  Server: cvs.openpkg.org                  Name:   Michael van Elst
  Root:   /e/openpkg/cvs                   Email:  [EMAIL PROTECTED]
  Module: openpkg-src openpkg-web          Date:   09-Jan-2003 15:23:18
  Branch: HEAD                             Handle: 2003010914231601

  Modified files:
    openpkg-src/openpkg-tool
                            openpkg-build.pl openpkg-index.pl
                            openpkg-tool.spec openpkg.pod
    openpkg-web             news.txt

  Log:
    changed index format, compatibility code, code cleanup, comments,
    clean revdep sort, optionally ignore XML parser

  Summary:
    Revision    Changes     Path
    1.27        +584 -355   openpkg-src/openpkg-tool/openpkg-build.pl
    1.9         +54 -5      openpkg-src/openpkg-tool/openpkg-index.pl
    1.20        +2  -2      openpkg-src/openpkg-tool/openpkg-tool.spec
    1.8         +6  -0      openpkg-src/openpkg-tool/openpkg.pod
    1.2624      +1  -0      openpkg-web/news.txt
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: openpkg-src/openpkg-tool/openpkg-build.pl
  ============================================================================
  $ cvs diff -u -r1.26 -r1.27 openpkg-build.pl
  --- openpkg-src/openpkg-tool/openpkg-build.pl 8 Jan 2003 15:12:38 -0000       1.26
  +++ openpkg-src/openpkg-tool/openpkg-build.pl 9 Jan 2003 14:23:17 -0000       1.27
  @@ -29,8 +29,8 @@
   $|=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 $opt_s $opt_S/;
  -getopts('R:r:f:uUaAzZP:N:E:iD:p:qsS');
  +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 $opt_s $opt_S $opt_X/;
  +getopts('R:r:f:uUaAzZP:N:E:iD:p:qsSX');
   
   ##########################################################################
   
  @@ -106,6 +106,9 @@
   
   ##########################################################################
   
  +#
  +# evaluate a condition attribute from an option set
  +#
   sub conditional ($$) {
       my($cond,$with) = @_;
       my(@s,$res);
  @@ -138,40 +141,6 @@
       return $res;
   }
   
  -sub with_list ($$) {
  -    my($bags,$with) = @_;
  -    my($bag,$li);
  -    my(@out);
  -
  -    foreach $bag (@$bags) {
  -        next unless conditional($bag->{'cond'}, $with);
  -        foreach $li (@{$bag->{'rdf:bag'}}) {
  -            push @out, @{$li->{'rdf:li'}};
  -        }
  -    }
  -
  -    return \@out;
  -}
  -
  -sub make_hash ($$$) {
  -    my($bags,$tag,$with) = @_;
  -    my($bag,$li);
  -    my(%out,$el);
  -
  -    foreach $bag (@$bags) {
  -        next unless conditional($bag->{'cond'}, $with);
  -        foreach $li (@{$bag->{'rdf:bag'}}) {
  -            foreach (@{$li->{'rdf:li'}}) {
  -                next unless exists $_->{$tag};
  -                $el = $_->{$tag}->[0];
  -                $out{$el->{'ID'}} = $el->{'content'};
  -            }
  -        }
  -    }
  -
  -    return \%out;
  -}
  -
   ##########################################################################
   
   my($RPM,$RPM_PRIV,$RPM_NPRIV,$CURL,$PROG);
  @@ -326,15 +295,111 @@
       }
   
       return {
  -        name    => $nam,
  -        version => $ver,
  -        release => $rel,
  -        proxy   => $pxy,
  -        prefix  => $pre,
  -        with    => $with
  +        name    => $nam,     # the full name of the resource
  +        version => $ver,     # the version (or value)
  +        release => $rel,     # and release number
  +        proxy   => $pxy,     # wether the resource is a PROXY resource
  +        prefix  => $pre,     # the packagename (if resource is an option)
  +        with    => $with     # the buildoption (if resource is an option)
  +    };
  +}
  +
  +sub parse_depends ($) {
  +    my($dep) = @_;
  +    my($name, $op, $val);
  +
  +    if (ref $dep) {
  +        #
  +        # dependency from new index stored as a node
  +        #
  +        # content of the node is the name
  +        # certain attributes denote the comparison operator
  +        # the value of such an attribute is the comparison operand
  +        #
  +        # the operator (and operand) are optional and there can
  +        # only be one
  +        #
  +        $name    = $dep->{content};
  +        $op = undef;
  +        $op = 'equ' if exists $dep->{equ};
  +        $op = 'geq' if exists $dep->{geq};
  +        $op = 'leq' if exists $dep->{leq};
  +        $op = 'gt'  if exists $dep->{gt};
  +        $op = 'lt'  if exists $dep->{lt};
  +        if (defined $op) {
  +            $val = $dep->{$op};
  +        }
  +    } elsif ($dep =~ /\S/) {
  +        #
  +        # dependency from old index stored as text string
  +        #
  +        # "name operator operand"
  +        # or
  +        # "name"
  +        #
  +        ($name,$op,$val) = $dep =~ /(\S+)\s*(?:(\S+)\s*(\S+))?\s*$/;
  +        if (defined $op) {
  +            $op = {
  +                '=='  => 'equ', '='   => 'equ',
  +                '>='  => 'geq', '=>'  => 'geq',
  +                '<='  => 'leq', '=<'  => 'leq',
  +                '>'   => 'gt',  '<'   => 'lt'
  +            }->{$op};
  +            unless (defined $op) {
  +                print "# don't know how to handle dependency: $dep\n";
  +                return;
  +            }
  +        }
  +    }
  +
  +    return {
  +        name => $name,
  +        op   => $op,
  +        val  => $val
       };
   }
   
  +sub depends2provides ($) {
  +    my($dep) = @_;
  +    my($ver,$rel,$pxy);
  +
  +    ($ver,$rel,$pxy) = $dep->{val} =~ /^([^\s\-]+)-([^\s\+]+)(\+PROXY)?$/;
  +
  +    return {
  +        name    => $dep->{name},
  +        version => (defined $ver ? $ver : $dep->{val}),
  +        release => $rel,
  +        proxy   => $pxy
  +    }
  +}
  +
  +#
  +# convert parser output to dependency records
  +#
  +sub depend_list ($) {
  +    my($deps) = @_;
  +    foreach (@$deps) {
  +        $_ = parse_depends($_);
  +    }
  +    return $deps;
  +}
  +
  +#
  +# compute list of package names from dependency list
  +#
  +sub depends2pkglist ($) {
  +    my($deps) = @_;
  +    return map { $_->{name} } @$deps;
  +}
  +
  +#
  +# retrieve the local installed base
  +#
  +# for packages that provide option resources (packagename::buildoption)
  +# the options are parsed into the OPTIONS hash
  +#
  +# other packages will query options on demand
  +#
   sub get_installed () {
       my(%map);
       my(@l) = `$RPM_NPRIV --provides -qa`;
  @@ -371,23 +436,16 @@
       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;
  -}
  -
  +#
  +# compute reverse dependency map
  +#
  +#
   sub get_revdep ($) {
       my($env) = @_;
       my($i) = $env->{'installed'};
       my($r) = $env->{'repository'};
  -    my($pkg, %rev);
  -    my(@vers,$t,@names);
  +    my($pkg, %dep, %dlist, %rev);
  +    my(@vers,$t);
   
       print "# computing reverse dependencies\n";
   
  @@ -398,26 +456,39 @@
               next;
           }
   
  +        #
  +        # get list of package versions from repository
  +        #
           @vers = get_versions($r->{$pkg}, sub { 1; });
  +
  +        #
  +        # get forward dependencies from repository packages
  +        #
  +        # dep{a}{b} is true if b depends directly on a
  +        # dlist{a}  is list of packages that depend on a
  +        #
           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 (depends2pkglist($t->{depends})) {
  +                    $dep{$_}{$t->{name}} = 1;
  +                    push @{$dlist{$_}}, $t;
  +                }
               }
           }
       }
   
  -    foreach $pkg (keys %rev) {
  +    #
  +    # sort reverse dependencies
  +    #
  +    foreach $pkg (keys %dep) {
           $rev{$pkg} = [
               sort {
  -                revdep(\%rev, $b, $a->{name});
  -            } @{$rev{$pkg}}
  +                $dep{$a->{name}}{$b->{name}} ||
  +                -$dep{$b->{name}}{$a->{name}} ||
  +                $a->{name} cmp $b->{name}
  +            } @{$dlist{$pkg}}
           ];
       }
   
  @@ -450,6 +521,9 @@
       }
   }
   
  +#
  +# pull in OPTIONS for a package or an RPM file
  +#
   sub get_with ($;$) {
       my($t,$fn) = @_;
       my(@l,%with);
  @@ -465,11 +539,33 @@
       return $t->{OPTIONS};
   }
   
  +#
  +# compute absolute paths
  +#
  +# (url, fn) point to a base document
  +# the location is the file path fn if fn is
  +# defined, otherwise it is url.
  +#
  +# augment the pointer with suburl
  +#
  +# suburl can be an absolute url
  +# then the new pointer is (suburl, undef)
  +#
  +# suburl can be a absolute file path
  +# then the new pointer is (suburl, suburl)
  +#
  +# suburl can be a relative path
  +# then it augments url or fn accordingly
  +#
   sub relurl ($$$) {
       my($url,$fn,$suburl) = @_;
  -    my($subfn,$submap);
  +    my($subfn);
   
  -    unless ($suburl =~ /^\w+:\/\// || $suburl =~ /^\//) {
  +    if ($suburl =~ /^\w+:\/\//) {
  +        # NOP
  +    } elsif ($suburl =~ /^\//) {
  +        $subfn = $suburl;
  +    } else {
           if (defined $fn) {
               $subfn = $fn;
               $subfn =~ s/\/[^\/]*$//;
  @@ -488,19 +584,291 @@
       return ($suburl, $subfn);
   }
   
  +#
  +# return node value from XML parser
  +#
   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);
  +
  +#
  +# grep XML Bag against condition
  +# return as flat list
  +#
  +sub with_list ($$) {
  +    my($bags,$with) = @_;
  +    my($bag,$li,$el);
  +    my(@out);
  +
  +    foreach $bag (@$bags) {
  +        next unless conditional($bag->{'cond'}, $with);
  +        foreach $li (@{$bag->{'rdf:bag'}}) {
  +            $el = $li->{'resource'} || $li->{'rdf:li'};
  +            push @out, @$el;
  +        }
  +    }
  +
  +    return \@out;
  +}
  +
  +sub simple_text_parser ($$$$) {
  +    my($fh,$url,$with,$map) = @_;
  +    my(@include);
  +
  +    my($section);
  +    my($name,$version);
  +    my($href,$release,$desc);
  +    my(@prereq,@bprereq);
  +    my(@provides,@conflicts,@source,@nosource);
  +    my(%options);
  +    my($platform,$prefix);
  +    my($rec);
  +    my($tag,$cond,$attrname,$attrval,$body);
  +    my($useit);
  +
  +    print "# using simple text parser\n";
  +
  +    while (<$fh>) {
  +
  +        s/&gt;/>/g;
  +        s/&lt;/</g;
  +
  +        if (!(defined $href) && /<rdf:Description.*?href="([^"]*)"/) {
  +            $href      = $1;
  +            $section   = undef;
  +            $name      = undef;
  +            $release   = undef;
  +            $desc      = '';
  +            $platform  = undef;
  +            $prefix    = undef;
  +            @prereq    = ();
  +            @bprereq   = ();
  +            @provides  = ();
  +            @conflicts = ();
  +            @source    = ();
  +            @nosource  = ();
  +        }
  +
  +        if (!(defined $href) && /<Repository.*?href="([^"]*)"/) {
  +            push(@include, $1);
  +            next;
  +        }
  +
  +        next unless defined $href;
  +
  +        ($tag,$cond,$attrname,$attrval,$body) = /
  +            <
  +            (\/?[\w:]+)
  +            \s*
  +            (?:cond="([^"]+)")?
  +            (?:(\w+)="([^"]+)")?
  +            >
  +            (.*?)
  +            (?:<\/\1>)?
  +            $
  +            /mx;
  +
  +        $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 'NoSource') {
  +            $section = 'nosource' if $useit;
  +        } elsif ($tag eq '/NoSource') {
  +            $section = undef;
  +        } elsif ($tag eq 'Source') {
  +            $section = 'source' if $useit;
  +        } elsif ($tag eq '/Source') {
  +            $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' || $tag eq 'resource') {
  +            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 ($section eq 'source') {
  +                push(@source, $body);
  +            } elsif ($section eq 'nosource') {
  +                push(@nosource, $body);
  +            }
  +        } elsif ($tag eq '/rdf:Description') {
  +
  +            if (defined $href &&
  +                defined $name &&
  +                defined $version &&
  +                defined $release) {
  +
  +                @provides = map {
  +                    depends2provides(parse_depends($_))
  +                } @provides;
  +
  +                %options = map {
  +                    ( $_->{with} => $_->{version} )
  +                } grep {
  +                    defined $_->{with}
  +                } @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   => depend_list([ @bprereq ]),
  +                    keeps     => depend_list([ @prereq ]),
  +                    conflicts => [ @conflicts ],
  +                    source    => [ @source ],
  +                    nosource  => [ @nosource ],
  +                    desc      => $desc,
  +                    platform  => $platform,
  +                    prefix    => $prefix
  +                };
  +
  +                $rec->{OPTIONS} =
  +                    %options
  +                    ? { %options }
  +                    : parse_options($rec->{desc});
  +
  +                foreach (@provides) {
  +                    push(@{$map->{$_->{name}}->{vs($_)}}, $rec);
  +                }
  +            }
  +
  +            $href = undef;
  +        }
  +    }
  +
  +    return \@include;
  +}
  +
  +sub xml_parser ($$$$) {
  +    my($fh, $url, $with, $map) = @_;
  +    my(@include);
  +
  +    my($xml,$desc,$sub);
  +    my($provides,@provides,%options,$rec);
  +    my($href,$name,$version,$release);
  +
  +    print "# using XML parser\n";
  +
  +    $xml  = XML::Simple::XMLin($fh, forcearray => 1);
  +    $desc = $xml->{'Repository'}->[0]->{'rdf:Description'};
  +    $sub  = $xml->{'Repository'}->[0]->{'Repository'};
  +
  +    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];
  +        if ($provides->{'rdf:li'}) {
  +            $provides = $provides->{'rdf:li'};
  +        } else {
  +            $provides = $provides->{'resource'};
  +        }
  +        @provides = map {
  +            depends2provides(parse_depends($_))
  +        } @$provides;
  +
  +        %options = map {
  +            ( $_->{with} => $_->{version} )
  +        } grep {
  +            defined $_->{with}
  +        } @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   => depend_list(with_list($_->{'BuildPreReq'}, $with)),
  +            keeps     => depend_list(with_list($_->{'PreReq'}, $with)),
  +            conflicts => with_list($_->{'Conflicts'}, $with),
  +            source    => with_list($_->{'Source'}, $with),
  +            nosource  => with_list($_->{'NoSource'}, $with),
  +            desc      => xel($_->{'Description'})
  +        };
  +
  +        $rec->{OPTIONS} =
  +            %options
  +            ? { %options }
  +            : parse_options($rec->{desc});
  +
  +        foreach (@provides) {
  +            push(@{$map->{$_->{name}}->{vs($_)}}, $rec);
  +        }
  +    }
  +
  +    if ($sub) {
  +        @include = map { $_->{href} } @$sub;
  +    }
  +
  +    return \@include;
  +}
  +
  +sub open_index ($$) {
  +    my($url, $fn) = @_;
  +    my($fetch,$bzip2,$path);
   
       $fetch = defined $fn ? $fn : $url;
   
  @@ -530,239 +898,29 @@
   
       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,@source,@nosource);
  -        my(%options);
  -        my($platform,$prefix);
  -        my($rec);
  -        my($tag,$cond,$body);
  -        my($useit);
  -
  -        while (<RFH>) {
  -
  -            s/&gt;/>/g;
  -            s/&lt;/</g;
  -
  -            if (!(defined $href) && /<rdf:Description.*?href="([^"]*)"/) {
  -                $href      = $1;
  -                $section   = undef;
  -                $name      = undef;
  -                $release   = undef;
  -                $desc      = '';
  -                $platform  = undef;
  -                $prefix    = undef;
  -                @prereq    = ();
  -                @bprereq   = ();
  -                @provides  = ();
  -                @conflicts = ();
  -                @source    = ();
  -                @nosource  = ();
  -            }
  -
  -            if (!(defined $href) && /<Repository.*?href="([^"]*)"/) {
  -                push(@include, $1);
  -                next;
  -            }
  -
  -            next unless defined $href;
  -
  -            ($tag,$cond,$body) = /
  -                <
  -                (\/?[\w:]+)
  -                \s*
  -                (?:cond="([^"]+)")?
  -                >
  -                (.*?)
  -                (?:<\/\1>)?
  -                $
  -                /mx;
  -
  -            $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 'NoSource') {
  -                $section = 'nosource' if $useit;
  -            } elsif ($tag eq '/NoSource') {
  -                $section = undef;
  -            } elsif ($tag eq 'Source') {
  -                $section = 'nosource' if $useit;
  -            } elsif ($tag eq '/Source') {
  -                $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 ($section eq 'source') {
  -                    push(@source, $body);
  -                } elsif ($section eq 'nosource') {
  -                    push(@nosource, $body);
  -                }
  -            } elsif ($tag eq '/rdf:Description') {
  -
  -                if (defined $href &&
  -                    defined $name &&
  -                    defined $version &&
  -                    defined $release) {
  -
  -                    @provides = map { parse_provides($_) } @provides;
  -
  -                    %options = map {
  -                        ( $_->{with} => $_->{version} )
  -                    } grep {
  -                        defined $_->{with}
  -                    } @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 ],
  -                        nosource  => [ @source ],
  -                        nosource  => [ @nosource ],
  -                        desc      => $desc,
  -                        platform  => $platform,
  -                        prefix    => $prefix
  -                    };
  -
  -                    $rec->{OPTIONS} =
  -                        %options
  -                        ? { %options }
  -                        : parse_options($rec->{desc});
  -
  -                    foreach (@provides) {
  -                        push(@{$map{$_->{name}}->{vs($_)}}, $rec);
  -                    }
  -                }
  +#
  +# fetch index from file or URL
  +# recursively fetch sub-indexes
  +#
  +sub get_index ($$$$) {
  +    my($url,$fn,$with,$noxml) = @_;
  +    my(%map,$include);
  +
  +    open_index($url,$fn);
  +
  +    unless ($noxml) {
  +        eval {
  +            require XML::Simple;
  +        };
  +        $noxml = 1 if $@;
  +    }
   
  -                $href = undef;
  -            }
  -        }
  +    if ($noxml) {
  +        $include = simple_text_parser(\*RFH, $url, $with, \%map);
       } 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,%options,$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 { parse_provides($_) } @$provides;
  -
  -            %options = map {
  -                ( $_->{with} => $_->{version} )
  -            } grep {
  -                defined $_->{with}
  -            } @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   => with_list($_->{'BuildPreReq'}, $with),
  -                keeps     => with_list($_->{'PreReq'}, $with),
  -                conflicts => with_list($_->{'Conflicts'}, $with),
  -                source    => with_list($_->{'Source'}, $with),
  -                nosource  => with_list($_->{'NoSource'}, $with),
  -                desc      => xel($_->{'Description'})
  -            };
  -
  -            $rec->{OPTIONS} =
  -                %options
  -                ? { %options }
  -                : parse_options($rec->{desc});
  -
  -            foreach (@provides) {
  -                push(@{$map{$_->{name}}->{vs($_)}}, $rec);
  -            }
  -        }
  -
  -        if ($sub) {
  -            @include = map { $_->{href} } @$sub;
  -        }
  +        $include = xml_parser(\*RFH, $url, $with, \%map);
       }
   
       close(RFH)
  @@ -772,10 +930,10 @@
       # 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) {
  +    foreach (@$include) {
           my($submap);
           my($suburl,$subfn) = relurl($url,$fn,$_);
  -        $submap = get_index($suburl,$subfn,$with);
  +        $submap = get_index($suburl,$subfn,$with,$noxml);
           while (my($name,$vmap) = each %$submap) {
               while (my($vs,$recs) = each %$vmap) {
                   push @{$map{$name}->{$vs}}, @$recs;
  @@ -786,6 +944,8 @@
       return \%map;
   }
   
  +############################################################################
  +
   #
   # grep all versions of a name that
   # satisfy a condition
  @@ -807,10 +967,10 @@
   
       @recs = grep {
                   $env->{sourceonly} ? (
  -                    !(defined $_->{'platform'})
  +                    !(defined $_->{'prefix'})
                   ) : (
  -                    !(defined $_->{'platform'}) || (
  -                       defined $_->{'prefix'} &&
  +                    !(defined $_->{'prefix'}) || (
  +                       defined $_->{'platform'} &&
                          $_->{'platform'} eq $env->{config}->{platform} &&
                          $_->{'prefix'} eq $env->{config}->{prefix}
                       )
  @@ -933,6 +1093,20 @@
   }
   
   #
  +# strip doubles from depend/keep lists
  +# and a return a map name => depend/keep
  +#
  +sub unique_map {
  +    my(%out);
  +    foreach (@_) {
  +        foreach (@$_) {
  +            $out{$_->{name}} = $_;
  +        }
  +    }
  +    return %out;
  +}
  +
  +#
   # test wether target could be upgraded
   #
   sub target_newer ($$) {
  @@ -992,17 +1166,22 @@
       }
   }
   
  +############################################################################
  +
  +#
  +# LOGIC
  +#
  +
   #
   # locate target for a dependency
   #
   sub dep2target ($$) {
       my($dep, $env) = @_;
  -    my($name,@vers);
  +    my($name,$op,@vers);
       my($i,$r,$b,$cond,$version);
       my($t,$tdef);
   
  -    $dep =~ s/(\S+)\s*//;
  -    $name = $1;
  +    ($name, $op, $version) = ($dep->{name}, $dep->{op}, $dep->{val});
   
       $i = $env->{installed}->{$name};
       $r = $env->{repository}->{$name};
  @@ -1010,26 +1189,20 @@
   
       return unless $i || $r || $b;
   
  -    if ($dep =~ /^(?:>=|=>)\s*(\S+)$/) {
  -        $version = $1;
  +    if (!defined $op) {
  +        $cond = sub { 1; };
  +    } elsif ($op eq 'geq') {
           $cond = sub { vcmp($_[0],$version) >= 0; };
  -    } elsif ($dep =~ /^(?:<=|=<)\s*(\S+)$/) {
  -        $version = $1;
  +    } elsif ($op eq 'leq') {
           $cond = sub { vcmp($_[0],$version) <= 0; };
  -    } elsif ($dep =~ /^>\s*(\S+)$/) {
  -        $version = $1;
  +    } elsif ($op eq 'gt') {
           $cond = sub { vcmp($_[0],$version) > 0; };
  -    } elsif ($dep =~ /^<\s*(\S+)$/) {
  -        $version = $1;
  +    } elsif ($op eq 'lt') {
           $cond = sub { vcmp($_[0],$version) < 0; };
  -    } elsif ($dep =~ /^==?\s*(\S+)$/) {
  -        $version = $1;
  +    } elsif ($op eq 'equ') {
           $cond = sub { vcmp($_[0],$version) == 0; };
  -    } elsif ($dep =~ /^\s*$/) {
  -        $cond = sub { 1; };
       } else {
  -        print "# don't know how to handle PreReq: $name $dep\n";
  -        return;
  +        die "FATAL: internal error in dep2target\n";
       }
   
       $tdef = undef;
  @@ -1037,9 +1210,10 @@
       if ($i && (@vers = get_versions($i, $cond))) {
           foreach (@vers) {
               $t = $i->{$_}->[0];
  -            if (get_with($t), target_suitable($t, $env->{with})) {
  +            get_with($t);
  +            if (target_suitable($t, $env->{with})) {
                   $tdef = $t;
  -                if (!$env->{upgrade}) {
  +                unless ($env->{upgrade}) {
                       return ($t, 1);
                   }
               }
  @@ -1051,7 +1225,10 @@
   
       $t = chose_source($env, $name, $r, get_versions($r, $cond));
       if ($t) {
  -        return ($t, 0);
  +        if (!$tdef ||
  +            ($env->{upgrade} && target_newer($t, $env->{installed}))) {
  +            return ($t, 0);
  +        }
       }
   
       if ($tdef) {
  @@ -1061,7 +1238,9 @@
       return;
   }
   
  -
  +#
  +#
  +#
   sub make_dep ($$$$$$) {
       my($target,$depth,$env,$list,$blist,$clist) = @_;
       my($d,$k,%d,%k,$t,$old);
  @@ -1094,6 +1273,7 @@
               print "# excluding $target->{name} (no upgrade allowed)\n";
               return;
           }
  +        # pull in options
           get_with($t);
           if ($target->{REBUILD}) {
               target_setstatus($target,'DEPEND',1);
  @@ -1112,7 +1292,7 @@
               return;
           }
           # use options from installed base
  -        override_options($target->{OPTIONS}, $t->{OPTIONS},
  +        override_options(get_with($target), get_with($t),
                            $env->{config}->{optreg});
           # remember this is a rebuild for a proxy package
           $target->{PROXY} = $t->{PROXY};
  @@ -1137,8 +1317,8 @@
       #
       if (@$d || @$k) {
   
  -        %d = map { $_ => 1 } @$d, @$k;
  -        %k = map { $_ => 1 } @$k;
  +        %d = unique_map($d, $k);
  +        %k = unique_map($k);
   
           @deps     = ();
           $conflict = 0;
  @@ -1147,7 +1327,7 @@
               # old index misses a OpenPKG provider in the index... skip it
               next if $_ eq 'OpenPKG';
   
  -            ($t,$old) = dep2target($_, $env);
  +            ($t,$old) = dep2target($d{$_}, $env);
               if ($t) {
                   if ($old) {
                       print "# $target->{name} uses ".vsn($t)." for $_\n";
  @@ -1182,9 +1362,13 @@
       push(@$list, $target);
   
       foreach (@{$target->{nosource}}) {
  -        print "# ATTENTION: unpackaged source '$target->{source}->[$_]'\n";
  +        print "# ATTENTION: unpackaged source $_: $target->{source}->[$_]\n";
       }
   
  +    #
  +    # a dependency could not be resolved, don't bother with reverse
  +    # dependencies for this target
  +    #
       return if $conflict;
   
       if (!$env->{quick} &&
  @@ -1209,23 +1393,20 @@
       }
   }
   
  -sub remove_list ($$$) {
  -    my($targets, $keeps, $installed) = @_;
  -    my(%keep);
  -
  -    %keep = map { $_ => 1 } @$keeps;
  -    return [ grep {
  -               !$keep{$_} && !$installed->{$_->{name}}->{vs($_)};
  -             } @$targets
  -           ];
  -}
  -
  +#
  +# generate build lists for targets matched by pattern
  +#
  +# all input and output is passed in 'env' hash
  +#
   sub build_list ($$) {
       my($pattern, $env) = @_;
  -    my(@goals,@targets,@keeps,@conflicts,$bonly,$t);
  +    my(@goals,@targets,@keeps,@conflicts,@bonly,$t);
       my($name,$r,$i,@vers);
  -    my(@todo);
  +    my(@todo,%keep);
   
  +    #
  +    # handle various patterns
  +    #
       if (defined $pattern) {
           @todo = ();
           foreach (split(/\s+/,$pattern)) {
  @@ -1241,6 +1422,10 @@
               grep(/$p/, keys %{$env->{repository}})
           } @todo;
       } else {
  +        #
  +        # undefined pattern means -a option that selects
  +        # all packages from repository that are installed
  +        #
           @todo = grep {
                       my($n) = $_;
                       (ref $env->{installed}->{$n}) &&
  @@ -1296,13 +1481,23 @@
           make_dep($t,0,$env,\@targets,\@keeps,\@conflicts);
       }
   
  -    $bonly = remove_list(\@targets, \@keeps, $env->{installed});
  +    %keep = map { $_ => 1 } @keeps;
  +    @bonly = grep {
  +               !$keep{$_} && !$env->{installed}->{$_->{name}}->{vs($_)};
  +             } @targets;
   
  -    return (\@targets, $bonly, \@conflicts);
  +    return (\@targets, \@bonly, \@conflicts);
   }
   
   #######################################################################
   
  +#
  +# OUTPUT
  +#
  +
  +#
  +# compute path to binary RPM from rpm config and target data
  +#
   sub target2rpm ($$) {
       my($target,$c) = @_;
       my($tmpl) = $c->{template};
  @@ -1315,17 +1510,23 @@
       return $c->{rpmdir}.'/'.$tmpl;
   }
   
  -#######################################################################
  -
  +#
  +# compute new target based on old target augmented with options from
  +# a binary RPM file
  +#
   sub binary_target ($$) {
       my($t, $fn) = @_;
       my(%target) = %$t;
   
  +    # pull in options from binary RPM file
       get_with(\%target, $fn);
   
       return \%target;
   }
   
  +#
  +# return path to master package for a proxy package
  +#
   sub find_proxy ($$) {
       my($t,$bpkg) = @_;
       my(@l) = `$RPM_NPRIV -ql $t->{name}`;
  @@ -1339,6 +1540,14 @@
       return (glob("$prefix/RPM/PKG/$bpkg"))[0];
   }
   
  +#
  +# merge parameters from installed package
  +# with new parameter set and global parameters
  +# from configuration
  +#
  +# then map the result to --define command line arguments
  +# suitable for rpm
  +#
   sub make_defines ($$$) {
       my($old, $new, $c) = @_;
       my($with);
  @@ -1363,13 +1572,21 @@
       # skip parameter templates from index
       #
       $with = join(' ',map { "--define '$_ $old->{$_}'" }
  -                     grep { $old->{$_} !~ /^%/ } keys %$old);
  +                     sort grep { $old->{$_} !~ /^%/ } keys %$old);
   
       $with = ' '.$with if $with ne '';
   
       return $with;
   }
   
  +#
  +# print commands from package build list
  +#
  +# c      -> configuration to derive paths from
  +# uncond -> always do the --rebuild
  +# with   -> parameter set passed to build tool
  +# ignore -> generate script that does not stop on error
  +#
   sub print_list1 ($$$@$) {
       my($list,$c,$uncond,$with,$ignore) = @_;
       my($spkg,$bpkg,$ppkg);
  @@ -1440,6 +1657,12 @@
       }
   }
   
  +#
  +# print commands for the temporary package list
  +#
  +# temporary packages are only used for building other packages
  +# and are removed when everything is done
  +#
   sub print_list2 ($$) {
       my($list,$c) = @_;
       my($pkg);
  @@ -1450,6 +1673,11 @@
       }
   }
   
  +#
  +# instead of printing a command list, print a status map
  +# that shows all packages and how the build process would
  +# change their status
  +#
   sub print_status ($$$$$) {
       my($installed,$repository,$list,$bonly,$clist) = @_;
       my(%bonly) = map { $_ => 1 } @$bonly;
  @@ -1457,6 +1685,7 @@
       my($old,$tag,$new);
   
       foreach (@$list, @$clist) {
  +        next unless defined $_->{release};
           $map{$_->{name}} = {
               rel    => "$_->{version}-$_->{release}",
               status => $_->{STATUS}
  @@ -1472,6 +1701,7 @@
   
       @names = keys %map;
       foreach $n (keys %$installed) {
  +        next if $n =~ /::/;
           next if exists $map{$n};
           next unless grep { $_ ne '-' } keys %{$installed->{$n}};
           $map{$n}->{'status'} = 'OK';
  @@ -1479,6 +1709,7 @@
       }
   
       foreach $n (keys %$repository) {
  +        next if $n =~ /::/;
           next if exists $map{$n};
           next unless grep { $_ ne '-' } keys %{$repository->{$n}};
           $t = find_target($n, $repository);
  @@ -1537,18 +1768,16 @@
       $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);
  +$repository     = get_index($url.'00INDEX.rdf',$opt_f,\%with,$opt_X);
   
   $env = {
       config     => $config,
  @@ .
  patch -p0 <<'@@ .'
  Index: openpkg-src/openpkg-tool/openpkg-index.pl
  ============================================================================
  $ cvs diff -u -r1.8 -r1.9 openpkg-index.pl
  --- openpkg-src/openpkg-tool/openpkg-index.pl 8 Jan 2003 15:12:38 -0000       1.8
  +++ openpkg-src/openpkg-tool/openpkg-index.pl 9 Jan 2003 14:23:17 -0000       1.9
  @@ -68,11 +68,48 @@
       return $s;
   }
   
  +my %attrname = (
  +    '=='  => 'equ',
  +    '='   => 'equ',
  +    '>='  => 'geq',
  +    '=>'  => 'geq',
  +    '<='  => 'leq',
  +    '=<'  => 'leq',
  +    '>'   => 'gt',
  +    '<'   => 'lt'
  +);
  +my($opreg) = join '|',
  +    map {
  +        "\Q$_\E"
  +    } sort {
  +        length($b) <=> length($a) ||
  +        $b cmp $a
  +    } keys %attrname;
  +
  +sub make_resource ($) {
  +    my($s) = @_;
  +
  +    if ($s =~ /(\S+)\s*($opreg)\s*(.*?)\s*$/o) {
  +        return {
  +            resource  => $1,
  +            attrname  => $attrname{$2},
  +            attrval   => $3
  +        } 
  +    }
  +
  +    return {
  +        resource => $s
  +    }
  +}
  +
   sub commasep ($$) {
       my($k,$v) = @_;
   
  -    if ($k =~ /^(PreReq|BuildPreReq|Provides|Conflicts|NoSource)$/) {
  +    if ($k =~ /^(NoSource)$/) {
           return split(/\s*,\s*/, $v);
  +    } elsif ($k =~ /^(PreReq|BuildPreReq|Provides|Conflicts)$/) {
  +        return map { make_resource($_) }
  +               split(/\s*,\s*/, $v);
       }
   
       return $v;
  @@ -289,8 +326,11 @@
               # store option for current condition
               #
               if (exists $attr{'Name'}->{''}) {
  -                push @{$attr{'Provides'}->{$cond}},
  -                    $attr{'Name'}->{''}->[0].'::'.$1.' = '.optesc($2);
  +                push @{$attr{'Provides'}->{$cond}}, {
  +                    resource => $attr{'Name'}->{''}->[0].'::'.$1,
  +                    attrname => 'equ',
  +                    attrval  => optesc($2)
  +                }
               } else {
                   warn "ERROR: no package name set for option $1 = $2\n";
               }
  @@ -455,7 +495,16 @@
                   ($cond ne '' ? "<$tag cond=\"$upn\">\n" : "<$tag>\n").
                   "$i  <rdf:bag>\n".
                   join("",
  -                     map { "$i    <rdf:li>".e($_)."</rdf:li>\n" }
  +                     map {
  +                         ref $_
  +                         ? "$i    <resource".
  +                           ( exists $_->{attrname}
  +                             ? " $_->{attrname}=\"".e($_->{attrval})."\""
  +                             : ""
  +                           ).
  +                           ">".e($_->{resource})."</resource>\n"
  +                         : "$i    <rdf:li>".e($_)."</rdf:li>\n"
  +                     }
                        @{$a->{$k}->{$cond}}).
                   "$i  </rdf:bag>\n".
                   "$i</$tag>\n";
  @@ -819,7 +868,7 @@
           if (/\.spec$/) {
               $spec = readfile($_);
               $a    = spec2data($spec);
  -        } elsif (/([^\/]+\.src\.rpm)$/) {
  +        } elsif (/([^\/]+\.(?:no)?src\.rpm)$/) {
               $h    = relpath($prefix, $_);
               if ($cache) {
                   $mtime = (stat $_)[9];
  @@ .
  patch -p0 <<'@@ .'
  Index: openpkg-src/openpkg-tool/openpkg-tool.spec
  ============================================================================
  $ cvs diff -u -r1.19 -r1.20 openpkg-tool.spec
  --- openpkg-src/openpkg-tool/openpkg-tool.spec        8 Jan 2003 15:12:38 -0000      
 1.19
  +++ openpkg-src/openpkg-tool/openpkg-tool.spec        9 Jan 2003 14:23:17 -0000      
 1.20
  @@ -32,8 +32,8 @@
   Distribution: OpenPKG [EVAL]
   Group:        Bootstrapping
   License:      GPL
  -Version:      20030108
  -Release:      20030108
  +Version:      20030109
  +Release:      20030109
   
   #   list of sources
   Source0:      openpkg.sh
  @@ .
  patch -p0 <<'@@ .'
  Index: openpkg-src/openpkg-tool/openpkg.pod
  ============================================================================
  $ cvs diff -u -r1.7 -r1.8 openpkg.pod
  --- openpkg-src/openpkg-tool/openpkg.pod      30 Dec 2002 22:05:36 -0000      1.7
  +++ openpkg-src/openpkg-tool/openpkg.pod      9 Jan 2003 14:23:17 -0000       1.8
  @@ -59,6 +59,7 @@
   [B<-q>]
   [B<-s>]
   [B<-S>]
  +[B<-X>]
   [B<-P> I<priv-cmd>]
   [B<-N> I<non-priv-cmd>]
   [B<-p> I<platform>]
  @@ -248,6 +249,11 @@
   The package exists in the repository but isn't required yet.
   
   =back
  +
  +=item B<-X>
  +
  +Ignore an installed XML parser module but use the internal
  +simple text parser instead.
   
   =item B<-P> I<priv-cmd>
   
  @@ .
  patch -p0 <<'@@ .'
  Index: openpkg-web/news.txt
  ============================================================================
  $ cvs diff -u -r1.2623 -r1.2624 news.txt
  --- openpkg-web/news.txt      9 Jan 2003 14:02:56 -0000       1.2623
  +++ openpkg-web/news.txt      9 Jan 2003 14:23:16 -0000       1.2624
  @@ -1,3 +1,4 @@
  +09-Jan-2003: Upgraded package: P<openpkg-tool-20030109-20030109>
   09-Jan-2003: Upgraded package: P<make-3.80-20030109>
   09-Jan-2003: Upgraded package: P<openpkg-20030109-20030109>
   09-Jan-2003: Upgraded package: P<perl-gd-20030109-20030109>
  @@ .
______________________________________________________________________
The OpenPKG Project                                    www.openpkg.org
CVS Repository Commit List                     [EMAIL PROTECTED]

Reply via email to