浏览代码

support for parameter-based dependencies, partially drop %options support

Michael van Elst 23 年之前
父节点
当前提交
68aed022f2
共有 2 个文件被更改,包括 111 次插入121 次删除
  1. 89 39
      openpkg-tool/openpkg-build.pl
  2. 22 82
      openpkg-tool/openpkg-index.pl

+ 89 - 39
openpkg-tool/openpkg-build.pl

@@ -231,6 +231,9 @@ sub release_cmp ($$) {
 
 sub vcmp ($$) {
     my($a,$b) = @_;
+
+    return 0 if $a eq $b;
+
     my($av,$ar) = $a =~ /^(.*?)(?:\-([\d\.]+))?$/;
     my($bv,$br) = $b =~ /^(.*?)(?:\-([\d\.]+))?$/;
     my($c);
@@ -302,18 +305,67 @@ sub get_release () {
     return $url;
 }
 
+sub parse_provides ($) {
+    my($s) = @_;
+    my($nam,$val,$pre,$with,$pxy,$ver,$rel);
+
+    ($nam,$val) = $s =~ /^(\S+)\s*(?:=\s*(\S*?))?$/;
+
+    #
+    # build options are encoded as a Requirement
+    # <packagename>::<buildoption> = <value>
+    #
+    # since the value is interpreted as a version number
+    # you can only do equality tests
+    #
+    if (($pre,$with) = $nam =~ /^(\S+?)::(\S*)$/) {
+        $val =~ s/(?:\%([0-9a-fA-F][0-9a-fA-F]))/chr(hex($1))/eg;
+        ($ver,$rel,$pxy) = ($val, '', undef);
+    } else {
+        ($ver,$rel,$pxy) = $val =~ /^([^\s\-]+)-([^\s\+]+)(\+PROXY)?$/;
+    }
+
+    return {
+        name    => $nam,
+        version => $ver,
+        release => $rel,
+        proxy   => $pxy,
+        prefix  => $pre,
+        with    => $with
+    };
+}
+
 sub get_installed () {
     my(%map);
     my(@l) = `$RPM_NPRIV --provides -qa`;
+    my($p);
+    my($nam,$val,%options);
 
     foreach (@l) {
-        /^(\S+)\s*(?:=\s*([^\s\-]+)-([^\s\+]+)(\+PROXY)?)?$/;
-        push(@{$map{$1}->{"$2-$3"}}, {
-            name       => $1,
-            version    => (defined $2 ? $2 : '*'),
-            release    => (defined $3 ? $3 : '*'),
-            PROXY      => $4
-        });
+        $p = parse_provides($_);
+
+        if (defined $p->{with}) {
+            $options{$p->{prefix}}->{$p->{with}} = $p->{version}
+        }
+
+        push @{$map{$p->{name}}->{"$p->{version}-$p->{release}"}}, {
+            name       => $p->{name},
+            version    => (defined $p->{version} ? $p->{version} : '*'),
+            release    => (defined $p->{release} ? $p->{release} : '*'),
+            PROXY      => $p->{proxy}
+        };
+    }
+
+    #
+    # options are provided for a package
+    # apply them to all instances of the package
+    #
+    foreach $nam (keys %options) {
+        foreach $val (keys %{$map{$nam}}) {
+            foreach (@{$map{$nam}->{$val}}) {
+                $_->{OPTIONS} = $options{$nam};
+            }
+        }
     }
 
     return \%map;
@@ -378,10 +430,10 @@ sub get_revdep ($) {
 sub parse_options ($) {
     my($l) = @_;
     $l = join("\n", @$l) if ref $l;
-    return if ($l !~ m/(--define|%option\s+)/s);
+    return if ($l !~ m/(--define|\%option\s+)/s);
     my $with = {};
     $l =~ s/--define\s*'(\S+)\s+(\S+?)'/$with->{$1} = $2, ''/sge; # before openpkg-20021230
-    $l =~ s/%option\s+(\S+)\s+(\S+)/$with->{$1} = $2, ''/sge;     # after  openpkg-20021230
+    $l =~ s/\%option\s+(\S+)\s+(\S+)/$with->{$1} = $2, ''/sge;     # after  openpkg-20021230
     return $with;
 }
 
@@ -514,7 +566,6 @@ sub get_index ($$$) {
                 @bprereq   = ();
                 @provides  = ();
                 @conflicts = ();
-                %options   = ();
             }
 
             if (!(defined $href) && /<Repository.*?href="([^"]*)"/) {
@@ -543,10 +594,6 @@ sub get_index ($$$) {
                 $section = undef;
             } elsif ($section eq 'description') {
                 $desc .= $_;
-            } elsif ($tag eq 'Options') {
-                $section = 'options' if $useit;
-            } elsif ($tag eq '/Options') {
-                $section = undef;
             } elsif ($tag eq 'PreReq') {
                 $section = 'prereq' if $useit;
             } elsif ($tag eq '/PreReq') {
@@ -574,11 +621,7 @@ sub get_index ($$$) {
             } elsif ($tag eq 'Prefixes') {
                 $prefix = $body;
             } elsif ($tag eq 'rdf:li') {
-                if ($section eq 'options') {
-                    if ($body =~ /<.*?ID="([^"]+)".*?>\s*([^<]+?)\s*</) {
-                        $options{$1} = $2;
-                    }
-                } elsif ($section eq 'prereq') {
+                if ($section eq 'prereq') {
                     push(@prereq, $body);
                 } elsif ($section eq 'bprereq') {
                     push(@bprereq, $body);
@@ -594,13 +637,12 @@ sub get_index ($$$) {
                     defined $version &&
                     defined $release) {
 
-                    @provides = map {
-                        /(\S+)\s*(?:=\s*(\S+?)\-(\S+))?$/;
-                        {
-                            name    => $1,
-                            version => $2,
-                            release => $3
-                        }
+                    @provides = map { parse_provides($_) } @provides;
+
+                    %options = map {
+                        ( $_->{with} => $_->{version} )
+                    } grep {
+                        defined $_->{with}
                     } @provides;
 
                     unless (grep($_->{name} eq $name, @provides)) {
@@ -644,7 +686,7 @@ sub get_index ($$$) {
         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($provides,@provides,%options,$rec);
         my($href,$name,$version,$release);
 
         foreach (@$desc) {
@@ -661,14 +703,13 @@ sub get_index ($$$) {
 
             $provides = $_->{'Provides'}->[0]->{'rdf:bag'}->[0]->{'rdf:li'};
 
-            @provides = map {
-                /(\S+)\s*(?:=\s*(\S+?)\-(\S+))?$/;
-                {
-                    name    => $1,
-                    version => $2,
-                    release => $3
-                }
-            } @$provides;
+            @provides = map { parse_provides($_) } @$provides;
+
+            %options = map {
+                ( $_->{with} => $_->{version} )
+            } grep {
+                defined $_->{with}
+            } @provides;
 
             unless (grep($_->{name} eq $name, @provides)) {
                 push(@provides, {
@@ -692,8 +733,8 @@ sub get_index ($$$) {
             };
 
             $rec->{OPTIONS} =
-                exists $_->{'Options'}
-                ? make_hash($_->{'Options'}, 'Option', $with)
+                %options
+                ? { %options }
                 : parse_options($rec->{desc});
 
             foreach (@provides) {
@@ -951,10 +992,19 @@ sub dep2target ($$) {
 
     return unless $i || $r || $b;
 
-    if ($dep =~ /^>=\s*(\S+)$/) {
+    if ($dep =~ /^(?:>=|=>)\s*(\S+)$/) {
         $version = $1;
         $cond = sub { vcmp($_[0],$version) >= 0; };
-    } elsif ($dep =~ /^=\s*(\S+)$/) {
+    } elsif ($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*(\S+)$/) {
+        $version = $1;
+        $cond = sub { vcmp($_[0],$version) < 0; };
+    } elsif ($dep =~ /^==?\s*(\S+)$/) {
         $version = $1;
         $cond = sub { vcmp($_[0],$version) == 0; };
     } elsif ($dep =~ /^\s*$/) {

+ 22 - 82
openpkg-tool/openpkg-index.pl

@@ -35,7 +35,7 @@ use vars qw/$opt_r $opt_p $opt_C $opt_o $opt_c $opt_i/;
 use FileHandle;
 use DirHandle;
 
-my $l_prefix = "@l_prefix@";
+my $l_prefix = '@l_prefix@';
 my $RPM = "$l_prefix/bin/rpm";
 my $R2C = "$l_prefix/bin/rpm2cpio";
 my $BZ  = "$l_prefix/lib/openpkg/bzip2 -9";
@@ -78,6 +78,14 @@ sub commasep ($$) {
     return $v;
 }
 
+sub optesc ($) {
+    my($s) = @_;
+
+    $s =~ s/([\x00-\x1f\x80-\xbf\s\%])/sprintf("%%%02x",ord($1))/eg;
+
+    return $s;
+}
+
 sub vsub ($$) {
     my($var,$v) = @_;
 
@@ -135,36 +143,6 @@ sub find_options ($) {
     return $evar;
 }
 
-#
-# clean up %options macro from description
-#
-sub clean_options ($$) {
-    my($descr,$evar) = @_;
-    my($p);
-
-    $descr =~ s/\s*\%options.*\n//;
-    $descr =~ s/\n*$/\n/s;
-
-    if (%$evar) {
-
-        $p = 0;
-        foreach (keys %$evar) {
-            $p = length($_) if length($_) > $p;
-        }
-
-        $descr .= "\n" . join '', map {
-            sprintf(
-                "    %%option  %s  %s\n",
-                $_.' 'x($p-length($_)),
-                $evar->{$_}
-            )
-        } sort keys %$evar;
-
-    }
-
-    return $descr;
-}
-
 #
 # translate default section from spec-file
 # into a hash
@@ -198,7 +176,7 @@ sub package2data ($$) {
     #
     # map option macro
     #
-    $s =~ s/^#option\s+(\S+)\s*(.*?)\s*$/#ifndef $1\n#define $1 $2\n#endif/mg;
+    $s =~ s/^#option\s+(\S+)\s*(.*?)\s*$/#ifndef $1\n#define $1 $2\n#endif\n#provides $1 $2/mg;
 
     #
     # use option variables for interpolation
@@ -306,6 +284,17 @@ sub package2data ($$) {
             } else {
                 $var{$1} = $2;
             }
+        } elsif ($v =~ /^\#(?:provides)\s*(\S+)\s*(.*?)\s*$/) {
+            #
+            # store option for current condition
+            #
+            if (exists $attr{'Name'}->{''}) {
+                push @{$attr{'Provides'}->{$cond}},
+                    $attr{'Name'}->{''}->[0].'::'.$1.' = '.optesc($2);
+            } else {
+                warn "ERROR: no package name set for option $1 = $2\n";
+            }
+
         } elsif ($v =~ /^\s*([^\#]\S*)\s*:\s*(.*?)\s*$/) {
 
             #
@@ -351,14 +340,8 @@ sub spec2data ($) {
 
     if (exists $map{'description'}) {
         $o = find_options($map{'description'});
-
         $a = package2data($map{'*'}, $o );
-
-        $a->{'Options'} = { '' => $o };
-
-        $a->{'Description'} = { '' => [
-            clean_options($map{'description'}, $o)
-        ] };
+        $a->{'Description'} = { '' => [ $map{'description'} ] };
     } else {
         $a = package2data($map{'*'}, {});
     }
@@ -476,48 +459,6 @@ sub xml_bag ($$$;$) {
     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.
-#
-# each element of the bag is a name value pair
-#
-sub xml_vals ($$$$$) {
-    my($i,$a,$k,$tags,$tag) = @_;
-    my($out,$cond,$upn,$map);
-    return "" unless exists $a->{$k};
-    $out = '';
-    $i = ' ' x $i;
-
-    foreach $cond (sort keys %{$a->{$k}}) {
-        $map = $a->{$k}->{$cond};
-        next unless %$map;
-        $upn = e(upn($cond));
-        $out .= $i.
-                ($cond ne '' ? "<$tags cond=\"$upn\">\n" : "<$tags>\n").
-                "$i  <rdf:bag>\n".
-                join('',
-                     map {
-                         "$i    <rdf:li>".
-                         ( ( $map->{$_} =~ /^\%\{/ )
-                            ? "<$tag ID=\"".e($_)."\"/>"
-                            : "<$tag ID=\"".e($_)."\">".
-                              e($map->{$_}).
-                              "</$tag>"
-                         ).
-                         "</rdf:li>\n"
-                     }
-                     keys %$map
-                ).
-                "$i  </rdf:bag>\n".
-                "$i</$tags>\n";
-    }
-
-    return $out;
-}
-
 #
 # send out reference to another RDF
 #
@@ -622,7 +563,6 @@ EOFEOF
         xml_tag(6, $a, 'SigMD5'),
         xml_tag(6, $a, 'SigPGP'),
         xml_tag(6, $a, 'SigGPG'),
-        xml_vals(6, $a, 'Options', 'Options', 'Option'),
         xml_bag(6, $a, 'BuildPreReq'),
         xml_bag(6, $a, 'PreReq'),
         xml_bag(6, $a, 'Provides'),