git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/3] git-svn: Add support for cherry-pick merges
@ 2013-11-28 15:52 Andrew Wong
  2013-11-28 15:52 ` [RFC 1/3] git-svn: Generate mergeinfo for every commit Andrew Wong
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Andrew Wong @ 2013-11-28 15:52 UTC (permalink / raw)
  To: git; +Cc: Andrew Wong

This is a work-in-progress for adding support for cherry-pick merges.

When using git-svn, cherry-picked commits from another git-svn branch are now
being treated as simple commits. But in SVN, if the user uses "svn merge -c" to
cherry-pick commits from another SVN branch, SVN records that information in
svn:mergeinfo. These patches will enable git-svn to do the same.

Andrew Wong (3):
  git-svn: Generate mergeinfo for every commit
  git-svn: Support cherry-pick merges
  git-svn: Add config to control the path of mergeinfo

 git-svn.perl                      | 79 ++++++++++++++++++++++++++++++++++-----
 perl/Git/SVN/Editor.pm            |  5 ++-
 t/t9161-git-svn-mergeinfo-push.sh | 67 +++++++++++++++++++++++++++++++++
 3 files changed, 141 insertions(+), 10 deletions(-)

-- 
1.8.5.rc3.5.g96ccada

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC 1/3] git-svn: Generate mergeinfo for every commit
  2013-11-28 15:52 [RFC 0/3] git-svn: Add support for cherry-pick merges Andrew Wong
@ 2013-11-28 15:52 ` Andrew Wong
  2013-11-28 15:52 ` [RFC 2/3] git-svn: Support cherry-pick merges Andrew Wong
  2013-11-28 15:52 ` [RFC 3/3] git-svn: Add config to control the path of mergeinfo Andrew Wong
  2 siblings, 0 replies; 4+ messages in thread
From: Andrew Wong @ 2013-11-28 15:52 UTC (permalink / raw)
  To: git; +Cc: Andrew Wong

The previous behavior would only generate mergeinfo once using the first
commit, and use that mergeinfo for all remaining commits. The new behavior will
generate it once for every commit.
---
 git-svn.perl | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 7349ffe..9ddeaf4 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -974,8 +974,12 @@ 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);
@@ -993,7 +997,7 @@ sub cmd_dcommit {
 			                       print "Committed r$_[0]\n";
 			                       $cmt_rev = $_[0];
 			                },
-					mergeinfo => $_merge_info,
+					mergeinfo => $rev_merge_info,
 			                svn_path => '');
 
 			my $err_handler = $SVN::Error::handler;
-- 
1.8.5.rc3.5.g96ccada

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [RFC 2/3] git-svn: Support cherry-pick merges
  2013-11-28 15:52 [RFC 0/3] git-svn: Add support for cherry-pick merges Andrew Wong
  2013-11-28 15:52 ` [RFC 1/3] git-svn: Generate mergeinfo for every commit Andrew Wong
@ 2013-11-28 15:52 ` Andrew Wong
  2013-11-28 15:52 ` [RFC 3/3] git-svn: Add config to control the path of mergeinfo Andrew Wong
  2 siblings, 0 replies; 4+ messages in thread
From: Andrew Wong @ 2013-11-28 15:52 UTC (permalink / raw)
  To: git; +Cc: Andrew Wong

Detect a cherry-pick merge if there's only one parent and the git-svn-id
metadata exists. Then, get the parent's mergeinfo and merge this commit's
mergeinfo.
---
 git-svn.perl                      | 52 +++++++++++++++++++++++++++++++++++++--
 t/t9161-git-svn-mergeinfo-push.sh | 30 ++++++++++++++++++++++
 2 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 9ddeaf4..b04cac7 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -698,12 +698,14 @@ sub populate_merge_info {
 	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
@@ -785,6 +787,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("."), $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")
+				. ":$cherry_svnrev";
+
+			$aggregate_mergeinfo = merge_merge_info($aggregate_mergeinfo,
+					$cherry_pick_mergeinfo,
+					$target_branch);
+
+			return $aggregate_mergeinfo;
+		}
 	}
 
 	return undef;
diff --git a/t/t9161-git-svn-mergeinfo-push.sh b/t/t9161-git-svn-mergeinfo-push.sh
index 1eab701..f348392 100755
--- a/t/t9161-git-svn-mergeinfo-push.sh
+++ b/t/t9161-git-svn-mergeinfo-push.sh
@@ -91,6 +91,36 @@ 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 'dcommit a merge at the top of a stack' '
 	git checkout svnb1 &&
 	touch anotherfile &&
-- 
1.8.5.rc3.5.g96ccada

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [RFC 3/3] git-svn: Add config to control the path of mergeinfo
  2013-11-28 15:52 [RFC 0/3] git-svn: Add support for cherry-pick merges Andrew Wong
  2013-11-28 15:52 ` [RFC 1/3] git-svn: Generate mergeinfo for every commit Andrew Wong
  2013-11-28 15:52 ` [RFC 2/3] git-svn: Support cherry-pick merges Andrew Wong
@ 2013-11-28 15:52 ` Andrew Wong
  2 siblings, 0 replies; 4+ messages in thread
From: Andrew Wong @ 2013-11-28 15:52 UTC (permalink / raw)
  To: git; +Cc: Andrew Wong

Instead of always storing mergeinfo at the root, give an option to store the
merge info in a subdirectory. The subdirectory must exist before we try to set
its property.
---
 git-svn.perl                      | 21 +++++++++++++++------
 perl/Git/SVN/Editor.pm            |  5 ++++-
 t/t9161-git-svn-mergeinfo-push.sh | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index b04cac7..bfae579 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -693,7 +693,7 @@ 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);
@@ -729,7 +729,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 = '';
@@ -778,7 +778,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,
@@ -808,7 +809,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 $parent_mergeinfo = $props->{'svn:mergeinfo'};
 			unless (defined $parent_mergeinfo) {
 				$parent_mergeinfo = '';
@@ -824,7 +825,7 @@ sub populate_merge_info {
 			}
 			my $cherry_branchpath = $1;
 
-			my $cherry_pick_mergeinfo = canonicalize_path("$cherry_branchpath")
+			my $cherry_pick_mergeinfo = canonicalize_path("$cherry_branchpath/$merge_info_path")
 				. ":$cherry_svnrev";
 
 			$aggregate_mergeinfo = merge_merge_info($aggregate_mergeinfo,
@@ -1008,6 +1009,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) {
@@ -1030,7 +1037,8 @@ sub cmd_dcommit {
 				$rev_merge_info = populate_merge_info($d, $gs,
 				                             $uuid,
 				                             $linear_refs,
-				                             $rewritten_parent);
+				                             $rewritten_parent,
+							     $merge_info_path);
 			}
 
 			my %ed_opts = ( r => $last_rev,
@@ -1046,6 +1054,7 @@ sub cmd_dcommit {
 			                       $cmt_rev = $_[0];
 			                },
 					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 b3bcd47..dcbb8a0 100644
--- a/perl/Git/SVN/Editor.pm
+++ b/perl/Git/SVN/Editor.pm
@@ -42,6 +42,7 @@ sub new {
 	                       "$self->{svn_path}/" : '';
 	$self->{config} = $opts->{config};
 	$self->{mergeinfo} = $opts->{mergeinfo};
+	$self->{mergeinfopath} = $opts->{mergeinfopath};
 	return $self;
 }
 
@@ -484,7 +485,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 f348392..8a87ad7 100755
--- a/t/t9161-git-svn-mergeinfo-push.sh
+++ b/t/t9161-git-svn-mergeinfo-push.sh
@@ -121,6 +121,43 @@ test_expect_success 'check cherry-pick mergeinfo' '
 /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 svnb1 &&
 	touch anotherfile &&
-- 
1.8.5.rc3.5.g96ccada

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-11-28 15:52 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-28 15:52 [RFC 0/3] git-svn: Add support for cherry-pick merges Andrew Wong
2013-11-28 15:52 ` [RFC 1/3] git-svn: Generate mergeinfo for every commit Andrew Wong
2013-11-28 15:52 ` [RFC 2/3] git-svn: Support cherry-pick merges Andrew Wong
2013-11-28 15:52 ` [RFC 3/3] git-svn: Add config to control the path of mergeinfo Andrew Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).