openpkg/search.pl

Mon, 28 Jan 2013 17:37:18 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 28 Jan 2013 17:37:18 +0100
changeset 758
a2c6460cfb16
permissions
-rw-r--r--

Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.

michael@428 1 ##
michael@428 2 ## search.pl -- OpenPKG Package Searching
michael@428 3 ## Copyright (c) 2011-2012 OpenPKG GmbH <http://openpkg.com/>
michael@428 4 ##
michael@428 5 ## This software is property of the OpenPKG GmbH, DE MUC HRB 160208.
michael@428 6 ## All rights reserved. Licenses which grant limited permission to use,
michael@428 7 ## copy, modify and distribute this software are available from the
michael@428 8 ## OpenPKG GmbH.
michael@428 9 ##
michael@428 10 ## THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
michael@428 11 ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
michael@428 12 ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
michael@428 13 ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
michael@428 14 ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@428 15 ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@428 16 ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
michael@428 17 ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
michael@428 18 ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
michael@428 19 ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
michael@428 20 ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
michael@428 21 ## SUCH DAMAGE.
michael@428 22 ##
michael@428 23
michael@428 24 require 5.003;
michael@428 25
michael@428 26 # OpenPKG instance prefix and RPM
michael@428 27 my $my_prefix = $ENV{'OPENPKG_PREFIX'};
michael@428 28 my $my_rpm = "$my_prefix/bin/openpkg rpm";
michael@428 29 delete $ENV{'OPENPKG_PREFIX'};
michael@428 30
michael@428 31 # program identification
michael@428 32 my $progname = "search";
michael@428 33 my $progvers = "0.1.0";
michael@428 34
michael@428 35 # home-brewn getopt(3) style option parser
michael@428 36 sub getopts ($$@) {
michael@428 37 my ($opt_spec, $opts, @argv_orig) = @_;
michael@428 38 my (%optf) = map { m/(\w)/; $1 => $_ } $opt_spec =~ m/(\w:|\w)/g;
michael@428 39 my (@argv, $optarg);
michael@428 40
michael@428 41 foreach (@argv_orig) {
michael@428 42 if (@argv) {
michael@428 43 push @argv, $_;
michael@428 44 } elsif (defined $optarg) {
michael@428 45 if (exists $opts->{$optarg}) {
michael@428 46 $opts->{$optarg} .= " $_";
michael@428 47 } else {
michael@428 48 $opts->{$optarg} = $_;
michael@428 49 }
michael@428 50 $optarg = undef;
michael@428 51 } elsif (!/^[-]/) {
michael@428 52 push @argv, $_;
michael@428 53 } else {
michael@428 54 while (/^\-(\w)(.*)/) {
michael@428 55 if (exists $optf{$1}) {
michael@428 56 if (length($optf{$1}) > 1) {
michael@428 57 if ($2 ne '') {
michael@428 58 if (exists $opts->{$1}) {
michael@428 59 $opts->{$1} .= " $2";
michael@428 60 } else {
michael@428 61 $opts->{$1} = $2;
michael@428 62 }
michael@428 63 } else {
michael@428 64 $optarg = $1;
michael@428 65 }
michael@428 66 last;
michael@428 67 } else {
michael@428 68 $opts->{$1} = 1;
michael@428 69 }
michael@428 70 } else {
michael@428 71 warn "openpkg:$prog_name:WARNING: unknown option $_\n";
michael@428 72 }
michael@428 73 $_ = "-$2";
michael@428 74 }
michael@428 75 }
michael@428 76 }
michael@428 77 if (defined $optarg) {
michael@428 78 warn "openpkg:$prog_name:WARNING: option $optarg requires an argument\n";
michael@428 79 }
michael@428 80 foreach my $opt (keys %optf) {
michael@428 81 if (not exists $opts->{$opt}) {
michael@428 82 $opts->{$opt} = (length($optf{$opt}) > 1 ? "" : 0);
michael@428 83 }
michael@428 84 }
michael@428 85 return @argv;
michael@428 86 }
michael@428 87
michael@428 88 # execute a command
michael@428 89 my $run_cache = {};
michael@428 90 sub run ($) {
michael@428 91 my ($cmd) = @_;
michael@428 92 my $out = $run_cache->{$cmd};
michael@428 93 if (not defined($out)) {
michael@428 94 my @out = `$cmd`;
michael@428 95 $out = [ @out ];
michael@428 96 $run_cache->{$cmd} = $out;
michael@428 97 }
michael@428 98 return (wantarray ? @{$out} : join(//, @{$out}));
michael@428 99 }
michael@428 100
michael@428 101 # determine reasonable temporary directory
michael@428 102 my $tmpdir = ($ENV{"TMPDIR"} || "/tmp");
michael@428 103
michael@428 104 # parse command line options
michael@428 105 my $opts = {};
michael@428 106 @ARGV = getopts("hvr:", $opts, @ARGV);
michael@428 107
michael@428 108 # usage sanity check and usage help
michael@428 109 sub usage {
michael@428 110 my ($rc) = @_;
michael@428 111 my $usage = "openpkg:$prog_name:USAGE: openpkg search <regex>\n";
michael@428 112 if ($rc == 0) {
michael@428 113 print STDOUT $usage;
michael@428 114 }
michael@428 115 else {
michael@428 116 print STDERR $usage;
michael@428 117 }
michael@428 118 exit($rc);
michael@428 119 }
michael@428 120 if ($opts->{"h"}) {
michael@428 121 usage(0);
michael@428 122 }
michael@428 123 if (@ARGV == 0) {
michael@428 124 usage(1);
michael@428 125 }
michael@428 126
michael@428 127 # take command line arguments
michael@428 128 my $keyword = $ARGV[0];
michael@428 129
michael@428 130 # determine start URL
michael@428 131 my $url = $opts->{"r"} || "";
michael@428 132 if ($url eq "") {
michael@428 133 $url = run("$my_prefix/bin/openpkg release --fmt='%u' 2>/dev/null");
michael@428 134 $url =~ s/^\s+//s;
michael@428 135 $url =~ s/\s+$//s;
michael@428 136 }
michael@428 137 if ($url eq "") {
michael@428 138 print STDERR "openpkg:$prog_name:ERROR: no repository URL known\n";
michael@428 139 exit(1);
michael@428 140 }
michael@428 141
michael@428 142 # recursively download XML/RDF index
michael@428 143 sub relurl ($$) {
michael@428 144 my ($url, $suburl) = @_;
michael@428 145 if ($suburl =~ m/^\w+:\/\//) {
michael@428 146 $url = $suburl;
michael@428 147 }
michael@428 148 elsif ($suburl =~ m/^\//) {
michael@428 149 $url = "file://$suburl";
michael@428 150 }
michael@428 151 else {
michael@428 152 $url =~ s/(\/)?\/*[^\/]*$/$1$suburl/;
michael@428 153 }
michael@428 154 1 while ($url =~ s/\/\.\//\//s);
michael@428 155 1 while ($url =~ s/\/[^\/]+\/\.\.\//\//s);
michael@428 156 return $url;
michael@428 157 }
michael@428 158 sub get_index ($) {
michael@428 159 my ($url) = @_;
michael@428 160 if ($url =~ m/^\//) {
michael@428 161 $url = "file://$url";
michael@428 162 }
michael@428 163 if ($url =~ m/\/$/) {
michael@428 164 $url .= "00INDEX.rdf";
michael@428 165 }
michael@428 166 my $cmd = "$my_prefix/bin/openpkg curl -s -o- \"$url\" 2>/dev/null";
michael@428 167 if ($url =~ m/\.bz2$/) {
michael@428 168 $cmd .= " | $my_prefix/lib/openpkg/bzip2 -d -c";
michael@428 169 }
michael@428 170 my $xml = run($cmd);
michael@428 171 my @includes = ();
michael@428 172 while ($xml =~ m/<Repository\s+[^>]*href="([^"]*)"/gs) {
michael@428 173 push(@includes, $1);
michael@428 174 }
michael@428 175 foreach my $include (@includes) {
michael@428 176 $xml .= get_index(relurl($url, $include));
michael@428 177 }
michael@428 178 return $xml;
michael@428 179 }
michael@428 180 my $xml = get_index($url);
michael@428 181
michael@428 182 # parse XML/RDF index
michael@428 183 my $x = $xml;
michael@428 184 $x =~ s/<rdf:Description\s+about="([^"]+)".*?>(.+?)<\/rdf:Description>/do1($1, $2), ''/sge;
michael@428 185 sub do1 {
michael@428 186 my ($nvr, $xml) = @_;
michael@428 187 my ($name) = ($xml =~ m|<Name>(.+?)</Name>|s);
michael@428 188 my ($vers) = ($xml =~ m|<Version>(.+?)</Version>|s);
michael@428 189 my ($rele) = ($xml =~ m|<Release>(.+?)</Release>|s);
michael@428 190 my ($summ) = ($xml =~ m|<Summary>(.+?)</Summary>|s);
michael@428 191 my ($desc) = ($xml =~ m|<Description>(.+?)</Description>|s);
michael@428 192 if ( $name =~ m|$keyword|si
michael@428 193 or $summ =~ m|$keyword|si
michael@428 194 or $desc =~ m|$keyword|si) {
michael@428 195 do2($nvr, $name, $vers, $rele, $summ, $desc, $xml);
michael@428 196 }
michael@428 197 }
michael@428 198 sub do2 {
michael@428 199 my ($nvr, $name, $vers, $rele, $summ, $desc, $xml) = @_;
michael@428 200 return if ($name eq "openpkg");
michael@428 201 if ($opts->{"v"}) {
michael@428 202 # itemized verbose output
michael@428 203 my ($dist) = ($xml =~ m|<Distribution>(.+?)</Distribution>|s);
michael@428 204 my ($class) = ($xml =~ m|<Class>(.+?)</Class>|s);
michael@428 205 my ($group) = ($xml =~ m|<Group>(.+?)</Group>|s);
michael@428 206 my ($license) = ($xml =~ m|<License>(.+?)</License>|s);
michael@428 207 my ($packager) = ($xml =~ m|<Packager>(.+?)</Packager>|s);
michael@428 208 my ($url) = ($xml =~ m|<URL>(.+?)</URL>|s);
michael@428 209 my ($vendor) = ($xml =~ m|<Vendor>(.+?)</Vendor>|s);
michael@428 210
michael@428 211 print "Name: $name\n";
michael@428 212 print "Version: $vers\n";
michael@428 213 print "Release: $rele\n";
michael@428 214 print "Group: $group\n";
michael@428 215 print "Class: $class\n";
michael@428 216 print "Distrib: $dist\n";
michael@428 217 print "License: $license\n";
michael@428 218 print "Packager: $packager\n";
michael@428 219 print "Vendor: $vendor\n";
michael@428 220 print "Summary: $summ\n";
michael@428 221 print "URL: $url\n";
michael@428 222
michael@428 223 print "Description:\n";
michael@428 224 $desc =~ s/^\s+//mg;
michael@428 225 $desc =~ s/\s+$//mg;
michael@428 226 $desc =~ s/^/ /mg;
michael@428 227 print "$desc\n";
michael@428 228
michael@428 229 my ($prov) = ($xml =~ m|<Provides>(.+?)</Provides>|s);
michael@428 230 if (($prov || "") ne "") {
michael@428 231 print "Provides:\n";
michael@428 232 $prov =~ s/<resource\s+equ="([^"]*)">(.+?)<\/resource>/do3($1, $2), ''/sge;
michael@428 233 sub do3 {
michael@428 234 my ($val, $name) = @_;
michael@428 235 print " $name = $val\n";
michael@428 236 }
michael@428 237 }
michael@428 238
michael@428 239 print "\n";
michael@428 240 }
michael@428 241 else {
michael@428 242 # tabular brief output
michael@428 243 printf("%-20s %-10s %-9s %s\n", $name, $vers, $rele, $summ);
michael@428 244 }
michael@428 245 }
michael@428 246

mercurial