diff -r 71503088f51b -r f880f219c566 openpkg/search.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openpkg/search.pl Tue Jul 31 12:23:42 2012 +0200 @@ -0,0 +1,246 @@ +## +## search.pl -- OpenPKG Package Searching +## Copyright (c) 2011-2012 OpenPKG GmbH +## +## This software is property of the OpenPKG GmbH, DE MUC HRB 160208. +## All rights reserved. Licenses which grant limited permission to use, +## copy, modify and distribute this software are available from the +## OpenPKG GmbH. +## +## 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.003; + +# OpenPKG instance prefix and RPM +my $my_prefix = $ENV{'OPENPKG_PREFIX'}; +my $my_rpm = "$my_prefix/bin/openpkg rpm"; +delete $ENV{'OPENPKG_PREFIX'}; + +# program identification +my $progname = "search"; +my $progvers = "0.1.0"; + +# home-brewn getopt(3) style option parser +sub getopts ($$@) { + my ($opt_spec, $opts, @argv_orig) = @_; + my (%optf) = map { m/(\w)/; $1 => $_ } $opt_spec =~ m/(\w:|\w)/g; + my (@argv, $optarg); + + foreach (@argv_orig) { + 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 "openpkg:$prog_name:WARNING: unknown option $_\n"; + } + $_ = "-$2"; + } + } + } + if (defined $optarg) { + warn "openpkg:$prog_name:WARNING: option $optarg requires an argument\n"; + } + foreach my $opt (keys %optf) { + if (not exists $opts->{$opt}) { + $opts->{$opt} = (length($optf{$opt}) > 1 ? "" : 0); + } + } + return @argv; +} + +# execute a command +my $run_cache = {}; +sub run ($) { + my ($cmd) = @_; + my $out = $run_cache->{$cmd}; + if (not defined($out)) { + my @out = `$cmd`; + $out = [ @out ]; + $run_cache->{$cmd} = $out; + } + return (wantarray ? @{$out} : join(//, @{$out})); +} + +# determine reasonable temporary directory +my $tmpdir = ($ENV{"TMPDIR"} || "/tmp"); + +# parse command line options +my $opts = {}; +@ARGV = getopts("hvr:", $opts, @ARGV); + +# usage sanity check and usage help +sub usage { + my ($rc) = @_; + my $usage = "openpkg:$prog_name:USAGE: openpkg search \n"; + if ($rc == 0) { + print STDOUT $usage; + } + else { + print STDERR $usage; + } + exit($rc); +} +if ($opts->{"h"}) { + usage(0); +} +if (@ARGV == 0) { + usage(1); +} + +# take command line arguments +my $keyword = $ARGV[0]; + +# determine start URL +my $url = $opts->{"r"} || ""; +if ($url eq "") { + $url = run("$my_prefix/bin/openpkg release --fmt='%u' 2>/dev/null"); + $url =~ s/^\s+//s; + $url =~ s/\s+$//s; +} +if ($url eq "") { + print STDERR "openpkg:$prog_name:ERROR: no repository URL known\n"; + exit(1); +} + +# recursively download XML/RDF index +sub relurl ($$) { + my ($url, $suburl) = @_; + if ($suburl =~ m/^\w+:\/\//) { + $url = $suburl; + } + elsif ($suburl =~ m/^\//) { + $url = "file://$suburl"; + } + else { + $url =~ s/(\/)?\/*[^\/]*$/$1$suburl/; + } + 1 while ($url =~ s/\/\.\//\//s); + 1 while ($url =~ s/\/[^\/]+\/\.\.\//\//s); + return $url; +} +sub get_index ($) { + my ($url) = @_; + if ($url =~ m/^\//) { + $url = "file://$url"; + } + if ($url =~ m/\/$/) { + $url .= "00INDEX.rdf"; + } + my $cmd = "$my_prefix/bin/openpkg curl -s -o- \"$url\" 2>/dev/null"; + if ($url =~ m/\.bz2$/) { + $cmd .= " | $my_prefix/lib/openpkg/bzip2 -d -c"; + } + my $xml = run($cmd); + my @includes = (); + while ($xml =~ m/]*href="([^"]*)"/gs) { + push(@includes, $1); + } + foreach my $include (@includes) { + $xml .= get_index(relurl($url, $include)); + } + return $xml; +} +my $xml = get_index($url); + +# parse XML/RDF index +my $x = $xml; +$x =~ s/(.+?)<\/rdf:Description>/do1($1, $2), ''/sge; +sub do1 { + my ($nvr, $xml) = @_; + my ($name) = ($xml =~ m|(.+?)|s); + my ($vers) = ($xml =~ m|(.+?)|s); + my ($rele) = ($xml =~ m|(.+?)|s); + my ($summ) = ($xml =~ m|(.+?)|s); + my ($desc) = ($xml =~ m|(.+?)|s); + if ( $name =~ m|$keyword|si + or $summ =~ m|$keyword|si + or $desc =~ m|$keyword|si) { + do2($nvr, $name, $vers, $rele, $summ, $desc, $xml); + } +} +sub do2 { + my ($nvr, $name, $vers, $rele, $summ, $desc, $xml) = @_; + return if ($name eq "openpkg"); + if ($opts->{"v"}) { + # itemized verbose output + my ($dist) = ($xml =~ m|(.+?)|s); + my ($class) = ($xml =~ m|(.+?)|s); + my ($group) = ($xml =~ m|(.+?)|s); + my ($license) = ($xml =~ m|(.+?)|s); + my ($packager) = ($xml =~ m|(.+?)|s); + my ($url) = ($xml =~ m|(.+?)|s); + my ($vendor) = ($xml =~ m|(.+?)|s); + + print "Name: $name\n"; + print "Version: $vers\n"; + print "Release: $rele\n"; + print "Group: $group\n"; + print "Class: $class\n"; + print "Distrib: $dist\n"; + print "License: $license\n"; + print "Packager: $packager\n"; + print "Vendor: $vendor\n"; + print "Summary: $summ\n"; + print "URL: $url\n"; + + print "Description:\n"; + $desc =~ s/^\s+//mg; + $desc =~ s/\s+$//mg; + $desc =~ s/^/ /mg; + print "$desc\n"; + + my ($prov) = ($xml =~ m|(.+?)|s); + if (($prov || "") ne "") { + print "Provides:\n"; + $prov =~ s/(.+?)<\/resource>/do3($1, $2), ''/sge; + sub do3 { + my ($val, $name) = @_; + print " $name = $val\n"; + } + } + + print "\n"; + } + else { + # tabular brief output + printf("%-20s %-10s %-9s %s\n", $name, $vers, $rele, $summ); + } +} +