prt-auf: recognize optional dependencies (necessitates a new cache file format)
This commit is contained in:
parent
d3b4219e80
commit
1c14f4c46a
186
scripts/prt-auf
186
scripts/prt-auf
@ -14,22 +14,23 @@ use strict;
|
||||
my $title="prt-auf"; my $version=0.5;
|
||||
my $CONFDIR = "/var/lib/pkg"; my $prtalias="/etc/prt-get.aliases";
|
||||
my $pkgdb="$CONFDIR/db"; my $prtlocker="$CONFDIR/prt-get.locker";
|
||||
my $prtcache="$CONFDIR/prt-get.cache"; my @LOCKED; my %ALIASES; my %DEPENDS;
|
||||
my @allports; my %V_REPO; my %V_INST; my %DESC;
|
||||
my $prtcache="$CONFDIR/prt-auf.cache"; my @LOCKED; my %ALIASES; my %DEPENDS;
|
||||
my @allports; my %V_REPO; my %V_INST; my %DESC; my %SOFTDEPS;
|
||||
my @results; my $strf; my $ind; my $hh; my $portpath; my $built_pkg;
|
||||
my %osearch = ( cache => 0, regex => 0, path => 0, exact => 0, verbose => 0 );
|
||||
my %odepends = ( tree => 0, recursive => 0, all => 0 );
|
||||
my %odepends = ( soft => 0, tree => 0, recursive => 0, all => 0 );
|
||||
my %opkg = ( margs => "", aargs => "", rargs => "", runscripts => "yes",
|
||||
makecommand => "/usr/bin/pkgmk", addcommand => "/usr/bin/pkgadd",
|
||||
removecommand => "/usr/bin/pkgrm", test => "no" );
|
||||
my %olog = ( write => "disabled", mode => "overwrite", rm_on_success => "yes",
|
||||
file => "/var/log/pkgbuild/%n.log" );
|
||||
|
||||
my $prtconf = "/etc/prt-get.conf"; my @bldirs = parse_prt_conf($prtconf);
|
||||
my @basedirs = @{$bldirs[0]}; my @localports = @{$bldirs[1]};
|
||||
my $prtconf = "/etc/prt-get.conf";
|
||||
|
||||
################### Process the given command #########################
|
||||
my ($action, @query) = parse_args(@ARGV);
|
||||
$osearch{cache}=1 if ($0 =~ /cache$/);
|
||||
my @bldirs = parse_prt_conf($prtconf);
|
||||
my @basedirs = @{$bldirs[0]}; my @localports = @{$bldirs[1]};
|
||||
|
||||
# load some data structures into memory for the actions that need them
|
||||
if (($action !~ /^(fsearch|isinst|current)$/) and ($osearch{cache}==0)) {
|
||||
@ -106,22 +107,20 @@ if ($action =~ /^(listinst|listorphans)/) {
|
||||
} elsif ($action =~ /^(diff|quickdiff|current|isinst|dup)$/) {
|
||||
exit $ind;
|
||||
} elsif ($action =~ /^(depends|deptree|quickdep)$/) {
|
||||
print "-- dependencies ([i] = installed, [a] = provided by an alias)\n" if ($action =~ /^dep/);
|
||||
print "-- dependencies ([i] = installed, [a] = alias installed)\n" if ($action =~ /^dep/);
|
||||
my $indent=($action eq "deptree") ? " " : "";
|
||||
my @installed=keys %V_INST unless ($action eq "quickdep");
|
||||
my %seen; my $strf="%3s %s\n"; my $depline; my $dep; my $missing=0;
|
||||
foreach $depline (@results) {
|
||||
if ($depline =~ /MISSING/) { $missing=1; print "-- missing packages\n"; next; }
|
||||
my $cleandep = $depline;
|
||||
$cleandep =~ s/ .provided by .*// if ($action eq "deptree");
|
||||
$cleandep =~ s/ .satisfies dependency .*// if ($action eq "deptree");
|
||||
$dep = (split / /, $cleandep)[-1];
|
||||
next if ((! $dep) or (($seen{$dep}) and ($odepends{all}==0)));
|
||||
$seen{$dep}=1;
|
||||
if ($action ne "quickdep") {
|
||||
$ind = (grep { $_ eq $dep } @installed) ? "[i]" : "[ ]";
|
||||
if ($ind ne "[i]") {
|
||||
$ind = (who_aliased_to($dep)) ? "[a]" : $ind;
|
||||
}
|
||||
$ind = ($depline =~ / .satisfies dependency /) ? "[a]" : $ind;
|
||||
}
|
||||
$depline .= " $V_REPO{$dep}" if $osearch{verbose}==1;
|
||||
$depline .= " $V_REPO{$dep}\n$DESC{$dep}" if $osearch{verbose}>1;
|
||||
@ -133,10 +132,11 @@ if ($action =~ /^(listinst|listorphans)/) {
|
||||
$strf = "%14s: %-s\n";
|
||||
exit 1 if ($#results < 0);
|
||||
my @fields = ("Name", "Repository", "Version", "Release", "Description",
|
||||
"Dependencies", "URL", "Packager", "Maintainer",
|
||||
"Dependencies", "Optional Deps", "URL", "Packager", "Maintainer",
|
||||
"Readme", "PreInstall", "PostInstall");
|
||||
for (my $i=0; $i<7; $i++) { printf $strf, $fields[$i], $results[$i]; }
|
||||
printf $strf, $fields[8], $results[8];
|
||||
for (my $i=0; $i<6; $i++) { printf $strf, $fields[$i], $results[$i]; }
|
||||
printf $strf, $fields[7], $results[7];
|
||||
printf $strf, $fields[9], $results[9];
|
||||
} elsif ($action eq "remove") {
|
||||
my %removed = %$ind;
|
||||
my @successes = grep { $removed{$_}==1 } keys %removed;
|
||||
@ -173,7 +173,6 @@ if ($action =~ /^(listinst|listorphans)/) {
|
||||
#################### Begin Subroutines #######################
|
||||
sub parse_args {
|
||||
my @query;
|
||||
$osearch{cache} = 1 if ($0 =~ /cache$/);
|
||||
while (my $arg = shift) {
|
||||
if ($arg =~ /^(search|dsearch|fsearch|path|info|list|remove)$/) { $action = $1;
|
||||
} elsif ($arg =~ /^(install|update|depinst|grpinst|sysup)$/) { $action = $1;
|
||||
@ -183,19 +182,21 @@ sub parse_args {
|
||||
} elsif ($arg =~ /^(readme|cat|edit|ls|help|version|cache)$/) { $action = $1;
|
||||
} elsif ($arg eq "--tree") { $odepends{tree} = 1;
|
||||
} elsif ($arg eq "--all") { $odepends{all} = 1;
|
||||
} elsif ($arg eq "--softdeps") { $odepends{soft} = 1;
|
||||
} elsif ($arg eq "--recursive") { $odepends{recursive} = 1;
|
||||
} elsif ($arg eq "--cache") { $osearch{cache} = 1;
|
||||
} elsif ($arg =~ /^--config=(.+)$/) { $prtconf = $1;
|
||||
} elsif ($arg eq "--path") { $osearch{path} = 1;
|
||||
} elsif ($arg eq "--regex") { $osearch{regex} = 1;
|
||||
} elsif ($arg =~ /^--filter=(.*)/) { $osearch{filter} = $1;
|
||||
} elsif ($arg =~ /^--filter=(.+)/) { $osearch{filter} = $1;
|
||||
} elsif ($arg eq "-v") { $osearch{verbose} += 1;
|
||||
} elsif ($arg eq "-vv") { $osearch{verbose} += 2;
|
||||
} elsif ($arg eq "--test") { $opkg{test} = "yes";
|
||||
} elsif ($arg eq "-fr") { $opkg{margs} .= " -f";
|
||||
} elsif ($arg =~ /^(-uf|-if|-us|-is|-ns|-kw)$/) { $opkg{margs} .= " $1";
|
||||
} elsif ($arg =~ /^--margs=(.*)/) { $opkg{margs} .= $1;
|
||||
} elsif ($arg =~ /^--aargs=(-r|--root)=(.*)/) { $opkg{aargs} .= "$1 $2";
|
||||
} elsif ($arg =~ /^--rargs=(-r|--root)=(.*)/) { $opkg{rargs} .= "$1 $2";
|
||||
} elsif ($arg =~ /^--margs=(.+)/) { $opkg{margs} .= $1;
|
||||
} elsif ($arg =~ /^--aargs=(-r|--root)=(.+)/) { $opkg{aargs} .= "$1 $2";
|
||||
} elsif ($arg =~ /^--rargs=(-r|--root)=(.+)/) { $opkg{rargs} .= "$1 $2";
|
||||
} elsif ($arg =~ /^-/) {
|
||||
print "'$arg' is not a recognized option.\n";
|
||||
} else { push (@query, $arg); }
|
||||
@ -311,16 +312,17 @@ sub who_aliased_to {
|
||||
sub printf_ports {
|
||||
my $FS; my @pstats; my $p; my $inputf=shift; my @targets=@_;
|
||||
my @pos; my @outfields; my $outputf; my %FS = ( "t"=>"\t", "n"=>"\n" );
|
||||
my %subscripts = ( "n"=>0, "p"=>1, "v"=>2, "r"=>3, "d"=>4, "e"=>5,
|
||||
"u"=>6, "P"=>7, "M"=>8, "R"=>9, "E"=>10, "O"=>11, "l"=>12, "i"=>13 );
|
||||
my %subscripts = ( "n"=>0, "p"=>1, "v"=>2, "r"=>3, "d"=>4, "o"=>5, "e"=>6,
|
||||
"u"=>7, "P"=>8, "M"=>9, "R"=>10, "E"=>11, "O"=>12, "l"=>13, "i"=>14);
|
||||
if ($inputf eq "CACHE") {
|
||||
open (CACHE,'>',$prtcache) or die "cannot create a new cache file";
|
||||
print CACHE "V5\n";
|
||||
print CACHE "V5.1\n";
|
||||
my %cached;
|
||||
foreach my $pp (@targets) {
|
||||
$p = (split /\//, $pp)[-1];
|
||||
$p = (split /\//, $pp)[-1]; next if ($cached{$p});
|
||||
@pstats = get_pkgfile_fields($pp,"all");
|
||||
printf CACHE "%s\n"x($#pstats+1), @pstats;
|
||||
printf CACHE "\n";
|
||||
printf CACHE "\n"; $cached{$p}=1;
|
||||
} close (CACHE);
|
||||
print "cache created.\n";
|
||||
} else {
|
||||
@ -329,19 +331,19 @@ sub printf_ports {
|
||||
foreach (@outfields) {
|
||||
if (m/\\(t|n)/) { $outputf .= $FS{$1}; next; }
|
||||
$strf = $_;
|
||||
s/%(p|n|v|r|d|e|u|P|M|R|E|O|l|i)/_Z_$subscripts{$1}/g;
|
||||
s/%(p|n|v|r|d|o|e|u|P|M|R|E|O|l|i)/_Z_$subscripts{$1}/g;
|
||||
push @pos, grep { s/([0-9]+)(.*)/$1/ } (split /_Z_/, $_);
|
||||
$strf =~ s/%(p|n|v|r|d|e|u|P|M|R|E|O|l|i)/%s/g;
|
||||
$strf =~ s/%(p|n|v|r|d|o|e|u|P|M|R|E|O|l|i)/%s/g;
|
||||
$outputf .= $strf;
|
||||
}
|
||||
|
||||
foreach my $pp (@targets) {
|
||||
$p = (split /\//, $pp)[-1];
|
||||
@pstats = get_pkgfile_fields($pp,"all");
|
||||
$pstats[12] = (grep /^$p$/, @LOCKED) ? "yes" : "no";
|
||||
$pstats[13] = (grep /^$p$/, keys %V_INST) ? "yes" : "no";
|
||||
if (($pstats[13] eq "yes") and ($V_INST{$p} ne $V_REPO{$p})) {
|
||||
$pstats[13] = "diff" }
|
||||
$pstats[13] = (grep /^$p$/, @LOCKED) ? "yes" : "no";
|
||||
$pstats[14] = (grep /^$p$/, keys %V_INST) ? "yes" : "no";
|
||||
if (($pstats[14] eq "yes") and ($V_INST{$p} ne $V_REPO{$p})) {
|
||||
$pstats[14] = "diff" }
|
||||
printf STDOUT $outputf, @pstats[@pos];
|
||||
}
|
||||
}
|
||||
@ -349,19 +351,22 @@ sub printf_ports {
|
||||
|
||||
sub fill_hashes_from_cache {
|
||||
open (my $cf,$prtcache) or die "cannot use $prtcache as a cache!\n";
|
||||
my $p; my $deps;
|
||||
my $p; my $parent; my $deps; my $softDeps;
|
||||
my $ignored=<$cf>; # first line only contains the cache format version
|
||||
|
||||
while (1) {
|
||||
$p = <$cf>; last unless defined $p;
|
||||
chomp($p);
|
||||
$ignored = <$cf>; $V_REPO{$p} = <$cf>; chomp($V_REPO{$p});
|
||||
$V_REPO{$p} .= <$cf>; $DESC{$p} = <$cf>;
|
||||
$deps = <$cf>;
|
||||
chomp($deps, $DESC{$p}, $V_REPO{$p});
|
||||
$DEPENDS{$p} = ($deps ne "") ? $deps : " ";
|
||||
chomp($p); $parent = <$cf>; chomp($parent);
|
||||
push @allports, "$parent/$p";
|
||||
$V_REPO{$p} = <$cf>; chomp($V_REPO{$p});
|
||||
$V_REPO{$p} .= "-".<$cf>; $DESC{$p} = <$cf>;
|
||||
$deps = <$cf>; $softDeps = <$cf>;
|
||||
chomp($deps, $softDeps, $DESC{$p}, $V_REPO{$p});
|
||||
$DEPENDS{$p} = $deps;
|
||||
$SOFTDEPS{$p} = $softDeps;
|
||||
$DEPENDS{$p} =~ s/, / /g; $DEPENDS{$p} =~ s/,/ /g;
|
||||
for (my $i=6; $i<13; $i++) { $ignored = <$cf>; }
|
||||
$SOFTDEPS{$p} =~ s/, / /g; $SOFTDEPS{$p} =~ s/,/ /g;
|
||||
for (my $i=7; $i<14; $i++) { $ignored = <$cf>; }
|
||||
}
|
||||
close ($cf);
|
||||
}
|
||||
@ -371,11 +376,13 @@ sub fill_hashes_from_pkgfiles {
|
||||
my $p = (split /\//, $pp)[-1];
|
||||
|
||||
if (! $V_REPO{$p}) { # only populate hashes with the first port found
|
||||
my ($rver, $rrel, $rdesc, $rdeps) = get_pkgfile_fields($pp);
|
||||
my ($rver, $rrel, $rdesc, $rdeps, $rsoftdeps) = get_pkgfile_fields($pp);
|
||||
$V_REPO{$p} = ($rver) ? $rver : "0";
|
||||
$V_REPO{$p} .= ($rrel) ? "-$rrel" : "-1";
|
||||
$DEPENDS{$p} = ($rdeps) ? $rdeps : "";
|
||||
$SOFTDEPS{$p} = ($rsoftdeps) ? $rsoftdeps : "";
|
||||
$DEPENDS{$p} =~ s/, / /g; $DEPENDS{$p} =~ s/,/ /g;
|
||||
$SOFTDEPS{$p} =~ s/, / /g; $SOFTDEPS{$p} =~ s/,/ /g;
|
||||
$DESC{$p} = ($rdesc) ? $rdesc : "";
|
||||
}
|
||||
}
|
||||
@ -383,7 +390,7 @@ sub fill_hashes_from_pkgfiles {
|
||||
|
||||
sub get_pkgfile_fields {
|
||||
my ($descrip, $url, $maintainer, $packager, $Version, $Release)=('','','','','',0,0);
|
||||
my ($readme, $preInstall, $postInstall, $Dependencies)=("no","no","no",'');
|
||||
my ($readme, $preInstall, $postInstall, $Dependencies, $SoftDeps)=("no","no","no",'','');
|
||||
my $portpath = shift; my $Name = (split /\//, $portpath)[-1];
|
||||
my $pkgfile = "$portpath/Pkgfile";
|
||||
|
||||
@ -400,16 +407,18 @@ sub get_pkgfile_fields {
|
||||
elsif (s/^version=(.*)/$1/) { $Version = $_; }
|
||||
elsif (s/^release=(.*)/$1/) { $Release = $_; }
|
||||
elsif (s/^# Depends on:\s*(.*)/$1/) { $Dependencies = $_; }
|
||||
elsif (s/^# (Optional|Nice to have):\s*(.*)/$2/) { $SoftDeps = $_; }
|
||||
elsif (s/^# Packager:\s*(.*)/$1/) { $packager = $_; }
|
||||
elsif (s/^# Maintainer:\s*(.*)/$1/) { $maintainer = $_; }
|
||||
else {}
|
||||
} close(PF);
|
||||
|
||||
$Dependencies =~ s/, / /g; $Dependencies =~ s/,/ /g;
|
||||
$SoftDeps =~ s/, / /g; $SoftDeps =~ s/,/ /g;
|
||||
if (shift) {
|
||||
return $Name, $portpath, $Version, $Release, $descrip, $Dependencies, $url,
|
||||
$packager, $maintainer, $readme, $preInstall, $postInstall;
|
||||
} else { return $Version, $Release, $descrip, $Dependencies; }
|
||||
return $Name, $portpath, $Version, $Release, $descrip, $Dependencies,
|
||||
$SoftDeps, $url, $packager, $maintainer, $readme, $preInstall, $postInstall;
|
||||
} else { return $Version, $Release, $descrip, $Dependencies, $SoftDeps; }
|
||||
}
|
||||
|
||||
sub find_port_by_file { # for now only used to search footprints, but can be generalized
|
||||
@ -612,70 +621,71 @@ sub deporder {
|
||||
# otherwise returns a flattened list, pruned of duplicates.
|
||||
# Recursion does NOT continue beyond a dependency satisfied by an alias.
|
||||
|
||||
my $format=shift; our $indent="0 "; our $height=0; our @seeds = @_;
|
||||
our @ancestry=(); our @outfile=(); our @missing; my %installable; my %seen;
|
||||
my $format=shift; our $indent="0 "; our $height=0;
|
||||
our @ancestry=(); our @outfile=(); our @missing; my %seen;
|
||||
|
||||
foreach my $s (@seeds) {
|
||||
if (find_port_by_name($s,1,0,0)) { $installable{$s} = 1;
|
||||
} else { $installable{$s} = 0;
|
||||
print "$s not found in the ports tree; ignoring.\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $s (grep { $installable{$_}==1 } @seeds) {
|
||||
recurse_deptree($s);
|
||||
}
|
||||
recurse_deptree($odepends{soft},@_);
|
||||
|
||||
sub recurse_deptree {
|
||||
my $s = shift;
|
||||
if (! $V_REPO{$s}) { push @missing, "$s"; return; }
|
||||
my $substitute = who_aliased_to($s);
|
||||
my $note = ($substitute) ? " (provided by $substitute)" : "";
|
||||
push @outfile, (${indent}x(1+$height))."$s$note";
|
||||
my $greedy=shift; my @seeds=@_; my %curdeps; my @optionals;
|
||||
push @missing, grep { (! $V_REPO{$_}) } @seeds;
|
||||
@seeds = grep { ($V_REPO{$_}) } @seeds;
|
||||
|
||||
my $depstr = $DEPENDS{$s} unless ($substitute);
|
||||
if ($depstr) {
|
||||
my @sdeps = split /[ ,]/, $depstr;
|
||||
foreach my $sd (@sdeps) {
|
||||
if (grep /^$sd$/, @ancestry) {
|
||||
print "Warning: cyclic dependency found!\n";
|
||||
print ((join " => ", @ancestry)."$sd\n");
|
||||
return;
|
||||
foreach my $s (@seeds) {
|
||||
my $substitute = who_aliased_to($s);
|
||||
$s = "$substitute (satisfies dependency $s)" if ($substitute);
|
||||
push @outfile, (${indent}x(1+$height))."$s";
|
||||
next if ($substitute);
|
||||
|
||||
%curdeps = map { $_ => 0 } split /[ ,]/, $DEPENDS{$s};
|
||||
# if the user toggles --softdeps, consider only the
|
||||
# optional dependencies that are already installed
|
||||
if ($odepends{soft}*$greedy == 1) {
|
||||
@optionals = grep { ($V_INST{$_}) } split /[ ,]/, $SOFTDEPS{$s};
|
||||
foreach (@optionals) { $curdeps{$_} = 1 }
|
||||
}
|
||||
|
||||
SUCCESSOR: foreach my $sd (keys %curdeps) {
|
||||
if (grep /^$sd$/, @ancestry) {
|
||||
if (($greedy|$curdeps{$sd}) == 1) { next SUCCESSOR;
|
||||
} else {
|
||||
print "Warning: cyclic dependency found!\n";
|
||||
print ((join " => ", @ancestry)." => $sd\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
push (@ancestry,$sd);
|
||||
$height = 1+$#ancestry;
|
||||
recurse_deptree($greedy|$curdeps{$sd},$sd);
|
||||
pop @ancestry;
|
||||
$height = 1+$#ancestry;
|
||||
}
|
||||
push (@ancestry,$sd);
|
||||
$height = 1+$#ancestry;
|
||||
recurse_deptree($sd);
|
||||
pop @ancestry;
|
||||
$height = 1+$#ancestry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($format eq "deptree") {
|
||||
@outfile = grep { s/0 / /g; !m/^\s*$/; } @outfile;
|
||||
} else {
|
||||
@outfile = grep !$seen{$_}++,
|
||||
(grep { s/0 //g; s/ .provided by .*//g; !m/^\s*$/; } sort(@outfile));
|
||||
@outfile = grep { !$seen{$_}++ } (grep
|
||||
{ s/0 //g; s/ .satisfies dependency .*//g; !m/^\s*$/; } sort(@outfile));
|
||||
}
|
||||
return @outfile if (($#missing < 0) or ($format eq "quickdep"));
|
||||
return @outfile, "MISSING", @missing if ($#missing >= 0);
|
||||
}
|
||||
|
||||
sub up_inst { # returns scalar references to five arrays
|
||||
my $type=shift; my @requested=@_; my %EXEMPT; my %WANTED; my %pdirs;
|
||||
my $type=shift; my @requested=@_; my @targets; my %EXEMPT; my %WANTED; my %pdirs;
|
||||
my %builtpkg; my %mkcmd; my %addcmd; my %status; my %logfile; my %pvars;
|
||||
my $PKGMK=$opkg{makecommand}; my $PKGADD=$opkg{addcommand};
|
||||
my $SUDO="/usr/bin/doas"; my $FAKEROOT="/usr/bin/fakeroot";
|
||||
|
||||
# prepend commands with sudo/doas/fakeroot if the effective user id is not root
|
||||
$SUDO = (-x $SUDO) ? $SUDO : "/usr/bin/sudo";
|
||||
$FAKEROOT = (-x $FAKEROOT) ? $FAKEROOT : $SUDO;
|
||||
if ($> != 0) { $PKGADD = "$SUDO $PKGADD"; $PKGMK = "$FAKEROOT $PKGMK"; }
|
||||
|
||||
# resolve all dependencies unless the command was 'grpinst'
|
||||
my @targets=($type eq "grpinst") ? @_ : deporder("quickdep",@_);
|
||||
|
||||
# filter out the invalid ports if deporder did not already do so
|
||||
@targets = grep { ($V_REPO{$_}) } @targets if ($type eq "grpinst");
|
||||
# resolve all dependencies if the command was not 'grpinst',
|
||||
# putting glibc{,-32} at the front of the queue
|
||||
if ($type eq "grpinst") {
|
||||
@targets=grep { ($V_REPO{$_}) } @requested;
|
||||
} else {
|
||||
@targets=grep { !m/^glibc(|-32)$/ } deporder("quickdep", @requested);
|
||||
unshift @targets, grep { m/^glibc(|-32)$/ } @requested;
|
||||
}
|
||||
|
||||
# exempt any locked ports from an update operation
|
||||
%EXEMPT = map { $_ => 1 } @LOCKED;
|
||||
|
Loading…
Reference in New Issue
Block a user