Most of the code was already there.

This would allow pkg_add to auto-configure a mirror, for the case where
PKG_PATH was not specified and where pkg.conf does not exist.

It only triggers when a location ends up empty and when run in interactive
mode, e.g., it shouldn't interfere with local lookups.

Good idea, or awful ?

Index: OpenBSD/PackageLocator.pm
===================================================================
RCS file: /cvs/src/usr.sbin/pkg_add/OpenBSD/PackageLocator.pm,v
retrieving revision 1.105
diff -u -p -r1.105 PackageLocator.pm
--- OpenBSD/PackageLocator.pm   30 Jan 2016 11:29:29 -0000      1.105
+++ OpenBSD/PackageLocator.pm   22 Jun 2016 13:51:40 -0000
@@ -24,6 +24,7 @@ use OpenBSD::PackageRepositoryList;
 use OpenBSD::PackageRepository;
 
 my $default_path;
+my $is_configured;
 
 sub build_default_path
 {
@@ -37,17 +38,91 @@ sub build_default_path
                while (my $o = OpenBSD::PackageRepository->parse(\$v, $state)) {
                        $default_path->add($o);
                }
+               $is_configured = 1;
                return;
        }
        $default_path->add(OpenBSD::PackageRepository->new("./", 
$state)->can_be_empty);
-       return if $state->defines('NOINSTALLPATH');
+       if ($state->defines('NOINSTALLPATH')) {
+               $is_configured = 1;
+               return;
+       }
 
        return unless defined $state->config->value('installpath');
+       $is_configured = 1;
        for my $i ($state->config->value("installpath")) {
                $default_path->add(OpenBSD::PackageRepository->new($i, $state));
        }
 }
 
+sub discover_mirror
+{
+       my ($self, $state) = @_;
+
+       # can't ask the user -> no mirror
+       return undef unless $state->is_interactive;
+
+
+       require OpenBSD::PackageRepository;
+       my $fake = 
OpenBSD::PackageRepository->new("http://129.128.5.191/cgi-bin/";, $state);
+       # XXX
+       bless $fake, "OpenBSD::PackageRepository::Cgi";
+       my $l = $fake->list;
+       my @m = @$l;
+       my %h;
+       for my $d (@m) {
+               my $e = $d;
+               $d =~ s,^http://(.*?)(/.*?)?\s+(.*)$,$1\t$3,;
+               $e =~ s/\s+.*$//;
+               $h{$d} = $e;
+       }
+       $m[0] = "<None>";
+       my $i = $state->ask_list("No mirror configured, choose one", @m);
+       if ($i eq "<None>") {
+               return undef;
+       }
+       return $h{$i};
+}
+
+sub convert_to_packages
+{
+       my ($self, $url) = @_;
+       # mirror was "designed" for base releases.
+       # convert into short installpath version
+       $url =~ s,^http://(.*)/pub/OpenBSD$,$1, or
+           $url =~ s,$,/%c/packages/%a,;
+       return $url;
+}
+
+sub last_chance
+{
+       if ($is_configured) {
+               return [];
+       }
+       $is_configured = 1;
+       my ($self, @search) = @_;
+       my $state = pop @search;
+
+       my $url = $self->discover_mirror($state);
+       if (!defined $url) {
+               return [];
+       }
+       
+       $url = $self->convert_to_packages($url);
+
+       # try setting it "permanently"
+       if (open(my $f, ">>", OpenBSD::Paths->pkgconf)) {
+               print $f "installpath += $url\n";
+               close $f;
+       } else {
+               $state->errsay("Couldn't write to #1", OpenBSD::Paths->pkgconf);
+       }
+
+       # use it for the current round anyway
+       $default_path->add(OpenBSD::PackageRepository->new($url, $state));
+
+       return $self->match_locations(@search, $state);
+}
+
 sub default_path
 {
        if (!defined $default_path) {
@@ -107,4 +182,27 @@ sub match_locations
        return $self->default_path($state)->match_locations(@search);
 }
 
+package OpenBSD::PackageRepository::Cgi;
+our @ISA = qw(OpenBSD::PackageRepository::HTTP);
+
+# we know how to get a list, we just need to override the specific url
+# and parser
+sub get_http_list
+{
+       my ($self, $error) = @_;
+
+       require OpenBSD::Paths;
+       my $fullname = 
$self->url."ftplist.cgi?path=".OpenBSD::Paths->os_directory."/".OpenBSD::Paths->machine_architecture;
+       my $l = [];
+       my $fh = $self->open_read_ftp(OpenBSD::Paths->ftp." -o - $fullname", 
+           $error) or return;
+       while(<$fh>) {
+               chomp;
+               if (m/^http:\/\//) {
+                       push(@$l, $_);
+               }
+       }
+       $self->close_read_ftp($fh);
+       return $l;
+}
 1;
Index: OpenBSD/PackageRepositoryList.pm
===================================================================
RCS file: /cvs/src/usr.sbin/pkg_add/OpenBSD/PackageRepositoryList.pm,v
retrieving revision 1.30
diff -u -p -r1.30 PackageRepositoryList.pm
--- OpenBSD/PackageRepositoryList.pm    9 Jul 2015 12:57:55 -0000       1.30
+++ OpenBSD/PackageRepositoryList.pm    22 Jun 2016 13:51:40 -0000
@@ -86,7 +86,7 @@ sub match_locations
                        return $l;
                }
        }
-       return [];
+       return $self->{state}->repo->last_chance(@search);
 }
 
 1;
Index: OpenBSD/State.pm
===================================================================
RCS file: /cvs/src/usr.sbin/pkg_add/OpenBSD/State.pm,v
retrieving revision 1.34
diff -u -p -r1.34 State.pm
--- OpenBSD/State.pm    6 Apr 2015 11:07:24 -0000       1.34
+++ OpenBSD/State.pm    22 Jun 2016 13:51:40 -0000
@@ -137,6 +137,14 @@ sub match_locations
        return OpenBSD::PackageLocator->match_locations(@_, $self->{state});
 }
 
+sub last_chance
+{
+       my $self = shift;
+       require OpenBSD::PackageLocator;
+
+       return OpenBSD::PackageLocator->last_chance(@_, $self->{state});
+}
+
 sub grabPlist
 {
        my ($self, $url, $code) = @_;
@@ -340,6 +348,11 @@ sub handle_options
        }
        local $Exporter::ExportLevel = $state->{export_level};
        import OpenBSD::State;
+}
+
+sub is_interactive
+{
+       return 0;
 }
 
 sub defines

Reply via email to