File Coverage

blib/lib/Test/Perl/Critic/Git.pm
Criterion Covered Total %
statement 109 109 100.0
branch 16 24 66.6
condition 7 16 43.7
subroutine 18 18 100.0
pod 2 2 100.0
total 152 169 89.9


line stmt bran cond sub pod time code
1             package Test::Perl::Critic::Git;
2              
3 1     1   69318 use Cwd;
  1         2  
  1         74  
4 1     1   667 use utf8;
  1         15  
  1         5  
5 1     1   49 use 5.018;
  1         4  
6 1     1   6 use strict;
  1         2  
  1         21  
7 1     1   7 use warnings;
  1         2  
  1         30  
8 1     1   438 use Git::Diff;
  1         24957  
  1         35  
9 1     1   12 use File::Spec;
  1         2  
  1         23  
10 1     1   768 use Perl::Critic;
  1         1084151  
  1         53  
11 1     1   10 use Test::Builder;
  1         3  
  1         26  
12 1     1   12 use Perl::Critic::Utils;
  1         2  
  1         14  
13 1     1   898 use Perl::Critic::Violation;
  1         2  
  1         683  
14              
15             $Test::Perl::Critic::Git::VERSION = '0.000200';
16             $Test::Perl::Critic::Git::TEST = Test::Builder->new;
17             %Test::Perl::Critic::Git::CRITIC_ARGS = ();
18             %Test::Perl::Critic::Git::CHECK_ARGS = ();
19              
20             sub _matching_files {
21 1     1   4 my ( $ar_dirs, $hr_changed_files ) = @_;
22 1         2 my @a_perlfiles = Perl::Critic::Utils::all_perl_files( @{$ar_dirs} );
  1         7  
23 1 50       3440 if ( exists $Test::Perl::Critic::Git::CHECK_ARGS{explicit} ) {
24 1         2 my $rx_exclude = '\.(' . join( q/|/, @{ $Test::Perl::Critic::Git::CHECK_ARGS{explicit} } ) . ')$';
  1         5  
25 1         2 @a_perlfiles = grep { /$rx_exclude/sxm } @a_perlfiles;
  7         33  
26             }
27              
28 1         5690 my $s_current_dir = Cwd::cwd;
29 1         31 my @a_files = ();
30 1         22 for my $s_file (@a_perlfiles) {
31 1         15 for ( keys %{$hr_changed_files} ) {
  1         90  
32 4 50 33     124 push @a_files, $_ if ( $s_file eq File::Spec->catfile( $s_current_dir, $_ ) || $s_file eq $_ );
33             }
34             }
35 1         118 return \@a_files;
36             }
37              
38             sub _run_builder {
39 3     3   17 my ( $b_switch, $hr_files, $s_message ) = @_;
40 3 100 50     14 return $Test::Perl::Critic::Git::TEST->ok( !$b_switch, $s_message // '' ) if scalar keys %{$hr_files} == 0;
  3         46  
41             return $Test::Perl::Critic::Git::TEST->subtest(
42             $s_message,
43             sub {
44 2     2   2642 my $i_files_to_test = 0;
45 2         5 for my $s_file ( sort keys %{$hr_files} ) {
  2         10  
46 2         6 my $hr_file = $hr_files->{$s_file};
47 2         13 $i_files_to_test++;
48 2         5 my @a_violations = grep { exists $hr_file->{addition}->{ $_->line_number } } @{ $hr_file->{violations} };
  2         13  
  2         7  
49 2 100       52 if ( scalar @a_violations > 0 ) {
50 1         11 $Test::Perl::Critic::Git::TEST->ok( $b_switch, qq~File "$s_file" test failed~ );
51 1         415 $Test::Perl::Critic::Git::TEST->diag(qq{Perl::Critic had errors in "$s_file":});
52 1         438 $Test::Perl::Critic::Git::TEST->diag($_) for @a_violations;
53 1         713 next;
54             }
55 1         14 $Test::Perl::Critic::Git::TEST->ok( !$b_switch, $s_file );
56 1         500 $i_files_to_test--;
57             }
58 2 50 66     31 return $Test::Perl::Critic::Git::TEST->ok( ( ( !$b_switch && !$i_files_to_test ) || ( $b_switch && $i_files_to_test ) ) ? 1 : 0, $s_message // '' );
      50        
59             }
60 2         41 );
61             }
62              
63             sub import {
64 2     2   656 my ( $self, $hr_critic_args, $hr_git_args, $hr_check_args ) = @_;
65 2         5 my $s_caller = caller;
66             {
67 1     1   12 no strict 'refs'; ## no critic qw(ProhibitNoStrict)
  1         10  
  1         568  
  2         5  
68 2         6 *{ $s_caller . '::critic_on_changed_ok' } = \&critic_on_changed_ok;
  2         11  
69 2         4 *{ $s_caller . '::critic_on_changed_not_ok' } = \&critic_on_changed_not_ok;
  2         8  
70             }
71              
72             # -format is supported for backward compatibility.
73 2 50       8 $hr_critic_args->{-verbose} = $hr_critic_args->{-format} if exists $hr_critic_args->{-format};
74 2         5 %Test::Perl::Critic::Git::CRITIC_ARGS = %{$hr_critic_args};
  2         20  
75 2 100       8 %Test::Perl::Critic::Git::GIT_ARGS = $hr_git_args ? %{$hr_git_args} : ();
  1         3  
76 2 100       5 %Test::Perl::Critic::Git::CHECK_ARGS = $hr_check_args ? %{$hr_check_args} : ();
  1         4  
77 2         12 return $Test::Perl::Critic::Git::TEST->exported_to($s_caller);
78             }
79              
80             sub critic_on_changed_ok {
81 2     2 1 4028 my ( $ar_dirs, $s_message ) = @_;
82 2 50 33     18 $ar_dirs = [Cwd::cwd] if !$ar_dirs || scalar @{$ar_dirs} == 0;
  2         14  
83 2         20 my $hr_files = Git::Diff->new(%Test::Perl::Critic::Git::GIT_ARGS)->changes_by_line;
84 2 50       86 $hr_files = { map { ( $hr_files->{$_} ? ( $_, $hr_files->{$_} ) : () ) } @{ _matching_files( $ar_dirs, $hr_files ) } };
  1         25  
  2         9  
85              
86 2         72 my $o_critic = Perl::Critic->new(%Test::Perl::Critic::Git::CRITIC_ARGS);
87 2         1268041 Perl::Critic::Violation::set_format( $o_critic->config->verbose );
88 2         130 $hr_files->{$_}->{violations} = [ $o_critic->critique($_) ] for keys %{$hr_files};
  2         23  
89 2         3339 return _run_builder( 0, $hr_files, $s_message );
90             }
91              
92             sub critic_on_changed_not_ok {
93 1     1 1 3199 my ( $ar_dirs, $s_message ) = @_;
94 1 50 33     13 $ar_dirs = [Cwd::cwd] if !$ar_dirs || scalar @{$ar_dirs} == 0;
  1         14  
95 1         9 my $hr_files = Git::Diff->new(%Test::Perl::Critic::Git::GIT_ARGS)->changes_by_line;
96 1 50       36 $hr_files = { map { ( $hr_files->{$_} ? ( $_, $hr_files->{$_} ) : () ) } @{ _matching_files( $ar_dirs, $hr_files ) } };
  1         15  
  1         6  
97              
98 1         9 my $o_critic = Perl::Critic->new(%Test::Perl::Critic::Git::CRITIC_ARGS);
99 1         618646 Perl::Critic::Violation::set_format( $o_critic->config->verbose );
100 1         56 $hr_files->{$_}->{violations} = [ $o_critic->critique($_) ] for keys %{$hr_files};
  1         9  
101              
102 1         1744 return _run_builder( 1, $hr_files, $s_message );
103             }
104              
105             1;
106              
107             __END__
108              
109             =encoding utf8
110              
111             =head1 NAME
112              
113             Test::Perl::Critic::Git - Test module to run perl critic on changed git files
114              
115             =head1 VERSION
116              
117             Version 0.000200
118              
119             =head1 SUBROUTINES/METHODS
120              
121             =head2 critic_on_changed_ok
122              
123             Run perl critic on changed files and and raises errors, or even not :-D
124              
125             Params:
126              
127             Arrayref of String from directories which should be tested in the git-project.
128              
129             =head2 critic_on_changed_not_ok
130              
131             Same as critic_on_changed_ok but vice versa
132              
133             =head2 import
134              
135             Params:
136              
137             Hash-Ref: direct import params for L<Perl::Critic|Perl::Critic>
138             Hash-Ref: direct import params for L<Git|Git>
139             Hash-Ref: params in which conditions should be checked.
140              
141             =head1 SYNOPSIS
142              
143             eval "use Test::Perl::Critic::Git";
144             plan skip_all => "Test::Perl::Critic::Git required for testing perl critic" if $@;
145              
146             Test::Perl::Critic::Git->import({
147             -severity => 'brutal',
148             -profile => File::Spec->catfile($Bin, 'critic', 'profilerc'),
149             ...
150             });
151              
152             or
153              
154             Test::Perl::Critic::Git->import(
155             {
156             -severity => 'brutal',
157             -profile => File::Spec->catfile($Bin, 'critic', 'profilerc'),
158             ...
159             },
160             {
161             Directory => '/srv/git/cogito.git'
162             }
163             );
164              
165             or
166              
167             Test::Perl::Critic::Git->import(
168             {
169             -severity => 'brutal',
170             -profile => File::Spec->catfile($Bin, 'critic', 'profilerc'),
171             ...
172             }, {},
173             # do not test pl files and unit tests
174             {
175             exclude => ['pl','t']
176             }
177             );
178              
179             critic_on_changed_ok([
180             '.',
181             ...
182             ]);
183              
184             critic_on_changed_ok( ['.'], 'critic_on_changed_ok test' );
185              
186             critic_on_changed_not_ok( ['.'], 'critic_on_changed_not_ok test' );
187              
188             =head1 DIAGNOSTICS
189              
190             =head1 DEPENDENCIES
191              
192             =over 4
193              
194             =item * Internal usage
195              
196             L<Carp|Carp>, L<Git::Diff|Git::Diff>, L<Perl::Critic|Perl::Critic>, L<Test::Builder|Test::Builder>,
197             L<Perl::Critic::Utils|Perl::Critic::Utils>, L<Perl::Critic::Violation|Perl::Critic::Violation>
198              
199             =back
200              
201             =head1 INCOMPATIBILITIES
202              
203             =head1 BUGS AND LIMITATIONS
204              
205             A list of current bugs and issues can be found at the CPAN site
206              
207             https://gitlab.com/mziescha/test-perl-critic-git/issues
208              
209             To report a new bug or problem, use the link on this page.
210              
211             =head1 DESCRIPTION
212              
213             Test module to run perl critic on changed git files
214              
215             =head1 CONFIGURATION AND ENVIRONMENT
216              
217             configurable by import sub
218              
219             =head1 AUTHOR
220              
221             Mario Zieschang, C<< <mziescha at cpan.org> >>
222              
223             =head1 LICENSE AND COPYRIGHT
224              
225             =cut