{"thread":{"id":"20027","subject":"[PATCH/RFC] git-svn: Fix branch detection when repository root is inaccessible","startedAt":"2009-07-05T11:51:45Z","lastAt":"2009-07-07T15:30:46Z","messageCount":7,"participants":["Mattias Nissler","Eric Wong","Marc Branchaud"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"117456","messageId":"1246794706.4818.33.camel@kea","threadId":"20027","inReplyTo":null,"subject":"[PATCH/RFC] git-svn: Fix branch detection when repository root is inaccessible","fromName":"Mattias Nissler","fromEmail":"mattias.nissler@gmx.de","sentAt":"2009-07-05T11:51:45Z","receivedAt":"2009-07-05T11:51:45Z","isPatch":true,"sender":{"key":"mattias.nissler@gmx.de","avatar":null},"body":"For the case of multiple projects sharing a single SVN repository, it is\ncommon practice to create the standard SVN directory layout within a\nsubdirectory for each project. In such setups, access control is often\nused to limit what projects a given user may access. git-svn failed to\ndetect branches (e.g. when passing --stdlayout to clone) because it\nrelied on having access to the root directory in the repository. This\npatch solves this problem by making git-svn use paths relative to the\ngiven repository URL instead of the repository root.\n\nSigned-off-by: Mattias Nissler <mattias.nissler@gmx.de>\n---\n\nI've already posted this on May 31st but received no feedback, so here\nis the patch again against current git.git. I'm using this at work to be\nable to checkout a complete SVN project including all branches and tags\nin one go without having to create an individual remote for each branch\nand tag. Any chance we can get this into mainline git?\n\nCheers,\n\nMattias\n\n\n git-svn.perl |   83 +++++++++++++++++++++++++--------------------------------\n 1 files changed, 36 insertions(+), 47 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex d1af1a3..cc15731 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -876,10 +876,6 @@ sub cmd_multi_init {\n \t\tusage(1);\n \t}\n \n-\t# there are currently some bugs that prevent multi-init/multi-fetch\n-\t# setups from working well without this.\n-\t$Git::SVN::_minimize_url = 1;\n-\n \t$_prefix = '' unless defined $_prefix;\n \tif (defined $url) {\n \t\t$url = canonicalize_url($url);\n@@ -1180,7 +1176,7 @@ sub complete_url_ls_init {\n \t\t    \"wanted to set to: $gs->{url}\\n\";\n \t}\n \tcommand_oneline('config', $k, $gs->{url}) unless $orig_url;\n-\tmy $remote_path = \"$ra->{svn_path}/$repo_path\";\n+\tmy $remote_path = \"$gs->{path}/$repo_path\";\n \t$remote_path =~ s#/+#/#g;\n \t$remote_path =~ s#^/##g;\n \t$remote_path .= \"/*\" if $remote_path !~ /\\*/;\n@@ -2177,16 +2173,6 @@ sub ra {\n \t$ra;\n }\n \n-sub rel_path {\n-\tmy ($self) = @_;\n-\tmy $repos_root = $self->ra->{repos_root};\n-\treturn $self->{path} if ($self->{url} eq $repos_root);\n-\tmy $url = $self->{url} .\n-\t          (length $self->{path} ? \"/$self->{path}\" : $self->{path});\n-\t$url =~ s!^\\Q$repos_root\\E(?:/+|$)!!g;\n-\t$url;\n-}\n-\n # prop_walk(PATH, REV, SUB)\n # -------------------------\n # Recursively traverse PATH at revision REV and invoke SUB for each\n@@ -2512,10 +2498,7 @@ sub match_paths {\n \tif (my $path = $paths->{\"/$self->{path}\"}) {\n \t\treturn ($path->{action} eq 'D') ? 0 : 1;\n \t}\n-\tmy $repos_root = $self->ra->{repos_root};\n-\tmy $extended_path = $self->{url} . '/' . $self->{path};\n-\t$extended_path =~ s#^\\Q$repos_root\\E(/|$)##;\n-\t$self->{path_regex} ||= qr/^\\/\\Q$extended_path\\E\\//;\n+\t$self->{path_regex} ||= qr/^\\/\\Q$self->{path}\\E\\//;\n \tif (grep /$self->{path_regex}/, keys %$paths) {\n \t\treturn 1;\n \t}\n@@ -2538,15 +2521,14 @@ sub find_parent_branch {\n \tunless (defined $paths) {\n \t\tmy $err_handler = $SVN::Error::handler;\n \t\t$SVN::Error::handler = \\&Git::SVN::Ra::skip_unknown_revs;\n-\t\t$self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1, sub {\n-\t\t                   $paths =\n-\t\t\t\t      Git::SVN::Ra::dup_changed_paths($_[0]) });\n+\t\t$self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1,\n+\t\t\tsub { $paths = $_[0] });\n \t\t$SVN::Error::handler = $err_handler;\n \t}\n \treturn undef unless defined $paths;\n \n \t# look for a parent from another branch:\n-\tmy @b_path_components = split m#/#, $self->rel_path;\n+\tmy @b_path_components = split m#/#, $self->{path};\n \tmy @a_path_components;\n \tmy $i;\n \twhile (@b_path_components) {\n@@ -2564,11 +2546,11 @@ sub find_parent_branch {\n \tmy $r = $i->{copyfrom_rev};\n \tmy $repos_root = $self->ra->{repos_root};\n \tmy $url = $self->ra->{url};\n-\tmy $new_url = $repos_root . $branch_from;\n+\tmy $new_url = $url . $branch_from;\n \tprint STDERR  \"Found possible branch point: \",\n \t              \"$new_url => \", $self->full_url, \", $r\\n\";\n \t$branch_from =~ s#^/##;\n-\tmy $gs = $self->other_gs($new_url, $url, $repos_root,\n+\tmy $gs = $self->other_gs($new_url, $url,\n \t\t                 $branch_from, $r, $self->{ref_id});\n \tmy ($r0, $parent) = $gs->find_rev_before($r, 1);\n \t{\n@@ -2753,9 +2735,9 @@ sub parse_svn_date {\n }\n \n sub other_gs {\n-\tmy ($self, $new_url, $url, $repos_root,\n+\tmy ($self, $new_url, $url,\n \t    $branch_from, $r, $old_ref_id) = @_;\n-\tmy $gs = Git::SVN->find_by_url($new_url, $repos_root, $branch_from);\n+\tmy $gs = Git::SVN->find_by_url($new_url, $url, $branch_from);\n \tunless ($gs) {\n \t\tmy $ref_id = $old_ref_id;\n \t\t$ref_id =~ s/\\@\\d+$//;\n@@ -4431,6 +4413,31 @@ sub get_log {\n \tmy ($self, @args) = @_;\n \tmy $pool = SVN::Pool->new;\n \n+\t# svn_log_changed_path_t objects passed to get_log are likely to be\n+\t# overwritten even if only the refs are copied to an external variable,\n+\t# so we should dup the structures in their entirety.  Using an\n+\t# externally passed pool (instead of our temporary and quickly cleared\n+\t# pool in Git::SVN::Ra) does not help matters at all...\n+\tmy $receiver = pop @args;\n+\tmy $prefix = \"/\".$self->{svn_path};\n+\t$prefix =~ s#/+($)##;\n+\tmy $prefix_regex = qr#^\\Q$prefix\\E#;\n+\tpush(@args, sub {\n+\t\tmy ($paths) = $_[0];\n+\t\treturn &$receiver(@_) unless $paths;\n+\t\t$_[0] = ();\n+\t\tforeach my $p (keys %$paths) {\n+\t\t\tmy $i = $paths->{$p};\n+\t\t\t# Make path relative to our url, not repos_root\n+\t\t\t$p =~ s/$prefix_regex//;\n+\t\t\tmy %s = map { $_ => $i->$_; }\n+\t\t\t\tqw/copyfrom_path copyfrom_rev action/;\n+\t\t\t$s{'copyfrom_path'} =~ s/$prefix_regex// if $s{'copyfrom_path'};\n+\t\t\t$_[0]{$p} = \\%s;\n+\t\t}\n+\t\t&$receiver(@_);\n+\t});\n+\n \t# the limit parameter was not supported in SVN 1.1.x, so we\n \t# drop it.  Therefore, the receiver callback passed to it\n \t# is made aware of this limitation by being wrapped if\n@@ -4442,6 +4449,7 @@ sub get_log {\n \t\t\tpush(@args, sub { &$receiver(@_) if (--$limit >= 0) });\n \t\t}\n \t}\n+\n \tmy $ret = $self->SUPER::get_log(@args, $pool);\n \t$pool->clear;\n \t$ret;\n@@ -4600,8 +4608,7 @@ sub gs_fetch_loop_common {\n \t\t};\n \t\tsub _cb {\n \t\t\tmy ($paths, $r, $author, $date, $log) = @_;\n-\t\t\t[ dup_changed_paths($paths),\n-\t\t\t  { author => $author, date => $date, log => $log } ];\n+\t\t\t[ $paths, { author => $author, date => $date, log => $log } ];\n \t\t}\n \t\t$self->get_log([$longest_path], $min, $max, 0, 1, 1,\n \t\t               sub { $revs{$_[1]} = _cb(@_) });\n@@ -4823,24 +4830,6 @@ sub skip_unknown_revs {\n \tdie \"Error from SVN, ($errno): \", $err->expanded_message,\"\\n\";\n }\n \n-# svn_log_changed_path_t objects passed to get_log are likely to be\n-# overwritten even if only the refs are copied to an external variable,\n-# so we should dup the structures in their entirety.  Using an externally\n-# passed pool (instead of our temporary and quickly cleared pool in\n-# Git::SVN::Ra) does not help matters at all...\n-sub dup_changed_paths {\n-\tmy ($paths) = @_;\n-\treturn undef unless $paths;\n-\tmy %ret;\n-\tforeach my $p (keys %$paths) {\n-\t\tmy $i = $paths->{$p};\n-\t\tmy %s = map { $_ => $i->$_ }\n-\t\t              qw/copyfrom_path copyfrom_rev action/;\n-\t\t$ret{$p} = \\%s;\n-\t}\n-\t\\%ret;\n-}\n-\n package Git::SVN::Log;\n use strict;\n use warnings;\n-- \n1.6.3.3\n"},{"id":"117512","messageId":"20090706212742.GA8219@dcvr.yhbt.net","threadId":"20027","inReplyTo":"1246794706.4818.33.camel@kea","subject":"Re: [PATCH/RFC] git-svn: Fix branch detection when repository root is inaccessible","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2009-07-06T21:27:43Z","receivedAt":"2009-07-06T21:27:43Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Mattias Nissler <mattias.nissler@gmx.de> wrote:\n> For the case of multiple projects sharing a single SVN repository, it is\n> common practice to create the standard SVN directory layout within a\n> subdirectory for each project. In such setups, access control is often\n> used to limit what projects a given user may access. git-svn failed to\n> detect branches (e.g. when passing --stdlayout to clone) because it\n> relied on having access to the root directory in the repository. This\n> patch solves this problem by making git-svn use paths relative to the\n> given repository URL instead of the repository root.\n> \n> Signed-off-by: Mattias Nissler <mattias.nissler@gmx.de>\n> ---\n> \n> I've already posted this on May 31st but received no feedback, so here\n> is the patch again against current git.git. I'm using this at work to be\n> able to checkout a complete SVN project including all branches and tags\n> in one go without having to create an individual remote for each branch\n> and tag. Any chance we can get this into mainline git?\n> \n> Cheers,\n\nThanks Mattias, sorry about missing your previous posting.  Feel free\nto email me directly if I don't respond in a week or so in the future.\n\nFixing the minimize logic is definitely a wanted improvement I haven't\nbeen able to fix myself.  Unfortunately, your patch breaks the\nt9138-git-svn-multiple-branches.sh test for me.  I haven't looked at it\nat all, but I'll try to take a look at it later today after I process other\nthings in my overflowing work queue; but I definitely want access issues\nfixed for people with restrictive repo setups.\n\nOne thing I would do is to split out the making of dup_changed_paths()\nthe default behavior into a separate patch.  I think this is a good\nchange since it makes things less surprising for future hackers of\ngit svn.\n\nThanks again!\n\n>  git-svn.perl |   83 +++++++++++++++++++++++++--------------------------------\n>  1 files changed, 36 insertions(+), 47 deletions(-)\n> \n> diff --git a/git-svn.perl b/git-svn.perl\n> index d1af1a3..cc15731 100755\n> --- a/git-svn.perl\n> +++ b/git-svn.perl\n> @@ -876,10 +876,6 @@ sub cmd_multi_init {\n>  \t\tusage(1);\n>  \t}\n>  \n> -\t# there are currently some bugs that prevent multi-init/multi-fetch\n> -\t# setups from working well without this.\n> -\t$Git::SVN::_minimize_url = 1;\n> -\n>  \t$_prefix = '' unless defined $_prefix;\n>  \tif (defined $url) {\n>  \t\t$url = canonicalize_url($url);\n> @@ -1180,7 +1176,7 @@ sub complete_url_ls_init {\n>  \t\t    \"wanted to set to: $gs->{url}\\n\";\n>  \t}\n>  \tcommand_oneline('config', $k, $gs->{url}) unless $orig_url;\n> -\tmy $remote_path = \"$ra->{svn_path}/$repo_path\";\n> +\tmy $remote_path = \"$gs->{path}/$repo_path\";\n>  \t$remote_path =~ s#/+#/#g;\n>  \t$remote_path =~ s#^/##g;\n>  \t$remote_path .= \"/*\" if $remote_path !~ /\\*/;\n> @@ -2177,16 +2173,6 @@ sub ra {\n>  \t$ra;\n>  }\n>  \n> -sub rel_path {\n> -\tmy ($self) = @_;\n> -\tmy $repos_root = $self->ra->{repos_root};\n> -\treturn $self->{path} if ($self->{url} eq $repos_root);\n> -\tmy $url = $self->{url} .\n> -\t          (length $self->{path} ? \"/$self->{path}\" : $self->{path});\n> -\t$url =~ s!^\\Q$repos_root\\E(?:/+|$)!!g;\n> -\t$url;\n> -}\n> -\n>  # prop_walk(PATH, REV, SUB)\n>  # -------------------------\n>  # Recursively traverse PATH at revision REV and invoke SUB for each\n> @@ -2512,10 +2498,7 @@ sub match_paths {\n>  \tif (my $path = $paths->{\"/$self->{path}\"}) {\n>  \t\treturn ($path->{action} eq 'D') ? 0 : 1;\n>  \t}\n> -\tmy $repos_root = $self->ra->{repos_root};\n> -\tmy $extended_path = $self->{url} . '/' . $self->{path};\n> -\t$extended_path =~ s#^\\Q$repos_root\\E(/|$)##;\n> -\t$self->{path_regex} ||= qr/^\\/\\Q$extended_path\\E\\//;\n> +\t$self->{path_regex} ||= qr/^\\/\\Q$self->{path}\\E\\//;\n>  \tif (grep /$self->{path_regex}/, keys %$paths) {\n>  \t\treturn 1;\n>  \t}\n> @@ -2538,15 +2521,14 @@ sub find_parent_branch {\n>  \tunless (defined $paths) {\n>  \t\tmy $err_handler = $SVN::Error::handler;\n>  \t\t$SVN::Error::handler = \\&Git::SVN::Ra::skip_unknown_revs;\n> -\t\t$self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1, sub {\n> -\t\t                   $paths =\n> -\t\t\t\t      Git::SVN::Ra::dup_changed_paths($_[0]) });\n> +\t\t$self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1,\n> +\t\t\tsub { $paths = $_[0] });\n>  \t\t$SVN::Error::handler = $err_handler;\n>  \t}\n>  \treturn undef unless defined $paths;\n>  \n>  \t# look for a parent from another branch:\n> -\tmy @b_path_components = split m#/#, $self->rel_path;\n> +\tmy @b_path_components = split m#/#, $self->{path};\n>  \tmy @a_path_components;\n>  \tmy $i;\n>  \twhile (@b_path_components) {\n> @@ -2564,11 +2546,11 @@ sub find_parent_branch {\n>  \tmy $r = $i->{copyfrom_rev};\n>  \tmy $repos_root = $self->ra->{repos_root};\n>  \tmy $url = $self->ra->{url};\n> -\tmy $new_url = $repos_root . $branch_from;\n> +\tmy $new_url = $url . $branch_from;\n>  \tprint STDERR  \"Found possible branch point: \",\n>  \t              \"$new_url => \", $self->full_url, \", $r\\n\";\n>  \t$branch_from =~ s#^/##;\n> -\tmy $gs = $self->other_gs($new_url, $url, $repos_root,\n> +\tmy $gs = $self->other_gs($new_url, $url,\n>  \t\t                 $branch_from, $r, $self->{ref_id});\n>  \tmy ($r0, $parent) = $gs->find_rev_before($r, 1);\n>  \t{\n> @@ -2753,9 +2735,9 @@ sub parse_svn_date {\n>  }\n>  \n>  sub other_gs {\n> -\tmy ($self, $new_url, $url, $repos_root,\n> +\tmy ($self, $new_url, $url,\n>  \t    $branch_from, $r, $old_ref_id) = @_;\n> -\tmy $gs = Git::SVN->find_by_url($new_url, $repos_root, $branch_from);\n> +\tmy $gs = Git::SVN->find_by_url($new_url, $url, $branch_from);\n>  \tunless ($gs) {\n>  \t\tmy $ref_id = $old_ref_id;\n>  \t\t$ref_id =~ s/\\@\\d+$//;\n> @@ -4431,6 +4413,31 @@ sub get_log {\n>  \tmy ($self, @args) = @_;\n>  \tmy $pool = SVN::Pool->new;\n>  \n> +\t# svn_log_changed_path_t objects passed to get_log are likely to be\n> +\t# overwritten even if only the refs are copied to an external variable,\n> +\t# so we should dup the structures in their entirety.  Using an\n> +\t# externally passed pool (instead of our temporary and quickly cleared\n> +\t# pool in Git::SVN::Ra) does not help matters at all...\n> +\tmy $receiver = pop @args;\n> +\tmy $prefix = \"/\".$self->{svn_path};\n> +\t$prefix =~ s#/+($)##;\n> +\tmy $prefix_regex = qr#^\\Q$prefix\\E#;\n> +\tpush(@args, sub {\n> +\t\tmy ($paths) = $_[0];\n> +\t\treturn &$receiver(@_) unless $paths;\n> +\t\t$_[0] = ();\n> +\t\tforeach my $p (keys %$paths) {\n> +\t\t\tmy $i = $paths->{$p};\n> +\t\t\t# Make path relative to our url, not repos_root\n> +\t\t\t$p =~ s/$prefix_regex//;\n> +\t\t\tmy %s = map { $_ => $i->$_; }\n> +\t\t\t\tqw/copyfrom_path copyfrom_rev action/;\n> +\t\t\t$s{'copyfrom_path'} =~ s/$prefix_regex// if $s{'copyfrom_path'};\n> +\t\t\t$_[0]{$p} = \\%s;\n> +\t\t}\n> +\t\t&$receiver(@_);\n> +\t});\n> +\n>  \t# the limit parameter was not supported in SVN 1.1.x, so we\n>  \t# drop it.  Therefore, the receiver callback passed to it\n>  \t# is made aware of this limitation by being wrapped if\n> @@ -4442,6 +4449,7 @@ sub get_log {\n>  \t\t\tpush(@args, sub { &$receiver(@_) if (--$limit >= 0) });\n>  \t\t}\n>  \t}\n> +\n>  \tmy $ret = $self->SUPER::get_log(@args, $pool);\n>  \t$pool->clear;\n>  \t$ret;\n> @@ -4600,8 +4608,7 @@ sub gs_fetch_loop_common {\n>  \t\t};\n>  \t\tsub _cb {\n>  \t\t\tmy ($paths, $r, $author, $date, $log) = @_;\n> -\t\t\t[ dup_changed_paths($paths),\n> -\t\t\t  { author => $author, date => $date, log => $log } ];\n> +\t\t\t[ $paths, { author => $author, date => $date, log => $log } ];\n>  \t\t}\n>  \t\t$self->get_log([$longest_path], $min, $max, 0, 1, 1,\n>  \t\t               sub { $revs{$_[1]} = _cb(@_) });\n> @@ -4823,24 +4830,6 @@ sub skip_unknown_revs {\n>  \tdie \"Error from SVN, ($errno): \", $err->expanded_message,\"\\n\";\n>  }\n>  \n> -# svn_log_changed_path_t objects passed to get_log are likely to be\n> -# overwritten even if only the refs are copied to an external variable,\n> -# so we should dup the structures in their entirety.  Using an externally\n> -# passed pool (instead of our temporary and quickly cleared pool in\n> -# Git::SVN::Ra) does not help matters at all...\n> -sub dup_changed_paths {\n> -\tmy ($paths) = @_;\n> -\treturn undef unless $paths;\n> -\tmy %ret;\n> -\tforeach my $p (keys %$paths) {\n> -\t\tmy $i = $paths->{$p};\n> -\t\tmy %s = map { $_ => $i->$_ }\n> -\t\t              qw/copyfrom_path copyfrom_rev action/;\n> -\t\t$ret{$p} = \\%s;\n> -\t}\n> -\t\\%ret;\n> -}\n> -\n>  package Git::SVN::Log;\n>  use strict;\n>  use warnings;\n> -- \n> 1.6.3.3\n"},{"id":"117523","messageId":"1246919293.4618.12.camel@kea","threadId":"20027","inReplyTo":"20090706212742.GA8219@dcvr.yhbt.net","subject":"Re: [PATCH/RFC] git-svn: Fix branch detection when repository root is inaccessible","fromName":"Mattias Nissler","fromEmail":"mattias.nissler@gmx.de","sentAt":"2009-07-06T22:28:13Z","receivedAt":"2009-07-06T22:28:13Z","isPatch":true,"sender":{"key":"mattias.nissler@gmx.de","avatar":null},"body":"Hi Eric,\n\nOn Mon, 2009-07-06 at 14:27 -0700, Eric Wong wrote:\n> Fixing the minimize logic is definitely a wanted improvement I haven't\n> been able to fix myself.  Unfortunately, your patch breaks the\n> t9138-git-svn-multiple-branches.sh test for me.  \n\nI see the same here, not sure why I've missed it before. I've had a look\nat the problem and found that the test is actually depending on the\nminimizing logic, i.e. needs to specify -d project1/<tag-or-branch-dir>\nfor the tag or branch destination where the project1 prefix is due to\nthe minimization at clone time. Dropping the project1 part makes the\ntest succeed. I'll simply update the test to do so.\n\nI also think this is much better from a usability point of view since\nyou can now use the original branch or tag dir you've given to clone in\norder to specify the branch or tag destination.\n\n> I haven't looked at it\n> at all, but I'll try to take a look at it later today after I process other\n> things in my overflowing work queue; but I definitely want access issues\n> fixed for people with restrictive repo setups.\n> \n> One thing I would do is to split out the making of dup_changed_paths()\n> the default behavior into a separate patch.  I think this is a good\n> change since it makes things less surprising for future hackers of\n> git svn.\n\nOk, will do so. I'll send updated patches in reply to this mail.\n\nFinally, a big thanks for the nice job on git-svn. I've just experienced\nlots of trouble with the mercurial SVN integration and it's really a\npain in the ass even to just get a simple clean rebase done properly.\ngit-svn is really way more mature and it's a pleasure to use it for\neveryday work.\n\nMattias\n"},{"id":"117528","messageId":"1246923592.4618.17.camel@kea","threadId":"20027","inReplyTo":"20090706212742.GA8219@dcvr.yhbt.net","subject":"[PATCH 1/2] git-svn: Always duplicate paths returned from get_log","fromName":"Mattias Nissler","fromEmail":"mattias.nissler@gmx.de","sentAt":"2009-07-06T23:39:52Z","receivedAt":"2009-07-06T23:39:52Z","isPatch":true,"sender":{"key":"mattias.nissler@gmx.de","avatar":null},"body":"This makes get_log more safe to use because callers cannot run into path\nclobbering any more. The additional overhead will not affect performance\nsince the critical calls from the fetch loop need the path duplication\nanyway and the rest of the call sites is not performance critical.\n\nSigned-off-by: Mattias Nissler <mattias.nissler@gmx.de>\n---\n git-svn.perl |   46 +++++++++++++++++++++++-----------------------\n 1 files changed, 23 insertions(+), 23 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex d1af1a3..57d13af 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -2538,9 +2538,8 @@ sub find_parent_branch {\n \tunless (defined $paths) {\n \t\tmy $err_handler = $SVN::Error::handler;\n \t\t$SVN::Error::handler = \\&Git::SVN::Ra::skip_unknown_revs;\n-\t\t$self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1, sub {\n-\t\t                   $paths =\n-\t\t\t\t      Git::SVN::Ra::dup_changed_paths($_[0]) });\n+\t\t$self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1,\n+\t\t\t\t   sub { $paths = $_[0] });\n \t\t$SVN::Error::handler = $err_handler;\n \t}\n \treturn undef unless defined $paths;\n@@ -4431,6 +4430,26 @@ sub get_log {\n \tmy ($self, @args) = @_;\n \tmy $pool = SVN::Pool->new;\n \n+\t# svn_log_changed_path_t objects passed to get_log are likely to be\n+\t# overwritten even if only the refs are copied to an external variable,\n+\t# so we should dup the structures in their entirety.  Using an externally\n+\t# passed pool (instead of our temporary and quickly cleared pool in\n+\t# Git::SVN::Ra) does not help matters at all...\n+\tmy $receiver = pop @args;\n+\tpush(@args, sub {\n+\t\tmy ($paths) = $_[0];\n+\t\treturn &$receiver(@_) unless $paths;\n+\t\t$_[0] = ();\n+\t\tforeach my $p (keys %$paths) {\n+\t\t\tmy $i = $paths->{$p};\n+\t\t\tmy %s = map { $_ => $i->$_ }\n+\t\t\t\t      qw/copyfrom_path copyfrom_rev action/;\n+\t\t\t$_[0]{$p} = \\%s;\n+\t\t}\n+\t\t&$receiver(@_);\n+\t});\n+\n+\n \t# the limit parameter was not supported in SVN 1.1.x, so we\n \t# drop it.  Therefore, the receiver callback passed to it\n \t# is made aware of this limitation by being wrapped if\n@@ -4600,8 +4619,7 @@ sub gs_fetch_loop_common {\n \t\t};\n \t\tsub _cb {\n \t\t\tmy ($paths, $r, $author, $date, $log) = @_;\n-\t\t\t[ dup_changed_paths($paths),\n-\t\t\t  { author => $author, date => $date, log => $log } ];\n+\t\t\t[ $paths, { author => $author, date => $date, log => $log } ];\n \t\t}\n \t\t$self->get_log([$longest_path], $min, $max, 0, 1, 1,\n \t\t               sub { $revs{$_[1]} = _cb(@_) });\n@@ -4823,24 +4841,6 @@ sub skip_unknown_revs {\n \tdie \"Error from SVN, ($errno): \", $err->expanded_message,\"\\n\";\n }\n \n-# svn_log_changed_path_t objects passed to get_log are likely to be\n-# overwritten even if only the refs are copied to an external variable,\n-# so we should dup the structures in their entirety.  Using an externally\n-# passed pool (instead of our temporary and quickly cleared pool in\n-# Git::SVN::Ra) does not help matters at all...\n-sub dup_changed_paths {\n-\tmy ($paths) = @_;\n-\treturn undef unless $paths;\n-\tmy %ret;\n-\tforeach my $p (keys %$paths) {\n-\t\tmy $i = $paths->{$p};\n-\t\tmy %s = map { $_ => $i->$_ }\n-\t\t              qw/copyfrom_path copyfrom_rev action/;\n-\t\t$ret{$p} = \\%s;\n-\t}\n-\t\\%ret;\n-}\n-\n package Git::SVN::Log;\n use strict;\n use warnings;\n-- \n1.6.3.3\n"},{"id":"117527","messageId":"1246923602.4618.18.camel@kea","threadId":"20027","inReplyTo":"20090706212742.GA8219@dcvr.yhbt.net","subject":"[PATCH 2/2] git-svn: Fix branch detection when repository root is inaccessible","fromName":"Mattias Nissler","fromEmail":"mattias.nissler@gmx.de","sentAt":"2009-07-06T23:40:02Z","receivedAt":"2009-07-06T23:40:02Z","isPatch":true,"sender":{"key":"mattias.nissler@gmx.de","avatar":null},"body":"For the case of multiple projects sharing a single SVN repository, it is\ncommon practice to create the standard SVN directory layout within a\nsubdirectory for each project. In such setups, access control is often\nused to limit what projects a given user may access. git-svn failed to\ndetect branches (e.g. when passing --stdlayout to clone) because it\nrelied on having access to the root directory in the repository. This\npatch solves this problem by making git-svn use paths relative to the\ngiven repository URL instead of the repository root.\n\nSigned-off-by: Mattias Nissler <mattias.nissler@gmx.de>\n---\n git-svn.perl                         |   42 +++++++++++++---------------------\n t/t9138-git-svn-multiple-branches.sh |    8 +++---\n 2 files changed, 20 insertions(+), 30 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 57d13af..cf3948c 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -876,10 +876,6 @@ sub cmd_multi_init {\n \t\tusage(1);\n \t}\n \n-\t# there are currently some bugs that prevent multi-init/multi-fetch\n-\t# setups from working well without this.\n-\t$Git::SVN::_minimize_url = 1;\n-\n \t$_prefix = '' unless defined $_prefix;\n \tif (defined $url) {\n \t\t$url = canonicalize_url($url);\n@@ -1180,7 +1176,7 @@ sub complete_url_ls_init {\n \t\t    \"wanted to set to: $gs->{url}\\n\";\n \t}\n \tcommand_oneline('config', $k, $gs->{url}) unless $orig_url;\n-\tmy $remote_path = \"$ra->{svn_path}/$repo_path\";\n+\tmy $remote_path = \"$gs->{path}/$repo_path\";\n \t$remote_path =~ s#/+#/#g;\n \t$remote_path =~ s#^/##g;\n \t$remote_path .= \"/*\" if $remote_path !~ /\\*/;\n@@ -2177,16 +2173,6 @@ sub ra {\n \t$ra;\n }\n \n-sub rel_path {\n-\tmy ($self) = @_;\n-\tmy $repos_root = $self->ra->{repos_root};\n-\treturn $self->{path} if ($self->{url} eq $repos_root);\n-\tmy $url = $self->{url} .\n-\t          (length $self->{path} ? \"/$self->{path}\" : $self->{path});\n-\t$url =~ s!^\\Q$repos_root\\E(?:/+|$)!!g;\n-\t$url;\n-}\n-\n # prop_walk(PATH, REV, SUB)\n # -------------------------\n # Recursively traverse PATH at revision REV and invoke SUB for each\n@@ -2512,10 +2498,7 @@ sub match_paths {\n \tif (my $path = $paths->{\"/$self->{path}\"}) {\n \t\treturn ($path->{action} eq 'D') ? 0 : 1;\n \t}\n-\tmy $repos_root = $self->ra->{repos_root};\n-\tmy $extended_path = $self->{url} . '/' . $self->{path};\n-\t$extended_path =~ s#^\\Q$repos_root\\E(/|$)##;\n-\t$self->{path_regex} ||= qr/^\\/\\Q$extended_path\\E\\//;\n+\t$self->{path_regex} ||= qr/^\\/\\Q$self->{path}\\E\\//;\n \tif (grep /$self->{path_regex}/, keys %$paths) {\n \t\treturn 1;\n \t}\n@@ -2545,7 +2528,7 @@ sub find_parent_branch {\n \treturn undef unless defined $paths;\n \n \t# look for a parent from another branch:\n-\tmy @b_path_components = split m#/#, $self->rel_path;\n+\tmy @b_path_components = split m#/#, $self->{path};\n \tmy @a_path_components;\n \tmy $i;\n \twhile (@b_path_components) {\n@@ -2563,11 +2546,11 @@ sub find_parent_branch {\n \tmy $r = $i->{copyfrom_rev};\n \tmy $repos_root = $self->ra->{repos_root};\n \tmy $url = $self->ra->{url};\n-\tmy $new_url = $repos_root . $branch_from;\n+\tmy $new_url = $url . $branch_from;\n \tprint STDERR  \"Found possible branch point: \",\n \t              \"$new_url => \", $self->full_url, \", $r\\n\";\n \t$branch_from =~ s#^/##;\n-\tmy $gs = $self->other_gs($new_url, $url, $repos_root,\n+\tmy $gs = $self->other_gs($new_url, $url,\n \t\t                 $branch_from, $r, $self->{ref_id});\n \tmy ($r0, $parent) = $gs->find_rev_before($r, 1);\n \t{\n@@ -2752,9 +2735,9 @@ sub parse_svn_date {\n }\n \n sub other_gs {\n-\tmy ($self, $new_url, $url, $repos_root,\n+\tmy ($self, $new_url, $url,\n \t    $branch_from, $r, $old_ref_id) = @_;\n-\tmy $gs = Git::SVN->find_by_url($new_url, $repos_root, $branch_from);\n+\tmy $gs = Git::SVN->find_by_url($new_url, $url, $branch_from);\n \tunless ($gs) {\n \t\tmy $ref_id = $old_ref_id;\n \t\t$ref_id =~ s/\\@\\d+$//;\n@@ -4436,14 +4419,20 @@ sub get_log {\n \t# passed pool (instead of our temporary and quickly cleared pool in\n \t# Git::SVN::Ra) does not help matters at all...\n \tmy $receiver = pop @args;\n+\tmy $prefix = \"/\".$self->{svn_path};\n+\t$prefix =~ s#/+($)##;\n+\tmy $prefix_regex = qr#^\\Q$prefix\\E#;\n \tpush(@args, sub {\n \t\tmy ($paths) = $_[0];\n \t\treturn &$receiver(@_) unless $paths;\n \t\t$_[0] = ();\n \t\tforeach my $p (keys %$paths) {\n \t\t\tmy $i = $paths->{$p};\n-\t\t\tmy %s = map { $_ => $i->$_ }\n-\t\t\t\t      qw/copyfrom_path copyfrom_rev action/;\n+\t\t\t# Make path relative to our url, not repos_root\n+\t\t\t$p =~ s/$prefix_regex//;\n+\t\t\tmy %s = map { $_ => $i->$_; }\n+\t\t\t\tqw/copyfrom_path copyfrom_rev action/;\n+\t\t\t$s{'copyfrom_path'} =~ s/$prefix_regex// if $s{'copyfrom_path'};\n \t\t\t$_[0]{$p} = \\%s;\n \t\t}\n \t\t&$receiver(@_);\n@@ -4461,6 +4450,7 @@ sub get_log {\n \t\t\tpush(@args, sub { &$receiver(@_) if (--$limit >= 0) });\n \t\t}\n \t}\n+\n \tmy $ret = $self->SUPER::get_log(@args, $pool);\n \t$pool->clear;\n \t$ret;\ndiff --git a/t/t9138-git-svn-multiple-branches.sh b/t/t9138-git-svn-multiple-branches.sh\nindex cb9a6d2..3cd0671 100755\n--- a/t/t9138-git-svn-multiple-branches.sh\n+++ b/t/t9138-git-svn-multiple-branches.sh\n@@ -99,22 +99,22 @@ test_expect_success 'Multiple branch or tag paths require -d' '\n \n test_expect_success 'create new branches and tags' '\n \t( cd git_project &&\n-\t\tgit svn branch -m \"New branch 1\" -d project/b_one New1 ) &&\n+\t\tgit svn branch -m \"New branch 1\" -d b_one New1 ) &&\n \t( cd svn_project &&\n \t\tsvn_cmd up && test -e b_one/New1/a.file ) &&\n \n \t( cd git_project &&\n-\t\tgit svn branch -m \"New branch 2\" -d project/b_two New2 ) &&\n+\t\tgit svn branch -m \"New branch 2\" -d b_two New2 ) &&\n \t( cd svn_project &&\n \t\tsvn_cmd up && test -e b_two/New2/a.file ) &&\n \n \t( cd git_project &&\n-\t\tgit svn branch -t -m \"New tag 1\" -d project/tags_A Tag1 ) &&\n+\t\tgit svn branch -t -m \"New tag 1\" -d tags_A Tag1 ) &&\n \t( cd svn_project &&\n \t\tsvn_cmd up && test -e tags_A/Tag1/a.file ) &&\n \n \t( cd git_project &&\n-\t\tgit svn tag -m \"New tag 2\" -d project/tags_B Tag2 ) &&\n+\t\tgit svn tag -m \"New tag 2\" -d tags_B Tag2 ) &&\n \t( cd svn_project &&\n \t\tsvn_cmd up && test -e tags_B/Tag2/a.file )\n '\n-- \n1.6.3.3\n"},{"id":"117541","messageId":"20090707070559.GA13684@dcvr.yhbt.net","threadId":"20027","inReplyTo":"1246919293.4618.12.camel@kea","subject":"Re: [PATCH/RFC] git-svn: Fix branch detection when repository root is inaccessible","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2009-07-07T07:05:59Z","receivedAt":"2009-07-07T07:05:59Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Mattias Nissler <mattias.nissler@gmx.de> wrote:\n> Hi Eric,\n> \n> On Mon, 2009-07-06 at 14:27 -0700, Eric Wong wrote:\n> > Fixing the minimize logic is definitely a wanted improvement I haven't\n> > been able to fix myself.  Unfortunately, your patch breaks the\n> > t9138-git-svn-multiple-branches.sh test for me.  \n> \n> I see the same here, not sure why I've missed it before. I've had a look\n> at the problem and found that the test is actually depending on the\n> minimizing logic, i.e. needs to specify -d project1/<tag-or-branch-dir>\n> for the tag or branch destination where the project1 prefix is due to\n> the minimization at clone time. Dropping the project1 part makes the\n> test succeed. I'll simply update the test to do so.\n> \n> I also think this is much better from a usability point of view since\n> you can now use the original branch or tag dir you've given to clone in\n> order to specify the branch or tag destination.\n\nOK.  I was slightly concerned about potential breakage but I guess\nexisting imports will continue to work fine, so I suppose it's\nalright...\n\n> > I haven't looked at it\n> > at all, but I'll try to take a look at it later today after I process other\n> > things in my overflowing work queue; but I definitely want access issues\n> > fixed for people with restrictive repo setups.\n> > \n> > One thing I would do is to split out the making of dup_changed_paths()\n> > the default behavior into a separate patch.  I think this is a good\n> > change since it makes things less surprising for future hackers of\n> > git svn.\n> \n> Ok, will do so. I'll send updated patches in reply to this mail.\n\nThanks again Mattias.  Acked and pushed out with minor formatting fixes\nto git://git.bogomips.org/git-svn along with Yann's documentation\npatches.\n\n> Finally, a big thanks for the nice job on git-svn. I've just experienced\n> lots of trouble with the mercurial SVN integration and it's really a\n> pain in the ass even to just get a simple clean rebase done properly.\n> git-svn is really way more mature and it's a pleasure to use it for\n> everyday work.\n\nNo problem :)\n\n-- \nEric Wong\n"},{"id":"117565","messageId":"4A536A26.7090102@xiplink.com","threadId":"20027","inReplyTo":"1246923602.4618.18.camel@kea","subject":"Re: [PATCH 2/2] git-svn: Fix branch detection when repository root is inaccessible","fromName":"Marc Branchaud","fromEmail":"marcnarc@xiplink.com","sentAt":"2009-07-07T15:30:46Z","receivedAt":"2009-07-07T15:30:46Z","isPatch":true,"sender":{"key":"marcnarc@xiplink.com","avatar":"https://avatars.githubusercontent.com/u/14980203?v=4"},"body":"Loveley!  That aspect of -d was bothersome...\n\nAcked-by: Marc Branchaud <marcnarc@xiplink.com>\n\n\t\tM.\n\n\nMattias Nissler wrote:\n> For the case of multiple projects sharing a single SVN repository, it is\n> common practice to create the standard SVN directory layout within a\n> subdirectory for each project. In such setups, access control is often\n> used to limit what projects a given user may access. git-svn failed to\n> detect branches (e.g. when passing --stdlayout to clone) because it\n> relied on having access to the root directory in the repository. This\n> patch solves this problem by making git-svn use paths relative to the\n> given repository URL instead of the repository root.\n> \n> Signed-off-by: Mattias Nissler <mattias.nissler@gmx.de>\n> ---\n>  git-svn.perl                         |   42 +++++++++++++---------------------\n>  t/t9138-git-svn-multiple-branches.sh |    8 +++---\n>  2 files changed, 20 insertions(+), 30 deletions(-)\n> \n> diff --git a/git-svn.perl b/git-svn.perl\n> index 57d13af..cf3948c 100755\n> --- a/git-svn.perl\n> +++ b/git-svn.perl\n> @@ -876,10 +876,6 @@ sub cmd_multi_init {\n>  \t\tusage(1);\n>  \t}\n>  \n> -\t# there are currently some bugs that prevent multi-init/multi-fetch\n> -\t# setups from working well without this.\n> -\t$Git::SVN::_minimize_url = 1;\n> -\n>  \t$_prefix = '' unless defined $_prefix;\n>  \tif (defined $url) {\n>  \t\t$url = canonicalize_url($url);\n> @@ -1180,7 +1176,7 @@ sub complete_url_ls_init {\n>  \t\t    \"wanted to set to: $gs->{url}\\n\";\n>  \t}\n>  \tcommand_oneline('config', $k, $gs->{url}) unless $orig_url;\n> -\tmy $remote_path = \"$ra->{svn_path}/$repo_path\";\n> +\tmy $remote_path = \"$gs->{path}/$repo_path\";\n>  \t$remote_path =~ s#/+#/#g;\n>  \t$remote_path =~ s#^/##g;\n>  \t$remote_path .= \"/*\" if $remote_path !~ /\\*/;\n> @@ -2177,16 +2173,6 @@ sub ra {\n>  \t$ra;\n>  }\n>  \n> -sub rel_path {\n> -\tmy ($self) = @_;\n> -\tmy $repos_root = $self->ra->{repos_root};\n> -\treturn $self->{path} if ($self->{url} eq $repos_root);\n> -\tmy $url = $self->{url} .\n> -\t          (length $self->{path} ? \"/$self->{path}\" : $self->{path});\n> -\t$url =~ s!^\\Q$repos_root\\E(?:/+|$)!!g;\n> -\t$url;\n> -}\n> -\n>  # prop_walk(PATH, REV, SUB)\n>  # -------------------------\n>  # Recursively traverse PATH at revision REV and invoke SUB for each\n> @@ -2512,10 +2498,7 @@ sub match_paths {\n>  \tif (my $path = $paths->{\"/$self->{path}\"}) {\n>  \t\treturn ($path->{action} eq 'D') ? 0 : 1;\n>  \t}\n> -\tmy $repos_root = $self->ra->{repos_root};\n> -\tmy $extended_path = $self->{url} . '/' . $self->{path};\n> -\t$extended_path =~ s#^\\Q$repos_root\\E(/|$)##;\n> -\t$self->{path_regex} ||= qr/^\\/\\Q$extended_path\\E\\//;\n> +\t$self->{path_regex} ||= qr/^\\/\\Q$self->{path}\\E\\//;\n>  \tif (grep /$self->{path_regex}/, keys %$paths) {\n>  \t\treturn 1;\n>  \t}\n> @@ -2545,7 +2528,7 @@ sub find_parent_branch {\n>  \treturn undef unless defined $paths;\n>  \n>  \t# look for a parent from another branch:\n> -\tmy @b_path_components = split m#/#, $self->rel_path;\n> +\tmy @b_path_components = split m#/#, $self->{path};\n>  \tmy @a_path_components;\n>  \tmy $i;\n>  \twhile (@b_path_components) {\n> @@ -2563,11 +2546,11 @@ sub find_parent_branch {\n>  \tmy $r = $i->{copyfrom_rev};\n>  \tmy $repos_root = $self->ra->{repos_root};\n>  \tmy $url = $self->ra->{url};\n> -\tmy $new_url = $repos_root . $branch_from;\n> +\tmy $new_url = $url . $branch_from;\n>  \tprint STDERR  \"Found possible branch point: \",\n>  \t              \"$new_url => \", $self->full_url, \", $r\\n\";\n>  \t$branch_from =~ s#^/##;\n> -\tmy $gs = $self->other_gs($new_url, $url, $repos_root,\n> +\tmy $gs = $self->other_gs($new_url, $url,\n>  \t\t                 $branch_from, $r, $self->{ref_id});\n>  \tmy ($r0, $parent) = $gs->find_rev_before($r, 1);\n>  \t{\n> @@ -2752,9 +2735,9 @@ sub parse_svn_date {\n>  }\n>  \n>  sub other_gs {\n> -\tmy ($self, $new_url, $url, $repos_root,\n> +\tmy ($self, $new_url, $url,\n>  \t    $branch_from, $r, $old_ref_id) = @_;\n> -\tmy $gs = Git::SVN->find_by_url($new_url, $repos_root, $branch_from);\n> +\tmy $gs = Git::SVN->find_by_url($new_url, $url, $branch_from);\n>  \tunless ($gs) {\n>  \t\tmy $ref_id = $old_ref_id;\n>  \t\t$ref_id =~ s/\\@\\d+$//;\n> @@ -4436,14 +4419,20 @@ sub get_log {\n>  \t# passed pool (instead of our temporary and quickly cleared pool in\n>  \t# Git::SVN::Ra) does not help matters at all...\n>  \tmy $receiver = pop @args;\n> +\tmy $prefix = \"/\".$self->{svn_path};\n> +\t$prefix =~ s#/+($)##;\n> +\tmy $prefix_regex = qr#^\\Q$prefix\\E#;\n>  \tpush(@args, sub {\n>  \t\tmy ($paths) = $_[0];\n>  \t\treturn &$receiver(@_) unless $paths;\n>  \t\t$_[0] = ();\n>  \t\tforeach my $p (keys %$paths) {\n>  \t\t\tmy $i = $paths->{$p};\n> -\t\t\tmy %s = map { $_ => $i->$_ }\n> -\t\t\t\t      qw/copyfrom_path copyfrom_rev action/;\n> +\t\t\t# Make path relative to our url, not repos_root\n> +\t\t\t$p =~ s/$prefix_regex//;\n> +\t\t\tmy %s = map { $_ => $i->$_; }\n> +\t\t\t\tqw/copyfrom_path copyfrom_rev action/;\n> +\t\t\t$s{'copyfrom_path'} =~ s/$prefix_regex// if $s{'copyfrom_path'};\n>  \t\t\t$_[0]{$p} = \\%s;\n>  \t\t}\n>  \t\t&$receiver(@_);\n> @@ -4461,6 +4450,7 @@ sub get_log {\n>  \t\t\tpush(@args, sub { &$receiver(@_) if (--$limit >= 0) });\n>  \t\t}\n>  \t}\n> +\n>  \tmy $ret = $self->SUPER::get_log(@args, $pool);\n>  \t$pool->clear;\n>  \t$ret;\n> diff --git a/t/t9138-git-svn-multiple-branches.sh b/t/t9138-git-svn-multiple-branches.sh\n> index cb9a6d2..3cd0671 100755\n> --- a/t/t9138-git-svn-multiple-branches.sh\n> +++ b/t/t9138-git-svn-multiple-branches.sh\n> @@ -99,22 +99,22 @@ test_expect_success 'Multiple branch or tag paths require -d' '\n>  \n>  test_expect_success 'create new branches and tags' '\n>  \t( cd git_project &&\n> -\t\tgit svn branch -m \"New branch 1\" -d project/b_one New1 ) &&\n> +\t\tgit svn branch -m \"New branch 1\" -d b_one New1 ) &&\n>  \t( cd svn_project &&\n>  \t\tsvn_cmd up && test -e b_one/New1/a.file ) &&\n>  \n>  \t( cd git_project &&\n> -\t\tgit svn branch -m \"New branch 2\" -d project/b_two New2 ) &&\n> +\t\tgit svn branch -m \"New branch 2\" -d b_two New2 ) &&\n>  \t( cd svn_project &&\n>  \t\tsvn_cmd up && test -e b_two/New2/a.file ) &&\n>  \n>  \t( cd git_project &&\n> -\t\tgit svn branch -t -m \"New tag 1\" -d project/tags_A Tag1 ) &&\n> +\t\tgit svn branch -t -m \"New tag 1\" -d tags_A Tag1 ) &&\n>  \t( cd svn_project &&\n>  \t\tsvn_cmd up && test -e tags_A/Tag1/a.file ) &&\n>  \n>  \t( cd git_project &&\n> -\t\tgit svn tag -m \"New tag 2\" -d project/tags_B Tag2 ) &&\n> +\t\tgit svn tag -m \"New tag 2\" -d tags_B Tag2 ) &&\n>  \t( cd svn_project &&\n>  \t\tsvn_cmd up && test -e tags_B/Tag2/a.file )\n>  '\n"}]}