Documentation/scripts/prtsweep.pl

208 lines
5.1 KiB
Perl
Raw Normal View History

2022-05-26 17:11:09 -04:00
#!/usr/bin/perl -w
########################################################################
#
# prtsweep
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This is a script for removing rubbish from a CRUX port tree.
# Distributed under the terms of the GPL license.
#
# Partial Changelog:
# 1.2.1 - First rewrite in perl
# 1.2 - Added support for renamed sources
# 1.1.3 - Replace .md5sum with .signature in the KEEP_FILES list
2022-05-26 17:11:09 -04:00
#
########################################################################
use strict;
use Cwd qw(cwd getcwd);
use File::Path;
our $version = "1.2.1";
our %options = ( auto => 0, dryrun => 0, rmdir => 0, pkgtoo => 0, quiet => 0 );
our @portdirs;
our $argports;
sub print_usage {
print <<EOT;
Usage: prtsweep [OPTION]... [PORTDIRS]...
-a automatic mode, only valid when [PORTDIRS] are omitted
-d remove directories of dropped ports (no Pkgfile present)
-n dry-run, don't actually delete anything
-p delete any built packages too
-q quiet mode
Report bugs on libera.chat #crux-devel
2022-05-26 17:11:09 -04:00
EOT
exit(0);
}
sub parse_args {
foreach my $arg (@ARGV) {
if ($arg =~ /^-a$/) {
$options{auto} = 1;
} elsif ($arg =~ /^-d$/) {
$options{rmdir} = 1;
} elsif ($arg =~ /^-n$/) {
$options{dryrun} = 1;
} elsif ($arg =~ /^-p$/) {
$options{pkgtoo} = 1;
} elsif ($arg =~ /^-q$/) {
$options{quiet} = 1;
} elsif ($arg =~ /^--version$/) {
print $version."\n";
exit 0;
} elsif (-d "$arg") {
push (@portdirs, $arg);
} else {
print_usage();
}
}
$argports = @portdirs;
}
sub list_subdirs {
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";
2022-05-26 17:11:09 -04:00
}
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;
2022-05-26 17:11:09 -04:00
while (<FILE>) {
if (/^SHA256 \(.+\) =.*$/) {
$_ =~ s/^SHA256 \((.+)\) =.*$/$1/;
push (@signed, $_)
}
}
close (FILE);
return @signed ;
}
sub rm_emptydir {
my $port = shift; my $nf = shift;
my $msg = ($options{rmdir}==1) ? "\n":
" use -d to remove empty directories.\n";
my $modal = ($options{dryrun}==1) ? "would be" : "";
$msg = ($nf == 0) ? "$msg $port: empty directory $modal deleted.\n" :
"$msg cannot remove $port: directory not empty\n";
print $msg;
rmdir ($port) if (($nf == 0) and ($options{dryrun} == 0));
2022-05-26 17:11:09 -04:00
}
sub sweep {
my $port = 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=($options{pkgtoo} != 1) ? $path[-1].'#.*pkg\.tar.*' :
2022-05-26 17:11:09 -04:00
'ReallyLongStringThatWouldNeverMatchAnyBuiltPackage';
$builtpkg =~ s/\+/\\\+/;
opendir (DIR, $port) or return;
foreach my $f (sort(readdir(DIR))) {
next if ( $f eq "." or $f eq ".." );
$f =~ s/\+/\\\+/; # plus sign in filenames interferes with regex search
if ((grep /$f/, @wanted) >= 1 or ($f =~ /$builtpkg/)) {
print "... keeping file $port/$f.\n" unless $options{quiet} == 1;
} else {
my $ft=remove_notify("$port/$f");
remove_forreal("$port/$f", $ft) if $options{dryrun} == 0;
}
}
closedir (DIR);
}
sub remove_notify {
my $path=shift;
my $type = (-d $path) ? "directory" : "file";
my $append = ($options{dryrun}==1) ? "(dry run)\n" : "\n";
print "+ removing $type $path $append";
return $type;
}
sub remove_forreal {
my $path = shift; my $type = shift;
2022-05-26 17:11:09 -04:00
if ($type eq "file") {
unlink "$path" or return;
} else {
rmtree ($path,0,1);
}
}
sub do_sweep {
my $port = shift; my $nf = 0;
2022-05-26 17:11:09 -04:00
if (! -f "$port/.signature") {
opendir (PORTDIR,$port) or die "cannot open $port for reading\n";
foreach my $f (readdir PORTDIR) {
next if ($f eq '.' or $f eq '..');
$nf += 1;
}
closedir (PORTDIR);
print "no signature file, $port does not define a valid port.";
rm_emptydir($port,$nf);
} else {
sweep($port);
2022-05-26 17:11:09 -04:00
}
}
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 ;
}
# main
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);
2022-05-26 17:11:09 -04:00
}
}
} else {
foreach my $port (@portdirs) {
do_sweep($port);
2022-05-26 17:11:09 -04:00
}
}