File Coverage

blib/lib/App/GitHooks/Plugin/DetectCommitNoVerify.pm
Criterion Covered Total %
statement 37 42 88.1
branch 4 8 50.0
condition n/a
subroutine 8 8 100.0
pod 1 1 100.0
total 50 59 84.7


line stmt bran cond sub pod time code
1             package App::GitHooks::Plugin::DetectCommitNoVerify;
2              
3 5     5   1992204 use strict;
  5         12  
  5         207  
4 5     5   30 use warnings;
  5         10  
  5         161  
5              
6 5     5   29 use base 'App::GitHooks::Plugin';
  5         14  
  5         1811  
7              
8             # External dependencies.
9 5     5   8877 use Capture::Tiny qw();
  5         165919  
  5         630  
10              
11             # Internal dependencies.
12 5     5   1187 use App::GitHooks::Constants qw( :PLUGIN_RETURN_CODES );
  5         611  
  5         1435  
13 5     5   5373 use App::GitHooks::Hook::PreCommit;
  5         55993  
  5         3624  
14              
15              
16             =head1 NAME
17              
18             App::GitHooks::Plugin::DetectCommitNoVerify - Find out when someone uses --no-verify and append the pre-commit checks to the commit message.
19              
20              
21             =head1 DESCRIPTION
22              
23             Sometimes you just have to use C<--no-verify> to get past the checks and commit
24             as fast as possible. To prevent this from being too tempting, this plugin
25             checks when you use --no-verify and runs the pre-commit checks if you've
26             skipped them. It will let you commit even if the pre-commit checks fail, but it
27             will add their output to the commit message for posterity (and public shaming).
28              
29              
30             =head1 VERSION
31              
32             Version 1.0.2
33              
34             =cut
35              
36             our $VERSION = '1.0.2';
37              
38              
39             =head1 METHODS
40              
41             =head2 run_prepare_commit_msg()
42              
43             Code to execute as part of the prepare-commit-msg hook.
44              
45             my $success = App::GitHooks::Plugin::DetectCommitNoVerify->run_prepare_commit_msg();
46              
47             =cut
48              
49             sub run_prepare_commit_msg
50             {
51 2     2 1 36940 my ( $class, %args ) = @_;
52 2         8 my $app = delete( $args{'app'} );
53 2         6 my $commit_message = delete( $args{'commit_message'} );
54 2         14 my $repository = $app->get_repository();
55              
56             # Check if we've run the pre-commit hook.
57 2 50       399258 return $PLUGIN_RETURN_SKIPPED
58             if -e '.git/COMMIT-MSG-CHECKS';
59              
60             # Check the changes and gather the output.
61 2         22 my $changes_pass;
62             my $stdout = Capture::Tiny::capture_stdout(
63             sub
64             {
65             # Pretend we're running the pre-commit hook here to gather its output.
66 2     2   2822 my $local_app = $app->clone(
67             name => 'pre-commit',
68             );
69              
70             # Git commit messages don't seem to like utf8, so force disabling it.
71 2         850 my $terminal = $local_app->get_terminal();
72 2         34 $terminal->is_utf8(0);
73              
74             # Run all the tests for the pre-commit hook.
75 2         70 $changes_pass = App::GitHooks::Hook::PreCommit::run_all_tests( $local_app );
76             }
77 2         222 );
78              
79 1 50       454910 if ( !$changes_pass )
80             {
81             # "git revert" bypasses the pre-commit hook, so we can only use use the
82             # prepare-commit-msg hook to catch any show-stoppers.
83             # Since prepare-commit-msg doesn't support --no-verify, we should only
84             # perform the essential checks when we're analyzing a revert. Note that you
85             # can still do chmod -x .git/hooks/prepare-commit-msg to force-bypass this
86             # hook in this case.
87 1         18 my $staged_changes = $app->get_staged_changes();
88 1 50       120 if ( $staged_changes->is_revert() )
89             {
90 0         0 chomp( $stdout );
91 0         0 print $stdout, "\n";
92 0         0 print "\n";
93 0         0 print $app->color( 'red', "Fix the errors above and use 'git commit' to complete the revert." ) . "\n";
94 0         0 return $PLUGIN_RETURN_FAILED;
95             }
96              
97             # If output was generated by the pre-commit hooks, append it to the commit
98             # message.
99 1 50       115 if ( $stdout =~ /\w/ )
100             {
101 1         9 chomp( $stdout );
102              
103             # Git commit messages don't support ANSI control characters (which we
104             # use for colors), so we need to strip those out.
105 1         7 $stdout =~ s/\e\[[\d;]*[a-zA-Z]//g;
106              
107             # We need to append $stdout to $commit_message, as $commit_message will
108             # contain the message passed via -m and this should be at the top of
109             # the final message.
110 1         17 $commit_message->update_message( $commit_message->get_message() . "\n\n" . $stdout );
111             }
112             }
113              
114 1         50 return $PLUGIN_RETURN_PASSED;
115             }
116              
117              
118             =head1 BUGS
119              
120             Please report any bugs or feature requests through the web interface at
121             L.
122             I will be notified, and then you'll automatically be notified of progress on
123             your bug as I make changes.
124              
125              
126             =head1 SUPPORT
127              
128             You can find documentation for this module with the perldoc command.
129              
130             perldoc App::GitHooks::Plugin::DetectCommitNoVerify
131              
132              
133             You can also look for information at:
134              
135             =over
136              
137             =item * GitHub's request tracker
138              
139             L
140              
141             =item * AnnoCPAN: Annotated CPAN documentation
142              
143             L
144              
145             =item * CPAN Ratings
146              
147             L
148              
149             =item * MetaCPAN
150              
151             L
152              
153             =back
154              
155              
156             =head1 AUTHOR
157              
158             L,
159             C<< >>.
160              
161              
162             =head1 COPYRIGHT & LICENSE
163              
164             Copyright 2013-2014 Guillaume Aubert.
165              
166             This program is free software: you can redistribute it and/or modify it under
167             the terms of the GNU General Public License version 3 as published by the Free
168             Software Foundation.
169              
170             This program is distributed in the hope that it will be useful, but WITHOUT ANY
171             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
172             PARTICULAR PURPOSE. See the GNU General Public License for more details.
173              
174             You should have received a copy of the GNU General Public License along with
175             this program. If not, see http://www.gnu.org/licenses/
176              
177             =cut
178              
179             1;