On Fri, May 17, 2019 at 02:02:24PM +0200, Marc Espie wrote:
> Please try this instead.
> 
> What this does:
> 
> adds two complementary options to update-plist:
> -c maybe_comment
> -I maybe_ignored
> 
> For python, that would be
> UPDATE_PLIST_ARGS += -c MODPY_PYCACHE -I MODPY_COMMENT
> 
> 
> maybe_ignored is a variable that may expand to nothing
> depending on the flavor, and maybe_comment is a variable
> that may expand to @comment depending on the flavor.
> 
> This patch replaces write_restate with a 2-pass algorithm.
> First pass prepares the substituted lines.
> 
> Second line does write stuff to the files.
> 
> The way the variables work is as follows:
> - first pass counts keyed items for each plist, by making the 
> ignored vars vanish, and normalizing directories.
> - second pass notices keyed items that would be duplicated,
> and injects  ${MODPY_COMMENT} at the beginning of the line.
> 
> Yes, it's waaay more intricate than what you suggested,
> but it could be used in other scenarios instead of being
> python-only.
> 
> Of course, this does require testing. I may have made some
> stupid mistake somewhere.

And here is the version without stupid mistakes, along with the manpage
change, explicitly describing what's going on (somewhat long-winded, but
I think this required an example :)  )

I intend to commit this unless there are objections.

Ports diff:
----------
Index: infrastructure/bin/update-plist
===================================================================
RCS file: /cvs/ports/infrastructure/bin/update-plist,v
retrieving revision 1.173
diff -u -p -r1.173 update-plist
--- infrastructure/bin/update-plist     17 May 2019 10:24:18 -0000      1.173
+++ infrastructure/bin/update-plist     18 May 2019 10:21:46 -0000
@@ -52,7 +52,7 @@ package TrackedFile;
 sub new
 {
        my ($class, $name, $ext) = @_;
-       bless {name => $name, ext => $ext, items => []}, $class;
+       bless {name => $name, ext => $ext, items => [], items2 => []}, $class;
 }
 
 sub add
@@ -61,6 +61,28 @@ sub add
        push(@{$self->{items}}, $item);
 }
 
+sub add2
+{
+       my ($self, $item, $p) = @_;
+
+       if ($item->NoDuplicateNames) {
+               my $s = $p->subst->remove_ignored_vars($item->{prepared});
+               my $s2 = $p->subst->do($s);
+               if (defined (my $k = $item->keyword)) {
+                       $s2 =~ s/^\@\Q$k\E\s//;
+               }
+               $p->{stash}{$s2}++;
+
+               my $comment = $p->subst->{maybe_comment};
+
+               if ($s ne $item->{prepared} &&
+                       $item->{prepared} !~ m/^\Q$comment\E/) {
+                       $item->{candidate_for_comment} = $s2;
+               }
+       }
+       push(@{$self->{items2}}, $item);
+}
+
 sub fh
 {
        my $self = shift;
@@ -87,6 +109,16 @@ sub next_item
        }
 }
 
+sub next_item2
+{
+       my $self = shift;
+       if (@{$self->{items2}} != 0) {
+               return shift @{$self->{items2}};
+       } else {
+               return undef;
+       }
+}
+
 package TrackFile;
 
 sub new
