From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 395BE1F55F for ; Wed, 13 Sep 2023 01:18:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1694567935; bh=S41s0yr57I/CPaQgLsnNxldBfvTYzy72dLa2nu1r+4M=; h=From:To:Subject:Date:From; b=jfOFHgLzbM17d0s8FpZ76M+CWe7jGVU6Qz2u7E9J8W32Jc66eiB2zfNrnyoQrZfkW VQY8XaYOcL9wHyF3RbCY0DZTaOeZImvcAs2gc4Ip3X12na8wf8BJiH0hCwTZFNRfXl 5oYBt47T/S1/9TspjtsUG25g7EMt5X9C94wr8YQU= From: Eric Wong To: spew@80x24.org Subject: [PATCH] install/deps: safer defaults for ordinary users Date: Wed, 13 Sep 2023 01:18:55 +0000 Message-ID: <20230913011855.1801493-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: We'll leave forcing `--yes' to ci/run.sh and remove --purge usage with apt-get(1) entirely. Also start defining some more profiles aimed at users who want a minimal install for the subset of public-inbox they wish to use. --- ci/run.sh | 3 +- install/deps.perl | 122 ++++++++++++++++++++++++++++------------------ 2 files changed, 77 insertions(+), 48 deletions(-) diff --git a/ci/run.sh b/ci/run.sh index 5aa22491..54563f1c 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -1,6 +1,7 @@ #!/bin/sh # Copyright (C) all contributors # License: AGPL-3.0+ +# Beware, this alters system-wide package installation. set -e SUDO=${SUDO-'sudo'} PERL=${PERL-'perl'} MAKE=${MAKE-'make'} DO=${DO-''} @@ -15,7 +16,7 @@ NPROC=${NPROC-$({ getconf _NPROCESSORS_ONLN || getconf NPROCESSORS_ONLN || $PERL -w ci/profiles.perl | while read args do - $DO $SUDO $PERL -w install/deps.perl --allow-remove $args + $DO $SUDO $PERL -w install/deps.perl -y --allow-remove $args $DO $PERL Makefile.PL $DO $MAKE -j${BUILD_JOBS-$NPROC} $DO $MAKE -j${TEST_JOBS-1} ${TEST_TARGET-test} diff --git a/install/deps.perl b/install/deps.perl index a7b42607..6a60c592 100755 --- a/install/deps.perl +++ b/install/deps.perl @@ -4,14 +4,16 @@ eval 'exec perl -S $0 ${1+"$@"}' # no shebang if 0; # running under some shell use v5.12; -my $help = <{help}) { print $help; exit } my $pkg_fmt = $opt->{'pkg-fmt'} // do { my $fmt = pkg_fmt; @@ -31,7 +34,7 @@ my @test_essential = qw(Test::Simple); # we actually use Test::More # package profiles. Note we specify packages at maximum granularity, # which is typically deb for most things, but rpm seems to have the -# highest granularity for things in the Prl standard library. +# highest granularity for things in the Perl standard library. my $profiles = { # the smallest possible profile for testing essential => [ qw( @@ -47,10 +50,10 @@ my $profiles = { # everything optional for normal use optional => [ qw( + curl Date::Parse BSD::Resource DBD::SQLite - DBI Inline::C Mail::IMAPClient Net::Server @@ -66,14 +69,44 @@ my $profiles = { # optional developer stuff devtest => [ qw( XML::TreePP - curl w3m Plack::Test::ExternalServer ) ], }; +# only for distro-agnostic dependencies which are always true: +my $always_deps = { + 'DBD::SQLite' => [ qw(DBI) ], + 'Mail::IMAPClient' => [ qw(Parse::RecDescent) ], + 'Plack::Middleware::ReverseProxy' => [ qw(Plack) ], +}; + # bare minimum for v2 -$profiles->{v2essential} = [ @{$profiles->{essential}}, qw(DBD::SQLite DBI) ]; +$profiles->{v2essential} = [ @{$profiles->{essential}}, qw(DBD::SQLite) ]; + +# for old v1 installs +$profiles->{'www-v1'} = [ @{$profiles->{essential}}, qw(Plack) ]; +$profiles->{'www-thread'} = [ @{$profiles->{v2essential}}, qw(Plack) ]; + +# common profile for PublicInbox::WWW +$profiles->{'www-search'} = [ @{$profiles->{'www-thread'}}, qw(Xapian) ]; + +# bare mininum for lei +$profiles->{'lei-core'} = [ @{$profiles->{v2essential}}, qw(Xapian) ]; +push @{$profiles->{'lei-core'}}, 'Inline::C' if $^O ne 'linux'; + +# common profile for lei: +$profiles->{lei} = [ @{$profiles->{'lei-core'}}, qw(Mail::IMAPClient curl) ]; + +$profiles->{nntpd} = [ @{$profiles->{v2essential}} ]; +$profiles->{pop3d} = [ @{$profiles->{v2essential}} ]; +$profiles->{'imapd-bare'} = [ @{$profiles->{v2essential}}, + qw(Parse::RecDescent) ]; +$profiles->{imapd} = [ @{$profiles->{'imapd-bare'}}, qw(Xapian) ]; +$profiles->{pop3d} = [ @{$profiles->{v2essential}} ]; +$profiles->{watch} = [ @{$profiles->{v2essential}}, qw(Mail::IMAPClient) ]; +$profiles->{'watch-v1'} = [ @{$profiles->{essential}} ]; +$profiles->{'watch-maildir'} = [ @{$profiles->{v2essential}} ]; # package names which can't be mapped automatically and explicit # dependencies to prevent essential package removal: @@ -169,6 +202,12 @@ don't know how to check install status for $pkg_fmt my (@pkg_install, @pkg_remove, %all); for my $ary (values %$profiles) { + my @extra; + for my $pkg (@$ary) { + my $deps = $always_deps->{$pkg} // next; + push @extra, @$deps; + } + push @$ary, @extra; $all{$_} = \@pkg_remove for @$ary; } if ($^O =~ /\A(?:free|net|open)bsd\z/) { @@ -177,7 +216,8 @@ if ($^O =~ /\A(?:free|net|open)bsd\z/) { $profiles->{all} = [ keys %all ]; # pseudo-profile for all packages # parse the profile list from the command-line -for my $profile (@ARGV) { +my @profiles = @ARGV; +while (defined(my $profile = shift @profiles)) { if ($profile =~ s/-\z//) { # like apt-get, trailing "-" means remove profile2dst($profile, \@pkg_remove); @@ -191,57 +231,54 @@ while (my ($pkg, $dst_pkg_list) = each %all) { push @$dst_pkg_list, list(pkg2ospkg($pkg, $pkg_fmt)); } -my %inst = map { $_ => 1 } @pkg_install; -@pkg_remove = $opt->{'allow-remove'} ? grep { !$inst{$_} } @pkg_remove : (); -@pkg_install = grep { !$INST_CHECK->($_) } @pkg_install; - -my @apt_opts = - qw(-o APT::Install-Recommends=false -o APT::Install-Suggests=false); +my (%add, %rm); # uniquify lists +@pkg_install = grep { !$add{$_}++ && !$INST_CHECK->($_) } @pkg_install; +@pkg_remove = $opt->{'allow-remove'} ? grep { + !$add{$_} && !$rm{$_}++ && $INST_CHECK->($_) + } @pkg_remove : (); # OS-specific cleanups appreciated if ($pkg_fmt eq 'deb') { - my @quiet = $ENV{V} ? () : ('-q'); - root('apt-get', @apt_opts, qw(install --purge -y), @quiet, + my @apt_opt = qw(-o APT::Install-Recommends=false + -o APT::Install-Suggests=false); + push @apt_opt, '-y' if $opt->{yes}; + root('apt-get', @apt_opt, qw(install), @pkg_install, # apt-get lets you suffix a package with "-" to # remove it in an "install" sub-command: map { "$_-" } @pkg_remove); - root('apt-get', @apt_opts, qw(autoremove --purge -y), @quiet); + root('apt-get', @apt_opt, qw(autoremove)) if $opt->{'allow-remove'}; } elsif ($pkg_fmt eq 'pkg') { # FreeBSD - my @quiet = $ENV{V} ? () : ('-q'); + my @pkg_opt = $opt->{yes} ? qw(-y) : (); # don't remove stuff that isn't installed: - exclude_uninstalled(\@pkg_remove); - root(qw(pkg remove -y), @quiet, @pkg_remove) if @pkg_remove; - root(qw(pkg install -y), @quiet, @pkg_install) if @pkg_install; - root(qw(pkg autoremove -y), @quiet); + root(qw(pkg remove), @pkg_opt, @pkg_remove) if @pkg_remove; + root(qw(pkg install), @pkg_opt, @pkg_install) if @pkg_install; + root(qw(pkg autoremove), @pkg_opt) if $opt->{'allow-remove'}; } elsif ($pkg_fmt eq 'pkgin') { # NetBSD - my @quiet = $ENV{V} ? ('-'.('V'x$ENV{V})) : (); - exclude_uninstalled(\@pkg_remove); - root(qw(pkgin -y), @quiet, 'remove', @pkg_remove) if @pkg_remove; - root(qw(pkgin -y), @quiet, 'install', @pkg_install) if @pkg_install; - root(qw(pkgin -y), @quiet, 'autoremove'); + my @pkg_opt = $opt->{yes} ? qw(-y) : (); + root(qw(pkgin), @pkg_opt, 'remove', @pkg_remove) if @pkg_remove; + root(qw(pkgin), @pkg_opt, 'install', @pkg_install) if @pkg_install; + root(qw(pkgin), @pkg_opt, 'autoremove') if $opt->{'allow-remove'}; # TODO: yum / rpm support } elsif ($pkg_fmt eq 'rpm') { - my @quiet = $ENV{V} ? () : ('-q'); - exclude_uninstalled(\@pkg_remove); - root(qw(yum remove -y), @quiet, @pkg_remove) if @pkg_remove; - root(qw(yum install -y), @quiet, @pkg_install) if @pkg_install; + my @pkg_opt = $opt->{yes} ? qw(-y) : (); + root(qw(yum remove), @pkg_opt, @pkg_remove) if @pkg_remove; + root(qw(yum install), @pkg_opt, @pkg_install) if @pkg_install; } elsif ($pkg_fmt eq 'pkg_add') { # OpenBSD - exclude_uninstalled(\@pkg_remove); - my @quiet = $ENV{V} ? ('-'.('v'x$ENV{V})) : qw(-x); # -x : no progress + my @pkg_opt = $opt->{yes} ? qw(-I) : (); # -I means non-interactive if (@pkg_remove) { my @lifo = qw(xapian-bindings-perl); for my $dep (@lifo) { grep(/\A\Q$dep\E\z/, @pkg_remove) or next; - root(qw(pkg_delete -I), @quiet, $dep); + root(qw(pkg_delete), @pkg_opt, $dep); @pkg_remove = grep(!/\A\Q$dep\E\z/, @pkg_remove); } - root(qw(pkg_delete -I), @quiet, @pkg_remove); + root(qw(pkg_delete), @pkg_opt, @pkg_remove); } - root(qw(pkg_delete -a), @quiet); + root(qw(pkg_delete -a), @pkg_opt); # autoremove unspecified @pkg_install = map { "$_--" } @pkg_install; # disambiguate w3m - root(qw(pkg_add), @quiet, @pkg_install) if @pkg_install; + root(qw(pkg_add), @pkg_opt, @pkg_install) if @pkg_install; } else { die "unsupported package format: $pkg_fmt\n"; } @@ -290,15 +327,6 @@ sub profile2dst { } } -sub exclude_uninstalled { - my ($list) = @_; - my (@tmp, %seen); - for my $pkg (@$list) { - push @tmp, $pkg if !$seen{$pkg}++ && $INST_CHECK->($pkg); - } - @$list = @tmp; -} - sub root { warn "# @_\n"; return if $opt->{'dry-run'};