Code-TidyAll
view release on metacpan or search on metacpan
lib/Code/TidyAll/Git/Prereceive.pm view on Meta::CPAN
else {
print STDERR "*** Error running pre-receive hook (allowing push to proceed):\n$error";
}
};
die "$fail_msg\n" if $fail_msg;
}
sub check_input {
my ( $self, $input ) = @_;
my @lines = split( "\n", $input );
my ( @results, $tidyall );
foreach my $line (@lines) {
chomp($line);
my ( $base, $commit, $ref ) = split( /\s+/, $line );
# Create tidyall using configuration found in first commit
#
$tidyall ||= $self->create_tidyall($commit);
my @files = $self->get_changed_files( $base, $commit );
foreach my $file (@files) {
my $contents = $self->get_file_contents( $file, $commit );
if ( $contents =~ /\S/ && $contents =~ /\n/ ) {
push( @results, $tidyall->process_source( $contents, $file ) );
}
}
}
my $fail_msg;
if ( my @error_results = grep { $_->error } @results ) {
unless ( $self->check_repeated_push($input) ) {
my $error_count = scalar(@error_results);
$fail_msg = sprintf(
'%d file%s did not pass tidyall check',
$error_count, $error_count > 1 ? 's' : q{}
);
}
}
return $fail_msg;
}
sub create_tidyall {
my ( $self, $commit ) = @_;
my $temp_dir = tempdir_simple();
my @conf_names = $self->conf_name ? ( $self->conf_name ) : Code::TidyAll->default_conf_names;
my ($conf_file) = grep { $self->get_file_contents( $_, $commit ) } @conf_names
or die sprintf( 'could not find conf file %s', join( ' or ', @conf_names ) );
foreach my $rel_file ( $conf_file, @{ $self->extra_conf_files } ) {
my $contents = $self->get_file_contents( $rel_file, $commit )
or die sprintf( q{could not find file '%s' in repo root}, $rel_file );
$temp_dir->child($rel_file)->spew($contents);
}
my $tidyall = $self->tidyall_class->new_from_conf_file(
"$temp_dir/" . $conf_file,
mode => 'commit',
quiet => 1,
%{ $self->tidyall_options },
no_cache => 1,
no_backups => 1,
check_only => 1,
);
return $tidyall;
}
sub get_changed_files {
my ( $self, $base, $commit ) = @_;
my $output = capturex( $self->git_path, 'diff', '--numstat', '--name-only', "$base..$commit" );
my @files = grep {/\S/} split( "\n", $output );
return @files;
}
sub get_file_contents {
my ( $self, $file, $commit ) = @_;
my ( $contents, $error ) = capture { system( $self->git_path, 'show', "$commit:$file" ) };
return $contents;
}
sub check_repeated_push {
my ( $self, $input ) = @_;
my $allow = $self->allow_repeated_push;
return 0 unless defined $allow;
my $cwd = path($0)->realpath->parent;
my $last_push_file = $cwd->child('.prereceive_lastpush');
if ( -w $cwd || -w $last_push_file ) {
my $push_sig = sha1_hex($input);
if ( -f $last_push_file ) {
my ( $last_push_sig, $count ) = split( /\s+/, $last_push_file->slurp );
if ( $last_push_sig eq $push_sig ) {
++$count;
print STDERR "*** Identical push seen $count times\n";
if ( $count >= $allow ) {
print STDERR "*** Allowing push to proceed despite errors\n";
unlink($last_push_file);
return 1;
}
$last_push_file->spew( join( q{ }, $push_sig, $count ) );
return 0;
}
}
$last_push_file->spew( join( q{ }, $push_sig, 1 ) );
}
return 0;
}
1;
# ABSTRACT: Git pre-receive hook that requires files to be tidyall'd
__END__
=pod
=encoding UTF-8
=head1 NAME
( run in 2.382 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )