1 #!/home/andreas/src/installed-perls/v5.16.0/4e6d/bin/perl
21 my $optpod = <<'=back';
23 =item B<--focus=s> Default: tar
25 Valid values: C<tar> or C<dir>. RTFS.
31 =item B<--keepresults=i> Default: 4
33 Number of result-directories or result-tarballs to never delete.
35 =item B<--minage=f> Default: 690
37 Minimum age in days of the target directory
38 (measured with C<-M>).
40 =item B<--noninteractive|noni>
42 Don't ask, just apply the default answer.
44 =item B<--untildf=i> Default: 48000000
46 Run extinction until available blocks reported
47 by df is above this value.
51 The interactive question is normally answered with no as the default.
52 With --yes the default becomes yes.
58 What we look for is an old and big and outdated directory. For the
59 arbitrary current thresholds RTFS. When we have listed one, we exit.
60 We show it with age, size and neighbors of the same Distname.
64 The files in C<workdir/solved/> are removed too (which is good) but
65 they were not removed before 2016-03-31, so we should bulk remove the
66 left overs separately some day; this affects files like the output of:
68 ls -lt /home/andreas/data/cnntp-solver-2009/workdir/solved/Any-Moose-0.*
69 ls -lt /home/andreas/data/cnntp-solver-2009/workdir/solved/package-watchdog-*
71 Note that package-watchdog-0.07.slv is the oldest(2009) and
72 package-watchdog-0.04.yml is the newest (2013). Why? Because the
73 package has ceased to exist.
79 use lib
"$FindBin::Bin/../lib";
85 use File
::Basename
qw(dirname);
86 use File
::Path
qw(mkpath rmtree);
91 use Hash
::Util
qw(lock_keys);
94 my $redis = Redis
->new(reconnect
=> 120, every
=> 1000);
99 use CPAN
::DistnameInfo
;
100 use List
::AllUtils
qw(reduce);
103 use lib
"$FindBin::Bin/../CPAN-Blame/lib";
104 use CPAN
::Blame
::Config
::Cnntp
;
105 use CPAN
::DistnameInfo
;
106 use Term
::Prompt
qw(prompt);
108 use Filesys
::Df
qw(df);
109 use Time
::HiRes
qw(sleep);
111 my $ua = LWP
::UserAgent
->new();
112 $ua->default_header("Accept-Encoding", "gzip");
113 my $jsonxs = JSON
::XS
->new->indent(0);
115 my @opt = $optpod =~ /B<--(\S+)>/g;
117 lock_keys
%Opt, map { /([^=|!]+)/ } @opt;
124 for my $opt (qw(focus untildf minage keepresults)) {
125 next if defined $Opt{$opt};
126 LINE
: for my $line (split /\n/, $optpod) {
127 if ($line =~ /--\Q$opt\E=.+?Default: (.+)/) {
136 warn "df bavail: $df->{bavail}\n";
142 for my $ext (qw(slv.LCK yml slvdv.gz slv slvdv)) {
143 my $workdirfile = "/home/andreas/data/cnntp-solver-2009/workdir/solved/$distv.$ext";
144 if (-e
$workdirfile) {
145 warn "Deleting $workdirfile\n";
146 unlink $workdirfile or die "Could not unlink '$workdirfile': $!";
149 for my $zs (qw(analysis:distv:calctimestamp)) {
150 warn "zrem-redis: redis-cli zrem $zs $distv\n";
152 $redis->zrem($zs, $distv);
156 sub treat_dir
($$$$) {
157 my($parent, $distv, $dist, $v) = @_;
158 my $query = sprintf "http://fastapi.metacpan.org/v1/release/_search?q=distribution:%s&fields=name,date,status,version,author&size=400", $dist;
160 my $resp = $ua->get($query);
162 my $jsontxt = $resp->decoded_content;
163 my $j = eval { $jsonxs->decode($jsontxt); };
164 return if ! $j or $@
;
165 my $hits = $j->{hits
}{hits
};
166 my($releasedate) = map { $_->{fields
}{date
} } grep { $_->{fields
}{name
} eq $distv } @
$hits;
167 unless ($releasedate) {
168 warn "Did not find own releasedate for $distv";
171 my $cpanversion = reduce
{
172 CPAN
::Version
->vgt($a,$b) ?
$a : $b
173 } map { $_->{fields
}{version
} } grep { $_->{fields
}{date
} ge $releasedate } @
$hits;
174 if (CPAN
::Version
->vgt($cpanversion, $v)) {
175 my $default_answer = $Opt{yes
} ?
"y" : "n";
177 if ($Opt{noninteractive
}) {
178 $answer = $default_answer;
180 $answer = lc prompt
"x",
181 "Shall I delete $distv (cpanversion=$cpanversion) and related workdir files? (y/n)", "", 'y';
183 if ($answer eq "y") {
184 rmtree
"$parent/$distv";
190 my $root = $CPAN::Blame
::Config
::Cnntp
::Config
->{ctgetreports_dir
};
191 my $bavail = show_df
;
192 my $outer_purged_something = 0;
193 LOOP
: while ($bavail < $Opt{untildf
}) {
194 my $purged_something = 0;
195 opendir my $dh, $root or die "Could not open '$root': $!";
196 OUTER
: for my $letter (readdir $dh) {
197 next unless $letter =~ /^[A-Za-z]$/;
198 opendir my $dh2, "$root/$letter" or die "Could not open '$root/$letter': $!";
200 INNER
: for my $distdir (readdir $dh2) {
201 next if $distdir eq "." or $distdir eq "..";
202 my $tdir_or_tar = "$root/$letter/$distdir";
203 my($distv, $isdir, $want_treat_dir);
205 } elsif (-d
$tdir_or_tar) {
206 warn "looking at directory $tdir_or_tar";
207 if ($Opt{focus
} eq "tar") {
209 } elsif ($Opt{focus
} eq "dir") {
210 if (-f
"$tdir_or_tar.tar") {
211 warn "skipping $tdir_or_tar because tarball also found";
216 die "Illegal focus '$Opt{focus}'";
220 } elsif ($distdir =~ /(.+)\.tar$/) {
227 my $d = CPAN
::DistnameInfo
->new("FOO/$distv.tgz");
230 if ($want_treat_dir) {
231 treat_dir
("$root/$letter", $distdir, $dist, $v);
236 my $a = $odist{$dist}{$distv} ||= [];
242 M
=> -M
$tdir_or_tar,
249 for my $d (sort {scalar keys %{$odist{$b}} <=> scalar keys %{$odist{$a}}} keys %odist) {
251 next unless scalar keys %$l > $Opt{keepresults
};
253 my $oldest = reduce
{ $a > $b ?
$a : $b } map { $_->{M
} } map { @
{$l->{$_}} } keys %$l;
254 next unless $oldest >= $Opt{minage
};
257 DISTV
: for my $distv (keys %$l) {
258 for my $i (0..$#{$l->{$distv}}) {
259 if ($l->{$distv}[$i]{M
} == $oldest) {
260 $abs_of_oldest = $l->{$distv}[$i]{abs};
265 open my $duh, "-|", du
=> "-s", $abs_of_oldest or die "Could not fork for 'du -s $abs_of_oldest': $!";
266 my($duline) = <$duh>;
267 my($du_of_oldest) = split " ", $duline;
269 # next unless $du_of_oldest > 7000; # arbitrary
270 my $ll = []; # = [ map { @{$l->{$_}} } sort { $l->{$b}->{M} <=> $l->{$a}->{M} } keys %$l ];
271 for my $distv (keys %$l) {
272 for my $i (0..$#{$l->{$distv}}) {
273 push @
$ll, $l->{$distv}[$i];
276 my $lll = [ sort { $b->{M
} <=> $a->{M
} } @
$ll ];
277 $lll->[0]{du
} = $du_of_oldest;
278 print YAML
::XS
::Dump
$lll;
279 my $default_answer = $Opt{yes
} ?
"y" : "n";
281 if ($Opt{noninteractive
}) {
282 $answer = $default_answer;
284 $answer = lc prompt
"x",
285 "Shall I delete $lll->[0]{abs} (Mtime=$lll->[0]{M}) and related workdir files? (y/n)", "", $default_answer;
287 if ($answer eq "y") {
288 warn "Deleting $lll->[0]{abs}\n";
289 rmtree
$lll->[0]{abs};
290 my $distv = $lll->[0]{distv
};
293 $purged_something = 1;
294 $outer_purged_something = 1;
296 warn "Nothing deleted\n";
302 unless ($purged_something) {
303 my $else = $outer_purged_something ?
" else" : "";
304 die "Nothing$else found to delete, giving up";
311 # cperl-indent-level: 4