As noticed by landry, going to the ports tree for dependencies can fail
hilariously in case of a PORTSDIR_PATH.

Most specifically, assuming you are building something like firefox-102
in one of your ports directory, when building the debug package,
dependency look-up in pkg_create is going to follow PORTSDIR_PATH, thus 
ending up possibly in another firefox directory which contains firefox-100.

And since debug packages dependencies are tight, this will fail every time.

We're already checking for dependency pkgpath matching the pkgpath we're
building, so it's mostly a question of deducing the ports root from the
current directory.

and overriding PORTSDIR_PATH in ask_tree.

(another possibility would be to actively parse the dependency, not go back
to the ports tree, and just set FLAVOR and SUBPACKAGE correctly, but this
is somewhat more complicated and this appears to work).

Note the "Overriding..." print. This is intended as checking that things work
as expected and not intended for commit.

(I've also added an extra check on plist->pkgname and error message display
while debugging that thingy, along with moving the full action tweaks in
the father, so the messages reflect what has actually been run)

Okay ?


Index: OpenBSD/PkgCreate.pm
===================================================================
RCS file: /cvs/src/usr.sbin/pkg_add/OpenBSD/PkgCreate.pm,v
retrieving revision 1.182
diff -u -p -r1.182 PkgCreate.pm
--- OpenBSD/PkgCreate.pm        28 Jun 2022 09:01:45 -0000      1.182
+++ OpenBSD/PkgCreate.pm        28 Jun 2022 09:59:24 -0000
@@ -980,6 +980,7 @@ sub really_solve_dependency
        $state->progress->message($dep->{pkgpath});
 
        my $v;
+       my $path;
 
        # look in installed packages, but only for different paths
        my $p1 = $dep->{pkgpath};
@@ -987,7 +988,16 @@ sub really_solve_dependency
        $p1 =~ s/\,.*//;
        $p2 =~ s/\,.*//;
        $p2 =~ s,^debug/,,;
-       if ($p1 ne $p2) {
+       if ($p1 eq $p2) {
+               # try to figure out where we live
+               require Cwd;
+               my $dir = Cwd::getcwd();
+               if (defined $dir) {
+                       if ($dir =~ s,/\Q$p1\E$,,) {
+                               $path = $dir;
+                       }
+               }
+       } else {
                # look in installed packages
                $v = $self->find_dep_in_installed($state, $dep);
        }
@@ -997,7 +1007,7 @@ sub really_solve_dependency
 
        # and in portstree otherwise
        if (!defined $v) {
-               $v = $self->solve_from_ports($state, $dep, $package);
+               $v = $self->solve_from_ports($state, $dep, $package, $path);
        }
        return $v;
 }
@@ -1032,13 +1042,19 @@ sub to_cache
 
 sub ask_tree
 {
-       my ($self, $state, $pkgpath, $portsdir, $data, @action) = @_;
+       my ($self, $state, $pkgpath, $portsdir, $path, $data, @action) = @_;
 
        my $make = OpenBSD::Paths->make;
        my $errors = OpenBSD::Temp->file;
        if (!defined $errors) {
                $state->fatal(OpenBSD::Temp->last_error);
        }
+       push(@action, 'PORTS_PRIVSEP=No');
+       if (defined $path) {
+               push(@action, "PORTSDIR_PATH=$path");
+               $state->say("Overriding PORTSDIR_PATH=#1 for dependency #2", 
+                   $path, $pkgpath);
+       }
        my $pid = open(my $fh, "-|");
        if (!defined $pid) {
                $state->fatal("cannot fork: #1", $!);
@@ -1059,7 +1075,6 @@ sub ask_tree
                $( = $); $< = $>;
                # XXX we're already running as ${BUILD_USER}
                # so we can't do this again
-               push(@action, 'PORTS_PRIVSEP=No');
                $DB::inhibit_exit = 0;
                exec $make ('make', @action);
        }
@@ -1067,7 +1082,7 @@ sub ask_tree
        while(<$fh>) {  # XXX avoid spurious errors from child
        }
        close($fh);
-       if ($? != 0) {
+       if ($? != 0 || !defined $plist || !defined $plist->pkgname) {
                $state->errsay("child running '#2' failed: #1", 
                    $state->child_error,
                    join(' ', 'make', @action));
@@ -1084,7 +1099,7 @@ sub ask_tree
 
 sub really_solve_from_ports
 {
-       my ($self, $state, $dep, $portsdir) = @_;
+       my ($self, $state, $dep, $portsdir, $path) = @_;
 
        my $diskcache = $self->diskcachename($dep);
        my $plist;
@@ -1093,6 +1108,7 @@ sub really_solve_from_ports
                $plist = OpenBSD::PackingList->fromfile($diskcache);
        } else {
                $plist = $self->ask_tree($state, $dep->{pkgpath}, $portsdir,
+                   $path,
                    \&OpenBSD::PackingList::PrelinkStuffOnly,
                    'print-plist-libs-with-depends',
                    'wantlib_args=no-wantlib-args');
@@ -1113,7 +1129,7 @@ my $cache = {};
 
 sub solve_from_ports
 {
-       my ($self, $state, $dep, $package) = @_;
+       my ($self, $state, $dep, $package, $path) = @_;
 
        my $portsdir = $state->defines('PORTSDIR');
        return undef unless defined $portsdir;
@@ -1122,7 +1138,7 @@ sub solve_from_ports
                $pkgname = $cache->{$dep->{pkgpath}};
        } else {
                $pkgname = $self->really_solve_from_ports($state, $dep, 
-                   $portsdir);
+                   $portsdir, $path);
                $cache->{$dep->{pkgpath}} = $pkgname;
        }
        if (!defined $pkgname) {

Reply via email to