openpkg/search.pl

changeset 428
f880f219c566
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/openpkg/search.pl	Tue Jul 31 12:23:42 2012 +0200
     1.3 @@ -0,0 +1,246 @@
     1.4 +##
     1.5 +##  search.pl -- OpenPKG Package Searching
     1.6 +##  Copyright (c) 2011-2012 OpenPKG GmbH <http://openpkg.com/>
     1.7 +##
     1.8 +##  This software is property of the OpenPKG GmbH, DE MUC HRB 160208.
     1.9 +##  All rights reserved. Licenses which grant limited permission to use,
    1.10 +##  copy, modify and distribute this software are available from the
    1.11 +##  OpenPKG GmbH.
    1.12 +##
    1.13 +##  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
    1.14 +##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    1.15 +##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    1.16 +##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
    1.17 +##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.18 +##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.19 +##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    1.20 +##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    1.21 +##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    1.22 +##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    1.23 +##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.24 +##  SUCH DAMAGE.
    1.25 +##
    1.26 +
    1.27 +require 5.003;
    1.28 +
    1.29 +#   OpenPKG instance prefix and RPM
    1.30 +my $my_prefix = $ENV{'OPENPKG_PREFIX'};
    1.31 +my $my_rpm = "$my_prefix/bin/openpkg rpm";
    1.32 +delete $ENV{'OPENPKG_PREFIX'};
    1.33 +
    1.34 +#   program identification
    1.35 +my $progname  = "search";
    1.36 +my $progvers  = "0.1.0";
    1.37 +
    1.38 +#   home-brewn getopt(3) style option parser
    1.39 +sub getopts ($$@) {
    1.40 +    my ($opt_spec, $opts, @argv_orig) = @_;
    1.41 +    my (%optf) = map { m/(\w)/; $1 => $_ } $opt_spec =~ m/(\w:|\w)/g;
    1.42 +    my (@argv, $optarg);
    1.43 +
    1.44 +    foreach (@argv_orig) {
    1.45 +        if (@argv) {
    1.46 +            push @argv, $_;
    1.47 +        } elsif (defined $optarg) {
    1.48 +            if (exists $opts->{$optarg}) {
    1.49 +                $opts->{$optarg} .= " $_";
    1.50 +            } else {
    1.51 +                $opts->{$optarg} = $_;
    1.52 +            }
    1.53 +            $optarg = undef;
    1.54 +        } elsif (!/^[-]/) {
    1.55 +            push @argv, $_;
    1.56 +        } else {
    1.57 +            while (/^\-(\w)(.*)/) {
    1.58 +                if (exists $optf{$1}) {
    1.59 +                    if (length($optf{$1}) > 1) {
    1.60 +                        if ($2 ne '') {
    1.61 +                            if (exists $opts->{$1}) {
    1.62 +                                $opts->{$1} .= " $2";
    1.63 +                            } else {
    1.64 +                                $opts->{$1} = $2;
    1.65 +                            }
    1.66 +                        } else {
    1.67 +                            $optarg = $1;
    1.68 +                        }
    1.69 +                        last;
    1.70 +                    } else {
    1.71 +                        $opts->{$1} = 1;
    1.72 +                    }
    1.73 +                } else {
    1.74 +                    warn "openpkg:$prog_name:WARNING: unknown option $_\n";
    1.75 +                }
    1.76 +                $_ = "-$2";
    1.77 +            }
    1.78 +        }
    1.79 +    }
    1.80 +    if (defined $optarg) {
    1.81 +        warn "openpkg:$prog_name:WARNING: option $optarg requires an argument\n";
    1.82 +    }
    1.83 +    foreach my $opt (keys %optf) {
    1.84 +        if (not exists $opts->{$opt}) {
    1.85 +            $opts->{$opt} = (length($optf{$opt}) > 1 ? "" : 0);
    1.86 +        }
    1.87 +    }
    1.88 +    return @argv;
    1.89 +}
    1.90 +
    1.91 +#   execute a command
    1.92 +my $run_cache = {};
    1.93 +sub run ($) {
    1.94 +    my ($cmd) = @_;
    1.95 +    my $out = $run_cache->{$cmd};
    1.96 +    if (not defined($out)) {
    1.97 +        my @out = `$cmd`;
    1.98 +        $out = [ @out ];
    1.99 +        $run_cache->{$cmd} = $out;
   1.100 +    }
   1.101 +    return (wantarray ? @{$out} : join(//, @{$out}));
   1.102 +}
   1.103 +
   1.104 +#   determine reasonable temporary directory
   1.105 +my $tmpdir = ($ENV{"TMPDIR"} || "/tmp");
   1.106 +
   1.107 +#   parse command line options
   1.108 +my $opts = {};
   1.109 +@ARGV = getopts("hvr:", $opts, @ARGV);
   1.110 +
   1.111 +#   usage sanity check and usage help
   1.112 +sub usage {
   1.113 +    my ($rc) = @_;
   1.114 +    my $usage = "openpkg:$prog_name:USAGE: openpkg search <regex>\n";
   1.115 +    if ($rc == 0) {
   1.116 +        print STDOUT $usage;
   1.117 +    }
   1.118 +    else {
   1.119 +        print STDERR $usage;
   1.120 +    }
   1.121 +    exit($rc);
   1.122 +}
   1.123 +if ($opts->{"h"}) {
   1.124 +    usage(0);
   1.125 +}
   1.126 +if (@ARGV == 0) {
   1.127 +    usage(1);
   1.128 +}
   1.129 +
   1.130 +#   take command line arguments
   1.131 +my $keyword = $ARGV[0];
   1.132 +
   1.133 +#   determine start URL
   1.134 +my $url = $opts->{"r"} || "";
   1.135 +if ($url eq "") {
   1.136 +    $url = run("$my_prefix/bin/openpkg release --fmt='%u' 2>/dev/null");
   1.137 +    $url =~ s/^\s+//s;
   1.138 +    $url =~ s/\s+$//s;
   1.139 +}
   1.140 +if ($url eq "") {
   1.141 +    print STDERR "openpkg:$prog_name:ERROR: no repository URL known\n";
   1.142 +    exit(1);
   1.143 +}
   1.144 +
   1.145 +#   recursively download XML/RDF index
   1.146 +sub relurl ($$) {
   1.147 +    my ($url, $suburl) = @_;
   1.148 +    if ($suburl =~ m/^\w+:\/\//) {
   1.149 +        $url = $suburl;
   1.150 +    }
   1.151 +    elsif ($suburl =~ m/^\//) {
   1.152 +        $url = "file://$suburl";
   1.153 +    }
   1.154 +    else {
   1.155 +        $url =~ s/(\/)?\/*[^\/]*$/$1$suburl/;
   1.156 +    }
   1.157 +    1 while ($url =~ s/\/\.\//\//s);
   1.158 +    1 while ($url =~ s/\/[^\/]+\/\.\.\//\//s);
   1.159 +    return $url;
   1.160 +}
   1.161 +sub get_index ($) {
   1.162 +    my ($url) = @_;
   1.163 +    if ($url =~ m/^\//) {
   1.164 +        $url = "file://$url";
   1.165 +    }
   1.166 +    if ($url =~ m/\/$/) {
   1.167 +        $url .= "00INDEX.rdf";
   1.168 +    }
   1.169 +    my $cmd = "$my_prefix/bin/openpkg curl -s -o- \"$url\" 2>/dev/null";
   1.170 +    if ($url =~ m/\.bz2$/) {
   1.171 +        $cmd .= " | $my_prefix/lib/openpkg/bzip2 -d -c";
   1.172 +    }
   1.173 +    my $xml = run($cmd);
   1.174 +    my @includes = ();
   1.175 +    while ($xml =~ m/<Repository\s+[^>]*href="([^"]*)"/gs) {
   1.176 +        push(@includes, $1);
   1.177 +    }
   1.178 +    foreach my $include (@includes) {
   1.179 +        $xml .= get_index(relurl($url, $include));
   1.180 +    }
   1.181 +    return $xml;
   1.182 +}
   1.183 +my $xml = get_index($url);
   1.184 +
   1.185 +#   parse XML/RDF index
   1.186 +my $x = $xml;
   1.187 +$x =~ s/<rdf:Description\s+about="([^"]+)".*?>(.+?)<\/rdf:Description>/do1($1, $2), ''/sge;
   1.188 +sub do1 {
   1.189 +    my ($nvr, $xml) = @_;
   1.190 +    my ($name) = ($xml =~ m|<Name>(.+?)</Name>|s);
   1.191 +    my ($vers) = ($xml =~ m|<Version>(.+?)</Version>|s);
   1.192 +    my ($rele) = ($xml =~ m|<Release>(.+?)</Release>|s);
   1.193 +    my ($summ) = ($xml =~ m|<Summary>(.+?)</Summary>|s);
   1.194 +    my ($desc) = ($xml =~ m|<Description>(.+?)</Description>|s);
   1.195 +    if (   $name =~ m|$keyword|si
   1.196 +        or $summ =~ m|$keyword|si
   1.197 +        or $desc =~ m|$keyword|si) {
   1.198 +        do2($nvr, $name, $vers, $rele, $summ, $desc, $xml);
   1.199 +    }
   1.200 +}
   1.201 +sub do2 {
   1.202 +    my ($nvr, $name, $vers, $rele, $summ, $desc, $xml) = @_;
   1.203 +    return if ($name eq "openpkg");
   1.204 +    if ($opts->{"v"}) {
   1.205 +        #   itemized verbose output
   1.206 +        my ($dist)     = ($xml =~ m|<Distribution>(.+?)</Distribution>|s);
   1.207 +        my ($class)    = ($xml =~ m|<Class>(.+?)</Class>|s);
   1.208 +        my ($group)    = ($xml =~ m|<Group>(.+?)</Group>|s);
   1.209 +        my ($license)  = ($xml =~ m|<License>(.+?)</License>|s);
   1.210 +        my ($packager) = ($xml =~ m|<Packager>(.+?)</Packager>|s);
   1.211 +        my ($url)      = ($xml =~ m|<URL>(.+?)</URL>|s);
   1.212 +        my ($vendor)   = ($xml =~ m|<Vendor>(.+?)</Vendor>|s);
   1.213 +
   1.214 +        print "Name:     $name\n";
   1.215 +        print "Version:  $vers\n";
   1.216 +        print "Release:  $rele\n";
   1.217 +        print "Group:    $group\n";
   1.218 +        print "Class:    $class\n";
   1.219 +        print "Distrib:  $dist\n";
   1.220 +        print "License:  $license\n";
   1.221 +        print "Packager: $packager\n";
   1.222 +        print "Vendor:   $vendor\n";
   1.223 +        print "Summary:  $summ\n";
   1.224 +        print "URL:      $url\n";
   1.225 +
   1.226 +        print "Description:\n";
   1.227 +        $desc =~ s/^\s+//mg;
   1.228 +        $desc =~ s/\s+$//mg;
   1.229 +        $desc =~ s/^/    /mg;
   1.230 +        print "$desc\n";
   1.231 +
   1.232 +        my ($prov) = ($xml =~ m|<Provides>(.+?)</Provides>|s);
   1.233 +        if (($prov || "") ne "") {
   1.234 +            print "Provides:\n";
   1.235 +            $prov =~ s/<resource\s+equ="([^"]*)">(.+?)<\/resource>/do3($1, $2), ''/sge;
   1.236 +            sub do3 {
   1.237 +                my ($val, $name) = @_;
   1.238 +                print "    $name = $val\n";
   1.239 +            }
   1.240 +        }
   1.241 +
   1.242 +        print "\n";
   1.243 +    }
   1.244 +    else {
   1.245 +        #   tabular brief output
   1.246 +        printf("%-20s %-10s %-9s %s\n", $name, $vers, $rele, $summ);
   1.247 +    }
   1.248 +}
   1.249 +

mercurial