--- toast 2005/10/03 03:43:54 1.416 +++ toast 2005/10/03 05:48:05 1.417 @@ -263,6 +263,7 @@ "postarmprog" => superuser ? "/sbin/ldconfig" : "", "editprog" => "", "defaultcmd" => "help", + "findsites" => "all", "httpproxy" => exists($ENV{http_proxy}) ? $ENV{http_proxy} : "", "ftpproxy" => exists($ENV{ftp_proxy}) ? $ENV{ftp_proxy} : "", "confappend" => "", @@ -1274,6 +1275,7 @@ || $base =~ /^(.*)()$/; # Xmerge my($name, $version) = ($1, $2); $name =~ s/\./_/g; # helps parse() distinguish filenames from pkg names + $name =~ s/::/-/g; # perl module naming convention return (sanitize($name), sanitize($version)); } @@ -2153,95 +2155,120 @@ defined($name) || error; $name =~ /^[\w-]+$/ || error("invalid package name: $name"); my($lcname) = lc($name); + my($perlname) = $name; + $perlname =~ s/-/::/g; + my(@sites) = + ( + "freshmeat" => "http://freshmeat.net/projects-xml/$lcname/$lcname.xml", + "sourceforge" => "http://prdownloads.sourceforge.net/$lcname/", + "gnu" => "http://ftp.gnu.org/gnu/$lcname/", + "cpan" => "http://cpan.uwinnipeg.ca/module/$perlname", + ); + + my(%sites) = @sites; + my(@all) = grep(/^\w+$/, @sites); + my(@findsites) = split(/\s+/, findsites); + @findsites = map { ($_ eq "all") ? @all : $_ } @findsites; + @findsites = map { exists($sites{$_}) ? $sites{$_} : $_ } @findsites; + s/\*/\Q$name\E/g for @findsites; + @findsites = $myurl if $lcname eq $myname; + @findsites = uniq(@findsites); + my($url); - if($lcname eq $myname) + for $url (@findsites) { - $url = $myurl; - } - else - { - local(*XML, $_); - my($sitename) = "freshmeat.net"; - openurl(*XML, "http://freshmeat.net/projects-xml/$lcname/$lcname.xml"); - my($notfound, %fmurl); - while(<XML>) + my(@ret) = eval { - $notfound = /^Error: project not found/i ? 1 : 0 if !defined($notfound); - $fmurl{$1} = $2 while m!<url_(\w+)>([^<]+)</!g; - } - close(XML) || error("unable to contact freshmeat.net"); + my($tries) = 1; + if($url =~ m!^http://(freshmeat.net)/.*\.xml$!) + { + local(*XML, $_); + my($sitename) = $1; + openurl(*XML, $url); + my($notfound, %fmurl); + while(<XML>) + { + $notfound = /^Error: project not found/i ? 1 : 0 + if !defined($notfound); + $fmurl{$1} = $2 while m!<url_(\w+)>([^<]+)</!g; + } + close(XML) || error("unable to contact $sitename"); - error("no listing for package $name on $sitename") if $notfound; + error("no listing for package $name on $sitename") if $notfound; - my($redirurl); - $redirurl ||= $fmurl{$_} for qw(bz2 tgz zip deb rpm homepage); - $redirurl || error("no suitable URL for package $name on $sitename"); + my($redirurl); + $redirurl ||= $fmurl{$_} for qw(bz2 tgz zip deb rpm homepage); + $redirurl || error("no suitable URL for package $name on $sitename"); - my($redirhead) = httphead($redirurl); - $redirhead =~ /^Location: ([^\r\n]+)/im || - error("unexpected response from $redirurl"); - $url = $1; - # wget can't always get FTP directory listing correctly w/o trailing slash - $url .= "/" if $url =~ m!^ftp:.*/[^/\.]+$!; # e.g. atop - $url = cleanurl($url); - } + my($redirhead) = httphead($redirurl); + $redirhead =~ /^Location: ([^\r\n]+)/im || + error("unexpected response from $redirurl"); + $url = $1; + # wget can't always get FTP directory listing w/o trailing slash + $url .= "/" if $url =~ m!^ftp:.*/[^/\.]+$!; # e.g. atop + $url = cleanurl($url); + $tries = 3; + } - my(@links) = $url; - for(1..3) - { - $url = $links[$#links]; - @links = sort cmpab grep(lookslikepkgurl( - $_, defined($version) ? $name : undef, $version), @links); - my(@result); - for(@links) - { - my($v) = $version; - (undef, $v) = guessnv($_) unless defined($v); - push(@result, [$name, $v, undef, $_]) - } - if(scalar(@result) == 1) - { - eval + my(@links) = $url; + for(1..$tries) { - @result = findnewerpkg(@{$result[0]}) - } - } - return @result if @result; - last if lookslikepkgurl($url); + $url = $links[$#links]; + @links = sort cmpab grep(lookslikepkgurl( + $_, defined($version) ? $name : undef, $version), @links); + my(@result); + for(@links) + { + my($v) = $version; + (undef, $v) = guessnv($_) unless defined($v); + push(@result, [$name, $v, undef, $_]) + } + if(scalar(@result) == 1) + { + eval { @result = findnewerpkg(@{$result[0]}) } + } + return @result if @result; + last if lookslikepkgurl($url); - @links = linksfromurl($url); - my(@urls) = grep(lookslikepkgurl($_, $name, $version), @links); - my($ext); - for $ext (qw[.tar.bz2 .tar.gz .tgz .zip .deb .rpm]) - { - my(@matches) = grep(stripquery($_) =~ /\Q$ext\E$/i, @urls); + @links = linksfromurl($url); + my(@urls) = grep(lookslikepkgurl($_, $name, $version), @links); + my($ext); + for $ext (qw[.tar.bz2 .tar.gz .tgz .zip .deb .rpm]) + { + my(@matches) = grep(stripquery($_) =~ /\Q$ext\E$/i, @urls); - my(@namematches) = grep { my($n) = guessnv($_); $n eq $name } @matches; - @matches = @namematches if @namematches; + my(@namematches) = + grep { my($n) = guessnv($_); $n eq $name } @matches; + @matches = @namematches if @namematches; - if(defined($version)) - { - my(@vermatches) = - grep { my(undef, $v) = guessnv($_); $v eq $version } @matches; - @matches = @vermatches if @vermatches; - } + if(defined($version)) + { + my(@vermatches) = + grep { my(undef, $v) = guessnv($_); $v eq $version } @matches; + @matches = @vermatches if @vermatches; + } - @matches = sort cmpab @matches; - @result = (); - for(@matches) - { - my($undef, $v) = guessnv($_); - push(@result, [$name, $v, undef, $_]); + @matches = sort cmpab @matches; + @result = (); + for(@matches) + { + my($undef, $v) = guessnv($_); + push(@result, [$name, $v, undef, $_]); + } + return @result if @result; + } + + @links = grep(/^\Q$url\E/, @links); + last unless @links; } - return @result if @result; - } + }; - @links = grep(/^\Q$url\E/, @links); - last unless @links; + return @ret if @ret; + explain($_) for(split(/\n/, $@)); } - error("can't find URLs for " . pkgname($name, $version) . " at $url"); + error("can't find " . pkgname($name, $version)); } sub pkgurls($$) @@ -6310,10 +6337,11 @@ similar to that of B<toast status>, but all information comes from the network rather than the on-disk package database. If a given package has not been added and no URLs were specified on the command line, -B<toast find> looks for an exact name match on freshmeat.net; otherwise -it attempts to list the directory or directories to which the package's -URL(s) belong. If an explicit version number is given, only that version -is listed; otherwise all versions are listed from oldest to newest. +B<toast find> looks for an exact name match on the web sites specified +by the B<findsites> option; otherwise it attempts to list the directory +or directories to which the package's URL(s) belong. If an explicit +version number is given, only that version is listed; otherwise all +versions are listed from oldest to newest. =item S<B<toast add> I<PACKAGE> ...> @@ -6715,6 +6743,17 @@ equivalent to running B<toast help>, regardless of this option's setting. Default: C<help>. +=item B<--findsites=>I<SITELIST> + +Set the list of web sites or other locations searched by B<toast +find> for packages that have not already been added. I<SITELIST> +is a space-separated list of URLs and/or special words taken from the +following list: C<freshmeat>, C<sourceforge>, C<gnu>, C<cpan>, or C<all> +(which stands for all of the preceding words in the order given). +The C<*> character will be replaced by the name of the package to find +wherever it occurs. If you want a literal C<*> character, too bad. +Default: C<all>. + =item B<--httpproxy=>I<URL> If I<URL> is non-empty, B<toast get> will use the given URL as the @@ -7218,7 +7257,6 @@ - allow package name/version as URL; expand w/ autofind iff missing - optionally have toast add imply change, then make get+build smarter - toast status/env should allow multiple read-only storedirs/armdirs - - autofind should try other sites if freshmeat.net has no listing - fold archives by URL and/or hash? - zsh completions!