package Git::Repository::Plugin::Test;
our $VERSION = '0.005'; # VERSION: generated by DZP::OurPkgVersion

use base 'Git::Repository::Plugin';
use base 'Test::Builder::Module';

use Carp qw();
use File::Copy qw();
use File::Spec qw();
use File::Temp qw();

sub _keywords { qw( run_exit_ok run_exit_is branch_exists branch_not_exists ) }

sub run_exit_ok {
    my $repo = shift;
    return _run_exit($repo, 0, @_);
}

sub run_exit_is {
    return _run_exit(@_);
}

sub branch_exists {
    my $repo = shift;
    my $branch = shift;

    my $tb = __PACKAGE__->builder;
    $repo->run('show-ref', '--verify', '--quiet', _normalize_branchname($branch));
    my $exit = $? >> 8;
    return $tb->ok($exit == 0, qq('$branch' branch exists));
}

sub branch_not_exists {
    my $repo = shift;
    my $branch = shift;

    my $tb = __PACKAGE__->builder;
    $repo->run('show-ref', '--verify', '--quiet', _normalize_branchname($branch));
    my $exit = $? >> 8;
    return $tb->ok($exit == 1, qq('$branch' branch does not exist));
}

# Private Subs

sub _normalize_branchname {
    my $branch = shift;
    unless (index($branch, 'refs/heads/') == 0) {
        $branch = 'refs/heads/' . $branch;
    }
    return $branch;
}

sub _run_exit {
    my $repo = shift;
    my $expected_exit = shift;
    my ($cmd, $opt) = _split_args(@_);

    $opt->{quiet} = !$ENV{TEST_VERBOSE};

    my $out = eval { $repo->run(@$cmd, $opt) };
    my $exit = $? >> 8;

    my $test_name = sprintf('`%s` should exit %d',
        join(' ', 'git', @$cmd), $expected_exit);

    my $tb = __PACKAGE__->builder;

    $tb->level(2);
    my $rv = $tb->is_num($exit, $expected_exit, $test_name);

    if ($out && (!$rv || $ENV{TEST_VERBOSE})) {
        $tb->diag($out);
    }

    return $rv;
}

sub _split_args {
    # split the cmd and options like Git::Repository::Command::new does
    my @args = @_;
    my @o;
    my @cmd = grep { !( ref eq 'HASH' ? push @o, $_ : 0 ) } @args;
    Carp::croak "Too many option hashes given: @o" if @o > 1;
    return (\@cmd, (shift @o || {}));
}

1;

__END__

=pod

=head1 NAME

Git::Repository::Plugin::Test - Helper methods for testing interactions with Git

=head1 VERSION

version 0.005

=head1 SYNOPSIS

    use Test::More tests => 2;
    use Git::Repository qw(Test);

    my $repo = Git::Repository->new(...);

    # run Git commands as tests
    $repo->run_exit_ok('status');
    $repo->run_exit_is(1, 'nonexistant-subcommand');

=head1 DESCRIPTION

Adds C<run_exit_ok> and C<run_exit_is> methods to the Git::Repository object
that can be used for testing Git operations.

=head1 METHODS

L<Git::Repository::Plugin::Test|Git::Repository::Plugin::Test> adds the
following methods:

=head2 run_exit_ok(@cmd)

Like L<Git::Repository|Git::Repository>'s C<run> but exceptions are caught and
reported as test failures.

=head2 run_exit_is($expected_exit_code, @cmd)

Like L<Git::Repository|Git::Repository>'s C<run> but exceptions are caught and
reported as test failures unless exit code matches expected exit code.

=head2 branch_exists($branchname)
=head2 branch_not_exists($branchname)

Test for the existance of a branch.

=head1 SEE ALSO

L<Git::Repository|Git::Repository>, L<Test::Builder|Test::Builder>, L<Git::Repository::Plugin::TestSetUp|Git::Repository::Plugin::TestSetUp>

=head1 AUTHOR

Nathaniel G. Nutter <nnutter@cpan.org>

=head1 COPYRIGHT

Copyright 2013 - Nathaniel G. Nutter

=head1 LICENSE

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
