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

use base 'Git::Repository::Plugin';

sub _keywords { qw( init_tmp_repo new_tmp_repo clone_tmp_repo hook_path install_hook ) }

sub init_tmp_repo {
    my $class = shift;
    my @options = @_;
    my $dir = File::Temp::tempdir();
    Git::Repository->run('init', @options, $dir);
    return $dir;
}

sub new_tmp_repo {
    my $class = shift;
    my ($cmd, $opt) = _split_args(@_);

    my $dir = $class->init_tmp_repo(@$cmd);

    my $is_bare = grep { $_ eq '--bare' } @$cmd;
    my $type = $is_bare ? 'git_dir' : 'work_tree';
    my $repo = $class->new($type => $dir, $opt);

    return $repo;
}

sub clone_tmp_repo {
    my $class = shift;
    my ($cmd, $opt) = _split_args(@_);

    my $dir = File::Temp::tempdir();
    Git::Repository->run('clone', @$cmd, $dir);

    my $is_bare = grep { $_ eq '--bare' } @$cmd;
    my $type = $is_bare ? 'git_dir' : 'work_tree';
    my $repo = $class->new($type => $dir, $opt);

    return $repo;
}

sub install_hook {
    my ($repo, $source, $target) = @_;

    my $dest = $repo->hook_path($target);
    my $copy_rv = File::Copy::copy($source, $dest);
    unless ($copy_rv) {
        Carp::croak "install_hook failed: $!";
    }

    my $chmod_rv = chmod 0755, $dest;
    unless ($chmod_rv) {
        Carp::croak "install_hook failed: $!";
    }
}

# Undocumented Subs

sub hook_path {
    my ($repo, $target) = @_;
    return File::Spec->join($repo->git_dir, 'hooks', $target);
}

# Private Subs

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::TestSetUp - Helper methods for setting up a Git repository

=head1 VERSION

version 0.005

=head1 SYNOPSIS

    use Git::Repository qw(TestSetUp);

    # easily create a temporary repository to test with
    my $repo = Git::Repository->new_tmp_repo();

    # install a hook into the temporary repository
    $repo->install_hook('my-hook-file', 'pre-receive');

    # clone an existing repo into a temporary directory
    my $clone_repo = Git::Repository->clone_tmp_repo('--bare', $repo->git_dir);

=head1 DESCRIPTION

Adds methods to the Git::Repository object that can be used for setting up Git
repositories.

=head1 METHODS

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

=head2 init_tmp_repo(@init_opts)

Initializes a new repository in a temporary directory.  Options, such as
C<--bare>, can be passed in.

=head2 new_tmp_repo(@init_opts, $options)

Initializes a new repository in a temporary directory and returns a
L<Git::Repository|Git::Repository> object.  Like C<init_tmp_repo>,
C<new_tmp_repo> accepts a list of options for the C<init> command and like
L<Git::Repository|Git::Repository>'s C<new> C<new_tmp_repo> also accepts a
reference to an option hash.

=head2 clone_tmp_repo(@clone_opts, $options)

Clones a repository into a temporary directory and returns a
L<Git::Repository|Git::Repository> object.  Like C<init_tmp_repo>,
C<new_tmp_repo> accepts a list of options for the C<init> command and like
L<Git::Repository|Git::Repository>'s C<new> C<new_tmp_repo> also accepts a
reference to an option hash.

=head2 install_hook($source, $target)

Install a C<$target>, e.g. 'pre-receive', hook into the repository.

=head1 SEE ALSO

L<Git::Repository|Git::Repository>

=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
