From 405dba7aa1b5291c12787cd8ce0165b977e3d7bc Mon Sep 17 00:00:00 2001 From: Ferenc Erki Date: Fri, 17 Jan 2025 23:57:41 +0100 Subject: [PATCH 1/7] Split out test git repository settings --- t/scm/git.t | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/t/scm/git.t b/t/scm/git.t index 77999f7af..816f8c96b 100755 --- a/t/scm/git.t +++ b/t/scm/git.t @@ -48,13 +48,13 @@ 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; - ok( -d $clone_target_dir, "$clone_target_dir could be created" ); rmdir $clone_target_dir; @@ -72,8 +72,6 @@ subtest 'clone into existing directory', sub { my $clone_target_dir = tempdir( CLEANUP => 1 ); - set repository => $test_repo_name, url => $test_repo_dir; - ok( -d $clone_target_dir, "$clone_target_dir is the clone target directory now" ); From 1f33a73dee522ecb9a6fcc7c279236146bf00f6d Mon Sep 17 00:00:00 2001 From: Ferenc Erki Date: Sat, 18 Jan 2025 00:13:19 +0100 Subject: [PATCH 2/7] Split out git test initialization --- t/scm/git.t | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/t/scm/git.t b/t/scm/git.t index 816f8c96b..3d510468b 100755 --- a/t/scm/git.t +++ b/t/scm/git.t @@ -53,7 +53,7 @@ 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 ); + my $clone_target_dir = init_test(); ok( -d $clone_target_dir, "$clone_target_dir could be created" ); @@ -70,7 +70,7 @@ subtest 'clone into non-existing directory', sub { subtest 'clone into existing directory', sub { plan tests => 5; - my $clone_target_dir = tempdir( CLEANUP => 1 ); + my $clone_target_dir = init_test(); ok( -d $clone_target_dir, "$clone_target_dir is the clone target directory now" ); @@ -114,3 +114,9 @@ sub git_repo_ok { return; } + +sub init_test { + my $clone_target_dir = tempdir( CLEANUP => 1 ); + + return $clone_target_dir; +} From 3ca1a3d74e0bd6939c15f5397b28d80fc5a12a4c Mon Sep 17 00:00:00 2001 From: Ferenc Erki Date: Thu, 16 Jan 2025 21:08:36 +0100 Subject: [PATCH 3/7] Split out test git user configuration --- t/scm/git.t | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/t/scm/git.t b/t/scm/git.t index 3d510468b..b85a1d669 100755 --- a/t/scm/git.t +++ b/t/scm/git.t @@ -28,6 +28,9 @@ else { plan skip_all => 'Can not find git command'; } +my $git_user_name = 'Rex'; +my $git_user_email = 'noreply@rexify.org'; + my $empty_config_file = $OSNAME eq 'MSWin32' ? q() : File::Spec->devnull(); my $git_environment = { @@ -86,10 +89,7 @@ sub prepare_test_repo { 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 noreply@rexify.org', - cwd => $directory, - env => $git_environment; + configure_git_user($directory); i_run 'git commit --allow-empty -m commit', cwd => $directory, @@ -115,6 +115,20 @@ 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 $clone_target_dir = tempdir( CLEANUP => 1 ); From 3242fc332fddece647d80e1ef7c89b7af8044868 Mon Sep 17 00:00:00 2001 From: Ferenc Erki Date: Thu, 16 Jan 2025 21:12:16 +0100 Subject: [PATCH 4/7] Add test for pulling new git commits --- t/scm/git.t | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/t/scm/git.t b/t/scm/git.t index b85a1d669..73b9d3d8d 100755 --- a/t/scm/git.t +++ b/t/scm/git.t @@ -22,7 +22,7 @@ $::QUIET = 1; my $git = can_run('git'); if ( defined $git ) { - plan tests => 9; + plan tests => 11; } else { plan skip_all => 'Can not find git command'; @@ -84,6 +84,55 @@ 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(); +}; + sub prepare_test_repo { my $directory = shift; @@ -130,7 +179,42 @@ sub configure_git_user { } 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; +} From d67aea5221c9459aff5a1885cdd80211c72c22c6 Mon Sep 17 00:00:00 2001 From: Ferenc Erki Date: Sun, 19 Jan 2025 00:50:51 +0100 Subject: [PATCH 5/7] Detect default branch of git origin --- ChangeLog | 1 + lib/Rex/SCM/Git.pm | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7f74a27ee..b04a288e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ Revision history for Rex [ENHANCEMENTS] - Quote command arguments on Windows - Support command environment variables on Windows + - Detect default branch of git origin [MAJOR] diff --git a/lib/Rex/SCM/Git.pm b/lib/Rex/SCM/Git.pm index 204f8c3d4..d48b0a908 100644 --- a/lib/Rex/SCM/Git.pm +++ b/lib/Rex/SCM/Git.pm @@ -34,7 +34,13 @@ 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; Rex::Logger::info( "Pulling " . $repo_info->{"url"} . " to " . ( $checkout_to ? $checkout_to : "." ) ); From 2bd21c84c8e07a508715d88dfae1ede1ab8ad022 Mon Sep 17 00:00:00 2001 From: Ferenc Erki Date: Thu, 16 Jan 2025 12:43:45 +0100 Subject: [PATCH 6/7] Add tests for git branch checkout operations --- t/scm/git.t | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 3 deletions(-) diff --git a/t/scm/git.t b/t/scm/git.t index 73b9d3d8d..13bbb9e4d 100755 --- a/t/scm/git.t +++ b/t/scm/git.t @@ -22,7 +22,7 @@ $::QUIET = 1; my $git = can_run('git'); if ( defined $git ) { - plan tests => 11; + plan tests => 15; } else { plan skip_all => 'Can not find git command'; @@ -46,11 +46,12 @@ 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 { @@ -133,6 +134,79 @@ subtest 'checkout new commits with rebase', sub { 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; @@ -140,10 +214,28 @@ sub prepare_test_repo { 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; } @@ -218,3 +310,15 @@ sub reset_test_repo { 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; +} From 954da76072506b3efaa2ee35106e74efa3f29275 Mon Sep 17 00:00:00 2001 From: Ferenc Erki Date: Fri, 17 Jan 2025 21:22:59 +0100 Subject: [PATCH 7/7] Fix git branch checkout operations --- ChangeLog | 1 + lib/Rex/SCM/Git.pm | 3 +++ 2 files changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index b04a288e5..123a53953 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Revision history for Rex [API CHANGES] [BUG FIXES] + - Fix git branch checkout operations [DOCUMENTATION] diff --git a/lib/Rex/SCM/Git.pm b/lib/Rex/SCM/Git.pm index d48b0a908..a354d5eca 100644 --- a/lib/Rex/SCM/Git.pm +++ b/lib/Rex/SCM/Git.pm @@ -41,6 +41,9 @@ sub checkout { ( 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 : "." ) );