prtsweep.pl: fall back to md5sums if signature file is not found

This commit is contained in:
John McQuah 2023-08-07 08:50:12 -04:00
parent 9ca23cc68d
commit 495ce0457f
2 changed files with 146 additions and 140 deletions

View File

@ -115,8 +115,8 @@ algorithm makes it easy to wash all your locally-curated repositories, in contra
to the algorithm in \fBprtsweep\fP(1) which looks at the sup files used by \fBports\fP(8).
.PP
Another contrast between the two tools is that \fBprtwash\fP sources each Pkgfile to
generate its keep list, whereas \fBprtsweep\fP reads the signatures file. Spawning an
external bash shell for each port should in theory make \fBprtwash\fP slower
generate its keep list, whereas \fBprtsweep\fP reads the SHA256 or MD5 sums from a manifest.
Spawning an external bash shell for each port should in theory make \fBprtwash\fP slower
than \fBprtsweep\fP (which does everything in native perl), but on modern hardware the
difference is basically undetectable.
.PP

View File

@ -24,22 +24,22 @@ parse_args();
print_usage() if ((2*$argports-1)*(1-2*$options{auto}) < 0);
if ($options{auto} == 1) {
my @basedirs = getportdirs();
foreach my $collection (@basedirs) {
print "====> Sweeping port collection $collection\n";
foreach my $port (list_subdirs($collection)) {
do_sweep($port);
}
}
my @basedirs = getportdirs();
foreach my $collection (@basedirs) {
print "====> Sweeping port collection $collection\n";
foreach my $port (list_subdirs($collection)) {
do_sweep($port);
}
}
} else {
foreach my $port (@portdirs) {
do_sweep($port);
}
foreach my $port (@portdirs) {
do_sweep($port);
}
}
######################### subroutines #################################
sub print_usage {
print <<EOT;
print <<EOT;
Usage: prtsweep [OPTION]... [PORTDIRS]...
-a automatic mode, only valid when [PORTDIRS] are omitted
@ -50,157 +50,163 @@ Usage: prtsweep [OPTION]... [PORTDIRS]...
Report bugs on libera.chat #crux-devel
EOT
exit(0);
exit(0);
}
sub parse_args {
foreach my $arg (@ARGV) {
if ($arg eq "-a") {
$options{auto} = 1;
} elsif ($arg eq "-d") {
$options{rmdir} = 1;
} elsif ($arg eq "-n") {
$options{dryrun} = 1;
} elsif ($arg eq "-p") {
$options{pkgtoo} = 1;
} elsif ($arg eq "-q") {
$options{quiet} = 1;
} elsif ($arg eq "--version") {
print $version."\n";
exit 0;
} elsif ((-d "$arg") || # false for symlink to a portdir,
(-f "$arg/.signature")) { # so a second test is needed
push (@portdirs, $arg);
} elsif (-f "$arg") {
print "WARN: $arg is not a port directory or recognized option, ignoring.\n";
} else {
print_usage();
}
}
$argports = @portdirs;
foreach my $arg (@ARGV) {
if ($arg eq "-a") {
$options{auto} = 1;
} elsif ($arg eq "-d") {
$options{rmdir} = 1;
} elsif ($arg eq "-n") {
$options{dryrun} = 1;
} elsif ($arg eq "-p") {
$options{pkgtoo} = 1;
} elsif ($arg eq "-q") {
$options{quiet} = 1;
} elsif ($arg eq "--version") {
print $version."\n";
exit 0;
} elsif ((-d "$arg") || # false for symlink to a portdir,
(-f "$arg/.signature") ||
(-f "$arg/.md5sum")) { # so further tests are needed
push (@portdirs, $arg);
} elsif (-f "$arg") {
print "WARN: $arg is not a port directory or recognized option, ignoring.\n";
} else {
print_usage();
}
}
$argports = @portdirs;
}
sub list_subdirs {
my $path = shift;
my @list;
while ($path =~ s/\/\//\//g) {}
$path =~ s/\/$//;
my $path = shift;
my @list;
while ($path =~ s/\/\//\//g) {}
$path =~ s/\/$//;
opendir(DIR, $path) or return;
foreach my $entry(sort(readdir(DIR))) {
next if ( substr($entry,0,1) eq '.' );
push (@list, "$path/$entry") if ((-d "$path/$entry")
or (-f "$path/$entry/.signature"));
}
closedir(DIR);
return @list;
opendir(DIR, $path) or return;
foreach my $entry(sort(readdir(DIR))) {
next if ( substr($entry,0,1) eq '.' );
push (@list, "$path/$entry") if ((-d "$path/$entry")
or (-f "$path/$entry/.signature"));
}
closedir(DIR);
return @list;
}
sub parse_signature {
my @signed = ("Pkgfile",".footprint",".signature","README","README.md",
"pre-install","post-install",".32bit",".nostrip");
my $sigfile = shift;
open (FILE, $sigfile) or return @signed;
while (<FILE>) {
if (/^SHA256 \(.+\) =.*$/) {
$_ =~ s/^SHA256 \((.+)\) =.*$/$1/;
push (@signed, $_)
}
}
close (FILE);
return @signed ;
sub parse_manifest {
my $sigfile = shift;
my $sigtype = (split /\//, $sigfile)[-1];
my @keeplist = ("Pkgfile",".footprint","README","README.md",
"pre-install","post-install",".32bit",".nostrip");
push (@keeplist,$sigtype);
open (FILE, $sigfile) or return @keeplist;
while (<FILE>) {
if (($sigtype eq ".signature") and (/^SHA256 \((.+)\) =.*$/)) {
push (@keeplist, $1);
} elsif ($sigtype eq ".md5sum") {
my ($m, $f) = split /\s+/, $_;
push (@keeplist, $f);
}
}
close (FILE);
return @keeplist ;
}
sub sweep {
my $port = shift;
while ($port =~ s/\/\//\//g) {}
$port =~ s/\/$//;
my @path = split /\//, $port;
my $port = shift; my $sigtype = shift;
while ($port =~ s/\/\//\//g) {}
$port =~ s/\/$//;
my @path = split /\//, $port;
print "=======> $port\n" unless $options{quiet}==1;
my @wanted = parse_signature ("$port/.signature");
my $builtpkg=$path[-1].'#.*pkg\.tar\.(bz2|gz|lz|xz)$';
$builtpkg =~ s/\+/\\\+/; # plus sign in filenames interferes with regex search
print "=======> $port\n" unless $options{quiet}==1;
my %wanted = map { $_ => 1 } parse_manifest ("$port/.$sigtype");
my $builtpkg=$path[-1].'#.*pkg\.tar\.(bz2|gz|lz|xz)$';
$builtpkg =~ s/\+/\\\+/; # plus sign in filenames interferes with regex search
opendir (DIR, $port) or return;
foreach my $f (sort(readdir(DIR))) {
next if ( $f eq '.' or $f eq '..' );
$f =~ s/\+/\\\+/;
if ((grep /$f/, @wanted) >= 1 or
($f =~ /$builtpkg/)*($options{pkgtoo}==0)) {
print "... keeping file $port/$f.\n" unless $options{quiet} == 1;
} else {
remove ("$port/$f");
}
}
closedir (DIR);
opendir (DIR, $port) or return;
foreach my $f (sort(readdir(DIR))) {
next if ( $f eq '.' or $f eq '..' );
if (($wanted{$f}) or
($f =~ /$builtpkg/)*($options{pkgtoo}==0)) {
print "... keeping file $port/$f.\n" unless $options{quiet} == 1;
} else {
remove ("$port/$f");
}
}
closedir (DIR);
}
sub remove {
my $path=shift;
my $append = ($options{dryrun}==1) ? "(dry run)\n" : "\n";
if (-d $path) {
print "+ removing directory $path $append";
rmtree ($path,0,1) if ($options{dryrun}==0);
} else {
print "+ removing file $path $append";
if ($options{dryrun}==0) { unlink "$path" or return; }
}
my $path=shift;
my $append = ($options{dryrun}==1) ? "(dry run)\n" : "\n";
if (-d $path) {
print "+ removing directory $path $append";
rmtree ($path,0,1) if ($options{dryrun}==0);
} else {
print "+ removing file $path $append";
if ($options{dryrun}==0) { unlink "$path" or return; }
}
}
sub do_sweep {
# argument either a real directory (not symlink) or has a signature;
# this subroutine determines which condition was satisfied.
my $port = shift; my $nf = 0;
if (! -f "$port/.signature") {
opendir (PORTDIR,$port) or return;
foreach my $f (readdir PORTDIR) {
next if ($f eq '.' or $f eq '..');
$nf += 1;
}
closedir (PORTDIR);
print "WARN: $port/.signature not found, invalid port directory.";
rm_emptydir($port,$nf);
} else {
sweep($port);
}
# argument either a real directory (not symlink) or has a manifest;
# this subroutine determines which condition was satisfied.
my $port = shift; my $nf = 0;
if ((! -f "$port/.signature") and (! -f "$port/.md5sum")) {
opendir (PORTDIR,$port) or return;
foreach my $f (readdir PORTDIR) {
next if ($f eq '.' or $f eq '..');
$nf += 1;
}
closedir (PORTDIR);
print "WARN: no signature or md5sum found in directory $port, skipping.\n";
rm_emptydir($port,$nf);
} elsif (-f "$port/.signature") {
sweep($port,"signature");
} else {
sweep($port,"md5sum");
}
}
sub rm_emptydir {
my $port = shift; my $nf = shift;
my $msg = ($options{rmdir}==1) ? "\n":
"\n Use -d to remove empty directories.\n";
my $modal = ($options{dryrun}==0) ? "" : "would be";
my $post = ($nf == 0) ? " Empty directory $port $modal deleted.\n" :
" Cannot remove $port: directory not empty\n";
$msg = ($options{rmdir}==1) ? "$msg $post" : $msg ;
print $msg;
rmdir ($port) if (($nf == 0) and ($options{dryrun} == 0));
my $port = shift; my $nf = shift;
my $msg = ($options{rmdir}==1) ? "\n":
"\n Use -d to remove empty directories.\n";
my $modal = ($options{dryrun}==0) ? "" : "would be";
my $post = ($nf == 0) ? " Empty directory $port $modal deleted.\n" :
" Cannot remove $port: directory not empty\n";
$msg = ($options{rmdir}==1) ? "$msg $post" : $msg ;
print $msg;
rmdir ($port) if (($nf == 0) and ($options{dryrun} == 0));
}
sub getportdirs {
my $collection;
my @basedirs;
my $portetc = "/etc/ports/";
opendir (PORTS_DEFS,$portetc) or die "cannot open $portetc for reading";
foreach (readdir PORTS_DEFS) {
next if ($_ eq '.' or $_ eq '..');
if (/.*(rsync|httpup)$/) {
open SYNC, $portetc.$_ or die "cannot open $portetc.$_";
while (<SYNC>) {
$collection=$2 if /^(destination|ROOT_DIR)=(.+)$/;
}
close SYNC;
push (@basedirs , $collection);
} elsif (/.*git$/) {
open SYNC, $portetc.$_ or die "cannot open $portetc.$_";
while (<SYNC>) {
$collection="/usr/ports/$1" if /^NAME=(.+)$/;
}
close SYNC;
push (@basedirs , $collection);
} else {}
}
closedir PORTS_DEFS;
return @basedirs ;
my $collection;
my @basedirs;
my $portetc = "/etc/ports/";
opendir (PORTS_DEFS,$portetc) or die "cannot open $portetc for reading";
foreach (readdir PORTS_DEFS) {
next if ($_ eq '.' or $_ eq '..');
if (/.*(rsync|httpup)$/) {
open SYNC, $portetc.$_ or die "cannot open $portetc.$_";
while (<SYNC>) {
$collection=$2 if /^(destination|ROOT_DIR)=(.+)$/;
}
close SYNC;
push (@basedirs , $collection);
} elsif (/.*git$/) {
open SYNC, $portetc.$_ or die "cannot open $portetc.$_";
while (<SYNC>) {
$collection="/usr/ports/$1" if /^NAME=(.+)$/;
}
close SYNC;
push (@basedirs , $collection);
} else {}
}
closedir PORTS_DEFS;
return @basedirs ;
}