File Coverage

blib/lib/Test/Perl/Critic/Git.pm
Criterion Covered Total %
statement 99 100 99.0
branch 13 20 65.0
condition 8 16 50.0
subroutine 17 17 100.0
pod 2 2 100.0
total 139 155 89.6


line stmt bran cond sub pod time code
1             package Test::Perl::Critic::Git;
2              
3 1     1   81734 use Cwd;
  1         2  
  1         71  
4 1     1   633 use utf8;
  1         16  
  1         6  
5 1     1   52 use 5.018;
  1         4  
6 1     1   4 use strict;
  1         2  
  1         20  
7 1     1   4 use warnings;
  1         2  
  1         40  
8 1     1   504 use Git::Diff;
  1         24691  
  1         29  
9 1     1   623 use Perl::Critic;
  1         1030474  
  1         55  
10 1     1   9 use Test::Builder;
  1         4  
  1         28  
11 1     1   6 use Perl::Critic::Utils;
  1         2  
  1         13  
12 1     1   876 use Perl::Critic::Violation;
  1         4  
  1         572  
13              
14             $Test::Perl::Critic::Git::VERSION = '0.000105';
15             $Test::Perl::Critic::Git::TEST = Test::Builder->new;
16             %Test::Perl::Critic::Git::CRITIC_ARGS = ();
17             %Test::Perl::Critic::Git::GIT_ARGS = ();
18              
19             sub _matching_files {
20 1     1   10 my ( $ar_dirs, $hr_changed_files ) = @_;
21 1         13 my @a_perlfiles = Perl::Critic::Utils::all_perl_files( @{$ar_dirs} );
  1         22  
22              
23 1         3272 require File::Spec;
24 1         5530 my $s_current_dir = Cwd::cwd;
25              
26 1         31 my @a_files = ();
27 1         21 for my $s_file (@a_perlfiles) {
28 7         31 for ( keys %{$hr_changed_files} ) {
  7         43  
29 21 50 33     308 push @a_files, $_ if ( $s_file eq File::Spec->catfile( $s_current_dir, $_ ) || $s_file eq $_ );
30             }
31             }
32 1         120 return \@a_files;
33             }
34              
35             sub _run_builder {
36 3     3   13 my ( $b_switch, $hr_files, $s_message ) = @_;
37 3 100 50     9 return $Test::Perl::Critic::Git::TEST->ok(!$b_switch, $s_message // '') if scalar keys %{$hr_files} == 0;
  3         47  
38             return $Test::Perl::Critic::Git::TEST->subtest( $s_message, sub {
39 2     2   2760 my $i_files_to_test = 0;
40 2         5 for my $s_file ( sort keys %{$hr_files} ) {
  2         13  
41 2         6 my $hr_file = $hr_files->{$s_file};
42 2         5 $i_files_to_test++;
43 2         5 my @a_violations = grep { exists $hr_file->{addition}->{ $_->line_number } } @{ $hr_file->{violations} };
  2         17  
  2         9  
44 2 100       21 if ( scalar @a_violations > 0 ) {
45 1         10 $Test::Perl::Critic::Git::TEST->ok( $b_switch, qq~File "$s_file" test failed~ );
46 1         423 $Test::Perl::Critic::Git::TEST->diag( qq{Perl::Critic had errors in "$s_file":});
47 1         443 $Test::Perl::Critic::Git::TEST->diag($_) for @a_violations;
48 1         692 next;
49             }
50 1         15 $Test::Perl::Critic::Git::TEST->ok( !$b_switch, $s_file );
51 1         516 $i_files_to_test--;
52             }
53 2 50 66     34 return $Test::Perl::Critic::Git::TEST->ok((( !$b_switch && !$i_files_to_test ) || ( $b_switch && $i_files_to_test ) ) ? 1 : 0, $s_message // '');
      50        
54 2         47 });
55             }
56              
57             sub import {
58 2     2   770 my ( $self, $hr_critic_args, $hr_git_args ) = @_;
59 2         5 my $s_caller = caller;
60             {
61 1     1   10 no strict 'refs'; ## no critic qw(ProhibitNoStrict)
  1         2  
  1         533  
  2         5  
62 2         5 *{ $s_caller . '::critic_on_changed_ok' } = \&critic_on_changed_ok;
  2         11  
63 2         6 *{ $s_caller . '::critic_on_changed_not_ok' } = \&critic_on_changed_not_ok;
  2         8  
64             }
65              
66             # -format is supported for backward compatibility.
67 2 50       8 $hr_critic_args->{-verbose} = $hr_critic_args->{-format} if exists $hr_critic_args->{-format};
68 2         4 %Test::Perl::Critic::Git::CRITIC_ARGS = %{$hr_critic_args};
  2         6  
69 2 50       6 %Test::Perl::Critic::Git::GIT_ARGS = $hr_git_args ? %{$hr_git_args} : ();
  0         0  
70 2         10 return $Test::Perl::Critic::Git::TEST->exported_to($s_caller);
71             }
72              
73             sub critic_on_changed_ok {
74 2     2 1 2523 my ( $ar_dirs, $s_message ) = @_;
75 2 100 66     18 $ar_dirs = [Cwd::cwd] if !$ar_dirs || scalar @{$ar_dirs} == 0;
  2         6444  
76 2         97 my $hr_files = Git::Diff->new(%Test::Perl::Critic::Git::GIT_ARGS)->changes_by_line;
77 2 50       274 $hr_files = { map { ( $hr_files->{$_} ? ( $_, $hr_files->{$_} ) : () ) } @{ _matching_files( $ar_dirs, $hr_files ) } };
  1         18  
  2         24  
78              
79 2         58 my $o_critic = Perl::Critic->new(%Test::Perl::Critic::Git::CRITIC_ARGS);
80 2         1118285 Perl::Critic::Violation::set_format( $o_critic->config->verbose );
81 2         151 $hr_files->{$_}->{violations} = [ $o_critic->critique($_) ] for keys %{$hr_files};
  2         17  
82              
83 2         3676 return _run_builder( 0, $hr_files, $s_message );
84             }
85              
86             sub critic_on_changed_not_ok {
87 1     1 1 2388 my ( $ar_dirs, $s_message ) = @_;
88 1 50 33     40 $ar_dirs = [Cwd::cwd] if !$ar_dirs || scalar @{$ar_dirs} == 0;
  1         9  
89 1         10 my $hr_files = Git::Diff->new(%Test::Perl::Critic::Git::GIT_ARGS)->changes_by_line;
90 1 50       36 $hr_files = { map { ( $hr_files->{$_} ? ( $_, $hr_files->{$_} ) : () ) } @{ _matching_files( $ar_dirs, $hr_files ) } };
  1         16  
  1         5  
91              
92 1         7 my $o_critic = Perl::Critic->new(%Test::Perl::Critic::Git::CRITIC_ARGS);
93 1         549705 Perl::Critic::Violation::set_format( $o_critic->config->verbose );
94 1         58 $hr_files->{$_}->{violations} = [ $o_critic->critique($_) ] for keys %{$hr_files};
  1         15  
95              
96 1         1738 return _run_builder( 1, $hr_files, $s_message );
97             }
98              
99             1;
100              
101             __END__
102              
103             =encoding utf8
104              
105             =head1 NAME
106              
107             Test::Perl::Critic::Git - Test module to run perl critic on changed git files
108              
109             =head1 VERSION
110              
111             Version 0.000105
112              
113             =head1 SUBROUTINES/METHODS
114              
115             =head2 critic_on_changed_ok
116              
117             Run perl critic on changed files and and raises errors, or even not :-D
118              
119             Params:
120              
121             $hr_critic_args - direct import params for L<Perl::Critic|Perl::Critic>
122              
123             $hr_git_args - direct import params for L<Git|Git>
124              
125             =head2 critic_on_changed_not_ok
126              
127             Same as critic_on_changed_ok but vice versa
128              
129             =head1 SYNOPSIS
130              
131             eval "use Test::Perl::Critic::Git";
132             plan skip_all => "Test::Perl::Critic::Git required for testing perl critic" if $@;
133              
134             Test::Perl::Critic::Git->import({
135             -severity => 'brutal',
136             -profile => File::Spec->catfile($Bin, 'critic', 'profilerc'),
137             ...
138             });
139              
140             critic_on_changed_ok([
141             '.',
142             ...
143             ]);
144              
145             critic_on_changed_ok( ['.'], 'critic_on_changed_ok test' );
146              
147             critic_on_changed_not_ok( ['.'], 'critic_on_changed_not_ok test' );
148              
149             =head1 DIAGNOSTICS
150              
151             =head1 DEPENDENCIES
152              
153             =over 4
154              
155             =item * Internal usage
156              
157             L<Carp|Carp>, L<Git::Diff|Git::Diff>, L<Perl::Critic|Perl::Critic>, L<Test::Builder|Test::Builder>,
158             L<Perl::Critic::Utils|Perl::Critic::Utils>, L<Perl::Critic::Violation|Perl::Critic::Violation>
159              
160             =back
161              
162             =head1 INCOMPATIBILITIES
163              
164             =head1 BUGS AND LIMITATIONS
165              
166             A list of current bugs and issues can be found at the CPAN site
167              
168             https://gitlab.com/mziescha/test-perl-critic-git/issues
169              
170             To report a new bug or problem, use the link on this page.
171              
172             =head1 DESCRIPTION
173              
174             Test module to run perl critic on changed git files
175              
176             =head1 CONFIGURATION AND ENVIRONMENT
177              
178             configurable by import sub
179              
180             =head1 AUTHOR
181              
182             Mario Zieschang, C<< <mziescha at cpan.org> >>
183              
184             =head1 LICENSE AND COPYRIGHT
185              
186             =cut