Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ Revision history for Rex
[API CHANGES]

[BUG FIXES]
- Fix git branch checkout operations

[DOCUMENTATION]

[ENHANCEMENTS]
- Quote command arguments on Windows
- Support command environment variables on Windows
- Detect default branch of git origin

[MAJOR]

Expand Down
11 changes: 10 additions & 1 deletion lib/Rex/SCM/Git.pm
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ sub checkout {
my $clone_args = join( " ", @{ $checkout_opt->{clone_args} || [''] } );

if ( is_dir("$checkout_to/.git") ) {
my $branch = $checkout_opt->{"branch"} || "master";
my $head_ref = i_run 'git symbolic-ref refs/remotes/origin/HEAD',
cwd => $checkout_to,
%run_opt;

( my $default_origin_branch = $head_ref ) =~ s{refs/remotes/origin/}{}msx;

my $branch = $checkout_opt->{"branch"} || $default_origin_branch;

i_run "git checkout -B $branch", cwd => $checkout_to, %run_opt;

Rex::Logger::info( "Pulling "
. $repo_info->{"url"} . " to "
. ( $checkout_to ? $checkout_to : "." ) );
Expand Down
226 changes: 216 additions & 10 deletions t/scm/git.t
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ $::QUIET = 1;
my $git = can_run('git');

if ( defined $git ) {
plan tests => 9;
plan tests => 15;
}
else {
plan skip_all => 'Can not find git command';
}

my $git_user_name = 'Rex';
my $git_user_email = '[email protected]';

my $empty_config_file = $OSNAME eq 'MSWin32' ? q() : File::Spec->devnull();

my $git_environment = {
Expand All @@ -43,17 +46,18 @@ ok( $git_version, qq(Git version returned as '$git_version') );
my $test_repo_dir = tempdir( CLEANUP => 1 );
ok( -d $test_repo_dir, "$test_repo_dir is the test repo directory now" );

my $test_repo_name = 'test_repo';
my $test_branch_name = 'test_branch';

prepare_test_repo($test_repo_dir);
git_repo_ok($test_repo_dir);

my $test_repo_name = 'test_repo';
set repository => $test_repo_name, url => $test_repo_dir;

subtest 'clone into non-existing directory', sub {
plan tests => 6;

my $clone_target_dir = tempdir( CLEANUP => 1 );

set repository => $test_repo_name, url => $test_repo_dir;
my $clone_target_dir = init_test();

ok( -d $clone_target_dir, "$clone_target_dir could be created" );

Expand All @@ -70,9 +74,7 @@ subtest 'clone into non-existing directory', sub {
subtest 'clone into existing directory', sub {
plan tests => 5;

my $clone_target_dir = tempdir( CLEANUP => 1 );

set repository => $test_repo_name, url => $test_repo_dir;
my $clone_target_dir = init_test();

ok( -d $clone_target_dir,
"$clone_target_dir is the clone target directory now" );
Expand All @@ -83,20 +85,157 @@ subtest 'clone into existing directory', sub {
git_repo_ok($clone_target_dir);
};

subtest 'checkout new commits', sub {
plan tests => 4;

my $clone_target_dir = init_test( clone => TRUE );

my $test_commit_message = 'new_origin_commit';

i_run "git commit --allow-empty -m $test_commit_message",
cwd => $test_repo_dir,
env => $git_environment;

lives_ok {
checkout $test_repo_name,
path => $clone_target_dir,
}
'pulling new commit';

git_last_commit_message_ok( $clone_target_dir, $test_commit_message );

reset_test_repo();
};

subtest 'checkout new commits with rebase', sub {
plan tests => 4; ## no critic (ProhibitDuplicateLiteral)

my $clone_target_dir = init_test( clone => TRUE );

i_run 'git commit --allow-empty -m new_origin_commit',
cwd => $test_repo_dir,
env => $git_environment;

my $test_commit_message = 'new_local_commit';

i_run "git commit --allow-empty -m $test_commit_message",
cwd => $clone_target_dir,
env => $git_environment;

lives_ok {
checkout $test_repo_name,
path => $clone_target_dir,
rebase => TRUE,
}
'pulling new commit with rebase';

git_last_commit_message_ok( $clone_target_dir, $test_commit_message );

reset_test_repo();
};

subtest 'clone a branch', sub {
plan tests => 5; ## no critic (ProhibitDuplicateLiteral)

my $clone_target_dir = init_test();

lives_ok {
checkout $test_repo_name,
path => $clone_target_dir,
branch => $test_branch_name,
}
'cloning a branch';

git_repo_ok($clone_target_dir);
git_branch_ok( $clone_target_dir, $test_branch_name );
};

subtest 'checkout a branch after cloning', sub {
plan tests => 6; ## no critic (ProhibitDuplicateLiteral)

my $clone_target_dir = init_test( clone => TRUE );

lives_ok {
checkout $test_repo_name,
path => $clone_target_dir,
branch => $test_branch_name,
}
'checking out a branch after cloning';

git_repo_ok($clone_target_dir);
git_branch_ok( $clone_target_dir, $test_branch_name );
};

subtest 'checkout new commits from a branch', sub {
plan tests => 4; ## no critic (ProhibitDuplicateLiteral)

my $clone_target_dir = init_test( clone => TRUE );

lives_ok {
checkout $test_repo_name,
path => $clone_target_dir,
branch => $test_branch_name,
}
'pulling new commit from branch';

git_branch_ok( $clone_target_dir, $test_branch_name );
git_last_commit_message_ok( $clone_target_dir, 'origin_branch_commit' );
};

subtest 'checkout new commits from a branch with rebase', sub {
plan tests => 5; ## no critic (ProhibitDuplicateLiteral)

my $clone_target_dir = init_test( clone => TRUE );

my $test_commit_message = 'local_branch_commit';

i_run "git commit --allow-empty -m $test_commit_message",
cwd => $clone_target_dir,
env => $git_environment;

git_last_commit_message_ok( $clone_target_dir, $test_commit_message );

lives_ok {
checkout $test_repo_name,
path => $clone_target_dir,
branch => $test_branch_name,
rebase => TRUE,
}
'pulling new commit from branch with rebase';

git_branch_ok( $clone_target_dir, $test_branch_name );
git_last_commit_message_ok( $clone_target_dir, $test_commit_message );
};

sub prepare_test_repo {
my $directory = shift;

i_run 'git init', cwd => $directory, env => $git_environment;

i_run 'git config user.name Rex', cwd => $directory, env => $git_environment;
i_run 'git config user.email [email protected]',
configure_git_user($directory);

my $default_branch = i_run 'git symbolic-ref HEAD',
cwd => $directory,
env => $git_environment;

$default_branch =~ s{refs/heads/}{}msx;

i_run 'git commit --allow-empty -m commit',
cwd => $directory,
env => $git_environment;

i_run "git checkout -b $test_branch_name",
cwd => $directory,
env => $git_environment;

i_run 'git commit --allow-empty -m origin_branch_commit',
cwd => $directory,
env => $git_environment;

i_run "git checkout $default_branch",
cwd => $directory,
env => $git_environment;

return;
}

Expand All @@ -116,3 +255,70 @@ sub git_repo_ok {

return;
}

sub configure_git_user {
my $directory = shift;

i_run "git config user.name $git_user_name",
cwd => $directory,
env => $git_environment;

i_run "git config user.email $git_user_email",
cwd => $directory,
env => $git_environment;

return;
}

sub init_test {
my %opts = @_;

my $clone_target_dir = tempdir( CLEANUP => 1 );

if ( $opts{clone} ) {
lives_ok {
checkout $test_repo_name,
path => $clone_target_dir,
}
'cloning the repo';

configure_git_user($clone_target_dir);
}

return $clone_target_dir;
}

sub git_last_commit_message_ok {
my ( $directory, $expected_commit_message ) = @_;

my $last_commit_message = i_run 'git log --oneline -1 --format=%s',
cwd => $directory,
env => $git_environment;

is( $last_commit_message, $expected_commit_message,
'got correct last commit message' );

return;
}

sub reset_test_repo {
i_run 'git reset --hard HEAD~1',
cwd => $test_repo_dir,
env => $git_environment;

git_last_commit_message_ok( $test_repo_dir, 'commit' );

return;
}

sub git_branch_ok {
my ( $directory, $expected_branch ) = @_;

my $current_branch = i_run 'git rev-parse --abbrev-ref HEAD',
cwd => $directory,
env => $git_environment;

is( $current_branch, $expected_branch, 'got correct current branch name' );

return;
}
Loading