[libcode-tidyall-perl] 163/374: various

Jonas Smedegaard js at alioth.debian.org
Sun Sep 29 22:26:11 UTC 2013


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository libcode-tidyall-perl.

commit 944645f8bd6ba24cd1a1c2e920401f7e3a4dbc50
Author: Jonathan Swartz <swartz at pobox.com>
Date:   Sun Sep 2 17:57:20 2012 -0700

    various
---
 lib/Code/TidyAll/Git/Precommit.pm |  158 +++++++++++++++++++++++++++++++++++++
 lib/Code/TidyAll/Git/Util.pm      |   22 ++++++
 lib/Code/TidyAll/Util.pm          |    1 +
 lib/Code/TidyAll/t/Git.pm         |   77 ++++++++++++++++++
 xt/author/Git.t                   |    3 +
 5 files changed, 261 insertions(+)

diff --git a/lib/Code/TidyAll/Git/Precommit.pm b/lib/Code/TidyAll/Git/Precommit.pm
new file mode 100644
index 0000000..d942a07
--- /dev/null
+++ b/lib/Code/TidyAll/Git/Precommit.pm
@@ -0,0 +1,158 @@
+package Code::TidyAll::Git::Precommit;
+use Capture::Tiny qw(capture_stdout capture_stderr);
+use Code::TidyAll;
+use Code::TidyAll::Util qw(dirname mkpath realpath tempdir_simple write_file);
+use Cwd qw(cwd);
+use Guard;
+use Log::Any qw($log);
+use IPC::System::Simple qw(capturex run);
+use Moo;
+use SVN::Look;
+use Try::Tiny;
+
+# Public
+has 'conf_file'       => ( is => 'ro', default => sub { "tidyall.ini" } );
+has 'reject_on_error' => ( is => 'ro' );
+has 'tidyall_class'   => ( is => 'ro', default => sub { "Code::TidyAll" } );
+has 'tidyall_options' => ( is => 'ro', default => sub { {} } );
+
+sub check {
+    my ( $class, %params ) = @_;
+
+    my $fail_msg;
+
+    try {
+        my $self          = $class->new(%params);
+        my $tidyall_class = $self->tidyall_class;
+
+        # Find conf file at git root
+        my $root_dir = capturex( "git", "rev-parse", "--show-toplevel" );
+        chomp($root_dir);
+        my $conf_file = join( "/", $root_dir, $self->conf_file );
+        die "could not find conf file '$conf_file'" unless -f $conf_file;
+
+        # Store the stash, and restore it upon exiting this scope
+        run("git stash -q --keep-index");
+        scope_guard { run("git stash pop -q") };
+
+        # Gather file paths to be committed
+        my $output = capturex( "git", "status", "--porcelain" );
+        my @files = ( $output =~ /^[MA]\s+(.*)/gm );
+
+        my $tidyall = $tidyall_class->new_from_conf_file(
+            $conf_file,
+            no_cache   => 1,
+            check_only => 1,
+            mode       => 'commit',
+            %{ $self->tidyall_options },
+        );
+        my @results = $tidyall->process_files( map { "$root_dir/$_" } @files );
+
+        if ( my @error_results = grep { $_->error } @results ) {
+            my $error_count = scalar(@error_results);
+            $fail_msg = join(
+                "\n",
+                sprintf(
+                    "%d file%s did not pass tidyall check",
+                    $error_count, $error_count > 1 ? "s" : ""
+                ),
+                map { join( ": ", $_->path, $_->msg ) } @error_results
+            );
+        }
+    }
+    catch {
+        my $error = $_;
+        die "Error during pre-commit hook (use --no-verify to skip hook):\n$error";
+    };
+    die $fail_msg if $fail_msg;
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Code::TidyAll::Git::Precommit - Git precommit hook that requires files to be
+tidyall'd
+
+=head1 SYNOPSIS
+
+  In .git/hooks/pre-commit:
+
+    #!/usr/bin/perl
+    use Code::TidyAll::Git::Precommit;
+    use strict;
+    use warnings;
+    
+    Code::TidyAll::Git::Precommit->check();
+
+=head1 DESCRIPTION
+
+This module implements a L<Git pre-commit
+hook|http://git-scm.com/book/en/Customizing-Git-Git-Hooks> that checks if all
+files are tidied and valid according to L<tidyall|tidyall>, and rejects the
+commit if not.
+
+=head1 METHODS
+
+=over
+
+=item check (key/value params...)
+
+Class method. Check that all files being added or modified in this commit are
+tidied and valid according to L<tidyall|tidyall>. If not, then the entire
+commit is rejected and the reason(s) are output to the client. e.g.
+
+    % git commit -m "fixups" CHI.pm CHI/Driver.pm 
+    2 files did not pass tidyall check
+    lib/CHI.pm: *** 'PerlTidy': needs tidying
+    lib/CHI/Driver.pm: *** 'PerlCritic': Code before strictures are enabled
+      at /tmp/Code-TidyAll-0e6K/Driver.pm line 2
+      [TestingAndDebugging::RequireUseStrict]
+
+In an emergency the hook can be bypassed by passing --no-verify to commit:
+
+    % git commit --no-verify ...
+
+or you can just move C<.git/hooks/pre-commit> out of the way temporarily.
+
+The configuration file C<tidyall.ini> must be checked into git in the repo root
+directory i.e. next to the .git directory.
+
+The hook will stash any changes not in the index beforehand, and restore them
+afterwards, via
+
+    git stash -q --keep-index
+    ....
+    git stash pop -q
+
+This means that if C<tidyall.ini> has uncommitted changes that are not in the
+index, they will not be used during the tidyall run.
+
+Passes mode = "commit" by default; see L<modes|tidyall/MODES>.
+
+Key/value parameters:
+
+=over
+
+=item no_stash
+
+Don't attempt to stash changes not in the index. This means the hook will
+process all
+
+=item tidyall_class
+
+Subclass to use instead of L<Code::TidyAll|Code::TidyAll>
+
+=item tidyall_options
+
+Hashref of options to pass to the L<Code::TidyAll|Code::TidyAll> constructor
+
+=back
+
+=back
+
+=cut
diff --git a/lib/Code/TidyAll/Git/Util.pm b/lib/Code/TidyAll/Git/Util.pm
new file mode 100644
index 0000000..75600ab
--- /dev/null
+++ b/lib/Code/TidyAll/Git/Util.pm
@@ -0,0 +1,22 @@
+package Code::TidyAll::Git::Util;
+use Cwd qw(realpath);
+use Code::TidyAll::Util qw(pushd uniq);
+use IPC::System::Simple qw(capturex);
+use strict;
+use warnings;
+use base qw(Exporter);
+
+our @EXPORT_OK = qw(git_uncommitted_files);
+
+sub git_uncommitted_files {
+    my ($dir) = @_;
+
+    $dir = realpath($dir);
+    my $pushd  = pushd($dir);
+    my $output = capturex( "git", "status" );
+    my @files  = ( $output =~ /(?:new file|modified):\s+(.*)/g );
+    @files = uniq( map { "$dir/$_" } @files );
+    return @files;
+}
+
+1;
diff --git a/lib/Code/TidyAll/Util.pm b/lib/Code/TidyAll/Util.pm
index 212eb9b..0a0c351 100644
--- a/lib/Code/TidyAll/Util.pm
+++ b/lib/Code/TidyAll/Util.pm
@@ -6,6 +6,7 @@ use File::Path;
 use File::Slurp qw(read_file write_file read_dir);
 use File::Spec::Functions qw(abs2rel rel2abs);
 use File::Temp qw(tempdir);
+use Guard;
 use List::MoreUtils qw(uniq);
 use Try::Tiny;
 use strict;
diff --git a/lib/Code/TidyAll/t/Git.pm b/lib/Code/TidyAll/t/Git.pm
new file mode 100644
index 0000000..dcaa639
--- /dev/null
+++ b/lib/Code/TidyAll/t/Git.pm
@@ -0,0 +1,77 @@
+package Code::TidyAll::t::Git;
+use Capture::Tiny qw(capture_stdout capture_stderr capture);
+use Code::TidyAll::Git::Util qw(git_uncommitted_files);
+use Code::TidyAll::Util qw(dirname mkpath pushd read_file realpath tempdir_simple write_file);
+use Code::TidyAll;
+use IPC::System::Simple qw(run);
+use Test::Class::Most parent => 'Code::TidyAll::Test::Class';
+
+my ( $precommit_hook_template, $tidyall_ini_template );
+
+sub test_git : Tests {
+    my ($self) = @_;
+
+    my $temp_dir  = tempdir_simple;
+    my $work_dir  = "$temp_dir/work";
+    my $hooks_dir = "$work_dir/.git/hooks";
+    my ( $stdout, $stderr );
+
+    my $committed = sub {
+        $stdout = capture_stdout { system('git status') };
+        like( $stdout, qr/nothing to commit/, "committed" );
+    };
+
+    my $uncommitted = sub {
+        $stdout = capture_stdout { system('git status') };
+        unlike( $stdout, qr/nothing to commit/, "uncommitted" );
+    };
+
+    run( "git", "init", $work_dir );
+    ok( -d $_, "$_ exists" ) for ( $work_dir, $hooks_dir );
+    my $pushd = pushd($work_dir);
+
+    write_file( "$work_dir/tidyall.ini", sprintf($tidyall_ini_template) );
+    write_file( "$work_dir/.gitignore",  ".tidyall.d" );
+    run( "git", "add", "tidyall.ini", ".gitignore" );
+    run( "git", "commit", "-m", "added", "tidyall.ini", ".gitignore" );
+
+    write_file( "$work_dir/foo.txt", "abc" );
+    cmp_deeply( [ git_uncommitted_files($work_dir) ], [], "no uncommitted files" );
+
+    run( "git", "add", "foo.txt" );
+    cmp_deeply( [ git_uncommitted_files($work_dir) ],
+        ["$work_dir/foo.txt"], "one uncommitted file" );
+
+    my $precommit_hook_file = "$hooks_dir/pre-commit";
+    my $precommit_hook = sprintf( $precommit_hook_template, realpath("lib") );
+    write_file( $precommit_hook_file, $precommit_hook );
+    chmod( 0775, $precommit_hook_file );
+
+    $stderr = capture_stderr { system( "git", "commit", "-m", "changed", "-a" ) };
+    like( $stderr, qr/1 file did not pass tidyall check/ );
+    like( $stderr, qr/needs tidying/ );
+    $uncommitted->();
+
+    write_file( "$work_dir/foo.txt", "ABC" );
+    $stderr = capture_stderr { system( "git", "commit", "-m", "changed", "-a" ) };
+    like( $stderr, qr/\[checked\] foo\.txt/ );
+    $committed->();
+}
+
+$precommit_hook_template = '#!/usr/bin/perl
+use lib qw(%s);
+use Code::TidyAll::Git::Precommit;
+use strict;
+use warnings;
+
+Code::TidyAll::Git::Precommit->check(
+    tidyall_options => { verbose => 1 }
+);
+';
+
+$tidyall_ini_template = '
+[+Code::TidyAll::Test::Plugin::UpperText]
+select = **/*.txt
+';
+
+1;
diff --git a/xt/author/Git.t b/xt/author/Git.t
new file mode 100644
index 0000000..89e2f84
--- /dev/null
+++ b/xt/author/Git.t
@@ -0,0 +1,3 @@
+#!/usr/bin/perl
+use Code::TidyAll::t::Git;
+Code::TidyAll::t::Git->runtests;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libcode-tidyall-perl.git



More information about the Pkg-perl-cvs-commits mailing list