@@ -125,6 +157,25 @@ sub write_all
 
                while (my $file = pop @stack) {
                        while (my $j = $file->next_item) {
+                               my $filename = $j->prepare_restate($file, $p);
+                               if (defined $filename) {
+                                       push(@stack, $file);
+                                       $file = $self->file($filename);
+                               }
+                       }
+               }
+       }
+
+       for my $i (@{$p->{base_plists}}) {
+               # we mimic the way pkg_create writes files
+               $p->{restate} = {};
+
+               my @stack = ();
+               push(@stack, $self->file($i));
+
+
+               while (my $file = pop @stack) {
+                       while (my $j = $file->next_item2) {
                                my $filename = $j->write_restate($file, $p);
                                if (defined $filename) {
                                        push(@stack, $file);
@@ -390,12 +441,33 @@ sub write_restate
        return undef;
 }
 
+sub prepare_restate
+{
+       my ($o, $file, $p) = @_;
+       $o->prepare_backsubst($file, $p);
+       return undef;
+}
+
+sub prepare_backsubst
+{
+       my ($o, $file, $p) = @_;
+       my $s = $p->subst->do_backsubst($o->fullstring, $o->unsubst, $o);
+       $o->{prepared} = $s;
+       $file->add2($o, $p);
+}
+
 # default backsubstitution and writing. 
 sub write_backsubst
 {
        my ($o, $file, $p) = @_;
-       my $s = $p->subst->do_backsubst($o->fullstring, $o->unsubst, $o);
-       print {$file->fh} $s, "\n";
+
+       if (defined (my $s = $o->{candidate_for_comment})) {
+               if ($p->{stash}{$s} > 1) {
+                       $o->{prepared} = 
+                           $p->subst->{maybe_comment}.$o->{prepared};
+               }
+       }
+       print {$file->fh} $o->{prepared}, "\n";
 }
 
 # extra objects that get copied very late (e.g., @extra)
@@ -665,10 +737,11 @@ sub tie_objects
 }
 
 # we will never do backsubst on CVSTags
-sub write_backsubst
+sub prepare_backsubst
 {
        my ($o, $file, $p) = @_;
-       $o->write($file->fh);
+       $o->{prepared} = $o->fullstring;
+       $file->add2($o, $p);
 }
 
 # this is extra stuff that PkgCreate  builds but that we don't want to copy
@@ -694,6 +767,10 @@ sub write_restate
 {
 }
 
+sub prepare_restate
+{
+}
+
 package OpenBSD::PackingElement::ExtraInfo;
 sub copy_annotations
 {
@@ -889,6 +966,19 @@ sub write_restate
        return undef;
 }
 
+sub prepare_restate
+{
+       my ($self, $file, $p) = @_;
+       # don't do backsubst on fragments, pkg_create does not!
+       $file->add2($self, $p);
+       my $base = $file->name;
+       my $frag = $self->frag;
+       $base =~ s/PFRAG\./PFRAG.$frag-/ or
+           $base =~ s/PLIST/PFRAG.$frag/;
+       return $base if $p->{tracker}{known}{$base};
+       return undef;
+}
+
 sub frag
 {
        my $self = shift;
@@ -1063,7 +1153,7 @@ sub check_lib_version
        }
 }
 
-sub write_backsubst
+sub prepare_backsubst
 {
        my ($self, $f, $p) = @_;
        if ($self->name =~ m,^(.*?)lib([^\/]+)\.so\.(\d+\.\d+)$,) {
@@ -1074,7 +1164,8 @@ sub write_backsubst
                    "\@lib ${path}lib$name.so.\$\{$k\}", $self->unsubst, $self);
                $self->check_lib_version($version, $name, 
                        $p->subst->value($k));
-               print {$f->fh} "$s\n";
+               $self->{prepared} = $s;
+               $f->add2($self, $p);
        } else {
                $self->SUPER::write_backsubst($f, $p);
        }
@@ -1229,6 +1320,17 @@ sub handle_options
                        my $var = shift;
                        push(@{$state->{dont_backsubst}}, $var);
                    },
+               'I' => sub {
+                       my $var = shift;
+                       push(@{$state->{maybe_ignored}}, $var);
+                   },
+               'c' => sub {
+                       my $var = shift;
+                       if (exists $state->{maybe_comment}) {
+                               $state->usage;
+                       }
+                       $state->{maybe_comment} = '${'.$var.'}';
+                   },
                's' => sub {
                        my $var = shift;
                        push(@{$state->{start_only}}, $var);
@@ -1243,10 +1345,10 @@ sub handle_options
                    },
 
        };
-       $state->SUPER::handle_options('rvqV:FC:i:j:L:s:S:X:P:w:e:E:', 
-           '[-Fmnrvx] [-C dir] [-E ext] [-e ext] [-i var] [-j jobs]',
-           '[-L logfile] [-P pkgdir] [-S var] [-s var] [-V var]',
-           '[-w suffix] [-X path] -- pkg_create_args ...');
+       $state->SUPER::handle_options('rvI:c:qV:FC:i:j:L:s:S:X:P:w:e:E:', 
+           '[-Fmnrvx] [-C dir] [-c comment] [-E ext] [-e ext] [-i var]',
+           '[-I ignored] [-j jobs] [-L logfile] [-P pkgdir] [-S var]',
+           '[-s var] [-V var] [-w suffix] [-X path] -- pkg_create_args ...');
        $state->{pkgdir} = $state->opt('P');
        $state->{scan_as_root} = $state->opt('r');
        $state->{verbose} = $state->opt('v');
@@ -1255,6 +1357,9 @@ sub handle_options
        $state->{extnew} = $state->opt('E') // ".new";
        $state->{extorig} = $state->opt('e') // ".orig";
        $state->{logfile} = $state->opt('L');
+       if (exists $state->{maybe_ignored} && !exists $state->{maybe_comment}) {
+               $state->usage;
+       }
 }
 
 package UpdatePlist;
Index: infrastructure/lib/OpenBSD/ReverseSubst.pm
===================================================================
RCS file: /cvs/ports/infrastructure/lib/OpenBSD/ReverseSubst.pm,v
retrieving revision 1.19
diff -u -p -r1.19 ReverseSubst.pm
--- infrastructure/lib/OpenBSD/ReverseSubst.pm  17 May 2019 10:04:13 -0000      
1.19
+++ infrastructure/lib/OpenBSD/ReverseSubst.pm  18 May 2019 10:21:46 -0000
@@ -175,8 +175,12 @@ sub new
            isversion => {},
            # under some cases, some variables are a priority
            disregard_count => {},
