--- /dev/null
+blib*
+Makefile
+Makefile.old
+Build
+_build*
+pm_to_blib*
+*.tar.gz
+.lwpcookies
+Test-NoTabs-*
+cover_db
--- /dev/null
+use strict;
+use warnings;
+use Module::Build;
+
+my $builder = Module::Build->new(
+ module_name => 'Test::NoTabs',
+ license => 'perl',
+ dist_author => 'Nick Gerakines <nick@socklabs.com>',
+ dist_version_from => 'lib/Test/NoTabs.pm',
+ requires => {
+ 'Test::More' => 0,
+ 'Test::Builder' => 0,
+ 'File::Spec' => 0,
+ 'FindBin' => 0,
+ 'File::Find' => 0,
+ 'Test::Group' => 0,
+ },
+ add_to_cleanup => [ 'Test-NoTabs-*' ],
+);
+
+$builder->create_build_script();
--- /dev/null
+Revision history for Test-NoTabs
+
+0.1 2006-08-24
+ - Module created and released on an unsuspecting world.
+
+0.2 2006-08-25
+ - Minor code changes and pod updates
+ - Added Makefile.PL for compatibility
+
+0.3 2006-08-26
+ - Added missing dependancy (Test::Group)
\ No newline at end of file
--- /dev/null
+Build.PL
+Makefile.PL
+Changes
+MANIFEST
+META.yml
+README
+lib/Test/NoTabs.pm
+t/00-load.t
+t/04-pod.t
+t/05-pod-coverage.t
+t/11-all.t
+t/12-fail.t
\ No newline at end of file
--- /dev/null
+--- #YAML:1.0
+name: Test-NoTabs
+version: 0.3
+author:
+ - Nick Gerakines <nick@socklabs.com>
+abstract: Check the presence of tabs in your project
+license: perl
+generated_by: Module::Build version 0.2612, without YAML.pm
--- /dev/null
+use Module::Build::Compat;
+Module::Build::Compat->run_build_pl(args => \@ARGV);
+Module::Build::Compat->write_makefile();
\ No newline at end of file
--- /dev/null
+Test-NoTabs
+
+The README is used to introduce the module and provide instructions on
+how to install the module, any machine dependencies it may have (for
+example C compilers and installed libraries) and any other information
+that should be provided before the module is installed.
+
+A README file is required for CPAN modules since CPAN extracts the README
+file from a module distribution so that people browsing the archive
+can use it get an idea of the modules uses. It is usually a good idea
+to provide version information here so that people can decide whether
+fixes for the module are worth downloading.
+
+INSTALLATION
+
+To install this module, run the following commands:
+
+ perl Build.PL
+ ./Build
+ ./Build test
+ ./Build install
+
+
+SUPPORT AND DOCUMENTATION
+
+After installing, you can find documentation for this module with the perldoc command.
+
+ perldoc Test::NoTabs
+
+You can also look for information at:
+
+ Search CPAN
+ http://search.cpan.org/dist/Test-NoTabs
+
+ CPAN Request Tracker:
+ http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-NoTabs
+
+ AnnoCPAN, annotated CPAN documentation:
+ http://annocpan.org/dist/Test-NoTabs
+
+ CPAN Ratings:
+ http://cpanratings.perl.org/d/Test-NoTabs
+
+COPYRIGHT AND LICENCE
+
+Copyright (C) 2006 Nick Gerakines
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
--- /dev/null
+package Test::NoTabs;
+
+use strict;
+use warnings;
+
+use Test::Builder;
+use File::Spec;
+use FindBin qw($Bin);
+use File::Find;
+
+use vars qw( $VERSION $PERL $UNTAINT_PATTERN $PERL_PATTERN);
+
+$VERSION = '0.3.1';
+
+$PERL = $^X || 'perl';
+$UNTAINT_PATTERN = qr|^([-+@\w./:\\]+)$|;
+$PERL_PATTERN = qr/^#!.*perl/;
+
+my %file_find_arg = ($] <= 5.006) ? () : (
+ untaint => 1,
+ untaint_pattern => $UNTAINT_PATTERN,
+ untaint_skip => 1,
+);
+
+my $Test = Test::Builder->new;
+my $updir = File::Spec->updir();
+
+sub import {
+ my $self = shift;
+ my $caller = caller;
+ {
+ no strict 'refs';
+ *{$caller.'::notabs_ok'} = \¬abs_ok;
+ *{$caller.'::all_perl_files_ok'} = \&all_perl_files_ok;
+ }
+ $Test->exported_to($caller);
+ $Test->plan(@_);
+}
+
+sub _all_perl_files {
+ my @all_files = _all_files(@_);
+ return grep { _is_perl_module($_) || _is_perl_script($_) } @all_files;
+}
+
+sub _all_files {
+ my @base_dirs = @_ ? @_ : File::Spec->catdir($Bin, $updir);
+ my @found;
+ my $want_sub = sub {
+ return if ($File::Find::dir =~ m![\\/]?CVS[\\/]|[\\/]?.svn[\\/]!); # Filter out cvs or subversion dirs/
+ return if ($File::Find::dir =~ m![\\/]?blib[\\/]libdoc$!); # Filter out pod doc in dist
+ return if ($File::Find::dir =~ m![\\/]?blib[\\/]man\d$!); # Filter out pod doc in dist
+ return if ($File::Find::name =~ m!Build$!i); # Filter out autogenerated Build script
+ return unless (-f $File::Find::name && -r _);
+ push @found, File::Spec->no_upwards( $File::Find::name );
+ };
+ my $find_arg = {
+ %file_find_arg,
+ wanted => $want_sub,
+ no_chdir => 1,
+ };
+ find( $find_arg, @base_dirs);
+ return @found;
+}
+
+sub notabs_ok {
+ my $file = shift;
+ my $test_txt = shift || "Found tabs in '$file'";
+ $file = _module_to_path($file);
+ open my $fh, $file or do { $Test->ok(0, $test_txt); $Test->diag("Could not open $file: $!"); return; };
+ my $line = 0;
+ while (<$fh>) {
+ $line++;
+ next if (/^\s*#/);
+ next if (/^\s*=.+/ .. /^\s*=(cut|back|end)/);
+ last if (/^\s*(__END__|__DATA__)/);
+ if ( /\t/ ) {
+ $Test->ok(0, $test_txt . " on line $line");
+ return 0;
+ }
+ }
+ $Test->ok(1, $test_txt);
+ return 1;
+}
+
+sub all_perl_files_ok {
+ my @files = _all_perl_files( @_ );
+ _make_plan();
+ foreach my $file ( @files ) {
+ notabs_ok($file);
+ }
+}
+
+sub _is_perl_module {
+ $_[0] =~ /\.pm$/i || $_[0] =~ /::/;
+}
+
+sub _is_perl_script {
+ my $file = shift;
+ return 1 if $file =~ /\.pl$/i;
+ return 1 if $file =~ /\.t$/;
+ open my $fh, $file or return;
+ my $first = <$fh>;
+ return 1 if defined $first && ($first =~ $PERL_PATTERN);
+ return;
+}
+
+sub _module_to_path {
+ my $file = shift;
+ return $file unless ($file =~ /::/);
+ my @parts = split /::/, $file;
+ my $module = File::Spec->catfile(@parts) . '.pm';
+ foreach my $dir (@INC) {
+ my $candidate = File::Spec->catfile($dir, $module);
+ next unless (-e $candidate && -f _ && -r _);
+ return $candidate;
+ }
+ return $file;
+}
+
+sub _make_plan {
+ unless ($Test->has_plan) {
+ $Test->plan( no_plan => 1 );
+ }
+ $Test->expected_tests;
+}
+
+sub _untaint {
+ my @untainted = map { ($_ =~ $UNTAINT_PATTERN) } @_;
+ return wantarray ? @untainted : $untainted[0];
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Test::NoTabs - Check the presence of tabs in your project
+
+=head1 SYNOPSIS
+
+C<Test::NoTabs> lets you check the presence of tabs in your perl code. It
+report its results in standard C<Test::Simple> fashion:
+
+ use Test::NoTabs tests => 1;
+ notabs_ok( 'lib/Module.pm', 'Module is tab free');
+
+Module authors can include the following in a t/notabs.t and have C<Test::NoTabs>
+automatically find and check all perl files in a module distribution:
+
+ use Test::NoTabs;
+ all_perl_files_ok();
+
+or
+
+ use Test::NoTabs;
+ all_perl_files_ok( @mydirs );
+
+=head1 DESCRIPTION
+
+This module scans your project/distribution for any perl files (scripts,
+modules, etc) for the presence of tabs.
+
+=head1 EXPORT
+
+A list of functions that can be exported. You can delete this section
+if you don't export anything, such as for a purely object-oriented module.
+
+=head1 FUNCTIONS
+
+=head2 all_perl_files_ok( [ @directories ] )
+
+Applies C<notabs_ok()> to all perl files found in C<@directories> (and sub
+directories). If no <@directories> is given, the starting point is one level
+above the current running script, that should cover all the files of a typical
+CPAN distribution. A perl file is *.pl or *.pm or *.t or a file starting
+with C<#!...perl>
+
+If the test plan is defined:
+
+ use Test::NoTabs tests => 3;
+ all_perl_files_ok();
+
+the total number of files tested must be specified.
+
+=head2 notabs_ok( $file [, $text] )
+
+Run a tab check on C<$file>. For a module, the path (lib/My/Module.pm) or the
+name (My::Module) can be both used.
+
+=head1 AUTHOR
+
+Nick Gerakines, C<< <nick at socklabs.com> >>
+
+=head1 BUGS
+
+Please report any bugs or feature requests to
+C<bug-test-notabs at rt.cpan.org>, or through the web interface at
+L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-NoTabs>.
+I will be notified, and then you'll automatically be notified of progress on
+your bug as I make changes.
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+ perldoc Test::NoTabs
+
+You can also look for information at:
+
+=over 4
+
+=item * AnnoCPAN: Annotated CPAN documentation
+
+L<http://annocpan.org/dist/Test-NoTabs>
+
+=item * CPAN Ratings
+
+L<http://cpanratings.perl.org/d/Test-NoTabs>
+
+=item * RT: CPAN's request tracker
+
+L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-NoTabs>
+
+=item * Search CPAN
+
+L<http://search.cpan.org/dist/Test-NoTabs>
+
+=back
+
+=head1 ACKNOWLEDGEMENTS
+
+Inspired by some code written by Paul Lindner.
+
+L<Test::Strict> was used as an example when creating this module and
+distribution.
+
+Rick Myers and Emanuele Zeppieri also provided valuable feedback.
+
+=head1 SEE ALSO
+
+L<Test::More>, L<Test::Pod>. L<Test::Distribution>, L<Test:NoWarnings>
+
+=head1 COPYRIGHT & LICENSE
+
+Copyright 2006 Nick Gerakines, all rights reserved.
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
--- /dev/null
+#!perl -T
+
+use Test::More tests => 1;
+
+BEGIN {
+ use_ok( 'Test::NoTabs' );
+}
+
+diag( "Testing Test::NoTabs $Test::NoTabs::VERSION, Perl $], $^X" );
--- /dev/null
+use Test::More;
+eval "use Test::Pod";
+plan skip_all => "Test::Pod required for testing POD" if $@;
+all_pod_files_ok();
--- /dev/null
+use Test::More;
+eval "use Test::Pod::Coverage";
+plan skip_all => "Test::Pod::Coverage required for testing POD coverage" if $@;
+all_pod_coverage_ok();
--- /dev/null
+use strict;
+
+use Test::NoTabs;
+
+use File::Temp qw( tempdir tempfile );
+
+all_perl_files_ok();
+
+notabs_ok( $0, "$0 is tab free" );
+
+my $tabbed_file1 = make_tabbed_file1();
+notabs_ok( $tabbed_file1 );
+
+my $tabbed_file2 = make_tabbed_file2();
+notabs_ok( $tabbed_file2 );
+
+my $tabbed_file3 = make_tabbed_file3();
+notabs_ok( $tabbed_file3 );
+
+
+sub make_tabbed_file1 {
+ my $tmpdir = tempdir();
+ my ($fh, $filename) = tempfile( DIR => $tmpdir, SUFFIX => '.pL' );
+ print $fh <<'DUMMY';
+#!/usr/bin/perl -w
+
+=pod
+
+=head1 NAME
+
+This test script doesn't do anything.
+
+=cut
+
+sub main {
+ my ($name) = @_;
+ print "Hello $name!\n";
+}
+
+DUMMY
+ return $filename;
+}
+
+sub make_tabbed_file2 {
+ my $tmpdir = tempdir();
+ my ($fh, $filename) = tempfile( DIR => $tmpdir, SUFFIX => '.pL' );
+ print $fh <<'DUMMY';
+#!/usr/bin/perl -w
+
+=pod
+
+=head1 NAME
+
+This test script doesn't do anything.
+
+ Its OK to have tabs in pod
+
+=cut
+
+sub main {
+ my ($name) = @_;
+ print "Hello $name!\n";
+}
+
+DUMMY
+ return $filename;
+}
+
+sub make_tabbed_file3 {
+ my $tmpdir = tempdir();
+ my ($fh, $filename) = tempfile( DIR => $tmpdir, SUFFIX => '.pm' );
+ print $fh <<'DUMMY';
+package My::Test;
+
+use strict;
+use warnings;
+
+sub new {
+ my ($class) = @_;
+ my $self = bless {}, $class;
+ return $self;
+}
+
+1;
+__END__
+ I can have tabs here too!
+DUMMY
+ return $filename;
+}
--- /dev/null
+use strict;
+
+use Test::More no_plan => 1;
+
+use Test::Group;
+
+use File::Temp qw( tempdir tempfile );
+
+my $perl = $^X || 'perl';
+my $inc = join(' -I ', @INC) || '';
+$inc = "-I $inc" if $inc;
+
+test 'bad file 1' => sub {
+ my $dir = make_bad_file_1();
+ my ($fh, $outfile) = tempfile();
+ ok( `$perl $inc -MTest::NoTabs -e "all_perl_files_ok( '$dir' )" 2>&1 > $outfile` );
+ local $/ = undef;
+ my $content = <$fh>;
+ like( $content, qr/^not ok 1 - Found tabs in '[^']*' on line 4/m, 'tabs found in tmp file' );
+};
+
+test 'bad file 2' => sub {
+ my $dir = make_bad_file_2();
+ my ($fh, $outfile) = tempfile();
+ ok( `$perl $inc -MTest::NoTabs -e "all_perl_files_ok( '$dir' )" 2>&1 > $outfile` );
+ local $/ = undef;
+ my $content = <$fh>;
+ like( $content, qr/^not ok 1 - Found tabs in '[^']*' on line 12/m, 'tabs found in tmp file' );
+};
+
+test 'bad file 3' => sub {
+ my $file = make_bad_file_3();
+ my ($fh, $outfile) = tempfile();
+ ok( `$perl $inc -MTest::NoTabs -e "all_perl_files_ok( '$file' )" 2>&1 > $outfile` );
+ local $/ = undef;
+ my $content = <$fh>;
+ like( $content, qr/^not ok 1 - Found tabs in '[^']*' on line 6/m, 'tabs found in tmp file' );
+};
+
+sub make_bad_file_1 {
+ my $tmpdir = tempdir();
+ my ($fh, $filename) = tempfile( DIR => $tmpdir, SUFFIX => '.pL' );
+ print $fh <<"DUMMY";
+#!perl
+
+sub main {
+\tprint "Hello!\n";
+}
+DUMMY
+ return $tmpdir;
+}
+
+sub make_bad_file_2 {
+ my $tmpdir = tempdir();
+ my ($fh, $filename) = tempfile( DIR => $tmpdir, SUFFIX => '.pL' );
+ print $fh <<"DUMMY";
+#!perl
+
+=pod
+
+=head1 NAME
+
+test.pL - A test script
+
+=cut
+
+sub main {
+\tprint "Hello!\n";
+}
+DUMMY
+ return $tmpdir;
+}
+
+sub make_bad_file_3 {
+ my $tmpdir = tempdir();
+ my ($fh, $filename) = tempfile( DIR => $tmpdir, SUFFIX => '.pm' );
+ print $fh <<"DUMMY";
+use strict;
+
+package My::Test;
+
+sub new {
+\tmy (\$class) = @_;
+\tmy \$self = bless { }, \$class;
+\treturn \$self;
+}
+
+1;
+__DATA__
+nick gerakines software engineer 22
+DUMMY
+ return $filename;
+}
+
--- /dev/null
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/../lib";
+
+use Config;
+use File::Spec;
+use Test::Chimps::Client;
+use Test::TAP::Model::Visual;
+
+chdir "$FindBin::Bin/..";
+
+my @tests = map glob, qw(t/*.t);
+my $start = time;
+my $model = Test::TAP::Model::Visual->new_with_tests(@tests);
+
+my $client = Test::Chimps::Client->new(
+ server => 'http://dev.socklabs.com/cgi-bin/chimps-server.pl',
+ model => $model,
+ report_variables => {
+ archname => $Config{archname},
+ committer => $ENV{USER} || $ENV{USERNAME},
+ osname => $Config{osname},
+ osvers => $Config{osvers},
+ project => 'Test-NoTabs',
+ duration => time - $start,
+ revision => get_revision(),
+ },
+);
+
+my ($status, $msg) = $client->send;
+if (! $status) {
+ print "Error: $msg\n";
+ exit(1);
+}
+
+sub get_revision {
+ return
+ # extract_revision('svk', 'svk info', qr/Mirrored From: .*Rev\. (\d+)/) ||
+ extract_revision('svn', 'svn info', qr/Revision: (\d+)/) ||
+ extract_svn_revision('.svn/entries') ||
+ 'unknown';
+}
+
+sub extract_revision {
+ my($cmd, $command, $re) = @_;
+
+ return unless has_command($cmd);
+
+ my $out = qx($command) or return;
+ $out =~ /$re/;
+ return $1;
+}
+
+sub has_command {
+ my $cmd = shift;
+ grep { -e File::Spec->catfile($_, $cmd) } split /:/, $ENV{PATH};
+}
+
+sub extract_svn_revision {
+ my $file = shift;
+ open my($fh), $file or return;
+ while (<$fh>) {
+ /revision="(\d+)"/ and return $1;
+ }
+ return;
+}