1 | #!/usr/bin/perl |
---|
2 | |
---|
3 | use strict; |
---|
4 | |
---|
5 | # -------------------------------------------------------------------------------- |
---|
6 | |
---|
7 | sub getModtimeAndSize($) { |
---|
8 | my ($file_or_dir) = @_; |
---|
9 | if (-f $file_or_dir or -d $file_or_dir) { |
---|
10 | my @st = stat($file_or_dir); |
---|
11 | if (not @st) { die "can't stat '$file_or_dir' ($!)"; } |
---|
12 | return ($st[9],$st[7]); # (stamp,size) |
---|
13 | } |
---|
14 | return (0,0); # does not exist -> use (epoch,zerosize) |
---|
15 | } |
---|
16 | |
---|
17 | sub getAgeAndSize($) { |
---|
18 | my ($file_or_dir) = @_; |
---|
19 | my ($mod,$size) = getModtimeAndSize($file_or_dir); |
---|
20 | return (time-$mod,$size); |
---|
21 | } |
---|
22 | |
---|
23 | # -------------------------------------------------------------------------------- |
---|
24 | |
---|
25 | sub scanPatches($$\@) { |
---|
26 | my ($patchDir,$mask,$patch_r) = @_; |
---|
27 | my $reg = qr/$mask/; |
---|
28 | opendir(DIR,$patchDir) || die "can't read directory '$patchDir' (Reason: $!)"; |
---|
29 | foreach (readdir(DIR)) { if ($_ =~ $reg) { push @$patch_r, $_; } } |
---|
30 | closedir(DIR); |
---|
31 | } |
---|
32 | |
---|
33 | sub patchesDiffer($$$) { |
---|
34 | my ($patchDir,$patch,$otherpatch) = @_; |
---|
35 | my $diff = `diff $patchDir/$patch $patchDir/$otherpatch | wc -l`; |
---|
36 | return ($diff>0); |
---|
37 | } |
---|
38 | |
---|
39 | sub getOldDuplicates($\@\%\%) { |
---|
40 | my ($patchDir,$patch_r,$age_r,$size_r) = @_; |
---|
41 | my @oldDups = (); |
---|
42 | |
---|
43 | my %size2patch = (); |
---|
44 | foreach my $patch (@$patch_r) { |
---|
45 | my $size = $$size_r{$patch}; |
---|
46 | my $otherpatch = $size2patch{$size}; |
---|
47 | if (defined $otherpatch) { # got another patch with same size |
---|
48 | my $diff = patchesDiffer($patchDir,$patch,$otherpatch); |
---|
49 | |
---|
50 | if ($diff) { |
---|
51 | } |
---|
52 | else { # no diff -> removed older |
---|
53 | if ($$age_r{$otherpatch} > $$age_r{$patch}) { |
---|
54 | push @oldDups, $otherpatch; |
---|
55 | $size2patch{$size} = $patch; |
---|
56 | } |
---|
57 | else { |
---|
58 | push @oldDups, $patch; |
---|
59 | } |
---|
60 | } |
---|
61 | } |
---|
62 | else { |
---|
63 | $size2patch{$size} = $patch; |
---|
64 | } |
---|
65 | } |
---|
66 | return @oldDups; |
---|
67 | } |
---|
68 | |
---|
69 | sub readableSize($) { |
---|
70 | my ($size) = @_; |
---|
71 | if ($size<1024) { $size.'b'; } |
---|
72 | else { |
---|
73 | $size = int($size/1024); |
---|
74 | if ($size<1024) { $size.'k'; } |
---|
75 | else { |
---|
76 | $size = int($size/1024); |
---|
77 | if ($size<1024) { $size.'M'; } |
---|
78 | else { |
---|
79 | $size = int($size/1024); |
---|
80 | $size.'G'; |
---|
81 | } |
---|
82 | } |
---|
83 | } |
---|
84 | } |
---|
85 | |
---|
86 | sub countAndSize($$$) { |
---|
87 | my ($name,$count,$size) = @_; |
---|
88 | return $count.' '.$name.' patches ('.readableSize($size).')'; |
---|
89 | } |
---|
90 | |
---|
91 | sub main() { |
---|
92 | my $args = scalar(@ARGV); |
---|
93 | if ($args!=3) { |
---|
94 | print "Usage: arb_cleanup_patches.sh name hours minkeep\n"; |
---|
95 | print " deletes all patches matching 'name_*.patch' if\n"; |
---|
96 | print " - the date-stamp created by arb_create_patch.sh is at end of name (ie. patch was not renamed manually),\n"; |
---|
97 | print " - they are older than 'hours' and\n"; |
---|
98 | print " - at least 'minkeep' patches remain present.\n"; |
---|
99 | die "missing arguments"; |
---|
100 | } |
---|
101 | |
---|
102 | my $mask = $ARGV[0].'.*_[0-9]{8}_[0-9]{6}\.patch'; |
---|
103 | my $olderThanHours = $ARGV[1]; |
---|
104 | my $minKeep = $ARGV[2]; |
---|
105 | |
---|
106 | my $ARBHOME = $ENV{ARBHOME}; |
---|
107 | if (not defined $ARBHOME) { die "environment variable 'ARBHOME' is not defined"; } |
---|
108 | |
---|
109 | my $patchDir = $ARBHOME.'/patches.arb'; |
---|
110 | if (not -d $patchDir) { |
---|
111 | print "Directory '$patchDir' does not exist (no need to clean up)\n"; |
---|
112 | } |
---|
113 | else { |
---|
114 | my @patch = (); |
---|
115 | scanPatches($patchDir,$mask,@patch); |
---|
116 | |
---|
117 | # print "Matching patches=".scalar(@patch)."\n"; |
---|
118 | |
---|
119 | my %age = (); |
---|
120 | my %size = (); |
---|
121 | foreach (@patch) { ($age{$_},$size{$_}) = getAgeAndSize($patchDir.'/'.$_); } |
---|
122 | |
---|
123 | my %unlink_patch = (); # key=patchname, value=why unlink |
---|
124 | { |
---|
125 | my @oldDups = getOldDuplicates($patchDir,@patch,%age,%size); |
---|
126 | foreach (@oldDups) { $unlink_patch{$_} = 'duplicate'; } |
---|
127 | } |
---|
128 | |
---|
129 | @patch = sort { $age{$a} <=> $age{$b}; } @patch; |
---|
130 | |
---|
131 | my $olderThanSeconds = $olderThanHours*60*60; |
---|
132 | my $patchCount = scalar(@patch); |
---|
133 | |
---|
134 | for (my $i=$minKeep; $i<$patchCount; $i++) { |
---|
135 | my $patch = $patch[$i]; |
---|
136 | if ($age{$patch}>$olderThanSeconds) { $unlink_patch{$patch} = 'old'; } |
---|
137 | } |
---|
138 | |
---|
139 | my $all_size = 0; |
---|
140 | my $unlinked_size = 0; |
---|
141 | |
---|
142 | foreach (@patch) { $all_size += $size{$_}; } |
---|
143 | |
---|
144 | foreach (sort keys %unlink_patch) { |
---|
145 | my $fullPatch = $patchDir.'/'.$_; |
---|
146 | unlink($fullPatch) || die "Failed to unlink '$fullPatch' (Reason: $!)"; |
---|
147 | print "- unlinked ".$unlink_patch{$_}." '$_'\n"; |
---|
148 | $unlinked_size += $size{$_}; |
---|
149 | } |
---|
150 | |
---|
151 | my $summary = ''; |
---|
152 | { |
---|
153 | my $unlinked_patches = scalar(keys %unlink_patch); |
---|
154 | my $all_patches = scalar(@patch); |
---|
155 | |
---|
156 | if ($unlinked_patches>0) { |
---|
157 | my $left_patches = $all_patches - $unlinked_patches; |
---|
158 | my $left_size = $all_size - $unlinked_size; |
---|
159 | |
---|
160 | $summary .= countAndSize('removed',$unlinked_patches,$unlinked_size); |
---|
161 | $summary .= ' '.countAndSize('kept',$left_patches,$left_size); |
---|
162 | } |
---|
163 | else { |
---|
164 | $summary .= countAndSize('existing',$all_patches,$all_size); |
---|
165 | } |
---|
166 | } |
---|
167 | print $summary."\n"; |
---|
168 | } |
---|
169 | } |
---|
170 | |
---|
171 | eval { main(); }; |
---|
172 | if ($@) { die "arb_cleanup_patches.pl: Error: $@\n"; } |
---|