+           # to be able to inject @comment  conditionally on some other
+           # variables
+           maybe_comment => $state->{maybe_comment},
            }, $class;
-       for my $k (qw(dont_backsubst start_only suffix_only no_version)) {
+       for my $k (qw(dont_backsubst start_only suffix_only no_version
+           maybe_ignored)) {
                if (defined $state->{$k}) {
                        for my $v (@{$state->{$k}}) {
                                $o->{$k}{$v} = 1;
@@ -184,6 +188,16 @@ sub new
                }
        }
        return $o;
+}
+
+sub remove_ignored_vars
+{
+       my ($self, $s) = @_;
+       for my $v (keys %{$self->{maybe_ignored}}) {
+               while ($s =~ s/\$\{\Q$v\E\}//) {}
+       }
+       $s =~ s,//,/,g;
+       return $s;
 }
 
 # those are actually just passed thru to pkg_create for special





Source diff:
-----------
Index: update-plist.1
===================================================================
RCS file: /cvs/src/share/man/man1/update-plist.1,v
retrieving revision 1.2
diff -u -p -r1.2 update-plist.1
--- update-plist.1      26 Jun 2018 06:56:07 -0000      1.2
+++ update-plist.1      18 May 2019 10:48:13 -0000
@@ -26,8 +26,10 @@
 .Nm
 .Op Fl Fmnqrvx
 .Op Fl C Ar dir
+.Op Fl c Ar var
 .Op Fl E Ar ext
 .Op Fl e Ar ext
+.Op Fl I Ar var
 .Op Fl i Ar var
 .Op Fl j Ar jobs
 .Op Fl S Ar var
@@ -83,6 +85,12 @@ Beware that this directory should then b
 dependencies's packing-lists change.
 But this will speed up packing-list regeneration for ports with
 lots of dependencies significantly.
+.It Fl c Ar var
+Variable
+.Ar var
+may be used as a way to insert
+.Cm \@ Ns comment
+when other variables vanish.
 .It Fl E Ar ext
 Write new files with
 .Ar ext
@@ -96,6 +104,12 @@ extension instead of the default
 .It Fl F
 Do not try to run
 .Xr pkg_locate 1 .
+.It Fl I Ar var
+Variable
+.Ar var
+may expand to nothing, in which case the variable from
+.Fl c Ar var
+can be used to prevent duplicate entries.
 .It Fl i Ar var
 Ignore variable
 .Ar var
@@ -214,6 +228,59 @@ and it currently does not add new substi
 .Ev ARCH
 nor
 .Ev MACHINE_ARCH .
+.Pp
+Some packages (notoriously Python packages) create some directories optionally
+based on flavors.
+Options
+.Fl c
+and
+.Fl I
+can be used to avoid duplicate directory definitions.
+.Pp
+Specifically, a generated packing-list would contain
+.Bd -literal -offset indent -compact
+lib/python${MODPY_VERSION}/site-packages/bpdb/
+lib/python${MODPY_VERSION}/site-packages/bpdb/${MODPY_PYCACHE}/
+.Ed
+which expands to
+.Bd -literal -offset indent -compact
+lib/python3.7/site-packages/bpdb/
+lib/python3.7/site-packages/bpdb/__pycache__/
+.Ed
+for python3, which is fine.
+.Pp
+But for python2, variable
+.Sq MODPY_PYCACHE
+will be empty, resulting in
+.Bd -literal -offset indent -compact
+lib/python2.7/site-packages/bpdb/
+lib/python2.7/site-packages/bpdb/
+.Ed
+thus a duplicate directory,
+.Xr pkg_create 1
+won't be happy.
+.Pp
+Using
+.Ev UPDATE_PLIST_ARGS = Fl c Ar MODPY_COMMENT Fl I Ar MODPY_PYCACHE
+will result in injecting
+.Sq ${MODPY_COMMENT}
+whereever
+.Nm
+finds a duplicate directory by replacing
+.Sq ${MODPY_PYCACHE}
+with nothing.
+.Pp
+This yields
+.Bd -literal -offset indent -compact
+lib/python${MODPY_VERSION}/site-packages/bpdb/
+${MODPY_COMMENT}lib/python${MODPY_VERSION}/site-packages/bpdb/MODPY_PYCACHE}/
+.Ed
+and for python2 this expands to
+.Bd -literal -offset indent -compact
+lib/python2.7/site-packages/bpdb/
+@comment lib/python2.7/site-packages/bpdb/
+.Ed
+which is exactly what we want.
 .Pp
 Specific items such as shared libraries or binaries will gain annotations
 and special handling, for instance

Reply via email to