package Git::Hooks::PerlCritic;
use 5.010;
use strict;
use warnings;

our $VERSION = '0.001001'; # VERSION

use Carp;
use Module::Load 'load';
use Git::Hooks;

(my $CFG = __PACKAGE__) =~ s/.*::/githooks./msx;

sub _changed {
	my $git = shift;

	my @changed
		= grep { /\.(p[lm]|t)$/xms }
		$git->command( qw/diff --cached --name-only --diff-filter=AM/ )

	return \@changed;

sub _set_critic {
   my ($git) = @_;
   my $pc_rc_filename = $git->get_config($CFG => 'profile');

	load 'Perl::Critic';
	load 'Perl::Critic::Violation';
	load 'Perl::Critic::Utils';

	my $pc = Perl::Critic->new('-profile' => $pc_rc_filename//q{});
	my $verbosity = $pc->config->verbose;

	# set the format to be a comment
	my $format = Perl::Critic::Utils::verbosity_to_format( $verbosity );
	Perl::Critic::Violation::set_format( "# $format" );

	return $pc;

sub _check_violations {
   my $git = shift;
	my $files = shift;

	my @violations;
	foreach my $file ( @{$files} ) {
		state $critic = _set_critic($git);

		@violations = $critic->critique( $file );

	return \@violations;

	my ( $git, $commit_msg_file ) = @_;

	my $changed    = _changed( $git );
	my $violations = _check_violations( $git, $changed );

	if ( @{$violations} ) {
		my $pcf = 'Path::Class::File'; load $pcf;
		my $file     = $pcf->new( $commit_msg_file );
		my $contents = $file->slurp;

		# a space is being prepended, suspect internal join, remove it
		( $contents .= "@$violations" ) =~ s/^\ #//xmsg;

		$file->spew( $contents );

	my $git = shift;

	my $changed    = _changed( $git );
	my $violations = _check_violations( $git, $changed );

	if ( @{$violations} ) {
		print @{$violations};
		# . operator causes the array ref to give count, otherwise it would
		# stringify
		croak '# please fix ' . @{$violations} . ' perl critic errors before committing';


# ABSTRACT: Perl Critic hooks for git



=head1 NAME

Git::Hooks::PerlCritic - Perl Critic hooks for git

=head1 VERSION

version 0.001001


Allows you to utilize L<Perl::Critic|Perl::Critic> via
L<git hooks|>
using the L<Git::Hooks|Git::Hooks> framework.

First setup L<|Git::Hooks/"USAGE">

Then you should choose to use only one of the available hooks.

=head1 HOOKS

=head2 pre-commit

	ln -s .git/hooks/pre-commit
	git config --add githooks.plugin PerlCritic

This hook will prevent a commit that doesn't pass L<Perl::Critic|Perl::Critic> from being

=head2 prepare-commit-msg

	ln -s .git/hooks/prepare-commit-msg
	git config --add githooks.plugin PerlCritic

This hook will simply append commented out critic warnings to the commit
message, so you may review them before committing.


Option I<profile> to define a perlcriticrc file. E.g.:

	git config --add githooks.perlcritic.profile subdir/.perlcriticrc

=head1 SEE ALSO


=item L<Git::Hooks|Git::Hooks>

=item L<Perl::Critic|Perl::Critic>

=item Alternative way to use Perl::Critic with Git::Hooks package: L<Git::Hooks::CheckFile|Git::Hooks::CheckFile/"CONFIGURATION">.


=head1 BUGS

Please report any bugs or feature requests on the bugtracker website or by email to

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired

=head1 AUTHORS

=over 4

=item *

Caleb Cushing <>

=item *

Mikko Koivunalho <>



This software is Copyright (c) 2014 by L<|>.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)