clean-old-distfiles 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #! /usr/bin/perl
  2. # ex:ts=8 sw=4:
  3. # $OpenBSD: clean-old-distfiles,v 1.7 2016/01/24 20:26:56 espie Exp $
  4. #
  5. # Copyright (c) 2012 Marc Espie <espie@openbsd.org>
  6. #
  7. # Permission to use, copy, modify, and distribute this software for any
  8. # purpose with or without fee is hereby granted, provided that the above
  9. # copyright notice and this permission notice appear in all copies.
  10. #
  11. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. use strict;
  19. use warnings;
  20. use feature qw(say);
  21. use OpenBSD::Getopt;
  22. use OpenBSD::md5;
  23. use File::Basename;
  24. sub usage
  25. {
  26. my $err = shift;
  27. my $prog = $0;
  28. $prog =~ s/.*\///;
  29. $err =~ s/\sat.*//s;
  30. say STDERR "$prog: $err";
  31. say STDERR "Usage: $prog [-nv] [-e except] [-h history] [cutdate]";
  32. exit 1;
  33. }
  34. our ($opt_v, $opt_n, $opt_e, $opt_h);
  35. eval { getopts('e:h:vn'); };
  36. if ($@) {
  37. usage($@);
  38. }
  39. if (@ARGV > 1) {
  40. usage("too many arguments");
  41. }
  42. if ($opt_h) {
  43. $opt_n = 1;
  44. $opt_v = 1;
  45. }
  46. sub really_remove
  47. {
  48. my $file = shift;
  49. say "rm $file" if $opt_v;
  50. return if $opt_n;
  51. if (unlink $file) {
  52. my $dirname = $file;
  53. do {
  54. $dirname = File::Basename::dirname $dirname;
  55. } while (rmdir $dirname);
  56. } else {
  57. say STDERR "Couldn't remove $file: $!";
  58. }
  59. }
  60. sub remove_file
  61. {
  62. my ($file, $sha) = @_;
  63. # let's do i-node caching to avoid doing the same file twice.
  64. my $basename = $file;
  65. my $inode;
  66. $basename =~ s/^.*\///; # remove directory
  67. $sha =~ m/(..)/;
  68. my $link = "by_cipher/sha256/$1/$sha/$basename";
  69. if (-f $link) {
  70. $inode = (stat _)[1];
  71. really_remove($link);
  72. }
  73. if (-f $file) {
  74. my $inode2 = (stat _)[1];
  75. if (defined $inode && $inode2 == $inode) {
  76. really_remove($file);
  77. } else {
  78. my $ck = OpenBSD::sha->new($file);
  79. if ($ck->stringize eq $sha) {
  80. really_remove($file);
  81. } else {
  82. say STDERR "SHA256 mismatch on $file: ",
  83. $ck->stringize, " vs $sha";
  84. }
  85. }
  86. }
  87. }
  88. my $cutdate = $ARGV[0];
  89. my $PORTSDIR = $ENV{PORTSDIR} // '/usr/ports';
  90. my $DISTDIR = $ENV{DISTDIR} // "$PORTSDIR/distfiles";
  91. chdir($DISTDIR) or die "Can't chdir to $DISTDIR";
  92. my $history = $opt_h ? $opt_h : 'history';
  93. open my $fh, '<', $history or die "No $history to prune";
  94. my $fh2;
  95. unless ($opt_n) {
  96. open $fh2, '>', "history.new" or die "Can't write new history";
  97. }
  98. my $except = {};
  99. if ($opt_e) {
  100. open(my $e, '<', $opt_e) or die "Can't read exception file $opt_e: $!";
  101. while (<$e>) {
  102. chomp;
  103. $except->{$_} = 1;
  104. }
  105. close $e;
  106. }
  107. while (<$fh>) {
  108. my ($ts, $file, $sha);
  109. if (m/^(\d+)\s+SHA256\s*\((.*)\) \= (.*)$/) {
  110. ($ts, $file, $sha) = ($1, $2, $3);
  111. } else {
  112. die "Bad history line $_";
  113. }
  114. if ($except->{$file} || (defined $cutdate && $ts > $cutdate)) {
  115. if ($fh2) {
  116. print $fh2 $_;
  117. }
  118. } else {
  119. remove_file($file, $sha);
  120. }
  121. }
  122. close $fh;
  123. if ($fh2) {
  124. close $fh2;
  125. unlink('history');
  126. rename('history.new', 'history');
  127. }