| File: | lib/CheckSpelling/CleanupFiles.pm |
| Coverage: | 100.0% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | #! -*-perl-*- | |||||
| 2 | ||||||
| 3 | package CheckSpelling::CleanupFiles; | |||||
| 4 | ||||||
| 5 | 1 1 1 | 111609 1 27 | use Cwd 'realpath'; | |||
| 6 | 1 1 1 | 1 1 15 | use File::Spec; | |||
| 7 | 1 1 1 | 158 1 16 | use CheckSpelling::Util; | |||
| 8 | 1 1 1 | 262 1 16 | use CheckSpelling::CheckDictionary; | |||
| 9 | 1 1 1 | 150 1 13 | use CheckSpelling::CheckPattern; | |||
| 10 | 1 1 1 | 236 1 17 | use CheckSpelling::EnglishList; | |||
| 11 | 1 1 1 | 4 1 493 | use Cwd qw(abs_path); | |||
| 12 | ||||||
| 13 | sub identity { | |||||
| 14 | 13 | 6 | my ($line) = @_; | |||
| 15 | 13 | 11 | return ($line, ''); | |||
| 16 | } | |||||
| 17 | ||||||
| 18 | sub call_check_line { | |||||
| 19 | 26 | 18 | my ($line) = @_; | |||
| 20 | 26 | 5 | my $warning; | |||
| 21 | 26 | 10 | our ($check_line, $output_fh, $warnings_fh); | |||
| 22 | 26 | 17 | ($line, $warning) = $check_line->($line); | |||
| 23 | 26 | 18 | if ($warning ne '') { | |||
| 24 | 3 | 6 | print $warnings_fh "$ARGV:$.:$warning"; | |||
| 25 | } | |||||
| 26 | 26 | 54 | print $output_fh $line."\n"; | |||
| 27 | } | |||||
| 28 | ||||||
| 29 | sub clean_files { | |||||
| 30 | 8 | 10919 | my @files = @_; | |||
| 31 | 8 | 10 | CheckSpelling::CheckPattern::reset_seen(); | |||
| 32 | 8 | 8 | my $type=CheckSpelling::Util::get_file_from_env('type'); | |||
| 33 | 8 | 8 | my $output=CheckSpelling::Util::get_file_from_env('output', '/dev/null'); | |||
| 34 | 8 | 4 | my $workspace_path=abs_path(CheckSpelling::Util::get_file_from_env('GITHUB_WORKSPACE', '.')); | |||
| 35 | 8 | 6 | my $used_config_files=CheckSpelling::Util::get_file_from_env('used_config_files', '/dev/null'); | |||
| 36 | 8 | 41 | $ENV{comment_char}='\s*#'; | |||
| 37 | 1 1 1 8 | 2 0 4 7 | open our $warnings_fh, '>>:encoding(UTF-8)', CheckSpelling::Util::get_file_from_env('early_warnings', '/dev/null'); | |||
| 38 | 8 | 12590 | open our $output_fh, '>>:encoding(UTF-8)', $output; | |||
| 39 | 8 | 201 | open my $used_config_files_fh, '>>:encoding(UTF-8)', $used_config_files; | |||
| 40 | 8 | 113 | my $old_file; | |||
| 41 | 8 | 3 | our $check_line; | |||
| 42 | ||||||
| 43 | 8 | 21 | if ($type =~ /^(?:line_forbidden|patterns|excludes|only|reject)$/) { | |||
| 44 | 1 | 1 | $check_line = \&CheckSpelling::CheckPattern::process_line; | |||
| 45 | } elsif ($type =~ /^(?:dictionary|expect|allow)$/) { | |||||
| 46 | 1 | 1 | $check_line = \&CheckSpelling::CheckDictionary::process_line; | |||
| 47 | } else { | |||||
| 48 | 6 | 5 | $check_line = \&identity; | |||
| 49 | } | |||||
| 50 | ||||||
| 51 | 8 | 8 | for my $file (@files) { | |||
| 52 | 13 | 187 | my $maybe_bad=abs_path($file); | |||
| 53 | 13 | 43 | if ($maybe_bad !~ /^\Q$workspace_path\E/) { | |||
| 54 | 1 | 18 | print "::error ::Configuration files must live within $workspace_path...\n"; | |||
| 55 | 1 | 3 | print "::error ::Unfortunately, file '$file' appears to reside elsewhere.\n"; | |||
| 56 | 1 | 11 | return 3; | |||
| 57 | } | |||||
| 58 | 12 | 12 | if ($maybe_bad =~ m{/\.git/}i) { | |||
| 59 | 1 | 13 | print "::error ::Configuration files must not live within `.git/`...\n"; | |||
| 60 | 1 | 3 | print "::error ::Unfortunately, file '$file' appears to.\n"; | |||
| 61 | 1 | 5 | return 4; | |||
| 62 | } | |||||
| 63 | 11 | 10 | my $fh; | |||
| 64 | 11 | 85 | if (open($fh, '<:encoding(UTF-8)', $file)) { | |||
| 65 | 10 | 181 | $ARGV = $file; | |||
| 66 | 10 | 17 | print $used_config_files_fh "$file\0"; | |||
| 67 | 10 | 12 | seek($fh, -1, 2); | |||
| 68 | 10 | 89 | read($fh, $buffer, 1); | |||
| 69 | 10 | 26 | my $length = tell($fh); | |||
| 70 | 10 | 12 | seek($fh, 0, 0); | |||
| 71 | 10 | 6 | my $add_nl_at_eof = 0; | |||
| 72 | 10 | 5 | if ($length == 0) { | |||
| 73 | 3 | 41 | print STDERR "$file:1:1 ... 1, Notice - File is empty (empty-file)\n"; | |||
| 74 | } else { | |||||
| 75 | 7 | 13 | if ($buffer !~ /\R/) { | |||
| 76 | 1 | 1 | $add_nl_at_eof = 1; | |||
| 77 | } | |||||
| 78 | # local $/ = undef; | |||||
| 79 | 7 | 6 | my ($nl, $first_end, $end, $line); | |||
| 80 | 7 | 0 | my %eol_counts; | |||
| 81 | 7 | 3 | my $content = ''; | |||
| 82 | 7 | 17 | while (!eof($fh)) { | |||
| 83 | 7 | 26 | read $fh, $buffer, 4096; | |||
| 84 | 7 | 6 | $content .= $buffer; | |||
| 85 | 7 | 16 | while ($content =~ s/([^\r\n\x0b\f\x85\x{2028}\x{2029}]*)(\r\n|\n|\r|\x0b|\f|\x85|\x{2028}|\x{2029})//m) { | |||
| 86 | 25 | 16 | ++$.; | |||
| 87 | 25 | 19 | my ($line, $end) = ($1, $2); | |||
| 88 | 25 | 21 | unless (defined $nl) { | |||
| 89 | 7 | 2 | $nl = $end; | |||
| 90 | } elsif ($end ne $nl) { | |||||
| 91 | print $warnings_fh "$file:$.:$-[0] ... $+[0], Warning - Entry has inconsistent line endings (unexpected-line-ending)\n"; | |||||
| 92 | } | |||||
| 93 | 25 | 20 | ++$eol_counts{$end}; | |||
| 94 | 25 | 10 | my $warning; | |||
| 95 | 25 | 14 | call_check_line($line); | |||
| 96 | } | |||||
| 97 | } | |||||
| 98 | 7 | 7 | if ($content ne '') { | |||
| 99 | 1 | 1 | call_check_line($content); | |||
| 100 | } | |||||
| 101 | 7 | 7 | if ($add_nl_at_eof) { | |||
| 102 | 1 | 1 | my $line_length = length $_; | |||
| 103 | 1 | 5 | print STDERR "$file:$.:1 ... $length, Warning - Missing newline at end of file (no-newline-at-eof)\n"; | |||
| 104 | 1 | 1 | print $output_fh "\n"; | |||
| 105 | } | |||||
| 106 | 7 | 9 | my $eol_a = $eol_counts{"\n"} || 0; | |||
| 107 | 7 | 11 | my $eol_d = $eol_counts{"\r"} || 0; | |||
| 108 | 7 | 9 | my $eol_d_a = $eol_counts{"\r\n"} || 0; | |||
| 109 | 7 | 1 | my @line_endings; | |||
| 110 | 7 | 14 | push @line_endings, "DOS [$eol_d_a]" if $eol_d_a; | |||
| 111 | 7 | 7 | push @line_endings, "UNIX [$eol_a]" if $eol_a; | |||
| 112 | 7 | 4 | push @line_endings, "Mac classic [$eol_d]" if $eol_d; | |||
| 113 | 7 | 7 | if (scalar @line_endings > 1) { | |||
| 114 | 1 | 1 | my $line_length = length $_; | |||
| 115 | 1 | 2 | my $mixed_endings = CheckSpelling::EnglishList::build(@line_endings); | |||
| 116 | 1 | 16 | printf STDERR "$file:$.:1 ... $length, Warning - Mixed $mixed_endings line endings (mixed-line-endings)\n"; | |||
| 117 | } | |||||
| 118 | } | |||||
| 119 | 10 | 49 | close($fh); | |||
| 120 | } | |||||
| 121 | } | |||||
| 122 | 6 | 28 | close $used_config_files_fh; | |||
| 123 | 6 | 67 | close $output_fh; | |||
| 124 | 6 | 44 | close $warnings_fh; | |||
| 125 | 6 | 13 | return 0; | |||
| 126 | } | |||||
| 127 | ||||||
| 128 | 1; | |||||