From e5c25ef7725d0e9535016e4d43c7894ada60f9e7 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 12:44:31 -0500 Subject: [PATCH 01/25] Replace unnecessary 'use' with 'require' --- lib/Directory/Simplify/Instruction/Generator.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index d2bab1b..4f6c2ac 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -4,7 +4,7 @@ use strict; use warnings; use overload '""' => 'as_string'; use File::Basename qw/ dirname /; -use File::Compare qw/ compare /; +require File::Compare; # :squash-remove-start: require Directory::Simplify::Instruction::CopyTimestamp; From 5c6f506ed95bb44773cd8ebbe09f55324123aa9f Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 12:48:07 -0500 Subject: [PATCH 02/25] Refactor 'oldest_mtime' to be static --- lib/Directory/Simplify/Instruction/Generator.pm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index 4f6c2ac..fdbd1d8 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -87,11 +87,12 @@ sub _entries_are_hard_linkable { return 0; } -sub oldest_mtime { - my $self = shift; - return sort { +sub _oldest_mtime { + my @entries = @_; + my @sorted = sort { $a->{mtime} <=> $b->{mtime} - } @_; + } @entries; + return @sorted; } sub more_linked { @@ -149,7 +150,7 @@ sub instructions { foreach my $bucket ($self->buckets) { # of the bucket, find the oldest timestamp - my ($oldest_entry) = $self->oldest_mtime(@{$bucket}); + my ($oldest_entry) = _oldest_mtime(@{$bucket}); # of the bucket, find the file most embedded in the file system my @to_link = $self->more_linked(@{$bucket}); From 02f97c2a9036b803eb9ab32a69526ac0549f76dd Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 13:29:55 -0500 Subject: [PATCH 03/25] Refactor 'more_linked' - Make method static. - Don't call dirname() in sort block. Relegate this to *::File. This carries with it a slight performance boost; calculate dirname of file only once upon instantiation, instead of (N log N) * 2 times. - Move determination of read-only entries higher. This carries with it a slight performance boost as well, no longer redundantly testing directory write-ability N log N times (reduced to N times), and no longer requires memory to keep track of warnings issued. --- lib/Directory/Simplify/File.pm | 2 ++ .../Simplify/Instruction/Generator.pm | 33 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/Directory/Simplify/File.pm b/lib/Directory/Simplify/File.pm index 6591751..d794097 100644 --- a/lib/Directory/Simplify/File.pm +++ b/lib/Directory/Simplify/File.pm @@ -3,6 +3,7 @@ package Directory::Simplify::File; use strict; use warnings; require Cwd; +use File::Basename qw/ dirname /; sub new { my $class = shift; @@ -11,6 +12,7 @@ sub new { rel_name => $rel_name, name => Cwd::abs_path($rel_name), }, $class; + $self->{dirname} = dirname($self->{name}); (@{$self}{qw/ dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks /}) = lstat $self->{name}; diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index fdbd1d8..9fe7571 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -3,7 +3,6 @@ package Directory::Simplify::Instruction::Generator; use strict; use warnings; use overload '""' => 'as_string'; -use File::Basename qw/ dirname /; require File::Compare; # :squash-remove-start: @@ -95,19 +94,12 @@ sub _oldest_mtime { return @sorted; } -sub more_linked { - my $self = shift; - my %warned; - return sort { - if (! -w &dirname($a->{name})) { - warn "Warning: $a->{name} not able to be unlinked!" unless $warned{$a->{name}}++; - return 1; # favor a -> front - } elsif (! -w &dirname($b->{name})) { - warn "Warning: $b->{name} not able to be unlinked!" unless $warned{$b->{name}}++; - return -1; # favor b -> front - } +sub _more_linked { + my @entries = @_; + my @sorted = sort { $b->{nlink} <=> $a->{nlink} - } @_; + } @entries; + return @sorted; } sub _entries_are_already_hard_linked { @@ -149,11 +141,20 @@ sub instructions { my @inst; foreach my $bucket ($self->buckets) { - # of the bucket, find the oldest timestamp + # Of the bucket, find the oldest timestamp, regardless of read-only my ($oldest_entry) = _oldest_mtime(@{$bucket}); - # of the bucket, find the file most embedded in the file system - my @to_link = $self->more_linked(@{$bucket}); + # Limit link/unlink operations to files in non-readonly directories + my @non_readonly; + foreach my $entry (@{$bucket}) { + unless (-w $entry->{dirname}) { + warn "Warning: $entry->{name} not able to be unlinked!"; + } + push @non_readonly, $entry; + } + + # Of the linkable files, find the file most embedded in the file system + my @to_link = _more_linked(@non_readonly); my $most_linked_entry = shift @to_link; foreach my $entry (@to_link) { # XXX there shouldn't be a need to update entries' link counts, From 907a7113a89eebd2905d207408a2310202474f03 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 12:41:07 -0500 Subject: [PATCH 04/25] Remove Perl 4 sigils (PBP) --- lib/Directory/Simplify/FileHash.pm | 2 +- lib/Directory/Simplify/Instruction/Generator.pm | 12 ++++++------ simplify_static_dir-main.pl | 10 +++++----- t/TestFunctions.pm | 10 +++++----- t/freed-bytes-commas.t | 6 +++--- t/freed-bytes.t | 8 ++++---- t/link-counting.t | 10 +++++----- t/normal-linkage.t | 10 +++++----- t/normal-non-linkage.t | 10 +++++----- t/sha1collision-non-linkage.t | 10 +++++----- t/timestamp-preservation.t | 14 +++++++------- t/zero-size-non-linkage.t | 10 +++++----- 12 files changed, 56 insertions(+), 56 deletions(-) diff --git a/lib/Directory/Simplify/FileHash.pm b/lib/Directory/Simplify/FileHash.pm index 54a0eb8..921573c 100644 --- a/lib/Directory/Simplify/FileHash.pm +++ b/lib/Directory/Simplify/FileHash.pm @@ -43,7 +43,7 @@ sub add { $self->{_entries}->{$hash} = []; } push @{$self->{_entries}->{$hash}}, $file; - &{$callback}($file) if ref $callback eq 'CODE'; + $callback->($file) if ref $callback eq 'CODE'; } $self->{_files_in_hash}->{$file->{name}} = 1; } diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index 9fe7571..b8a474e 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -42,7 +42,7 @@ sub buckets { next ELIMINATOR if $self->_entry_should_be_skipped($entry); foreach my $bucket_idx (0 .. $#these_buckets) { - if (&_entries_are_hard_linkable($these_buckets[$bucket_idx]->[0], $entry)) { + if (_entries_are_hard_linkable($these_buckets[$bucket_idx]->[0], $entry)) { push @{$these_buckets[$bucket_idx]}, $entry; next ELIMINATOR; } @@ -71,16 +71,16 @@ sub _entries_are_hard_linkable { my ($entry_a, $entry_b) = @_; # obviously, if the sizes aren't the same, they're not the same file - unless (&_entries_sizes_match($entry_a, $entry_b)) { + unless (_entries_sizes_match($entry_a, $entry_b)) { return 0; } # they're the same file, don't try it - if (&_entries_are_already_hard_linked($entry_a, $entry_b)) { + if (_entries_are_already_hard_linked($entry_a, $entry_b)) { return 0; } - if (&_entries_contents_match($entry_a, $entry_b)) { + if (_entries_contents_match($entry_a, $entry_b)) { return 1; } return 0; @@ -123,7 +123,7 @@ sub _entries_sizes_match { sub _entries_contents_match { my ($entry_a, $entry_b) = @_; - my $contents_same = (0 == &File::Compare::compare($entry_a->{name}, $entry_b->{name})); + my $contents_same = (0 == File::Compare::compare($entry_a->{name}, $entry_b->{name})); # warn about hash collision unless ($contents_same) { @@ -168,7 +168,7 @@ sub instructions { target => $entry, ); } - if (&Scalar::Util::refaddr($most_linked_entry) != &Scalar::Util::refaddr($oldest_entry)) { + if (Scalar::Util::refaddr($most_linked_entry) != Scalar::Util::refaddr($oldest_entry)) { # most_linked_entry should get its timestamp updated push @inst, Directory::Simplify::Instruction::CopyTimestamp->new( source => $oldest_entry, diff --git a/simplify_static_dir-main.pl b/simplify_static_dir-main.pl index 78ecfe4..41a2e04 100755 --- a/simplify_static_dir-main.pl +++ b/simplify_static_dir-main.pl @@ -117,15 +117,15 @@ require Directory::Simplify::Utils; sub HELP_MESSAGE { my $fh = shift; - &pod2usage( + pod2usage( -verbose => 1, -exitval => 0, ); } MAIN: { - &getopts('vfm:M:z', \ my %opts) - || &pod2usage( + getopts('vfm:M:z', \ my %opts) + || pod2usage( -exitval => 2, -msg => "Try '$0 --help' for more information", ); @@ -145,7 +145,7 @@ MAIN: { print STDERR 'Finding files...' if $verbose; - &find(sub { + find(sub { # outright skip directories (don't report skip) return if -d $File::Find::name; @@ -214,7 +214,7 @@ MAIN: { my $report_every = 1; # seconds my $processed_bytes = 0; my $last_report = time; - my $total_size_hr = sprintf "%0.4G %s", Directory::Simplify::Utils::hr_size(&sum(map { $_->{size} } @files) or 0); + my $total_size_hr = sprintf "%0.4G %s", Directory::Simplify::Utils::hr_size(sum(map { $_->{size} } @files) or 0); my $cb; if ($print_progress) { printf STDERR "\e\x{37}"; diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index 94441ff..6c60dee 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -37,9 +37,9 @@ sub are_hardlinked { return "$dev:$ino"; }; - my $starter_ident = &$gen_ident($starter); + my $starter_ident = $gen_ident->($starter); foreach my $file (@_) { - if (&$gen_ident($file) ne $starter_ident) { + if ($gen_ident->($file) ne $starter_ident) { return 0; } } @@ -62,7 +62,7 @@ sub filemtime { sub has_mtime { my $mtime = shift; foreach my $file (@_) { - if (&filemtime($file) != $mtime) { + if (filemtime($file) != $mtime) { return 0; } } @@ -80,11 +80,11 @@ sub mktempdir { sub prep_tar { my $tarball = shift // (dirname(__FILE__) . '/t.tar'); - my $td = &mktempdir; + my $td = mktempdir(); # Note: Using chdir from Cwd automatically keeps $ENV{PWD} up-to-date (just # in case) - my $oldpwd = &getcwd; + my $oldpwd = getcwd(); chdir $td; my $tar = Archive::Tar->new; diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index fc5b13f..1ba5ac6 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -7,13 +7,13 @@ use Test::Simple use TestFunctions; -my $test_dir = &mktempdir; -&put_file( +my $test_dir = mktempdir(); +put_file( "$test_dir/1", "$test_dir/2", ); -my (undef, $stdout, $stderr) = &run_script_capture('-f', $test_dir); +my (undef, $stdout, $stderr) = run_script_capture('-f', $test_dir); ok "freed 1,048,576 bytes (1 MB)\n" eq $stderr, 'prints freed bytes with commas'; sub put_file { diff --git a/t/freed-bytes.t b/t/freed-bytes.t index 3945e3e..fabbe02 100644 --- a/t/freed-bytes.t +++ b/t/freed-bytes.t @@ -7,7 +7,7 @@ use Test::Simple use TestFunctions; -my $tarball_dir = &prep_tar; +my $tarball_dir = prep_tar(); my $test_dir = "$tarball_dir/t/freed-bytes"; my @files = ( "$test_dir/1", @@ -17,7 +17,7 @@ my @files = ( ); # Smoke test -ok !&are_hardlinked(@files), 'not hardlinked before we start'; -my (undef, $stdout, $stderr) = &run_script_capture('-f', $test_dir, $test_dir); -ok &file_exists(@files), 'files were not accidentally deleted'; +ok !are_hardlinked(@files), 'not hardlinked before we start'; +my (undef, $stdout, $stderr) = run_script_capture('-f', $test_dir, $test_dir); +ok file_exists(@files), 'files were not accidentally deleted'; ok "freed 24 bytes (24 B)\n" eq $stderr, 'prints correct number of freed bytes'; diff --git a/t/link-counting.t b/t/link-counting.t index e88b004..d2de4c8 100644 --- a/t/link-counting.t +++ b/t/link-counting.t @@ -7,7 +7,7 @@ use Test::Simple use TestFunctions; -my $tarball_dir = &prep_tar; +my $tarball_dir = prep_tar(); my $test_dir = "$tarball_dir/t/link-counting"; my @files = ( "$test_dir/most-links", @@ -15,7 +15,7 @@ my @files = ( ); # Smoke test -ok !&are_hardlinked(@files), 'not hardlinked before we start'; -&run_script($test_dir); -ok &file_exists(@files), 'files were not accidentally deleted'; -ok &are_hardlinked(@files), 'files with existing links got hardlinked'; +ok !are_hardlinked(@files), 'not hardlinked before we start'; +run_script($test_dir); +ok file_exists(@files), 'files were not accidentally deleted'; +ok are_hardlinked(@files), 'files with existing links got hardlinked'; diff --git a/t/normal-linkage.t b/t/normal-linkage.t index 1743053..9c25b82 100644 --- a/t/normal-linkage.t +++ b/t/normal-linkage.t @@ -7,7 +7,7 @@ use Test::Simple use TestFunctions; -my $tarball_dir = &prep_tar; +my $tarball_dir = prep_tar(); my $test_dir = "$tarball_dir/t/normal"; my @files = ( "$test_dir/foo/same", @@ -15,7 +15,7 @@ my @files = ( ); # Smoke test -ok !&are_hardlinked(@files), 'not hardlinked before we start'; -&run_script($test_dir); -ok &file_exists(@files), 'files were not accidentally deleted'; -ok &are_hardlinked(@files), 'files with the same contents got hardlinked'; +ok !are_hardlinked(@files), 'not hardlinked before we start'; +run_script($test_dir); +ok file_exists(@files), 'files were not accidentally deleted'; +ok are_hardlinked(@files), 'files with the same contents got hardlinked'; diff --git a/t/normal-non-linkage.t b/t/normal-non-linkage.t index afbd0f4..c9b372d 100644 --- a/t/normal-non-linkage.t +++ b/t/normal-non-linkage.t @@ -7,7 +7,7 @@ use Test::Simple use TestFunctions; -my $tarball_dir = &prep_tar; +my $tarball_dir = prep_tar(); my $test_dir = "$tarball_dir/t/normal"; my @files = ( "$test_dir/foo/same", @@ -15,7 +15,7 @@ my @files = ( ); # Smoke test -ok !&are_hardlinked(@files), 'not hardlinked before we start'; -&run_script($test_dir); -ok &file_exists(@files), 'files were not accidentally deleted'; -ok !&are_hardlinked(@files), 'files with different contents did not get hardlinked'; +ok !are_hardlinked(@files), 'not hardlinked before we start'; +run_script($test_dir); +ok file_exists(@files), 'files were not accidentally deleted'; +ok !are_hardlinked(@files), 'files with different contents did not get hardlinked'; diff --git a/t/sha1collision-non-linkage.t b/t/sha1collision-non-linkage.t index f494436..f7d8c67 100644 --- a/t/sha1collision-non-linkage.t +++ b/t/sha1collision-non-linkage.t @@ -7,7 +7,7 @@ use Test::Simple use TestFunctions; -my $tarball_dir = &prep_tar; +my $tarball_dir = prep_tar(); my $test_dir = "$tarball_dir/t/sha1-collision"; my @files = ( "$test_dir/shattered-1.pdf", @@ -15,7 +15,7 @@ my @files = ( ); # Smoke test -ok !&are_hardlinked(@files), 'not hardlinked before we start'; -&run_script($test_dir); -ok &file_exists(@files), 'files were not accidentally deleted'; -ok !&are_hardlinked(@files), 'files with the same SHA-1 hash did not get hardlinked'; +ok !are_hardlinked(@files), 'not hardlinked before we start'; +run_script($test_dir); +ok file_exists(@files), 'files were not accidentally deleted'; +ok !are_hardlinked(@files), 'files with the same SHA-1 hash did not get hardlinked'; diff --git a/t/timestamp-preservation.t b/t/timestamp-preservation.t index c8eea03..09be7a8 100644 --- a/t/timestamp-preservation.t +++ b/t/timestamp-preservation.t @@ -7,7 +7,7 @@ use Test::Simple use TestFunctions; -my $tarball_dir = &prep_tar; +my $tarball_dir = prep_tar(); my $test_dir = "$tarball_dir/t/timestamp-preservation"; my @files = ( "$test_dir/newer-more-linked", @@ -15,9 +15,9 @@ my @files = ( ); # Smoke test -ok !&are_hardlinked(@files), 'not hardlinked before we start'; -my $should_have_mtime = &filemtime($files[1]); -&run_script($test_dir); -ok &file_exists(@files), 'files were not accidentally deleted'; -ok &are_hardlinked(@files); -ok &has_mtime($should_have_mtime, @files), 'timestamps updated to use oldest'; +ok !are_hardlinked(@files), 'not hardlinked before we start'; +my $should_have_mtime = filemtime($files[1]); +run_script($test_dir); +ok file_exists(@files), 'files were not accidentally deleted'; +ok are_hardlinked(@files); +ok has_mtime($should_have_mtime, @files), 'timestamps updated to use oldest'; diff --git a/t/zero-size-non-linkage.t b/t/zero-size-non-linkage.t index 1f841fd..b4c4257 100644 --- a/t/zero-size-non-linkage.t +++ b/t/zero-size-non-linkage.t @@ -7,7 +7,7 @@ use Test::Simple use TestFunctions; -my $tarball_dir = &prep_tar; +my $tarball_dir = prep_tar(); my $test_dir = "$tarball_dir/t/zero-size"; my @files = ( "$test_dir/empty1", @@ -15,7 +15,7 @@ my @files = ( ); # Smoke test -ok !&are_hardlinked(@files), 'not hardlinked before we start'; -&run_script($test_dir); -ok &file_exists(@files), 'files were not accidentally deleted'; -ok !&are_hardlinked(@files), 'zero-sized files did not get hardlinked'; +ok !are_hardlinked(@files), 'not hardlinked before we start'; +run_script($test_dir); +ok file_exists(@files), 'files were not accidentally deleted'; +ok !are_hardlinked(@files), 'zero-sized files did not get hardlinked'; From 7dbbb5422a23ec3a86557faf71a53d120e083c8d Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 12:37:07 -0500 Subject: [PATCH 05/25] Unpack @_ first (PBP) --- lib/Directory/Simplify/File.pm | 3 +-- lib/Directory/Simplify/FileHash.pm | 4 ++-- .../Simplify/Instruction/CopyTimestamp.pm | 4 ++-- .../Simplify/Instruction/Generator.pm | 4 ++-- .../Simplify/Instruction/Hardlink.pm | 4 ++-- lib/Directory/Simplify/Utils.pm | 6 +++-- t/TestFunctions.pm | 22 +++++++++++-------- t/freed-bytes-commas.t | 3 ++- 8 files changed, 28 insertions(+), 22 deletions(-) diff --git a/lib/Directory/Simplify/File.pm b/lib/Directory/Simplify/File.pm index d794097..ea8d24a 100644 --- a/lib/Directory/Simplify/File.pm +++ b/lib/Directory/Simplify/File.pm @@ -6,8 +6,7 @@ require Cwd; use File::Basename qw/ dirname /; sub new { - my $class = shift; - my $rel_name = shift; + my ($class, $rel_name) = @_; my $self = bless { rel_name => $rel_name, name => Cwd::abs_path($rel_name), diff --git a/lib/Directory/Simplify/FileHash.pm b/lib/Directory/Simplify/FileHash.pm index 921573c..51bde63 100644 --- a/lib/Directory/Simplify/FileHash.pm +++ b/lib/Directory/Simplify/FileHash.pm @@ -13,11 +13,11 @@ require Directory::Simplify::File; # :squash-remove-end: sub new { - my $class = shift; + my ($class, %args) = @_; return bless { _entries => {}, _files_in_hash => {}, - @_, + %args, }, $class; } diff --git a/lib/Directory/Simplify/Instruction/CopyTimestamp.pm b/lib/Directory/Simplify/Instruction/CopyTimestamp.pm index fba95c9..e808409 100644 --- a/lib/Directory/Simplify/Instruction/CopyTimestamp.pm +++ b/lib/Directory/Simplify/Instruction/CopyTimestamp.pm @@ -9,9 +9,9 @@ require Directory::Simplify::Utils; # :squash-remove-end: sub new { - my $class = shift; + my ($class, %args) = @_; return bless { - @_, + %args, }, $class; } diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index b8a474e..204aad4 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -11,11 +11,11 @@ require Directory::Simplify::Instruction::Hardlink; # :squash-remove-end: sub new { - my $class = shift; + my ($class, %args) = @_; return bless { filehash => undef, min_size => 1, - @_, + %args, }, $class; } diff --git a/lib/Directory/Simplify/Instruction/Hardlink.pm b/lib/Directory/Simplify/Instruction/Hardlink.pm index 24d274e..cce7565 100644 --- a/lib/Directory/Simplify/Instruction/Hardlink.pm +++ b/lib/Directory/Simplify/Instruction/Hardlink.pm @@ -9,10 +9,10 @@ require Directory::Simplify::Utils; # :squash-remove-end: sub new { - my $class = shift; + my ($class, %args) = @_; return bless { freed => 0, - @_, + %args, }, $class; } diff --git a/lib/Directory/Simplify/Utils.pm b/lib/Directory/Simplify/Utils.pm index 5c05489..d0fe408 100644 --- a/lib/Directory/Simplify/Utils.pm +++ b/lib/Directory/Simplify/Utils.pm @@ -4,8 +4,9 @@ use strict; use warnings; sub addcommas { + my @numbers = @_; my @added; - foreach my $num (@_) { + foreach my $num (@numbers) { # don't split anything after the decimal my @parts = split /\./, $num; while ($parts[0] =~ s/(\d)(\d{3}(?:\D|$))/$1,$2/) { @@ -36,11 +37,12 @@ sub hr_size { sub shell_quote { # shell-escape argument for inclusion in non-interpolated single quotes + my @words = @_; my @transformed = map { (my $out = $_) =~ s/'/'\\''/g; "'$out'"; - } @_; + } @words; wantarray ? @transformed : $transformed[0]; } diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index 6c60dee..7b8275d 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -30,7 +30,7 @@ our @EXPORT = qw/ use constant SCRIPT => $ENV{SCRIPT} // abs_path dirname(__FILE__) . '/../simplify_static_dir-main.pl'; sub are_hardlinked { - my $starter = shift; + my ($starter, @files) = @_; my $gen_ident = sub { my ($dev, $ino) = stat $_[0]; @@ -38,7 +38,7 @@ sub are_hardlinked { }; my $starter_ident = $gen_ident->($starter); - foreach my $file (@_) { + foreach my $file (@files) { if ($gen_ident->($file) ne $starter_ident) { return 0; } @@ -47,7 +47,8 @@ sub are_hardlinked { } sub file_exists { - foreach my $file (@_) { + my @files = @_; + foreach my $file (@files) { unless (-e $file) { return 0; } @@ -56,12 +57,13 @@ sub file_exists { } sub filemtime { - (stat shift)[9]; + my $file = shift; + return (stat $file)[9]; } sub has_mtime { - my $mtime = shift; - foreach my $file (@_) { + my ($mtime, @files) = @_; + foreach my $file (@files) { if (filemtime($file) != $mtime) { return 0; } @@ -96,7 +98,8 @@ sub prep_tar { } sub run_script_capture { - my @cmd =(SCRIPT, @_); + my @args = @_; + my @cmd = (SCRIPT, @args); use IPC::Open3 qw/ open3 /; my $stderr = File::Temp->new( @@ -123,8 +126,9 @@ sub run_script_capture { } sub run_script { - print STDERR '+ ' . SCRIPT . " @_\n"; - system SCRIPT, @_; + my @args = @_; + print STDERR '+ ' . SCRIPT . " @args\n"; + return system SCRIPT, @args; } 1; diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index 1ba5ac6..7ffdeb8 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -17,8 +17,9 @@ my (undef, $stdout, $stderr) = run_script_capture('-f', $test_dir); ok "freed 1,048,576 bytes (1 MB)\n" eq $stderr, 'prints freed bytes with commas'; sub put_file { + my @files = @_; my $bytes = 1048576; # 1 MB - foreach my $file (@_) { + foreach my $file (@files) { open my $fh, '>', $file or die "Failed to open file $file for writing: $!"; for (my $bytes_written = 0; $bytes_written < $bytes; ++$bytes_written) { From 31fe372e098baa433ff6f153822f046178f84cfd Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 12:37:27 -0500 Subject: [PATCH 06/25] Fix implicit return (PBP) --- lib/Directory/Simplify/File.pm | 4 ++-- lib/Directory/Simplify/FileHash.pm | 3 ++- lib/Directory/Simplify/Instruction/CopyTimestamp.pm | 1 + lib/Directory/Simplify/Instruction/Generator.pm | 6 +++--- lib/Directory/Simplify/Instruction/Hardlink.pm | 1 + lib/Directory/Simplify/Utils.pm | 6 +++--- simplify_static_dir-main.pl | 1 + t/freed-bytes-commas.t | 1 + t/normal-linkage.t | 1 - 9 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/Directory/Simplify/File.pm b/lib/Directory/Simplify/File.pm index ea8d24a..2c4f492 100644 --- a/lib/Directory/Simplify/File.pm +++ b/lib/Directory/Simplify/File.pm @@ -15,7 +15,7 @@ sub new { (@{$self}{qw/ dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks /}) = lstat $self->{name}; - $self + return $self; } sub hash { @@ -26,7 +26,7 @@ sub hash { $ctx->addfile($self->{name}); $self->{_hash} = $ctx->hexdigest; } - $self->{_hash} + return $self->{_hash}; } 1; diff --git a/lib/Directory/Simplify/FileHash.pm b/lib/Directory/Simplify/FileHash.pm index 51bde63..a45ec4b 100644 --- a/lib/Directory/Simplify/FileHash.pm +++ b/lib/Directory/Simplify/FileHash.pm @@ -47,11 +47,12 @@ sub add { } $self->{_files_in_hash}->{$file->{name}} = 1; } + return; } sub entries { my $self = shift; - values %{$self->{_entries}} + return values %{$self->{_entries}}; } 1; diff --git a/lib/Directory/Simplify/Instruction/CopyTimestamp.pm b/lib/Directory/Simplify/Instruction/CopyTimestamp.pm index e808409..88cb3de 100644 --- a/lib/Directory/Simplify/Instruction/CopyTimestamp.pm +++ b/lib/Directory/Simplify/Instruction/CopyTimestamp.pm @@ -19,6 +19,7 @@ sub run { my $self = shift; # preserve older time stamp utime $self->{source}->{atime}, $self->{source}->{mtime}, $self->{target}->{name}; + return; } sub bytes_freed { diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index 204aad4..98d6c86 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -21,7 +21,7 @@ sub new { sub as_string { my $self = shift; - join "\n", $self->instructions; + return join "\n", $self->instructions; } sub buckets { @@ -55,7 +55,7 @@ sub buckets { push @buckets, @these_buckets; } - @buckets + return @buckets; } sub _entry_should_be_skipped { @@ -176,7 +176,7 @@ sub instructions { ); } } - @inst + return @inst; } 1; diff --git a/lib/Directory/Simplify/Instruction/Hardlink.pm b/lib/Directory/Simplify/Instruction/Hardlink.pm index cce7565..a039f49 100644 --- a/lib/Directory/Simplify/Instruction/Hardlink.pm +++ b/lib/Directory/Simplify/Instruction/Hardlink.pm @@ -31,6 +31,7 @@ sub run { if (--$self->{target}->{nlink} == 0) { $self->{freed} = $self->{target}->{size}; } + return; } sub bytes_freed { diff --git a/lib/Directory/Simplify/Utils.pm b/lib/Directory/Simplify/Utils.pm index d0fe408..f4adc25 100644 --- a/lib/Directory/Simplify/Utils.pm +++ b/lib/Directory/Simplify/Utils.pm @@ -13,7 +13,7 @@ sub addcommas { } push @added, (join '.', @parts); } - wantarray ? @added : $added[0] + return wantarray ? @added : $added[0]; } sub hr_size { @@ -32,7 +32,7 @@ sub hr_size { # default to ($sz, 'bytes') @ret = ($sz, $sizes[0]) unless @ret; - wantarray ? @ret : "@ret" + return wantarray ? @ret : "@ret"; } sub shell_quote { @@ -43,7 +43,7 @@ sub shell_quote { =~ s/'/'\\''/g; "'$out'"; } @words; - wantarray ? @transformed : $transformed[0]; + return wantarray ? @transformed : $transformed[0]; } 1; diff --git a/simplify_static_dir-main.pl b/simplify_static_dir-main.pl index 41a2e04..6b5577f 100755 --- a/simplify_static_dir-main.pl +++ b/simplify_static_dir-main.pl @@ -121,6 +121,7 @@ sub HELP_MESSAGE { -verbose => 1, -exitval => 0, ); + return; } MAIN: { diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index 7ffdeb8..27dafa6 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -26,4 +26,5 @@ sub put_file { print $fh 'A'; } } + return; } diff --git a/t/normal-linkage.t b/t/normal-linkage.t index 9c25b82..3eecb92 100644 --- a/t/normal-linkage.t +++ b/t/normal-linkage.t @@ -1,4 +1,3 @@ -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; From 15c466e581f46450ec4c85e545cefa2b531aff44 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 13:04:52 -0500 Subject: [PATCH 07/25] Refactor FileHash to expect named arguments --- lib/Directory/Simplify/FileHash.pm | 13 +++---------- simplify_static_dir-main.pl | 4 ++-- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/Directory/Simplify/FileHash.pm b/lib/Directory/Simplify/FileHash.pm index a45ec4b..e3c827a 100644 --- a/lib/Directory/Simplify/FileHash.pm +++ b/lib/Directory/Simplify/FileHash.pm @@ -22,16 +22,9 @@ sub new { } sub add { - my $self = shift; - my (@files, $callback); - if (ref $_[0] eq 'HASH') { - # Called method like { files => [] } - my %opts = %{$_[0]}; - @files = @{$opts{files}}; - $callback = $opts{callback}; - } else { - @files = @_; - } + my ($self, %args) = @_; + my @files = @{$args{files}}; + my $callback = $args{callback}; foreach my $file (@files) { unless (ref $file eq 'Directory::Simplify::File') { $file = Directory::Simplify::File->new($file); diff --git a/simplify_static_dir-main.pl b/simplify_static_dir-main.pl index 6b5577f..9dc2cc7 100755 --- a/simplify_static_dir-main.pl +++ b/simplify_static_dir-main.pl @@ -230,10 +230,10 @@ MAIN: { } }; } - $filehash->add({ + $filehash->add( files => \@files, callback => $cb, - }); + ); print STDERR "done.\n" if $verbose; From 98c2c04263faff3026b57712388d1d315ae7bf13 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 13:05:12 -0500 Subject: [PATCH 08/25] Remove postfix if/for (PBP) --- lib/Directory/Simplify/FileHash.pm | 4 +- lib/Directory/Simplify/Utils.pm | 4 +- simplify_static_dir-main.pl | 59 +++++++++++++++++------------- t/TestFunctions.pm | 4 +- 4 files changed, 43 insertions(+), 28 deletions(-) diff --git a/lib/Directory/Simplify/FileHash.pm b/lib/Directory/Simplify/FileHash.pm index e3c827a..4b1029f 100644 --- a/lib/Directory/Simplify/FileHash.pm +++ b/lib/Directory/Simplify/FileHash.pm @@ -36,7 +36,9 @@ sub add { $self->{_entries}->{$hash} = []; } push @{$self->{_entries}->{$hash}}, $file; - $callback->($file) if ref $callback eq 'CODE'; + if (ref $callback eq 'CODE') { + $callback->($file); + } } $self->{_files_in_hash}->{$file->{name}} = 1; } diff --git a/lib/Directory/Simplify/Utils.pm b/lib/Directory/Simplify/Utils.pm index f4adc25..6438e16 100644 --- a/lib/Directory/Simplify/Utils.pm +++ b/lib/Directory/Simplify/Utils.pm @@ -30,7 +30,9 @@ sub hr_size { } # default to ($sz, 'bytes') - @ret = ($sz, $sizes[0]) unless @ret; + unless (@ret) { + @ret = ($sz, $sizes[0]); + } return wantarray ? @ret : "@ret"; } diff --git a/simplify_static_dir-main.pl b/simplify_static_dir-main.pl index 9dc2cc7..c9f2ec4 100755 --- a/simplify_static_dir-main.pl +++ b/simplify_static_dir-main.pl @@ -143,8 +143,9 @@ MAIN: { my @dirs_to_process = map { Cwd::abs_path($_) } (@ARGV ? @ARGV : ($ENV{PWD})); my @files; - print STDERR 'Finding files...' - if $verbose; + if ($verbose) { + print STDERR 'Finding files...'; + } find(sub { # outright skip directories (don't report skip) @@ -158,9 +159,10 @@ MAIN: { push @files, Directory::Simplify::File->new($File::Find::name); }, @dirs_to_process); - printf STDERR "%d files found", - scalar @files - if $verbose; + if ($verbose) { + printf STDERR '%d files found', + scalar @files; + } # Limit to or exclude file patterns specified by `-m' or `-M', respectively # @@ -175,20 +177,18 @@ MAIN: { @files = grep { $_->{rel_name} =~ $files_match } @files; - if ($file_ct_before_filter != scalar @files) { - printf STDERR " (%d files filtered by -m rule)", - $file_ct_before_filter - scalar @files - if $verbose; + if ($verbose && $file_ct_before_filter != scalar @files) { + printf STDERR ' (%d files filtered by -m rule)', + $file_ct_before_filter - scalar @files; } if (length $files_exclude) { $file_ct_before_filter = scalar @files; @files = grep { not $_->{rel_name} =~ $files_exclude } @files; - if ($file_ct_before_filter != scalar @files) { - printf STDERR " (%d files filtered by -M rule)", - $file_ct_before_filter - scalar @files - if $verbose; + if ($verbose && $file_ct_before_filter != scalar @files) { + printf STDERR ' (%d files filtered by -M rule)', + $file_ct_before_filter - scalar @files; } } @@ -196,21 +196,26 @@ MAIN: { # unique size. The reasoning being that file sizes do not match, there's no # possible way those two files can have the same contents. my %file_sizes; - ++$file_sizes{$_->{size}} foreach @files; + foreach my $file (@files) { + ++$file_sizes{$file->{size}}; + } @files = grep { $file_sizes{$_->{size}} > 1 } @files; - printf STDERR " (%d candidates).\n", - scalar @files - if $verbose; + if ($verbose) { + printf STDERR " (%d candidates).\n", + scalar @files; + } unless (@files) { printf STDERR "Nothing to do.\n"; exit 0; } - print STDERR "Generating hashes..." if $verbose; + if ($verbose) { + print STDERR 'Generating hashes...'; + } my $filehash = Directory::Simplify::FileHash->new; my $report_every = 1; # seconds my $processed_bytes = 0; @@ -234,8 +239,9 @@ MAIN: { files => \@files, callback => $cb, ); - print STDERR "done.\n" - if $verbose; + if ($verbose) { + print STDERR "done.\n"; + } my $generator = Directory::Simplify::Instruction::Generator->new( filehash => $filehash, @@ -245,14 +251,17 @@ MAIN: { my $freed_bytes = 0; foreach my $inst ($generator->instructions) { - print STDERR $inst, "\n" if $verbose; + if ($verbose) { + print STDERR $inst, "\n"; + } $inst->run; $freed_bytes += $inst->bytes_freed; } - printf STDERR "freed %s bytes (%0.4G %s)\n", - Directory::Simplify::Utils::addcommas($freed_bytes), - Directory::Simplify::Utils::hr_size($freed_bytes) - if $print_freed or $verbose; + if ($print_freed or $verbose) { + printf STDERR "freed %s bytes (%0.4G %s)\n", + Directory::Simplify::Utils::addcommas($freed_bytes), + Directory::Simplify::Utils::hr_size($freed_bytes); + } } diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index 7b8275d..f19d91d 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -116,7 +116,9 @@ sub run_script_capture { print STDERR "+ @cmd\n"; my $pid = open3 $in, '>&CATCHOUT', '>&CATCHERR', @cmd; waitpid $pid, 0; - seek $_, 0, 0 for \*CATCHOUT, \*CATCHERR; + foreach my $handle (\*CATCHOUT, \*CATCHERR) { + seek $handle, 0, 0; + } return ( $?, From 62f2503cb08deec3c4b9c0f8053d44925eb6e00c Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 13:39:42 -0500 Subject: [PATCH 09/25] Remove vim modelines That's what .editorconfig is for. --- lib/Directory/Simplify/File.pm | 1 - lib/Directory/Simplify/Instruction/CopyTimestamp.pm | 1 - lib/Directory/Simplify/Instruction/Generator.pm | 1 - lib/Directory/Simplify/Instruction/Hardlink.pm | 1 - lib/Directory/Simplify/Utils.pm | 1 - make-allinone.sh | 1 - simplify_static_dir-main.pl | 1 - t/TestFunctions.pm | 1 - t/freed-bytes-commas.t | 1 - t/freed-bytes.t | 1 - t/link-counting.t | 1 - t/normal-non-linkage.t | 1 - t/sha1collision-non-linkage.t | 1 - t/timestamp-preservation.t | 1 - t/zero-size-non-linkage.t | 1 - util/squash | 1 - 16 files changed, 16 deletions(-) diff --git a/lib/Directory/Simplify/File.pm b/lib/Directory/Simplify/File.pm index 2c4f492..7192622 100644 --- a/lib/Directory/Simplify/File.pm +++ b/lib/Directory/Simplify/File.pm @@ -1,5 +1,4 @@ package Directory::Simplify::File; -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; require Cwd; diff --git a/lib/Directory/Simplify/Instruction/CopyTimestamp.pm b/lib/Directory/Simplify/Instruction/CopyTimestamp.pm index 88cb3de..ca1e6ce 100644 --- a/lib/Directory/Simplify/Instruction/CopyTimestamp.pm +++ b/lib/Directory/Simplify/Instruction/CopyTimestamp.pm @@ -1,5 +1,4 @@ package Directory::Simplify::Instruction::CopyTimestamp; -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; use overload '""' => 'as_string'; diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index 98d6c86..6a805b8 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -1,5 +1,4 @@ package Directory::Simplify::Instruction::Generator; -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; use overload '""' => 'as_string'; diff --git a/lib/Directory/Simplify/Instruction/Hardlink.pm b/lib/Directory/Simplify/Instruction/Hardlink.pm index a039f49..4d6c24f 100644 --- a/lib/Directory/Simplify/Instruction/Hardlink.pm +++ b/lib/Directory/Simplify/Instruction/Hardlink.pm @@ -1,5 +1,4 @@ package Directory::Simplify::Instruction::Hardlink; -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; use overload '""' => 'as_string'; diff --git a/lib/Directory/Simplify/Utils.pm b/lib/Directory/Simplify/Utils.pm index 6438e16..54d395f 100644 --- a/lib/Directory/Simplify/Utils.pm +++ b/lib/Directory/Simplify/Utils.pm @@ -1,5 +1,4 @@ package Directory::Simplify::Utils; -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/make-allinone.sh b/make-allinone.sh index 6bbaa4d..4fe10d9 100755 --- a/make-allinone.sh +++ b/make-allinone.sh @@ -1,5 +1,4 @@ #!/bin/bash -# vi: et sts=4 sw=4 ts=4 WORKDIR=${0%/*} OUT=$WORKDIR/simplify_static_dir.pl diff --git a/simplify_static_dir-main.pl b/simplify_static_dir-main.pl index c9f2ec4..b7bf35f 100755 --- a/simplify_static_dir-main.pl +++ b/simplify_static_dir-main.pl @@ -1,5 +1,4 @@ #!/usr/bin/perl -# vi: et sts=4 sw=4 ts=4 package main; use strict; diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index f19d91d..7f610a0 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -1,5 +1,4 @@ package TestFunctions; -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index 27dafa6..c675997 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -1,4 +1,3 @@ -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/t/freed-bytes.t b/t/freed-bytes.t index fabbe02..b269a6b 100644 --- a/t/freed-bytes.t +++ b/t/freed-bytes.t @@ -1,4 +1,3 @@ -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/t/link-counting.t b/t/link-counting.t index d2de4c8..bbd80f7 100644 --- a/t/link-counting.t +++ b/t/link-counting.t @@ -1,4 +1,3 @@ -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/t/normal-non-linkage.t b/t/normal-non-linkage.t index c9b372d..4187f4a 100644 --- a/t/normal-non-linkage.t +++ b/t/normal-non-linkage.t @@ -1,4 +1,3 @@ -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/t/sha1collision-non-linkage.t b/t/sha1collision-non-linkage.t index f7d8c67..501bfc4 100644 --- a/t/sha1collision-non-linkage.t +++ b/t/sha1collision-non-linkage.t @@ -1,4 +1,3 @@ -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/t/timestamp-preservation.t b/t/timestamp-preservation.t index 09be7a8..60e52c6 100644 --- a/t/timestamp-preservation.t +++ b/t/timestamp-preservation.t @@ -1,4 +1,3 @@ -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/t/zero-size-non-linkage.t b/t/zero-size-non-linkage.t index b4c4257..55d3121 100644 --- a/t/zero-size-non-linkage.t +++ b/t/zero-size-non-linkage.t @@ -1,4 +1,3 @@ -# vi: et sts=4 sw=4 ts=4 use strict; use warnings; diff --git a/util/squash b/util/squash index a015533..c0bd4af 100755 --- a/util/squash +++ b/util/squash @@ -1,5 +1,4 @@ #!/usr/bin/perl -# vi: et sts=4 sw=4 ts=4 # Squashes together the parts of the app into the single script. # (Adapted from the script that squashes App::Ack - see https://github.com/beyondgrep/ack3) From f3db5cf5ee0f9fd996ab06688d69679f8ccb4837 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 13:44:02 -0500 Subject: [PATCH 10/25] CI: Start all tests with bangline Perl::Critic will think they're modules otherwise. --- t/freed-bytes-commas.t | 1 + t/freed-bytes.t | 1 + t/link-counting.t | 1 + t/normal-linkage.t | 1 + t/normal-non-linkage.t | 1 + t/sha1collision-non-linkage.t | 1 + t/timestamp-preservation.t | 1 + t/zero-size-non-linkage.t | 1 + 8 files changed, 8 insertions(+) diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index c675997..a61355a 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -1,3 +1,4 @@ +#!perl use strict; use warnings; diff --git a/t/freed-bytes.t b/t/freed-bytes.t index b269a6b..cdb2f0f 100644 --- a/t/freed-bytes.t +++ b/t/freed-bytes.t @@ -1,3 +1,4 @@ +#!perl use strict; use warnings; diff --git a/t/link-counting.t b/t/link-counting.t index bbd80f7..c712a5b 100644 --- a/t/link-counting.t +++ b/t/link-counting.t @@ -1,3 +1,4 @@ +#!perl use strict; use warnings; diff --git a/t/normal-linkage.t b/t/normal-linkage.t index 3eecb92..230c3dd 100644 --- a/t/normal-linkage.t +++ b/t/normal-linkage.t @@ -1,3 +1,4 @@ +#!perl use strict; use warnings; diff --git a/t/normal-non-linkage.t b/t/normal-non-linkage.t index 4187f4a..ca01c3e 100644 --- a/t/normal-non-linkage.t +++ b/t/normal-non-linkage.t @@ -1,3 +1,4 @@ +#!perl use strict; use warnings; diff --git a/t/sha1collision-non-linkage.t b/t/sha1collision-non-linkage.t index 501bfc4..9ccd208 100644 --- a/t/sha1collision-non-linkage.t +++ b/t/sha1collision-non-linkage.t @@ -1,3 +1,4 @@ +#!perl use strict; use warnings; diff --git a/t/timestamp-preservation.t b/t/timestamp-preservation.t index 60e52c6..ef46cac 100644 --- a/t/timestamp-preservation.t +++ b/t/timestamp-preservation.t @@ -1,3 +1,4 @@ +#!perl use strict; use warnings; diff --git a/t/zero-size-non-linkage.t b/t/zero-size-non-linkage.t index 55d3121..bbacec8 100644 --- a/t/zero-size-non-linkage.t +++ b/t/zero-size-non-linkage.t @@ -1,3 +1,4 @@ +#!perl use strict; use warnings; From 971b76ab3746966e360b7b546ee948b5959c69be Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 13:44:37 -0500 Subject: [PATCH 11/25] CI: Move to plan-less tests --- t/freed-bytes-commas.t | 3 +-- t/freed-bytes.t | 3 +-- t/link-counting.t | 3 +-- t/normal-linkage.t | 3 +-- t/normal-non-linkage.t | 3 +-- t/sha1collision-non-linkage.t | 3 +-- t/timestamp-preservation.t | 3 +-- t/zero-size-non-linkage.t | 3 +-- 8 files changed, 8 insertions(+), 16 deletions(-) diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index a61355a..01ffdfd 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -2,8 +2,7 @@ use strict; use warnings; -use Test::Simple - tests => 1; +use Test::More 'no_plan'; use TestFunctions; diff --git a/t/freed-bytes.t b/t/freed-bytes.t index cdb2f0f..bb52994 100644 --- a/t/freed-bytes.t +++ b/t/freed-bytes.t @@ -2,8 +2,7 @@ use strict; use warnings; -use Test::Simple - tests => 3; +use Test::More 'no_plan'; use TestFunctions; diff --git a/t/link-counting.t b/t/link-counting.t index c712a5b..6ef6d25 100644 --- a/t/link-counting.t +++ b/t/link-counting.t @@ -2,8 +2,7 @@ use strict; use warnings; -use Test::Simple - tests => 3; +use Test::More 'no_plan'; use TestFunctions; diff --git a/t/normal-linkage.t b/t/normal-linkage.t index 230c3dd..f4ab8d6 100644 --- a/t/normal-linkage.t +++ b/t/normal-linkage.t @@ -2,8 +2,7 @@ use strict; use warnings; -use Test::Simple - tests => 3; +use Test::More 'no_plan'; use TestFunctions; diff --git a/t/normal-non-linkage.t b/t/normal-non-linkage.t index ca01c3e..38146de 100644 --- a/t/normal-non-linkage.t +++ b/t/normal-non-linkage.t @@ -2,8 +2,7 @@ use strict; use warnings; -use Test::Simple - tests => 3; +use Test::More 'no_plan'; use TestFunctions; diff --git a/t/sha1collision-non-linkage.t b/t/sha1collision-non-linkage.t index 9ccd208..b18a15d 100644 --- a/t/sha1collision-non-linkage.t +++ b/t/sha1collision-non-linkage.t @@ -2,8 +2,7 @@ use strict; use warnings; -use Test::Simple - tests => 3; +use Test::More 'no_plan'; use TestFunctions; diff --git a/t/timestamp-preservation.t b/t/timestamp-preservation.t index ef46cac..ed3d167 100644 --- a/t/timestamp-preservation.t +++ b/t/timestamp-preservation.t @@ -2,8 +2,7 @@ use strict; use warnings; -use Test::Simple - tests => 4; +use Test::More 'no_plan'; use TestFunctions; diff --git a/t/zero-size-non-linkage.t b/t/zero-size-non-linkage.t index bbacec8..9ea20fe 100644 --- a/t/zero-size-non-linkage.t +++ b/t/zero-size-non-linkage.t @@ -2,8 +2,7 @@ use strict; use warnings; -use Test::Simple - tests => 3; +use Test::More 'no_plan'; use TestFunctions; From 9115c6bdcac19a8ef342339105e5c4b55e1425eb Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 13:56:52 -0500 Subject: [PATCH 12/25] CI: Fix TestFunctions - Use 'use parent' instead of '@ISA' - Add Perl::Critic leniency --- t/TestFunctions.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index 7f610a0..94d0e2a 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -14,7 +14,9 @@ use File::Basename qw/ require File::Temp; use Exporter; -our @ISA = qw/ Exporter /; +use parent 'Exporter'; +## no critic ( Modules::ProhibitAutomaticExportation ) +# This is a test function library, it's not production code... our @EXPORT = qw/ are_hardlinked file_exists From d6be215a064ed5db8bc5c7b5b406ec7f052fda29 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 14:00:46 -0500 Subject: [PATCH 13/25] Fix join()ed readline (PBP) Use $/ to slurp the whole handle instead of splitting and joining. --- t/TestFunctions.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index 94d0e2a..cb9a100 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -121,10 +121,11 @@ sub run_script_capture { seek $handle, 0, 0; } + local $/; return ( $?, - (join "\n", ), - (join "\n", ) + scalar , # slurp! + scalar , # slurp! ); } From 2987e063bd42099fc385b236a07b7870e6c6b1a3 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 14:26:37 -0500 Subject: [PATCH 14/25] Fix '!' inside 'unless' (PBP) --- simplify_static_dir-main.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplify_static_dir-main.pl b/simplify_static_dir-main.pl index b7bf35f..4d15c0d 100755 --- a/simplify_static_dir-main.pl +++ b/simplify_static_dir-main.pl @@ -151,7 +151,7 @@ MAIN: { return if -d $File::Find::name; # skip non-existent files and links - unless (-f $File::Find::name && ! -l $File::Find::name) { + if (! -f $File::Find::name || -l $File::Find::name) { return; } From 4e2e94881b1d41b3fe4549d42e6e63891c60487f Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 14:27:34 -0500 Subject: [PATCH 15/25] Use non-interpolating strings where possible --- simplify_static_dir-main.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplify_static_dir-main.pl b/simplify_static_dir-main.pl index 4d15c0d..9dd8579 100755 --- a/simplify_static_dir-main.pl +++ b/simplify_static_dir-main.pl @@ -219,7 +219,7 @@ MAIN: { my $report_every = 1; # seconds my $processed_bytes = 0; my $last_report = time; - my $total_size_hr = sprintf "%0.4G %s", Directory::Simplify::Utils::hr_size(sum(map { $_->{size} } @files) or 0); + my $total_size_hr = sprintf '%0.4G %s', Directory::Simplify::Utils::hr_size(sum(map { $_->{size} } @files) or 0); my $cb; if ($print_progress) { printf STDERR "\e\x{37}"; From 3e96b9bc19a8d042e1c2550ceee0c2d6eebf76ca Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 14:30:05 -0500 Subject: [PATCH 16/25] Use croak/carp instead of die/warn (PBP) --- lib/Directory/Simplify/Instruction/Generator.pm | 5 +++-- lib/Directory/Simplify/Instruction/Hardlink.pm | 5 +++-- t/freed-bytes-commas.t | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index 6a805b8..85cd1ef 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -2,6 +2,7 @@ package Directory::Simplify::Instruction::Generator; use strict; use warnings; use overload '""' => 'as_string'; +use Carp qw/ carp /; require File::Compare; # :squash-remove-start: @@ -126,7 +127,7 @@ sub _entries_contents_match { # warn about hash collision unless ($contents_same) { - warn "Hash collision between files:\n* $entry_a->{name}\n* $entry_b->{name}\n (don't panic)\n"; + carp "Hash collision between files:\n* $entry_a->{name}\n* $entry_b->{name}\n (don't panic)\n"; } return $contents_same; } @@ -147,7 +148,7 @@ sub instructions { my @non_readonly; foreach my $entry (@{$bucket}) { unless (-w $entry->{dirname}) { - warn "Warning: $entry->{name} not able to be unlinked!"; + carp "Warning: $entry->{name} not able to be unlinked!"; } push @non_readonly, $entry; } diff --git a/lib/Directory/Simplify/Instruction/Hardlink.pm b/lib/Directory/Simplify/Instruction/Hardlink.pm index 4d6c24f..2303e0f 100644 --- a/lib/Directory/Simplify/Instruction/Hardlink.pm +++ b/lib/Directory/Simplify/Instruction/Hardlink.pm @@ -2,6 +2,7 @@ package Directory::Simplify::Instruction::Hardlink; use strict; use warnings; use overload '""' => 'as_string'; +use Carp qw/ croak /; # :squash-remove-start: require Directory::Simplify::Utils; @@ -20,10 +21,10 @@ sub run { # hard link the files unless (unlink $self->{target}->{name}) { - die "Failed to remove file `$self->{target}->{name}': $!\n"; + croak "Failed to remove file `$self->{target}->{name}': $!\n"; } unless (link $self->{source}->{name}, $self->{target}->{name}) { - die "Failed to hard link `$self->{source}->{name}' => `$self->{target}->{name}': $!"; + croak "Failed to hard link `$self->{source}->{name}' => `$self->{target}->{name}': $!"; } # bookkeeping ++$self->{source}->{nlink}; diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index 01ffdfd..c7b9b0b 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -3,6 +3,7 @@ use strict; use warnings; use Test::More 'no_plan'; +use Carp qw/ croak /; use TestFunctions; @@ -20,7 +21,7 @@ sub put_file { my $bytes = 1048576; # 1 MB foreach my $file (@files) { open my $fh, '>', $file - or die "Failed to open file $file for writing: $!"; + or croak("Failed to open file $file for writing: $!"); for (my $bytes_written = 0; $bytes_written < $bytes; ++$bytes_written) { print $fh 'A'; } From 7d389377a10038eef08d23614e614a4c7eac77f0 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 14:30:23 -0500 Subject: [PATCH 17/25] CI: Fix unlabelled test --- t/timestamp-preservation.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/timestamp-preservation.t b/t/timestamp-preservation.t index ed3d167..c0ae713 100644 --- a/t/timestamp-preservation.t +++ b/t/timestamp-preservation.t @@ -18,5 +18,5 @@ ok !are_hardlinked(@files), 'not hardlinked before we start'; my $should_have_mtime = filemtime($files[1]); run_script($test_dir); ok file_exists(@files), 'files were not accidentally deleted'; -ok are_hardlinked(@files); +ok are_hardlinked(@files), 'files should be hardlinked'; ok has_mtime($should_have_mtime, @files), 'timestamps updated to use oldest'; From e0c91b46475bcc0bf3d134ba66ac521f76ad0dc9 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 15:00:46 -0500 Subject: [PATCH 18/25] Fix overly-complex 'map' (PBP) --- lib/Directory/Simplify/Utils.pm | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/Directory/Simplify/Utils.pm b/lib/Directory/Simplify/Utils.pm index 54d395f..37bea38 100644 --- a/lib/Directory/Simplify/Utils.pm +++ b/lib/Directory/Simplify/Utils.pm @@ -39,12 +39,11 @@ sub hr_size { sub shell_quote { # shell-escape argument for inclusion in non-interpolated single quotes my @words = @_; - my @transformed = map { - (my $out = $_) - =~ s/'/'\\''/g; - "'$out'"; - } @words; - return wantarray ? @transformed : $transformed[0]; + foreach my $word (@words) { + $word =~ s/'/'\\''/g; + $word = "'$word'"; + } + return wantarray ? @words : $words[0]; } 1; From a8db0b17fef2391cc44a460eb71ca652d82ada58 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 15:11:25 -0500 Subject: [PATCH 19/25] CI: Close file handles ASAP --- t/freed-bytes-commas.t | 1 + 1 file changed, 1 insertion(+) diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index c7b9b0b..2c96ca3 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -25,6 +25,7 @@ sub put_file { for (my $bytes_written = 0; $bytes_written < $bytes; ++$bytes_written) { print $fh 'A'; } + close $fh; } return; } From d13f8ff83c6b3782596f8368d856024f6b5d1185 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 15:29:45 -0500 Subject: [PATCH 20/25] CI: Add underscores to long number (PBP) --- t/freed-bytes-commas.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/freed-bytes-commas.t b/t/freed-bytes-commas.t index 2c96ca3..81af8d0 100644 --- a/t/freed-bytes-commas.t +++ b/t/freed-bytes-commas.t @@ -18,7 +18,7 @@ ok "freed 1,048,576 bytes (1 MB)\n" eq $stderr, 'prints freed bytes with commas' sub put_file { my @files = @_; - my $bytes = 1048576; # 1 MB + my $bytes = 1_048_576; # 1 MB foreach my $file (@files) { open my $fh, '>', $file or croak("Failed to open file $file for writing: $!"); From 76da18780719ddb28be4e1d30bd34be8fac11f42 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 15:37:17 -0500 Subject: [PATCH 21/25] CI: Improve method of capturing output --- t/TestFunctions.pm | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index cb9a100..fc68193 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -12,6 +12,8 @@ use File::Basename qw/ dirname /; require File::Temp; +use IPC::Open3 qw/ open3 /; +use Symbol qw/ gensym /; use Exporter; use parent 'Exporter'; @@ -102,7 +104,6 @@ sub run_script_capture { my @args = @_; my @cmd = (SCRIPT, @args); - use IPC::Open3 qw/ open3 /; my $stderr = File::Temp->new( TMPDIR => 1, CLEANUP => 1, @@ -112,20 +113,20 @@ sub run_script_capture { CLEANUP => 1, ); my $in = ''; - local *CATCHOUT = $stdout; - local *CATCHERR = $stderr; + my $child_out = gensym(); + my $child_err = gensym(); print STDERR "+ @cmd\n"; - my $pid = open3 $in, '>&CATCHOUT', '>&CATCHERR', @cmd; + my $pid = open3 $in, $child_out, $child_err, @cmd; waitpid $pid, 0; - foreach my $handle (\*CATCHOUT, \*CATCHERR) { + foreach my $handle ($child_out, $child_err) { seek $handle, 0, 0; } local $/; return ( $?, - scalar , # slurp! - scalar , # slurp! + scalar <$child_out>, # slurp! + scalar <$child_err>, # slurp! ); } From 8fdf3069ba08c5ffc10aa1a71f27e39f82366c65 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 17:36:02 -0500 Subject: [PATCH 22/25] Fix issue where mixed readonly/read-write dirs didn't hard link --- CHANGELOG.md | 5 +++++ lib/Directory/Simplify/Instruction/Generator.pm | 12 +++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14592ef..ad8ebb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this project will be documented in this file. - Omit output of progress bar unless -v flag is present - Add thousands separator commas to output +### Fixed + +- Fixed issue where removable files wouldn't be linked with non-removable + files. + ## [3.0.0] ### Changed diff --git a/lib/Directory/Simplify/Instruction/Generator.pm b/lib/Directory/Simplify/Instruction/Generator.pm index 85cd1ef..4369df3 100644 --- a/lib/Directory/Simplify/Instruction/Generator.pm +++ b/lib/Directory/Simplify/Instruction/Generator.pm @@ -145,17 +145,23 @@ sub instructions { my ($oldest_entry) = _oldest_mtime(@{$bucket}); # Limit link/unlink operations to files in non-readonly directories - my @non_readonly; + my (@non_readonly, @readonly); foreach my $entry (@{$bucket}) { unless (-w $entry->{dirname}) { carp "Warning: $entry->{name} not able to be unlinked!"; + push @readonly, $entry; + } else { + push @non_readonly, $entry; } - push @non_readonly, $entry; } # Of the linkable files, find the file most embedded in the file system my @to_link = _more_linked(@non_readonly); - my $most_linked_entry = shift @to_link; + @readonly = _more_linked(@readonly); + + # Select a basis for linkage, either the most-linked readonly entry (if + # any) or the most linked of the read-write entries. + my $most_linked_entry = shift @readonly // shift @to_link; foreach my $entry (@to_link) { # XXX there shouldn't be a need to update entries' link counts, # since this generates all the instructions at once From 2d06e1bd1b4240694b9d6d796b2622759c9f8574 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Thu, 20 Jul 2023 17:36:42 -0500 Subject: [PATCH 23/25] CI: Add test for mixed readonly/read-write files --- t/TestFunctions.pm | 16 +++++----- t/some-files-readonly.t | 68 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 7 deletions(-) create mode 100755 t/some-files-readonly.t diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index fc68193..c930840 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -23,6 +23,7 @@ our @EXPORT = qw/ are_hardlinked file_exists filemtime + gen_ident has_mtime mktempdir prep_tar @@ -35,14 +36,9 @@ use constant SCRIPT => $ENV{SCRIPT} // abs_path dirname(__FILE__) . '/../simplif sub are_hardlinked { my ($starter, @files) = @_; - my $gen_ident = sub { - my ($dev, $ino) = stat $_[0]; - return "$dev:$ino"; - }; - - my $starter_ident = $gen_ident->($starter); + my $starter_ident = gen_ident($starter); foreach my $file (@files) { - if ($gen_ident->($file) ne $starter_ident) { + if (gen_ident($file) ne $starter_ident) { return 0; } } @@ -64,6 +60,12 @@ sub filemtime { return (stat $file)[9]; } +sub gen_ident { + my $file = shift; + my ($dev, $ino) = stat $file; + return "$dev:$ino"; +} + sub has_mtime { my ($mtime, @files) = @_; foreach my $file (@files) { diff --git a/t/some-files-readonly.t b/t/some-files-readonly.t new file mode 100755 index 0000000..7120ca0 --- /dev/null +++ b/t/some-files-readonly.t @@ -0,0 +1,68 @@ +#!perl +use strict; +use warnings; + +require Data::Dumper; +use Test::More 'no_plan'; + +use TestFunctions; + +my $test_dir = mktempdir(); + +my %files = ( + rw1 => "$test_dir/rw-dir/1", + rw2 => "$test_dir/rw-dir/2", + ro1 => "$test_dir/ro-dir/ro-file", +); + +PREP: { + mkdir "$test_dir/ro-dir"; + mkdir "$test_dir/rw-dir"; + + # Create two read-write links + put_file($files{rw1}); + link $files{rw1}, $files{rw2}; + + # Create a new less-linked but read-only file with the same contents + put_file($files{ro1}); + + # Lastly, make the directory read-only + chmod 0555, "$test_dir/ro-dir"; +} + +my $ident_ro_before = gen_ident($files{ro1}); +my $ident_rw_before = gen_ident($files{rw1}); + +my ($exit_code, $stdout, $stderr) = run_script_capture('-f', $test_dir); +is $exit_code, 0, 'script should not fail'; + +ok file_exists(values %files), 'files were not accidentally deleted'; +is $ident_ro_before, gen_ident($files{ro1}), 'read-only file should not have been re-linked'; +ok are_hardlinked(values %files), 'all files should become hard-linked ' . prettify_file_idents(values %files); + +isnt $ident_rw_before, gen_ident($files{rw1}), 'the read-write file should become hard-linked'; + +sub put_file { + my @files = @_; + my $bytes = 1_048_576; # 1 MB + foreach my $file (@files) { + open my $fh, '>', $file + or croak("Failed to open file $file for writing: $!"); + for (my $bytes_written = 0; $bytes_written < $bytes; ++$bytes_written) { + print $fh 'A'; + } + close $fh; + } + return; +} + +sub prettify_file_idents { + my @files = @_; + my $d = Data::Dumper->new([{ + map { ($_, gen_ident($_)) } @files + }]); + $d->Indent(1); + $d->Sortkeys(1); + $d->Terse(1); + return $d->Dump; +} From ed9e369069191c0800b97b3a0878b31e5d27108e Mon Sep 17 00:00:00 2001 From: Dan Church Date: Mon, 24 Jul 2023 14:07:19 -0500 Subject: [PATCH 24/25] CI: Fix unused variables --- t/TestFunctions.pm | 9 --------- 1 file changed, 9 deletions(-) diff --git a/t/TestFunctions.pm b/t/TestFunctions.pm index c930840..8214a65 100644 --- a/t/TestFunctions.pm +++ b/t/TestFunctions.pm @@ -105,15 +105,6 @@ sub prep_tar { sub run_script_capture { my @args = @_; my @cmd = (SCRIPT, @args); - - my $stderr = File::Temp->new( - TMPDIR => 1, - CLEANUP => 1, - ); - my $stdout = File::Temp->new( - TMPDIR => 1, - CLEANUP => 1, - ); my $in = ''; my $child_out = gensym(); my $child_err = gensym(); From fd8793787b575dd23fed45afda7accefc74dd6a8 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Mon, 24 Jul 2023 15:54:42 -0500 Subject: [PATCH 25/25] Use perl-squasher project to create all-in-one script --- .editorconfig | 3 ++ .gitmodules | 4 ++ make-allinone.sh | 2 +- util/perl-squasher | 1 + util/squash | 91 ---------------------------------------------- 5 files changed, 9 insertions(+), 92 deletions(-) create mode 100644 .gitmodules create mode 160000 util/perl-squasher delete mode 100755 util/squash diff --git a/.editorconfig b/.editorconfig index b8a739d..af3a9c5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,5 +12,8 @@ indent_size = 4 [*.md] indent_size = 2 +[.gitmodules] +indent_style = tab + [{Makefile,*.mak}] indent_style = tab diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8afe3ee --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "perl-squasher"] + path = util/perl-squasher + url = https://codeberg.org/h3xx/perl-squasher.git + branch = main diff --git a/make-allinone.sh b/make-allinone.sh index 4fe10d9..8f3e79a 100755 --- a/make-allinone.sh +++ b/make-allinone.sh @@ -5,7 +5,7 @@ OUT=$WORKDIR/simplify_static_dir.pl echo "Outputting to $OUT" >&2 shopt -s globstar -"$WORKDIR/util/squash" \ +"$WORKDIR/util/perl-squasher/squash" \ "$WORKDIR/simplify_static_dir-main.pl" \ "$WORKDIR"/lib/**/*.pm \ > "$OUT" diff --git a/util/perl-squasher b/util/perl-squasher new file mode 160000 index 0000000..9d414ab --- /dev/null +++ b/util/perl-squasher @@ -0,0 +1 @@ +Subproject commit 9d414ab346caed6035db5a0512d6c89912a8826c diff --git a/util/squash b/util/squash deleted file mode 100755 index c0bd4af..0000000 --- a/util/squash +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/perl - -# Squashes together the parts of the app into the single script. -# (Adapted from the script that squashes App::Ack - see https://github.com/beyondgrep/ack3) -use warnings; -use strict; - -my $code; -for my $arg (@ARGV) { - my $filename = $arg; - if ($arg =~ /::/) { - my $key = "$arg.pm"; - $key =~ s{::}{/}g; - $filename = $INC{$key} or die "Can't find the file for $arg"; - } - - warn "Reading $filename\n"; - open my $fh, '<', $filename or die "Can't open $filename: $!"; - my $in_pod = 0; - my $in_section = ''; - my $ignore_lines = 0; - my $empty_lines = 0; - while (<$fh>) { - if (/#.*:squash-ignore-start:$/) { - $in_section = 'ignore'; - $ignore_lines = 1; - } elsif (/#.*:squash-ignore-end:$/) { - $in_section = ''; - $ignore_lines = 1; - } - if ($ignore_lines > 0) { - $ignore_lines--; - next; - } - - if ($in_section eq 'ignore') { - $empty_lines = 0 unless /^$/; - $code .= $_; - next; - } - - # Remove repeated newlines between paragraphs - # (Provided of course we're not in an 'ignore' section) - if (/^$/) { - ++$empty_lines; - if ($empty_lines > 1) { - next; - } - } else { - $empty_lines = 0; - } - - if (/#.*:squash-remove-start:$/) { - $in_section = 'remove'; - next; - } elsif (/#.*:squash-remove-end:$/) { - $in_section = ''; - next; - } - next if $in_section eq 'remove'; - next if /#.*:squash-remove-line:$/; - - next if /^\s*1;$/; - - if ($filename =~ /\.pm$/) { - # See if we're in module POD blocks - if (/^=(\w+)/) { - $in_pod = ($1 ne 'cut'); - next; - } - elsif ($in_pod) { - next; - } - next if /^# vi:/; - } - - # Remove Perl::Critic comments. - # I'd like to remove all comments, but this is a start - s{\s*##.+critic.*}{}; - $code .= $_; - } - - # Warn if there were unterminated :squash-*: sections - warn "$filename: Unterminated :squash-$in_section-start: section" if $in_section; - - close $fh; -} - -print $code; - -exit 0;