Last active
March 29, 2016 16:28
-
-
Save bsuh/c358ccd9da982a30a966 to your computer and use it in GitHub Desktop.
git-svn cherry-pick merge support http://git.661346.n2.nabble.com/RFC-0-3-git-svn-Add-support-for-cherry-pick-merges-td7600026.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/git-svn.perl b/git-svn.perl | |
index 05eced0..6127314 100755 | |
--- a/git-svn.perl | |
+++ b/git-svn.perl | |
@@ -703,17 +703,19 @@ sub merge_merge_info { | |
} | |
sub populate_merge_info { | |
- my ($d, $gs, $uuid, $linear_refs, $rewritten_parent) = @_; | |
+ my ($d, $gs, $uuid, $linear_refs, $rewritten_parent, $merge_info_path) = @_; | |
my %parentshash; | |
read_commit_parents(\%parentshash, $d); | |
my @parents = @{$parentshash{$d}}; | |
+ | |
+ my $rooturl = $gs->repos_root; | |
+ my ($target_branch) = $gs->full_pushurl =~ /^\Q$rooturl\E(.*)/; | |
+ | |
if ($#parents > 0) { | |
# Merge commit | |
my $all_parents_ok = 1; | |
my $aggregate_mergeinfo = ''; | |
- my $rooturl = $gs->repos_root; | |
- my ($target_branch) = $gs->full_pushurl =~ /^\Q$rooturl\E(.*)/; | |
if (defined($rewritten_parent)) { | |
# Replace first parent with newly-rewritten version | |
@@ -737,7 +739,7 @@ sub populate_merge_info { | |
my $ra = Git::SVN::Ra->new($branchurl); | |
my (undef, undef, $props) = | |
- $ra->get_dir(canonicalize_path("."), $svnrev); | |
+ $ra->get_dir(canonicalize_path($merge_info_path), $svnrev); | |
my $par_mergeinfo = $props->{'svn:mergeinfo'}; | |
unless (defined $par_mergeinfo) { | |
$par_mergeinfo = ''; | |
@@ -786,7 +788,8 @@ sub populate_merge_info { | |
# We now have a list of all SVN revnos which are | |
# merged by this particular parent. Integrate them. | |
next if $#revsin == -1; | |
- my $newmergeinfo = "$branchpath:" . join(',', @revsin); | |
+ my $newmergeinfo = canonicalize_path("$branchpath/$merge_info_path") | |
+ . ":" . join(',', @revsin); | |
$aggregate_mergeinfo = | |
merge_merge_info($aggregate_mergeinfo, | |
$newmergeinfo, | |
@@ -795,6 +798,52 @@ sub populate_merge_info { | |
if ($all_parents_ok and $aggregate_mergeinfo) { | |
return $aggregate_mergeinfo; | |
} | |
+ } elsif ($#parents == 0) { | |
+ # cherry-pick merge | |
+ my ($cherry_branchurl, $cherry_svnrev, $cherry_paruuid) = | |
+ cmt_metadata($d); | |
+ | |
+ if(defined $cherry_branchurl && defined $cherry_svnrev && defined $cherry_paruuid) | |
+ { | |
+ if (defined($rewritten_parent)) { | |
+ # Replace first parent with newly-rewritten version | |
+ shift @parents; | |
+ unshift @parents, $rewritten_parent; | |
+ } | |
+ | |
+ my $aggregate_mergeinfo = ''; | |
+ | |
+ # parent mergeinfo | |
+ my ($branchurl, $svnrev, $paruuid) = | |
+ cmt_metadata($parents[0]); | |
+ | |
+ my $ra = Git::SVN::Ra->new($branchurl); | |
+ my (undef, undef, $props) = | |
+ $ra->get_dir(canonicalize_path($merge_info_path), $svnrev); | |
+ my $parent_mergeinfo = $props->{'svn:mergeinfo'}; | |
+ unless (defined $parent_mergeinfo) { | |
+ $parent_mergeinfo = ''; | |
+ } | |
+ | |
+ $aggregate_mergeinfo = merge_merge_info($aggregate_mergeinfo, | |
+ $parent_mergeinfo, | |
+ $target_branch); | |
+ | |
+ # cherry-pick mergeinfo | |
+ unless ($cherry_branchurl =~ /^\Q$rooturl\E(.*)/) { | |
+ fatal "commit $d git-svn metadata changed mid-run!"; | |
+ } | |
+ my $cherry_branchpath = $1; | |
+ | |
+ my $cherry_pick_mergeinfo = canonicalize_path("$cherry_branchpath/$merge_info_path") | |
+ . ":$cherry_svnrev"; | |
+ | |
+ $aggregate_mergeinfo = merge_merge_info($aggregate_mergeinfo, | |
+ $cherry_pick_mergeinfo, | |
+ $target_branch); | |
+ | |
+ return $aggregate_mergeinfo; | |
+ } | |
} | |
return undef; | |
@@ -970,6 +1019,12 @@ sub cmd_dcommit { | |
if (defined($_merge_info)) { | |
$_merge_info =~ tr{ }{\n}; | |
} | |
+ my $merge_info_path = eval { | |
+ command_oneline(qw/config --get svn.mergeinfopath/) | |
+ }; | |
+ if (not defined($merge_info_path)) { | |
+ $merge_info_path = ""; | |
+ } | |
while (1) { | |
my $d = shift @$linear_refs or last; | |
unless (defined $last_rev) { | |
@@ -984,11 +1039,16 @@ sub cmd_dcommit { | |
} else { | |
my $cmt_rev; | |
- unless (defined($_merge_info) || ! $push_merge_info) { | |
- $_merge_info = populate_merge_info($d, $gs, | |
+ my $rev_merge_info; | |
+ if (defined($_merge_info)) { | |
+ $rev_merge_info = $_merge_info; | |
+ } | |
+ unless (defined($rev_merge_info) || ! $push_merge_info) { | |
+ $rev_merge_info = populate_merge_info($d, $gs, | |
$uuid, | |
$linear_refs, | |
- $rewritten_parent); | |
+ $rewritten_parent, | |
+ $merge_info_path); | |
} | |
my %ed_opts = ( r => $last_rev, | |
@@ -1003,7 +1063,8 @@ sub cmd_dcommit { | |
print "Committed r$_[0]\n"; | |
$cmt_rev = $_[0]; | |
}, | |
- mergeinfo => $_merge_info, | |
+ mergeinfo => $rev_merge_info, | |
+ mergeinfopath => $merge_info_path, | |
svn_path => ''); | |
my $err_handler = $SVN::Error::handler; | |
diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm | |
index 4c4199a..8f8e5e4 100644 | |
--- a/perl/Git/SVN/Editor.pm | |
+++ b/perl/Git/SVN/Editor.pm | |
@@ -41,6 +41,7 @@ sub new { | |
"$self->{svn_path}/" : ''; | |
$self->{config} = $opts->{config}; | |
$self->{mergeinfo} = $opts->{mergeinfo}; | |
+ $self->{mergeinfopath} = $opts->{mergeinfopath}; | |
$self->{pathnameencoding} = Git::config('svn.pathnameencoding'); | |
return $self; | |
} | |
@@ -529,7 +530,9 @@ sub apply_diff { | |
} | |
if (defined($self->{mergeinfo})) { | |
- $self->change_dir_prop($self->{bat}{''}, "svn:mergeinfo", | |
+ my $pbat = $self->ensure_path($self->{mergeinfopath}, \%deletions); | |
+ $self->change_dir_prop($pbat, | |
+ "svn:mergeinfo", | |
$self->{mergeinfo}); | |
} | |
$self->rmdirs if $_rmdir; | |
diff --git a/t/t9161-git-svn-mergeinfo-push.sh b/t/t9161-git-svn-mergeinfo-push.sh | |
index f113aca..38b4595 100755 | |
--- a/t/t9161-git-svn-mergeinfo-push.sh | |
+++ b/t/t9161-git-svn-mergeinfo-push.sh | |
@@ -91,6 +91,73 @@ test_expect_success 'check reintegration mergeinfo' ' | |
/branches/svnb5:6,11" | |
' | |
+test_expect_success 'make further commits to branch' ' | |
+ git checkout svnb2 && | |
+ touch newb2file-3 && | |
+ git add newb2file-3 && | |
+ git commit -m "later b2 commit 3" && | |
+ touch newb2file-4 && | |
+ git add newb2file-4 && | |
+ git commit -m "later b2 commit 4" && | |
+ touch newb2file-5 && | |
+ git add newb2file-5 && | |
+ git commit -m "later b2 commit 5" && | |
+ git svn dcommit | |
+ ' | |
+ | |
+test_expect_success 'cherry-pick merge' ' | |
+ git checkout svnb1 && | |
+ git cherry-pick svnb2 && | |
+ git cherry-pick svnb2^ && | |
+ git cherry-pick svnb2^^ && | |
+ git svn dcommit | |
+ ' | |
+ | |
+test_expect_success 'check cherry-pick mergeinfo' ' | |
+ mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1) | |
+ test "$mergeinfo" = "/branches/svnb2:3,8,16-17,20-22 | |
+/branches/svnb3:4,9 | |
+/branches/svnb4:5-6,10-12 | |
+/branches/svnb5:6,11" | |
+ ' | |
+ | |
+test_expect_success 'make further commits to branch' ' | |
+ git checkout svnb1 && | |
+ mkdir sub_directory && | |
+ touch sub_directory/newb1file && | |
+ git add sub_directory/newb1file && | |
+ git commit -m "sub directory b1 commit" && | |
+ git svn dcommit && | |
+ git checkout svnb2 && | |
+ mkdir sub_directory && | |
+ touch sub_directory/newb2file && | |
+ git add sub_directory/newb2file && | |
+ git commit -m "sub directory b2 commit" && | |
+ touch sub_directory/newb2file2 && | |
+ git add sub_directory/newb2file2 && | |
+ git commit -m "sub directory b2 commit 2" && | |
+ git svn dcommit | |
+ ' | |
+ | |
+test_expect_success 'cherry-pick mergeinfo sub directory' ' | |
+ git config svn.mergeinfopath sub_directory && | |
+ git checkout svnb1 && | |
+ git cherry-pick svnb2 && | |
+ git cherry-pick svnb2^ && | |
+ git svn dcommit && | |
+ git config --unset svn.mergeinfopath | |
+ ' | |
+ | |
+test_expect_success 'check cherry-pick mergeinfo sub directory' ' | |
+ mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1) | |
+ test "$mergeinfo" = "/branches/svnb2:3,8,16-17,20-22 | |
+/branches/svnb3:4,9 | |
+/branches/svnb4:5-6,10-12 | |
+/branches/svnb5:6,11" && | |
+ mergeinfo=$(cd sub_directory && svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1/sub_directory) && | |
+ test "$mergeinfo" = "/branches/svnb2/sub_directory:27-28" | |
+ ' | |
+ | |
test_expect_success 'dcommit a merge at the top of a stack' ' | |
git checkout origin/svnb1 && | |
touch anotherfile && |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment