{"thread":{"id":"28329","subject":"[PATCH v2] git-svn: teach git-svn to populate svn:mergeinfo","startedAt":"2011-09-07T17:36:05Z","lastAt":"2011-09-13T08:18:15Z","messageCount":4,"participants":["Bryan Jacobs","Eric Wong"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"175008","messageId":"20110907133605.07ecad1b@robyn.woti.com","threadId":"28329","inReplyTo":null,"subject":"[PATCH v2] git-svn: teach git-svn to populate svn:mergeinfo","fromName":"Bryan Jacobs","fromEmail":"bjacobs@woti.com","sentAt":"2011-09-07T17:36:05Z","receivedAt":"2011-09-07T17:36:05Z","isPatch":true,"sender":{"key":"bjacobs@woti.com","avatar":null},"body":"Allow git-svn to populate the svn:mergeinfo property automatically in\na narrow range of circumstances. Specifically, when dcommitting a\nrevision with multiple parents, all but (potentially) the first of\nwhich have been committed to SVN in the same repository as the target\nof the dcommit.\n\nIn this case, the merge info is the union of that given by each of the\nparents, plus all changes introduced to the first parent by the other\nparents.\n\nIn all other cases where a revision to be committed has multiple\nparents, cause \"git svn dcommit\" to raise an error rather than\ncompleting the commit and potentially losing history information in\nthe upstream SVN repository.\n\nThis behavior is disabled by default, and can be enabled by setting\nthe svn.pushmergeinfo config option.\n\nSigned-off-by: Bryan Jacobs <bjacobs@woti.com>\n---\n\nThis is the second revision of a patch I posted earlier. I believe this patch is now suitable for inclusion.\n\nSignificant changes from the last revision are:\n\n- All revisions in the commit list are checked beforehand to ensure that all non-first-parents of merge commits have suitable SVN metadata attached.\n- Cases where a merge commit is at the top of an uncommitted stack are tested and now work correctly.\n- Cleanups as suggested by Eric Wong.\n\nThis code is still vulnerable to race conditions if the git repository is modified while a dcommit is in progress, but this is a fundamental problem with git-svn's continual-rebasing-series approach, as previously discussed.\n\nI believe I have determined the source of the added+untracked files in the working copy. With this repository:\n\nbranch1: A - B\n            /\nbranch2:   C\n\nIf a file is added in C, and you attempt to dcommit B (C must be dcommitted or the problem will be detected and the commit will abort), git-svn runs a reset --mixed. So because the files added in C were present in B, they remain present but are untracked when you reset --mixed to A. So you cannot apply B to the rebased state because it would \"create\" the file you already have (with, admittedly, identical contents).\n\nI'm not clear on why git will not allow this to proceed - the file in the working copy is identical to the file that would be \"created\", so there's no loss of data. \"file would be overwritten\", yes, technically, but never altered, so no problem really... Might be a user-interface consistency issue to allow it, but I'd be inclined to say git's behavior should change.\n\nRegardless, this could be solved by using a reset --hard to A before beginning. Since we already disallow dcommitting with a dirty WC, this should be safe (never thought I'd say that about a reset --hard). I'm not going to write that change, though.\n\nOf course, users could also recover from even the worst disaster via the reflog.\n\n Documentation/git-svn.txt         |    8 +\n git-svn.perl                      |  255 +++++++++++++++++++++++++\n t/t9160-git-svn-mergeinfo-push.sh |  104 ++++++++++\n t/t9160/branches.dump             |  374 +++++++++++++++++++++++++++++++++++++\n 4 files changed, 741 insertions(+), 0 deletions(-)\n create mode 100755 t/t9160-git-svn-mergeinfo-push.sh\n create mode 100644 t/t9160/branches.dump\n\ndiff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt\nindex ed5eca1..89955a2 100644\n--- a/Documentation/git-svn.txt\n+++ b/Documentation/git-svn.txt\n@@ -213,6 +213,14 @@ discouraged.\n \tstore this information (as a property), and svn clients starting from\n \tversion 1.5 can make use of it. 'git svn' currently does not use it\n \tand does not set it automatically.\n++\n+[verse]\n+config key: svn.pushmergeinfo\n++\n+This option will cause git-svn to attempt to automatically populate the\n+svn:mergeinfo property in the SVN repository when possible. Currently, this can\n+only be done when dcommitting non-fast-forward merges where all parents but the\n+first have already been pushed into SVN.\n \n 'branch'::\n \tCreate a branch in the SVN repository.\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 89f83fd..bf60300 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -497,6 +497,195 @@ sub cmd_set_tree {\n \tunlink $gs->{index};\n }\n \n+sub split_merge_info_range {\n+\tmy ($range) = @_;\n+\tif ($range =~ /(\\d+)-(\\d+)/) {\n+\t\treturn (int($1), int($2));\n+\t} else {\n+\t\treturn (int($range), int($range));\n+\t}\n+}\n+\n+sub combine_ranges {\n+\tmy ($in) = @_;\n+\n+\tmy @fnums = ();\n+\tmy @arr = split(/,/, $in);\n+\tfor my $element (@arr) {\n+\t\tmy ($start, $end) = split_merge_info_range($element);\n+\t\tpush @fnums, $start;\n+\t}\n+\n+\tmy @sorted = @arr [ sort {\n+\t\t$fnums[$a] <=> $fnums[$b]\n+\t} 0..$#arr ];\n+\n+\tmy @return = ();\n+\tmy $last = -1;\n+\tmy $first = -1;\n+\tfor my $element (@sorted) {\n+\t\tmy ($start, $end) = split_merge_info_range($element);\n+\n+\t\tif ($last == -1) {\n+\t\t\t$first = $start;\n+\t\t\t$last = $end;\n+\t\t\tnext;\n+\t\t}\n+\t\tif ($start <= $last+1) {\n+\t\t\tif ($end > $last) {\n+\t\t\t\t$last = $end;\n+\t\t\t}\n+\t\t\tnext;\n+\t\t}\n+\t\tif ($first == $last) {\n+\t\t\tpush @return, \"$first\";\n+\t\t} else {\n+\t\t\tpush @return, \"$first-$last\";\n+\t\t}\n+\t\t$first = $start;\n+\t\t$last = $end;\n+\t}\n+\n+\tif ($first != -1) {\n+\t\tif ($first == $last) {\n+\t\t\tpush @return, \"$first\";\n+\t\t} else {\n+\t\t\tpush @return, \"$first-$last\";\n+\t\t}\n+\t}\n+\n+\treturn join(',', @return);\n+}\n+\n+sub merge_revs_into_hash {\n+\tmy ($hash, $minfo) = @_;\n+\tmy @lines = split(' ', $minfo);\n+\n+\tfor my $line (@lines) {\n+\t\tmy ($branchpath, $revs) = split(/:/, $line);\n+\n+\t\tif (exists($hash->{$branchpath})) {\n+\t\t\t# Merge the two revision sets\n+\t\t\tmy $combined = \"$hash->{$branchpath},$revs\";\n+\t\t\t$hash->{$branchpath} = combine_ranges($combined);\n+\t\t} else {\n+\t\t\t# Just do range combining for consolidation\n+\t\t\t$hash->{$branchpath} = combine_ranges($revs);\n+\t\t}\n+\t}\n+}\n+\n+sub merge_merge_info {\n+\tmy ($mergeinfo_one, $mergeinfo_two) = @_;\n+\tmy %result_hash = ();\n+\n+\tmerge_revs_into_hash(\\%result_hash, $mergeinfo_one);\n+\tmerge_revs_into_hash(\\%result_hash, $mergeinfo_two);\n+\n+\tmy $result = '';\n+\t# Sort below is for consistency's sake\n+\tfor my $branchname (sort keys(%result_hash)) {\n+\t\tmy $revlist = $result_hash{$branchname};\n+\t\t$result .= \"$branchname:$revlist\\n\"\n+\t}\n+\treturn $result;\n+}\n+\n+sub populate_merge_info {\n+\tmy ($d, $gs, $uuid, $linear_refs, $rewritten_parent) = @_;\n+\n+\tmy %parentshash;\n+\tread_commit_parents(\\%parentshash, $d);\n+\tmy @parents = @{$parentshash{$d}};\n+\tif ($#parents > 0) {\n+\t\t# Merge commit\n+\t\tmy $all_parents_ok = 1;\n+\t\tmy $aggregate_mergeinfo = '';\n+\t\tmy $rooturl = $gs->repos_root;\n+\n+\t\tif (defined($rewritten_parent)) {\n+\t\t\t# Replace first parent with newly-rewritten version\n+\t\t\tshift @parents;\n+\t\t\tunshift @parents, $rewritten_parent;\n+\t\t}\n+\n+\t\tforeach my $parent (@parents) {\n+\t\t\tmy ($branchurl, $svnrev, $paruuid) =\n+\t\t\t\tcmt_metadata($parent);\n+\n+\t\t\tunless (defined($svnrev)) {\n+\t\t\t\t# Should have been caught be preflight check\n+\t\t\t\tfatal \"merge commit $d has ancestor $parent, but that change \"\n+                     .\"does not have git-svn metadata!\";\n+\t\t\t}\n+\t\t\tunless ($branchurl =~ /^$rooturl(.*)/) {\n+\t\t\t\tfatal \"commit $parent git-svn metadata changed mid-run!\";\n+\t\t\t}\n+\t\t\tmy $branchpath = $1;\n+\n+\t\t\tmy $ra = Git::SVN::Ra->new($branchurl);\n+\t\t\tmy (undef, undef, $props) =\n+\t\t\t\t$ra->get_dir(canonicalize_path(\".\"), $svnrev);\n+\t\t\tmy $par_mergeinfo = $props->{'svn:mergeinfo'};\n+\t\t\tunless (defined $par_mergeinfo) {\n+\t\t\t\t$par_mergeinfo = '';\n+\t\t\t}\n+\t\t\t# Merge previous mergeinfo values\n+\t\t\t$aggregate_mergeinfo =\n+\t\t\t\tmerge_merge_info($aggregate_mergeinfo,\n+\t\t\t\t\t\t\t\t $par_mergeinfo, 0);\n+\n+\t\t\tnext if $parent eq $parents[0]; # Skip first parent\n+\t\t\t# Add new changes being placed in tree by merge\n+\t\t\tmy @cmd = (qw/rev-list --reverse/,\n+\t\t\t\t\t   $parent, qw/--not/);\n+\t\t\tforeach my $par (@parents) {\n+\t\t\t\tunless ($par eq $parent) {\n+\t\t\t\t\tpush @cmd, $par;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tmy @revsin = ();\n+\t\t\tmy ($revlist, $ctx) = command_output_pipe(@cmd);\n+\t\t\twhile (<$revlist>) {\n+\t\t\t\tmy $irev = $_;\n+\t\t\t\tchomp $irev;\n+\t\t\t\tmy (undef, $csvnrev, undef) =\n+\t\t\t\t\tcmt_metadata($irev);\n+\t\t\t\tunless (defined $csvnrev) {\n+\t\t\t\t\t# A child is missing SVN annotations...\n+\t\t\t\t\t# this might be OK, or might not be.\n+\t\t\t\t\twarn \"W:child $irev is merged into revision \"\n+\t\t\t\t\t\t .\"$d but does not have git-svn metadata. \"\n+\t\t\t\t\t\t .\"This means git-svn cannot determine the \"\n+\t\t\t\t\t\t .\"svn revision numbers to place into the \"\n+\t\t\t\t\t\t .\"svn:mergeinfo property. You must ensure \"\n+\t\t\t\t\t\t .\"a branch is entirely committed to \"\n+\t\t\t\t\t\t .\"SVN before merging it in order for \"\n+\t\t\t\t\t\t .\"svn:mergeinfo population to function \"\n+\t\t\t\t\t\t .\"properly\";\n+\t\t\t\t}\n+\t\t\t\tpush @revsin, $csvnrev;\n+\t\t\t}\n+\t\t\tcommand_close_pipe($revlist, $ctx);\n+\n+\t\t\tlast unless $all_parents_ok;\n+\n+\t\t\t# We now have a list of all SVN revnos which are\n+\t\t\t# merged by this particular parent. Integrate them.\n+\t\t\tnext if $#revsin == -1;\n+\t\t\tmy $newmergeinfo = \"$branchpath:\" . join(',', @revsin);\n+\t\t\t$aggregate_mergeinfo =\n+\t\t\t\tmerge_merge_info($aggregate_mergeinfo,\n+\t\t\t\t\t\t\t\t $newmergeinfo, 1);\n+\t\t}\n+\t\tif ($all_parents_ok and $aggregate_mergeinfo) {\n+\t\t\treturn $aggregate_mergeinfo;\n+\t\t}\n+\t}\n+\n+\treturn undef;\n+}\n+\n sub cmd_dcommit {\n \tmy $head = shift;\n \tcommand_noisy(qw/update-index --refresh/);\n@@ -547,6 +736,62 @@ sub cmd_dcommit {\n \t\t     \"without --no-rebase may be required.\"\n \t}\n \tmy $expect_url = $url;\n+\n+\tmy $push_merge_info = eval {\n+\t\tcommand_oneline(qw/config --get svn.pushmergeinfo/)\n+\t\t};\n+\tif (not defined($push_merge_info)\n+\t\t\tor $push_merge_info eq \"false\"\n+\t\t\tor $push_merge_info eq \"no\"\n+\t\t\tor $push_merge_info eq \"never\") {\n+\t\t$push_merge_info = 0;\n+\t}\n+\n+\tunless (defined $_merge_info or not $push_merge_info) {\n+\t\t# Preflight check of changes to ensure no issues with mergeinfo\n+\t\t# This includes check for uncommitted-to-SVN parents\n+\t\t# (other than the first parent, which we will handle),\n+\t\t# information from different SVN repos, and paths\n+\t\t# which are not underneath this repository root.\n+\t\tmy $rooturl = $gs->repos_root;\n+\t\tforeach my $d (@$linear_refs) {\n+\t\t\tmy %parentshash;\n+\t\t\tread_commit_parents(\\%parentshash, $d);\n+\t\t\tmy @realparents = @{$parentshash{$d}};\n+\t\t\tif ($#realparents > 0) {\n+\t\t\t\t# Merge commit\n+\t\t\t\tshift @realparents; # Remove/ignore first parent\n+\t\t\t\tforeach my $parent (@realparents) {\n+\t\t\t\t\tmy ($branchurl, $svnrev, $paruuid) = cmt_metadata($parent);\n+\t\t\t\t\tunless (defined $paruuid) {\n+\t\t\t\t\t\t# A parent is missing SVN annotations...\n+\t\t\t\t\t\t# abort the whole operation.\n+\t\t\t\t\t\tfatal \"$parent is merged into revision $d, \"\n+\t\t\t\t\t\t\t .\"but does not have git-svn metadata. \"\n+\t\t\t\t\t\t\t .\"Either dcommit the branch or use a \"\n+\t\t\t\t\t\t\t .\"local cherry-pick, FF merge, or rebase \"\n+\t\t\t\t\t\t\t .\"instead of an explicit merge commit.\";\n+\t\t\t\t\t}\n+\n+\t\t\t\t\tunless ($paruuid eq $uuid) {\n+\t\t\t\t\t\t# Parent has SVN metadata from different repository\n+\t\t\t\t\t\tfatal \"merge parent $parent for change $d has \"\n+\t\t\t\t\t\t\t .\"git-svn uuid $paruuid, while current change \"\n+\t\t\t\t\t\t\t .\"has uuid $uuid!\";\n+\t\t\t\t\t}\n+\n+\t\t\t\t\tunless ($branchurl =~ /^$rooturl(.*)/) {\n+\t\t\t\t\t\t# This branch is very strange indeed.\n+\t\t\t\t\t\tfatal \"merge parent $parent for $d is on branch \"\n+\t\t\t\t\t\t\t .\"$branchurl, which is not under the \"\n+\t\t\t\t\t\t\t .\"git-svn root $rooturl!\";\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tmy $rewritten_parent;\n \tGit::SVN::remove_username($expect_url);\n \twhile (1) {\n \t\tmy $d = shift @$linear_refs or last;\n@@ -561,6 +806,13 @@ sub cmd_dcommit {\n \t\t\tprint \"diff-tree $d~1 $d\\n\";\n \t\t} else {\n \t\t\tmy $cmt_rev;\n+\n+\t\t\tunless (defined $_merge_info or not $push_merge_info) {\n+\t\t\t\t$_merge_info = populate_merge_info($d, $gs, $uuid,\n+\t\t\t\t\t\t\t\t\t\t\t\t   $linear_refs,\n+\t\t\t\t\t\t\t\t\t\t\t\t   $rewritten_parent);\n+\t\t\t}\n+\n \t\t\tmy %ed_opts = ( r => $last_rev,\n \t\t\t                log => get_commit_entry($d)->{log},\n \t\t\t                ra => Git::SVN::Ra->new($url),\n@@ -603,6 +855,9 @@ sub cmd_dcommit {\n \t\t\t\t@finish = qw/reset --mixed/;\n \t\t\t}\n \t\t\tcommand_noisy(@finish, $gs->refname);\n+\n+\t\t\t$rewritten_parent = command_oneline(qw/rev-parse HEAD/);\n+\n \t\t\tif (@diff) {\n \t\t\t\t@refs = ();\n \t\t\t\tmy ($url_, $rev_, $uuid_, $gs_) =\ndiff --git a/t/t9160-git-svn-mergeinfo-push.sh b/t/t9160-git-svn-mergeinfo-push.sh\nnew file mode 100755\nindex 0000000..216f3d7\n--- /dev/null\n+++ b/t/t9160-git-svn-mergeinfo-push.sh\n@@ -0,0 +1,104 @@\n+#!/bin/sh\n+#\n+# Portions copyright (c) 2007, 2009 Sam Vilain\n+# Portions copyright (c) 2011 Bryan Jacobs\n+#\n+\n+test_description='git-svn svn mergeinfo propagation'\n+\n+. ./lib-git-svn.sh\n+\n+test_expect_success 'load svn dump' \"\n+\tsvnadmin load -q '$rawsvnrepo' \\\n+\t  < '$TEST_DIRECTORY/t9160/branches.dump' &&\n+\tgit svn init --minimize-url -R svnmerge \\\n+\t  -T trunk -b branches '$svnrepo' &&\n+\tgit svn fetch --all\n+\t\"\n+\n+test_expect_success 'propagate merge information' '\n+\tgit config svn.pushmergeinfo yes &&\n+\tgit checkout svnb1 &&\n+\tgit merge --no-ff svnb2 &&\n+\tgit svn dcommit\n+\t'\n+\n+test_expect_success 'check svn:mergeinfo' '\n+\tmergeinfo=$(svn_cmd propget svn:mergeinfo \"$svnrepo\"/branches/svnb1)\n+\ttest \"$mergeinfo\" = \"/branches/svnb2:3,8\"\n+\t'\n+\n+test_expect_success 'merge another branch' '\n+\tgit merge --no-ff svnb3 &&\n+\tgit svn dcommit\n+\t'\n+\n+test_expect_success 'check primary parent mergeinfo respected' '\n+\tmergeinfo=$(svn_cmd propget svn:mergeinfo \"$svnrepo\"/branches/svnb1)\n+\ttest \"$mergeinfo\" = \"/branches/svnb2:3,8\n+/branches/svnb3:4,9\"\n+\t'\n+\n+test_expect_success 'merge existing merge' '\n+\tgit merge --no-ff svnb4 &&\n+\tgit svn dcommit\n+\t'\n+\n+test_expect_success \"check both parents' mergeinfo respected\" '\n+\tmergeinfo=$(svn_cmd propget svn:mergeinfo \"$svnrepo\"/branches/svnb1)\n+\ttest \"$mergeinfo\" = \"/branches/svnb2:3,8\n+/branches/svnb3:4,9\n+/branches/svnb4:5-6,10-12\n+/branches/svnb5:6,11\"\n+\t'\n+\n+test_expect_success 'make further commits to branch' '\n+\tgit checkout svnb2 &&\n+\ttouch newb2file &&\n+\tgit add newb2file &&\n+\tgit commit -m \"later b2 commit\" &&\n+\ttouch newb2file-2 &&\n+\tgit add newb2file-2 &&\n+\tgit commit -m \"later b2 commit 2\" &&\n+\tgit svn dcommit\n+\t'\n+\n+test_expect_success 'second forward merge' '\n+\tgit checkout svnb1 &&\n+\tgit merge --no-ff svnb2 &&\n+\tgit svn dcommit\n+\t'\n+\n+test_expect_success 'check new mergeinfo added' '\n+\tmergeinfo=$(svn_cmd propget svn:mergeinfo \"$svnrepo\"/branches/svnb1)\n+\ttest \"$mergeinfo\" = \"/branches/svnb2:3,8,16-17\n+/branches/svnb3:4,9\n+/branches/svnb4:5-6,10-12\n+/branches/svnb5:6,11\"\n+\t'\n+\n+test_expect_success 'reintegration merge' '\n+\tgit checkout svnb4 &&\n+\tgit merge --no-ff svnb1 &&\n+\tgit svn dcommit\n+\t'\n+\n+test_expect_success 'check reintegration mergeinfo' '\n+\tmergeinfo=$(svn_cmd propget svn:mergeinfo \"$svnrepo\"/branches/svnb4)\n+\ttest \"$mergeinfo\" = \"/branches/svnb1:2-4,7-9,13-18\n+/branches/svnb2:3,8,16-17\n+/branches/svnb3:4,9\n+/branches/svnb4:5-6,10-12\n+/branches/svnb5:6,11\"\n+\t'\n+\n+test_expect_success 'dcommit a merge at the top of a stack' '\n+\tgit checkout svnb1 &&\n+\ttouch anotherfile &&\n+\tgit add anotherfile &&\n+\tgit commit -m \"a commit\" &&\n+\tgit merge svnb4 &&\n+\tgit svn dcommit\n+\t'\n+\n+test_done\ndiff --git a/t/t9160/branches.dump b/t/t9160/branches.dump\nnew file mode 100644\nindex 0000000..e61c3e7\n--- /dev/null\n+++ b/t/t9160/branches.dump\n@@ -0,0 +1,374 @@\n+SVN-fs-dump-format-version: 2\n+\n+UUID: 1ef08553-f2d1-45df-b38c-19af6b7c926d\n+\n+Revision-number: 0\n+Prop-content-length: 56\n+Content-length: 56\n+\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:08:02.941384Z\n+PROPS-END\n+\n+Revision-number: 1\n+Prop-content-length: 114\n+Content-length: 114\n+\n+K 7\n+svn:log\n+V 12\n+Base commit\n+\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:08:27.205062Z\n+PROPS-END\n+\n+Node-path: branches\n+Node-kind: dir\n+Node-action: add\n+Prop-content-length: 10\n+Content-length: 10\n+\n+PROPS-END\n+\n+\n+Node-path: trunk\n+Node-kind: dir\n+Node-action: add\n+Prop-content-length: 10\n+Content-length: 10\n+\n+PROPS-END\n+\n+\n+Revision-number: 2\n+Prop-content-length: 121\n+Content-length: 121\n+\n+K 7\n+svn:log\n+V 19\n+Create branch svnb1\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:09:43.628137Z\n+PROPS-END\n+\n+Node-path: branches/svnb1\n+Node-kind: dir\n+Node-action: add\n+Node-copyfrom-rev: 1\n+Node-copyfrom-path: trunk\n+\n+\n+Revision-number: 3\n+Prop-content-length: 121\n+Content-length: 121\n+\n+K 7\n+svn:log\n+V 19\n+Create branch svnb2\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:09:46.339930Z\n+PROPS-END\n+\n+Node-path: branches/svnb2\n+Node-kind: dir\n+Node-action: add\n+Node-copyfrom-rev: 1\n+Node-copyfrom-path: trunk\n+\n+\n+Revision-number: 4\n+Prop-content-length: 121\n+Content-length: 121\n+\n+K 7\n+svn:log\n+V 19\n+Create branch svnb3\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:09:49.394515Z\n+PROPS-END\n+\n+Node-path: branches/svnb3\n+Node-kind: dir\n+Node-action: add\n+Node-copyfrom-rev: 1\n+Node-copyfrom-path: trunk\n+\n+\n+Revision-number: 5\n+Prop-content-length: 121\n+Content-length: 121\n+\n+K 7\n+svn:log\n+V 19\n+Create branch svnb4\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:09:54.114607Z\n+PROPS-END\n+\n+Node-path: branches/svnb4\n+Node-kind: dir\n+Node-action: add\n+Node-copyfrom-rev: 1\n+Node-copyfrom-path: trunk\n+\n+\n+Revision-number: 6\n+Prop-content-length: 121\n+Content-length: 121\n+\n+K 7\n+svn:log\n+V 19\n+Create branch svnb5\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:09:58.602623Z\n+PROPS-END\n+\n+Node-path: branches/svnb5\n+Node-kind: dir\n+Node-action: add\n+Node-copyfrom-rev: 1\n+Node-copyfrom-path: trunk\n+\n+\n+Revision-number: 7\n+Prop-content-length: 110\n+Content-length: 110\n+\n+K 7\n+svn:log\n+V 9\n+b1 commit\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:10:20.292369Z\n+PROPS-END\n+\n+Node-path: branches/svnb1/b1file\n+Node-kind: file\n+Node-action: add\n+Prop-content-length: 10\n+Text-content-length: 0\n+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e\n+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709\n+Content-length: 10\n+\n+PROPS-END\n+\n+\n+Revision-number: 8\n+Prop-content-length: 110\n+Content-length: 110\n+\n+K 7\n+svn:log\n+V 9\n+b2 commit\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:10:38.429199Z\n+PROPS-END\n+\n+Node-path: branches/svnb2/b2file\n+Node-kind: file\n+Node-action: add\n+Prop-content-length: 10\n+Text-content-length: 0\n+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e\n+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709\n+Content-length: 10\n+\n+PROPS-END\n+\n+\n+Revision-number: 9\n+Prop-content-length: 110\n+Content-length: 110\n+\n+K 7\n+svn:log\n+V 9\n+b3 commit\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:10:52.843023Z\n+PROPS-END\n+\n+Node-path: branches/svnb3/b3file\n+Node-kind: file\n+Node-action: add\n+Prop-content-length: 10\n+Text-content-length: 0\n+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e\n+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709\n+Content-length: 10\n+\n+PROPS-END\n+\n+\n+Revision-number: 10\n+Prop-content-length: 110\n+Content-length: 110\n+\n+K 7\n+svn:log\n+V 9\n+b4 commit\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:11:17.489870Z\n+PROPS-END\n+\n+Node-path: branches/svnb4/b4file\n+Node-kind: file\n+Node-action: add\n+Prop-content-length: 10\n+Text-content-length: 0\n+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e\n+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709\n+Content-length: 10\n+\n+PROPS-END\n+\n+\n+Revision-number: 11\n+Prop-content-length: 110\n+Content-length: 110\n+\n+K 7\n+svn:log\n+V 9\n+b5 commit\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:11:32.277404Z\n+PROPS-END\n+\n+Node-path: branches/svnb5/b5file\n+Node-kind: file\n+Node-action: add\n+Prop-content-length: 10\n+Text-content-length: 0\n+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e\n+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709\n+Content-length: 10\n+\n+PROPS-END\n+\n+\n+Revision-number: 12\n+Prop-content-length: 192\n+Content-length: 192\n+\n+K 7\n+svn:log\n+V 90\n+Merge remote-tracking branch 'svnb5' into HEAD\n+\n+* svnb5:\n+  b5 commit\n+  Create branch svnb5\n+K 10\n+svn:author\n+V 7\n+bjacobs\n+K 8\n+svn:date\n+V 27\n+2011-09-02T16:11:54.274722Z\n+PROPS-END\n+\n+Node-path: branches/svnb4\n+Node-kind: dir\n+Node-action: change\n+Prop-content-length: 56\n+Content-length: 56\n+\n+K 13\n+svn:mergeinfo\n+V 21\n+/branches/svnb5:6,11\n+\n+PROPS-END\n+\n+\n+Node-path: branches/svnb4/b5file\n+Node-kind: file\n+Node-action: add\n+Prop-content-length: 10\n+Text-content-length: 0\n+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e\n+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709\n+Content-length: 10\n+\n+PROPS-END\n+\n+\n-- \n1.7.6.1.5.g8ba83.dirty\n"},{"id":"175248","messageId":"20110909222159.GA6530@dcvr.yhbt.net","threadId":"28329","inReplyTo":"20110907133605.07ecad1b@robyn.woti.com","subject":"Re: [PATCH v2] git-svn: teach git-svn to populate svn:mergeinfo","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2011-09-09T22:21:59Z","receivedAt":"2011-09-09T22:21:59Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Bryan Jacobs <bjacobs@woti.com> wrote:\n> This is the second revision of a patch I posted earlier. I believe\n> this patch is now suitable for inclusion.\n\nSome comments inline, but I can clean them up myself and push out in a\nbit.\n\n> --- a/Documentation/git-svn.txt\n> +++ b/Documentation/git-svn.txt\n> @@ -213,6 +213,14 @@ discouraged.\n>  \tstore this information (as a property), and svn clients starting from\n>  \tversion 1.5 can make use of it. 'git svn' currently does not use it\n>  \tand does not set it automatically.\n\nI noticed this conflicts when applying due to the missing --mergeinfo=\ndocumentation.  Did you intend to remove --mergeinfo entirely and\nreplace it with this?  I think some folks already depend on it (it's\nbeen around since last year).\n\n> +\tif (not defined($push_merge_info)\n> +\t\t\tor $push_merge_info eq \"false\"\n> +\t\t\tor $push_merge_info eq \"no\"\n> +\t\t\tor $push_merge_info eq \"never\") {\n\nI missed this the first time, but \"||\" and \"!\" are easier for\nC programmers to understand and higher in precedence (ref: perlop manpage)\n\n-- \nEric Wong\n"},{"id":"175334","messageId":"20110912102422.21aa6570@robyn.woti.com","threadId":"28329","inReplyTo":"20110909222159.GA6530@dcvr.yhbt.net","subject":"Re: [PATCH v2] git-svn: teach git-svn to populate svn:mergeinfo","fromName":"Bryan Jacobs","fromEmail":"bjacobs@woti.com","sentAt":"2011-09-12T14:24:22Z","receivedAt":"2011-09-12T14:24:22Z","isPatch":true,"sender":{"key":"bjacobs@woti.com","avatar":null},"body":"On Fri, 9 Sep 2011 15:21:59 -0700\nEric Wong <normalperson@yhbt.net> wrote:\n\n> Some comments inline, but I can clean them up myself and push out in a\n> bit.\n> \n> > --- a/Documentation/git-svn.txt\n> > +++ b/Documentation/git-svn.txt\n> > @@ -213,6 +213,14 @@ discouraged.\n> >  \tstore this information (as a property), and svn clients\n> > starting from version 1.5 can make use of it. 'git svn' currently\n> > does not use it and does not set it automatically.\n> \n> I noticed this conflicts when applying due to the missing --mergeinfo=\n> documentation.  Did you intend to remove --mergeinfo entirely and\n> replace it with this?  I think some folks already depend on it (it's\n> been around since last year).\n\nNo, that was me munging my patch base. Feel free to set the\ndocumentation for mergeinfo however you like, even documenting this\nfeature if you wish. The functionality of --mergeinfo still should work\nwith this patch, although obviously if it's provided the\nauto-population will be bypassed.\n\n> > +\tif (not defined($push_merge_info)\n> > +\t\t\tor $push_merge_info eq \"false\"\n> > +\t\t\tor $push_merge_info eq \"no\"\n> > +\t\t\tor $push_merge_info eq \"never\") {\n> \n> I missed this the first time, but \"||\" and \"!\" are easier for\n> C programmers to understand and higher in precedence (ref: perlop\n> manpage)\n> \n\nYou're right, \"||\" and \"!\" are better here. TMTOWTDI is the Perl motto,\nno? A double-edged sword.\n\nThanks for the help and review. I'll let you do the cleanup and push\nthe resulting patch when you feel it's ready (as you suggested), rather\nthan iterating again for these small changes.\n\nBryan Jacobs\n"},{"id":"175391","messageId":"20110913081815.GA19445@dcvr.yhbt.net","threadId":"28329","inReplyTo":"20110912102422.21aa6570@robyn.woti.com","subject":"Re: [PATCH v2] git-svn: teach git-svn to populate svn:mergeinfo","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2011-09-13T08:18:15Z","receivedAt":"2011-09-13T08:18:15Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Bryan Jacobs <bjacobs@woti.com> wrote:\n> Thanks for the help and review. I'll let you do the cleanup and push\n> the resulting patch when you feel it's ready (as you suggested), rather\n> than iterating again for these small changes.\n\nOK, it's pushed to \"master\" on git://bogomips.org/git-svn.git\nas commit 1e5814f3def08452aef4caa703f074ba7d167867.\n\nOn a side note, if you have more changes you want to make (and have free\ntime :)  git-svn.perl would really benefit from being split into\nseparate .pm files for ease-of-maintenance.\n"}]}