{"thread":{"id":"44290","subject":"problem with git worktree and git svn","startedAt":"2016-10-12T14:55:47Z","lastAt":"2016-10-26T21:17:18Z","messageCount":10,"participants":["Mathieu Arnold","Stefan Beller","Eric Wong","Duy Nguyen","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"303996","messageId":"6c83c905-b10a-7f54-873f-54186faacfc8@FreeBSD.org","threadId":"44290","inReplyTo":null,"subject":"problem with git worktree and git svn","fromName":"Mathieu Arnold","fromEmail":"mat@freebsd.org","sentAt":"2016-10-12T14:45:29Z","receivedAt":"2016-10-12T14:55:47Z","isPatch":false,"sender":{"key":"mat@freebsd.org","avatar":null},"body":"Hi,\n\nI'm a FreeBSD ports developer, and while our main repository is in\nSubversion, some of us use git-svn a lot for development.\n\nI discovered git worktree earlier this week, and I found it a great\nasset to be able to have more than one branch of my worktree accessible\nat the same time...\n\nAnyway, back to my problem, the way git-svn works, is that it looks for\na directory named \"svn\" in its gitdir and if it is not present, decide\nthe repository is using git-svn version 1 (whatever that is) and goes to\nparse all the revisions to recreate the svn directory.\nSo I can only use git svn commands in my main worktree, the one with the\nreal gitdir.\nTo fix that, all I had to do is to add a symlink named svn in each\nworktree's gitdir and pointing to ../../svn.\n\nI think all that needs to happen is that when adding a new worktree, if\nthe main git directory has a \"svn\" directory, add a symlink to it in the\nworktree's gitdir.\n\n-- \nMathieu Arnold\n\n\n"},{"id":"304028","messageId":"CAGZ79kZo5W1r0s26G3foB7caP6+u66mdzqzyneqXBX_B7A0RKg@mail.gmail.com","threadId":"44290","inReplyTo":"6c83c905-b10a-7f54-873f-54186faacfc8@FreeBSD.org","subject":"Re: problem with git worktree and git svn","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-10-12T21:05:11Z","receivedAt":"2016-10-12T21:10:23Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"+cc Duy who knows about worktree,\n+cc Eric Wong, who knows about git-svn\n\n\n\nOn Wed, Oct 12, 2016 at 7:45 AM, Mathieu Arnold <mat@freebsd.org> wrote:\n> Hi,\n>\n> I'm a FreeBSD ports developer, and while our main repository is in\n> Subversion, some of us use git-svn a lot for development.\n>\n> I discovered git worktree earlier this week, and I found it a great\n> asset to be able to have more than one branch of my worktree accessible\n> at the same time...\n>\n> Anyway, back to my problem, the way git-svn works, is that it looks for\n> a directory named \"svn\" in its gitdir and if it is not present, decide\n> the repository is using git-svn version 1 (whatever that is) and goes to\n> parse all the revisions to recreate the svn directory.\n> So I can only use git svn commands in my main worktree, the one with the\n> real gitdir.\n> To fix that, all I had to do is to add a symlink named svn in each\n> worktree's gitdir and pointing to ../../svn.\n\nFor some definition of fix. ;)\nSure it fixes your local setup now, but would we want to use that as well here?\nMy gut reaction:\n\n* not all platforms know symlinks\n* IIRC there is some worktree magic that tells you the \"main\" dir,\n  so if that was used in git-svn instead it should \"just work\".\n\n>\n> I think all that needs to happen is that when adding a new worktree, if\n> the main git directory has a \"svn\" directory, add a symlink to it in the\n> worktree's gitdir.\n>\n> --\n> Mathieu Arnold\n>\n>\n"},{"id":"304057","messageId":"20161013015233.GA18001@whir","threadId":"44290","inReplyTo":"CAGZ79kZo5W1r0s26G3foB7caP6+u66mdzqzyneqXBX_B7A0RKg@mail.gmail.com","subject":"Re: problem with git worktree and git svn","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2016-10-13T01:52:33Z","receivedAt":"2016-10-13T02:11:15Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"Stefan Beller <sbeller@google.com> wrote:\n> On Wed, Oct 12, 2016 at 7:45 AM, Mathieu Arnold <mat@freebsd.org> wrote:\n> \n> > I discovered git worktree earlier this week, and I found it a great\n> > asset to be able to have more than one branch of my worktree accessible\n> > at the same time...\n> >\n> > Anyway, back to my problem, the way git-svn works, is that it looks for\n> > a directory named \"svn\" in its gitdir and if it is not present, decide\n> > the repository is using git-svn version 1 (whatever that is) and goes to\n> > parse all the revisions to recreate the svn directory.\n> > So I can only use git svn commands in my main worktree, the one with the\n> > real gitdir.\n\nRight, I haven't updated git-svn to be worktree-aware, yet, but\na work-in-progress is below\n\n> > To fix that, all I had to do is to add a symlink named svn in each\n> > worktree's gitdir and pointing to ../../svn.\n> \n> For some definition of fix. ;)\n> Sure it fixes your local setup now, but would we want to use that as well here?\n> My gut reaction:\n> \n> * not all platforms know symlinks\n> * IIRC there is some worktree magic that tells you the \"main\" dir,\n>   so if that was used in git-svn instead it should \"just work\".\n> \n> >\n> > I think all that needs to happen is that when adding a new worktree, if\n> > the main git directory has a \"svn\" directory, add a symlink to it in the\n> > worktree's gitdir.\n\nI'm fairly sure the worktree C code should not care about how\ngit-svn works, but rather git-svn should be made aware of\nworktree bits...\n\nI haven't studied worktrees much nor do I use git-svn much,\nbut the following seems to work for fetch/rebase/dcommit:\n\n------------8<-----------\nSubject: [PATCH] git-svn: WIP worktree awareness\n\n---\n perl/Git/SVN.pm           | 29 ++++++++++++++++++++---------\n perl/Git/SVN/Migration.pm | 23 ++++++++++++-----------\n 2 files changed, 32 insertions(+), 20 deletions(-)\n\ndiff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm\nindex 018beb8..267cc09 100644\n--- a/perl/Git/SVN.pm\n+++ b/perl/Git/SVN.pm\n@@ -807,10 +807,20 @@ sub get_fetch_range {\n \t(++$min, $max);\n }\n \n+sub svn_dir {\n+\tmy $git_dir = scalar @_ ? $_[0] : $ENV{GIT_DIR};\n+\tmy $common = $ENV{GIT_COMMON_DIR} || \"$git_dir/commondir\";\n+\t$git_dir .= '/'.::file_to_s($common) if -e $common;\n+\tmy $svn_dir = $git_dir . '/svn';\n+\t$svn_dir =~ tr!/!/!s;\n+\t$svn_dir;\n+}\n+\n sub tmp_config {\n \tmy (@args) = @_;\n-\tmy $old_def_config = \"$ENV{GIT_DIR}/svn/config\";\n-\tmy $config = \"$ENV{GIT_DIR}/svn/.metadata\";\n+\tmy $svn_dir = svn_dir();\n+\tmy $old_def_config = \"$svn_dir/config\";\n+\tmy $config = \"$svn_dir/.metadata\";\n \tif (! -f $config && -f $old_def_config) {\n \t\trename $old_def_config, $config or\n \t\t       die \"Failed rename $old_def_config => $config: $!\\n\";\n@@ -1671,7 +1681,7 @@ sub tie_for_persistent_memoization {\n \t\treturn if $memoized;\n \t\t$memoized = 1;\n \n-\t\tmy $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n+\t\tmy $cache_path = svn_dir() . '/.caches/';\n \t\tmkpath([$cache_path]) unless -d $cache_path;\n \n \t\tmy %lookup_svn_merge_cache;\n@@ -1712,7 +1722,7 @@ sub tie_for_persistent_memoization {\n \tsub clear_memoized_mergeinfo_caches {\n \t\tdie \"Only call this method in non-memoized context\" if ($memoized);\n \n-\t\tmy $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n+\t\tmy $cache_path = svn_dir() . '/.caches/';\n \t\treturn unless -d $cache_path;\n \n \t\tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n@@ -2446,12 +2456,13 @@ sub _new {\n \t\t             \"refs/remotes/$prefix$default_ref_id\";\n \t}\n \t$_[1] = $repo_id;\n-\tmy $dir = \"$ENV{GIT_DIR}/svn/$ref_id\";\n+\tmy $svn_dir = svn_dir();\n+\tmy $dir = \"$svn_dir/$ref_id\";\n \n-\t# Older repos imported by us used $GIT_DIR/svn/foo instead of\n-\t# $GIT_DIR/svn/refs/remotes/foo when tracking refs/remotes/foo\n+\t# Older repos imported by us used $svn_dir/foo instead of\n+\t# $svn_dir/refs/remotes/foo when tracking refs/remotes/foo\n \tif ($ref_id =~ m{^refs/remotes/(.+)}) {\n-\t\tmy $old_dir = \"$ENV{GIT_DIR}/svn/$1\";\n+\t\tmy $old_dir = \"$svn_dir/$1\";\n \t\tif (-d $old_dir && ! -d $dir) {\n \t\t\t$dir = $old_dir;\n \t\t}\n@@ -2461,7 +2472,7 @@ sub _new {\n \tmkpath([$dir]);\n \tmy $obj = bless {\n \t\tref_id => $ref_id, dir => $dir, index => \"$dir/index\",\n-\t        config => \"$ENV{GIT_DIR}/svn/config\",\n+\t        config => \"$svn_dir/config\",\n \t        map_root => \"$dir/.rev_map\", repo_id => $repo_id }, $class;\n \n \t# Ensure it gets canonicalized\ndiff --git a/perl/Git/SVN/Migration.pm b/perl/Git/SVN/Migration.pm\nindex cf6ffa7..887fd93 100644\n--- a/perl/Git/SVN/Migration.pm\n+++ b/perl/Git/SVN/Migration.pm\n@@ -45,6 +45,7 @@ use Git qw(\n \tcommand_output_pipe\n \tcommand_close_pipe\n );\n+use Git::SVN;\n \n sub migrate_from_v0 {\n \tmy $git_dir = $ENV{GIT_DIR};\n@@ -82,7 +83,7 @@ sub migrate_from_v1 {\n \tmy $git_dir = $ENV{GIT_DIR};\n \tmy $migrated = 0;\n \treturn $migrated unless -d $git_dir;\n-\tmy $svn_dir = \"$git_dir/svn\";\n+\tmy $svn_dir = Git::SVN::svn_dir($git_dir);\n \n \t# just in case somebody used 'svn' as their $id at some point...\n \treturn $migrated if -d $svn_dir && ! -f \"$svn_dir/info/url\";\n@@ -100,24 +101,23 @@ sub migrate_from_v1 {\n \t\tnext unless -f \"$git_dir/$x/info/url\";\n \t\tmy $u = eval { ::file_to_s(\"$git_dir/$x/info/url\") };\n \t\tnext unless $u;\n-\t\tmy $dn = dirname(\"$git_dir/svn/$x\");\n+\t\tmy $dn = dirname(\"$svn_dir/$x\");\n \t\tmkpath([$dn]) unless -d $dn;\n \t\tif ($x eq 'svn') { # they used 'svn' as GIT_SVN_ID:\n-\t\t\tmkpath([\"$git_dir/svn/svn\"]);\n+\t\t\tmkpath([\"$svn_dir/svn\"]);\n \t\t\tprint STDERR \" - $git_dir/$x/info => \",\n-\t\t\t                \"$git_dir/svn/$x/info\\n\";\n-\t\t\trename \"$git_dir/$x/info\", \"$git_dir/svn/$x/info\" or\n+\t\t\t                \"$svn_dir/$x/info\\n\";\n+\t\t\trename \"$git_dir/$x/info\", \"$svn_dir/$x/info\" or\n \t\t\t       croak \"$!: $x\";\n \t\t\t# don't worry too much about these, they probably\n \t\t\t# don't exist with repos this old (save for index,\n \t\t\t# and we can easily regenerate that)\n \t\t\tforeach my $f (qw/unhandled.log index .rev_db/) {\n-\t\t\t\trename \"$git_dir/$x/$f\", \"$git_dir/svn/$x/$f\";\n+\t\t\t\trename \"$git_dir/$x/$f\", \"$svn_dir/$x/$f\";\n \t\t\t}\n \t\t} else {\n-\t\t\tprint STDERR \" - $git_dir/$x => $git_dir/svn/$x\\n\";\n-\t\t\trename \"$git_dir/$x\", \"$git_dir/svn/$x\" or\n-\t\t\t       croak \"$!: $x\";\n+\t\t\tprint STDERR \" - $git_dir/$x => $svn_dir/$x\\n\";\n+\t\t\trename \"$git_dir/$x\", \"$svn_dir/$x\" or croak \"$!: $x\";\n \t\t}\n \t\t$migrated++;\n \t}\n@@ -139,9 +139,10 @@ sub read_old_urls {\n \t\t\tpush @dir, $_;\n \t\t}\n \t}\n+\tmy $svn_dir = Git::SVN::svn_dir();\n \tforeach (@dir) {\n \t\tmy $x = $_;\n-\t\t$x =~ s!^\\Q$ENV{GIT_DIR}\\E/svn/!!o;\n+\t\t$x =~ s!^\\Q$svn_dir\\E/!!o;\n \t\tread_old_urls($l_map, $x, $_);\n \t}\n }\n@@ -150,7 +151,7 @@ sub migrate_from_v2 {\n \tmy @cfg = command(qw/config -l/);\n \treturn if grep /^svn-remote\\..+\\.url=/, @cfg;\n \tmy %l_map;\n-\tread_old_urls(\\%l_map, '', \"$ENV{GIT_DIR}/svn\");\n+\tread_old_urls(\\%l_map, '', Git::SVN::svn_dir());\n \tmy $migrated = 0;\n \n \trequire Git::SVN;\n-- \nEW\n"},{"id":"304068","messageId":"CACsJy8ADmHLW5ba4bVTGN9ccqpMDNFgkqE_5JvnqZ0BxWcaCvw@mail.gmail.com","threadId":"44290","inReplyTo":"20161013015233.GA18001@whir","subject":"Re: problem with git worktree and git svn","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2016-10-13T10:29:27Z","receivedAt":"2016-10-13T10:37:02Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Oct 13, 2016 at 8:52 AM, Eric Wong <e@80x24.org> wrote:\n> +sub svn_dir {\n> +       my $git_dir = scalar @_ ? $_[0] : $ENV{GIT_DIR};\n> +       my $common = $ENV{GIT_COMMON_DIR} || \"$git_dir/commondir\";\n> +       $git_dir .= '/'.::file_to_s($common) if -e $common;\n> +       my $svn_dir = $git_dir . '/svn';\n> +       $svn_dir =~ tr!/!/!s;\n> +       $svn_dir;\n> +}\n\n\nIf this is shell script, this function could be just\n\nsvn_dir() {\n    git rev-parse --git-path svn\n}\n\nwhich should give you correct path in either single or multi-worktree\ncontext and you don't need to bother with details like\n$GIT_COMMON_DIR. But I don't know how Perl bindings are implemented, I\ndon't know if we have something similar (or easy to add it, like\nGit::git_path()).\n\nI don't know much about git-svn, but from the look of it I agree\nreplacing $ENV{GIT_DIR}/svn with svn_dir() should fix it, assuming\nthat you don't hard code $ENV{GIT_DIR}/blahblah somewhere else. I\ndon't see any other potential problems (from multi-worktree\nperspective).\n-- \nDuy\n"},{"id":"304095","messageId":"20161013205555.GA599@dcvr","threadId":"44290","inReplyTo":"CACsJy8ADmHLW5ba4bVTGN9ccqpMDNFgkqE_5JvnqZ0BxWcaCvw@mail.gmail.com","subject":"Re: problem with git worktree and git svn","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2016-10-13T20:55:55Z","receivedAt":"2016-10-13T20:56:30Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"Duy Nguyen <pclouds@gmail.com> wrote:\n> On Thu, Oct 13, 2016 at 8:52 AM, Eric Wong <e@80x24.org> wrote:\n> > +sub svn_dir {\n> > +       my $git_dir = scalar @_ ? $_[0] : $ENV{GIT_DIR};\n> > +       my $common = $ENV{GIT_COMMON_DIR} || \"$git_dir/commondir\";\n> > +       $git_dir .= '/'.::file_to_s($common) if -e $common;\n> > +       my $svn_dir = $git_dir . '/svn';\n> > +       $svn_dir =~ tr!/!/!s;\n> > +       $svn_dir;\n> > +}\n> \n> \n> If this is shell script, this function could be just\n> \n> svn_dir() {\n>     git rev-parse --git-path svn\n> }\n\nAh, thanks; I missed --git-path.  I will do this in Git/SVN.pm:\n\n--- a/perl/Git/SVN.pm\n+++ b/perl/Git/SVN.pm\n@@ -808,12 +808,7 @@ sub get_fetch_range {\n }\n \n sub svn_dir {\n-\tmy $git_dir = scalar @_ ? $_[0] : $ENV{GIT_DIR};\n-\tmy $common = $ENV{GIT_COMMON_DIR} || \"$git_dir/commondir\";\n-\t$git_dir .= '/'.::file_to_s($common) if -e $common;\n-\tmy $svn_dir = $git_dir . '/svn';\n-\t$svn_dir =~ tr!/!/!s;\n-\t$svn_dir;\n+\tcommand_oneline(qw(rev-parse --git-path svn));\n }\n \n sub tmp_config {\n\n> which should give you correct path in either single or multi-worktree\n> context and you don't need to bother with details like\n> $GIT_COMMON_DIR. But I don't know how Perl bindings are implemented, I\n> don't know if we have something similar (or easy to add it, like\n> Git::git_path()).\n\nI'm not sure it's necessary given the convenience of command_oneline,\nand I'd rather avoid the overhead of documenting+supporting a new API\nfor Git.pm\n\n> I don't know much about git-svn, but from the look of it I agree\n> replacing $ENV{GIT_DIR}/svn with svn_dir() should fix it, assuming\n> that you don't hard code $ENV{GIT_DIR}/blahblah somewhere else. I\n> don't see any other potential problems (from multi-worktree\n> perspective).\n\nI think there was a place where $GIT_DIR/config was used, but\nonly for documentation purposes.\n"},{"id":"304099","messageId":"20161014014623.15223-1-e@80x24.org","threadId":"44290","inReplyTo":"20161013205555.GA599@dcvr","subject":"[PATCH 0/2] git-svn: implement \"git worktree\" awareness","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2016-10-14T01:46:21Z","receivedAt":"2016-10-14T01:47:09Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"+Cc Jakub since gitweb could probably take advantage of get_record\nfrom the first patch, too.  I'm not completely sure about the API\nfor this, though.\n\nThe following changes since commit 3cdd5d19178a54d2e51b5098d43b57571241d0ab:\n\n  Sync with maint (2016-10-11 14:55:48 -0700)\n\nare available in the git repository at:\n\n  git://bogomips.org/git-svn.git svn-wt\n\nfor you to fetch changes up to 112423eb905cf28c9445781a7647ba590d597ab3:\n\n  git-svn: \"git worktree\" awareness (2016-10-14 01:36:12 +0000)\n\n----------------------------------------------------------------\nEric Wong (2):\n      git-svn: reduce scope of input record separator change\n      git-svn: \"git worktree\" awareness\n\n git-svn.perl              | 13 +++++++------\n perl/Git.pm               | 16 +++++++++++++++-\n perl/Git/SVN.pm           | 24 +++++++++++++++---------\n perl/Git/SVN/Editor.pm    | 12 +++++-------\n perl/Git/SVN/Fetcher.pm   | 15 +++++----------\n perl/Git/SVN/Migration.pm | 37 ++++++++++++++++++++++---------------\n 6 files changed, 69 insertions(+), 48 deletions(-)\n-- \nEW\n\n"},{"id":"304100","messageId":"20161014014623.15223-3-e@80x24.org","threadId":"44290","inReplyTo":"20161014014623.15223-1-e@80x24.org","subject":"[PATCH 2/2] git-svn: \"git worktree\" awareness","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2016-10-14T01:46:23Z","receivedAt":"2016-10-14T01:48:44Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"git-svn internals were previously not aware of repository\nlayout differences for users of the \"git worktree\" command.\nIntroduce this awareness by using \"git rev-parse --git-path\"\ninstead of relying on outdated uses of GIT_DIR and friends.\n\nThanks-to: Duy Nguyen <pclouds@gmail.com>\nReported-by: Mathieu Arnold <mat@freebsd.org>\nSigned-off-by: Eric Wong <e@80x24.org>\n---\n git-svn.perl              |  9 +++++----\n perl/Git/SVN.pm           | 24 +++++++++++++++---------\n perl/Git/SVN/Migration.pm | 37 ++++++++++++++++++++++---------------\n 3 files changed, 42 insertions(+), 28 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 6d1a142..fa42364 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -1700,7 +1700,7 @@ sub cmd_gc {\n \t\t     \"files will not be compressed.\\n\";\n \t}\n \tFile::Find::find({ wanted => \\&gc_directory, no_chdir => 1},\n-\t\t\t \"$ENV{GIT_DIR}/svn\");\n+\t\t\t Git::SVN::svn_dir());\n }\n \n ########################### utility functions #########################\n@@ -1734,7 +1734,7 @@ sub post_fetch_checkout {\n \treturn unless verify_ref('HEAD^0');\n \n \treturn if $ENV{GIT_DIR} !~ m#^(?:.*/)?\\.git$#;\n-\tmy $index = $ENV{GIT_INDEX_FILE} || \"$ENV{GIT_DIR}/index\";\n+\tmy $index = command_oneline(qw(rev-parse --git-path index));\n \treturn if -f $index;\n \n \treturn if command_oneline(qw/rev-parse --is-inside-work-tree/) eq 'false';\n@@ -1836,8 +1836,9 @@ sub get_tree_from_treeish {\n sub get_commit_entry {\n \tmy ($treeish) = shift;\n \tmy %log_entry = ( log => '', tree => get_tree_from_treeish($treeish) );\n-\tmy $commit_editmsg = \"$ENV{GIT_DIR}/COMMIT_EDITMSG\";\n-\tmy $commit_msg = \"$ENV{GIT_DIR}/COMMIT_MSG\";\n+\tmy @git_path = qw(rev-parse --git-path);\n+\tmy $commit_editmsg = command_oneline(@git_path, 'COMMIT_EDITMSG');\n+\tmy $commit_msg = command_oneline(@git_path, 'COMMIT_MSG');\n \topen my $log_fh, '>', $commit_editmsg or croak $!;\n \n \tmy $type = command_oneline(qw/cat-file -t/, $treeish);\ndiff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm\nindex 018beb8..499e84b 100644\n--- a/perl/Git/SVN.pm\n+++ b/perl/Git/SVN.pm\n@@ -807,10 +807,15 @@ sub get_fetch_range {\n \t(++$min, $max);\n }\n \n+sub svn_dir {\n+\tcommand_oneline(qw(rev-parse --git-path svn));\n+}\n+\n sub tmp_config {\n \tmy (@args) = @_;\n-\tmy $old_def_config = \"$ENV{GIT_DIR}/svn/config\";\n-\tmy $config = \"$ENV{GIT_DIR}/svn/.metadata\";\n+\tmy $svn_dir = svn_dir();\n+\tmy $old_def_config = \"$svn_dir/config\";\n+\tmy $config = \"$svn_dir/.metadata\";\n \tif (! -f $config && -f $old_def_config) {\n \t\trename $old_def_config, $config or\n \t\t       die \"Failed rename $old_def_config => $config: $!\\n\";\n@@ -1671,7 +1676,7 @@ sub tie_for_persistent_memoization {\n \t\treturn if $memoized;\n \t\t$memoized = 1;\n \n-\t\tmy $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n+\t\tmy $cache_path = svn_dir() . '/.caches/';\n \t\tmkpath([$cache_path]) unless -d $cache_path;\n \n \t\tmy %lookup_svn_merge_cache;\n@@ -1712,7 +1717,7 @@ sub tie_for_persistent_memoization {\n \tsub clear_memoized_mergeinfo_caches {\n \t\tdie \"Only call this method in non-memoized context\" if ($memoized);\n \n-\t\tmy $cache_path = \"$ENV{GIT_DIR}/svn/.caches/\";\n+\t\tmy $cache_path = svn_dir() . '/.caches/';\n \t\treturn unless -d $cache_path;\n \n \t\tfor my $cache_file ((\"$cache_path/lookup_svn_merge\",\n@@ -2446,12 +2451,13 @@ sub _new {\n \t\t             \"refs/remotes/$prefix$default_ref_id\";\n \t}\n \t$_[1] = $repo_id;\n-\tmy $dir = \"$ENV{GIT_DIR}/svn/$ref_id\";\n+\tmy $svn_dir = svn_dir();\n+\tmy $dir = \"$svn_dir/$ref_id\";\n \n-\t# Older repos imported by us used $GIT_DIR/svn/foo instead of\n-\t# $GIT_DIR/svn/refs/remotes/foo when tracking refs/remotes/foo\n+\t# Older repos imported by us used $svn_dir/foo instead of\n+\t# $svn_dir/refs/remotes/foo when tracking refs/remotes/foo\n \tif ($ref_id =~ m{^refs/remotes/(.+)}) {\n-\t\tmy $old_dir = \"$ENV{GIT_DIR}/svn/$1\";\n+\t\tmy $old_dir = \"$svn_dir/$1\";\n \t\tif (-d $old_dir && ! -d $dir) {\n \t\t\t$dir = $old_dir;\n \t\t}\n@@ -2461,7 +2467,7 @@ sub _new {\n \tmkpath([$dir]);\n \tmy $obj = bless {\n \t\tref_id => $ref_id, dir => $dir, index => \"$dir/index\",\n-\t        config => \"$ENV{GIT_DIR}/svn/config\",\n+\t        config => \"$svn_dir/config\",\n \t        map_root => \"$dir/.rev_map\", repo_id => $repo_id }, $class;\n \n \t# Ensure it gets canonicalized\ndiff --git a/perl/Git/SVN/Migration.pm b/perl/Git/SVN/Migration.pm\nindex cf6ffa7..dc90f6a 100644\n--- a/perl/Git/SVN/Migration.pm\n+++ b/perl/Git/SVN/Migration.pm\n@@ -44,7 +44,9 @@ use Git qw(\n \tcommand_noisy\n \tcommand_output_pipe\n \tcommand_close_pipe\n+\tcommand_oneline\n );\n+use Git::SVN;\n \n sub migrate_from_v0 {\n \tmy $git_dir = $ENV{GIT_DIR};\n@@ -55,7 +57,9 @@ sub migrate_from_v0 {\n \t\tchomp;\n \t\tmy ($id, $orig_ref) = ($_, $_);\n \t\tnext unless $id =~ s#^refs/heads/(.+)-HEAD$#$1#;\n-\t\tnext unless -f \"$git_dir/$id/info/url\";\n+\t\tmy $info_url = command_oneline(qw(rev-parse --git-path),\n+\t\t\t\t\t\t\"$id/info/url\");\n+\t\tnext unless -f $info_url;\n \t\tmy $new_ref = \"refs/remotes/$id\";\n \t\tif (::verify_ref(\"$new_ref^0\")) {\n \t\t\tprint STDERR \"W: $orig_ref is probably an old \",\n@@ -82,7 +86,7 @@ sub migrate_from_v1 {\n \tmy $git_dir = $ENV{GIT_DIR};\n \tmy $migrated = 0;\n \treturn $migrated unless -d $git_dir;\n-\tmy $svn_dir = \"$git_dir/svn\";\n+\tmy $svn_dir = Git::SVN::svn_dir();\n \n \t# just in case somebody used 'svn' as their $id at some point...\n \treturn $migrated if -d $svn_dir && ! -f \"$svn_dir/info/url\";\n@@ -97,27 +101,28 @@ sub migrate_from_v1 {\n \t\tmy $x = $_;\n \t\tnext unless $x =~ s#^refs/remotes/##;\n \t\tchomp $x;\n-\t\tnext unless -f \"$git_dir/$x/info/url\";\n-\t\tmy $u = eval { ::file_to_s(\"$git_dir/$x/info/url\") };\n+\t\tmy $info_url = command_oneline(qw(rev-parse --git-path),\n+\t\t\t\t\t\t\"$x/info/url\");\n+\t\tnext unless -f $info_url;\n+\t\tmy $u = eval { ::file_to_s($info_url) };\n \t\tnext unless $u;\n-\t\tmy $dn = dirname(\"$git_dir/svn/$x\");\n+\t\tmy $dn = dirname(\"$svn_dir/$x\");\n \t\tmkpath([$dn]) unless -d $dn;\n \t\tif ($x eq 'svn') { # they used 'svn' as GIT_SVN_ID:\n-\t\t\tmkpath([\"$git_dir/svn/svn\"]);\n+\t\t\tmkpath([\"$svn_dir/svn\"]);\n \t\t\tprint STDERR \" - $git_dir/$x/info => \",\n-\t\t\t                \"$git_dir/svn/$x/info\\n\";\n-\t\t\trename \"$git_dir/$x/info\", \"$git_dir/svn/$x/info\" or\n+\t\t\t                \"$svn_dir/$x/info\\n\";\n+\t\t\trename \"$git_dir/$x/info\", \"$svn_dir/$x/info\" or\n \t\t\t       croak \"$!: $x\";\n \t\t\t# don't worry too much about these, they probably\n \t\t\t# don't exist with repos this old (save for index,\n \t\t\t# and we can easily regenerate that)\n \t\t\tforeach my $f (qw/unhandled.log index .rev_db/) {\n-\t\t\t\trename \"$git_dir/$x/$f\", \"$git_dir/svn/$x/$f\";\n+\t\t\t\trename \"$git_dir/$x/$f\", \"$svn_dir/$x/$f\";\n \t\t\t}\n \t\t} else {\n-\t\t\tprint STDERR \" - $git_dir/$x => $git_dir/svn/$x\\n\";\n-\t\t\trename \"$git_dir/$x\", \"$git_dir/svn/$x\" or\n-\t\t\t       croak \"$!: $x\";\n+\t\t\tprint STDERR \" - $git_dir/$x => $svn_dir/$x\\n\";\n+\t\t\trename \"$git_dir/$x\", \"$svn_dir/$x\" or croak \"$!: $x\";\n \t\t}\n \t\t$migrated++;\n \t}\n@@ -139,9 +144,10 @@ sub read_old_urls {\n \t\t\tpush @dir, $_;\n \t\t}\n \t}\n+\tmy $svn_dir = Git::SVN::svn_dir();\n \tforeach (@dir) {\n \t\tmy $x = $_;\n-\t\t$x =~ s!^\\Q$ENV{GIT_DIR}\\E/svn/!!o;\n+\t\t$x =~ s!^\\Q$svn_dir\\E/!!o;\n \t\tread_old_urls($l_map, $x, $_);\n \t}\n }\n@@ -150,7 +156,7 @@ sub migrate_from_v2 {\n \tmy @cfg = command(qw/config -l/);\n \treturn if grep /^svn-remote\\..+\\.url=/, @cfg;\n \tmy %l_map;\n-\tread_old_urls(\\%l_map, '', \"$ENV{GIT_DIR}/svn\");\n+\tread_old_urls(\\%l_map, '', Git::SVN::svn_dir());\n \tmy $migrated = 0;\n \n \trequire Git::SVN;\n@@ -239,7 +245,8 @@ sub minimize_connections {\n \t\t}\n \t}\n \tif (@emptied) {\n-\t\tmy $file = $ENV{GIT_CONFIG} || \"$ENV{GIT_DIR}/config\";\n+\t\tmy $file = $ENV{GIT_CONFIG} ||\n+\t\t\tcommand_oneline(qw(rev-parse --git-path config));\n \t\tprint STDERR <<EOF;\n The following [svn-remote] sections in your config file ($file) are empty\n and can be safely removed:\n-- \nEW\n\n"},{"id":"304101","messageId":"20161014014623.15223-2-e@80x24.org","threadId":"44290","inReplyTo":"20161014014623.15223-1-e@80x24.org","subject":"[PATCH 1/2] git-svn: reduce scope of input record separator change","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2016-10-14T01:46:22Z","receivedAt":"2016-10-14T01:54:18Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Reducing the scope of where we change the record separator ($/)\navoids bugs in calls which rely on the input record separator\nfurther down, such as the 'chomp' usage in command_oneline.\n\nThis is necessary for a future change to git-svn, but exists in\nGit.pm since it seems useful for gitweb and our other Perl\nscripts, too.\n\nSigned-off-by: Eric Wong <e@80x24.org>\n---\n git-svn.perl            |  4 ++--\n perl/Git.pm             | 16 +++++++++++++++-\n perl/Git/SVN/Editor.pm  | 12 +++++-------\n perl/Git/SVN/Fetcher.pm | 15 +++++----------\n 4 files changed, 27 insertions(+), 20 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 4d41d22..6d1a142 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -44,6 +44,7 @@ use Git qw(\n \tcommand_close_pipe\n \tcommand_bidi_pipe\n \tcommand_close_bidi_pipe\n+\tget_record\n );\n \n BEGIN {\n@@ -1880,10 +1881,9 @@ sub get_commit_entry {\n \t{\n \t\trequire Encode;\n \t\t# SVN requires messages to be UTF-8 when entering the repo\n-\t\tlocal $/;\n \t\topen $log_fh, '<', $commit_msg or croak $!;\n \t\tbinmode $log_fh;\n-\t\tchomp($log_entry{log} = <$log_fh>);\n+\t\tchomp($log_entry{log} = get_record($log_fh, undef));\n \n \t\tmy $enc = Git::config('i18n.commitencoding') || 'UTF-8';\n \t\tmy $msg = $log_entry{log};\ndiff --git a/perl/Git.pm b/perl/Git.pm\nindex ce7e4e8..d2c5a8d 100644\n--- a/perl/Git.pm\n+++ b/perl/Git.pm\n@@ -59,7 +59,7 @@ require Exporter;\n                 command_bidi_pipe command_close_bidi_pipe\n                 version exec_path html_path hash_object git_cmd_try\n                 remote_refs prompt\n-                get_tz_offset\n+                get_tz_offset get_record\n                 credential credential_read credential_write\n                 temp_acquire temp_is_locked temp_release temp_reset temp_path);\n \n@@ -538,6 +538,20 @@ sub get_tz_offset {\n \treturn sprintf(\"%s%02d%02d\", $sign, (gmtime(abs($t - $gm)))[2,1]);\n }\n \n+=item get_record ( FILEHANDLE, INPUT_RECORD_SEPARATOR )\n+\n+Read one record from FILEHANDLE delimited by INPUT_RECORD_SEPARATOR,\n+removing any trailing INPUT_RECORD_SEPARATOR.\n+\n+=cut\n+\n+sub get_record {\n+\tmy ($fh, $rs) = @_;\n+\tlocal $/ = $rs;\n+\tmy $rec = <$fh>;\n+\tchomp $rec if defined $rs;\n+\t$rec;\n+}\n \n =item prompt ( PROMPT , ISPASSWORD  )\n \ndiff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm\nindex 4c4199a..0df16ed 100644\n--- a/perl/Git/SVN/Editor.pm\n+++ b/perl/Git/SVN/Editor.pm\n@@ -7,7 +7,9 @@ use SVN::Delta;\n use Carp qw/croak/;\n use Git qw/command command_oneline command_noisy command_output_pipe\n            command_input_pipe command_close_pipe\n-           command_bidi_pipe command_close_bidi_pipe/;\n+           command_bidi_pipe command_close_bidi_pipe\n+           get_record/;\n+\n BEGIN {\n \t@ISA = qw(SVN::Delta::Editor);\n }\n@@ -57,11 +59,9 @@ sub generate_diff {\n \tpush @diff_tree, \"-l$_rename_limit\" if defined $_rename_limit;\n \tpush @diff_tree, $tree_a, $tree_b;\n \tmy ($diff_fh, $ctx) = command_output_pipe(@diff_tree);\n-\tlocal $/ = \"\\0\";\n \tmy $state = 'meta';\n \tmy @mods;\n-\twhile (<$diff_fh>) {\n-\t\tchomp $_; # this gets rid of the trailing \"\\0\"\n+\twhile (defined($_ = get_record($diff_fh, \"\\0\"))) {\n \t\tif ($state eq 'meta' && /^:(\\d{6})\\s(\\d{6})\\s\n \t\t\t\t\t($::sha1)\\s($::sha1)\\s\n \t\t\t\t\t([MTCRAD])\\d*$/xo) {\n@@ -173,9 +173,7 @@ sub rmdirs {\n \n \tmy ($fh, $ctx) = command_output_pipe(qw/ls-tree --name-only -r -z/,\n \t                                     $self->{tree_b});\n-\tlocal $/ = \"\\0\";\n-\twhile (<$fh>) {\n-\t\tchomp;\n+\twhile (defined($_ = get_record($fh, \"\\0\"))) {\n \t\tmy @dn = split m#/#, $_;\n \t\twhile (pop @dn) {\n \t\t\tdelete $rm->{join '/', @dn};\ndiff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm\nindex d8c21ad..64e900a 100644\n--- a/perl/Git/SVN/Fetcher.pm\n+++ b/perl/Git/SVN/Fetcher.pm\n@@ -9,7 +9,8 @@ use Carp qw/croak/;\n use File::Basename qw/dirname/;\n use Git qw/command command_oneline command_noisy command_output_pipe\n            command_input_pipe command_close_pipe\n-           command_bidi_pipe command_close_bidi_pipe/;\n+           command_bidi_pipe command_close_bidi_pipe\n+           get_record/;\n BEGIN {\n \t@ISA = qw(SVN::Delta::Editor);\n }\n@@ -86,11 +87,9 @@ sub _mark_empty_symlinks {\n \tmy $printed_warning;\n \tchomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`);\n \tmy ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt);\n-\tlocal $/ = \"\\0\";\n \tmy $pfx = defined($switch_path) ? $switch_path : $git_svn->path;\n \t$pfx .= '/' if length($pfx);\n-\twhile (<$ls>) {\n-\t\tchomp;\n+\twhile (defined($_ = get_record($ls, \"\\0\"))) {\n \t\ts/\\A100644 blob $empty_blob\\t//o or next;\n \t\tunless ($printed_warning) {\n \t\t\tprint STDERR \"Scanning for empty symlinks, \",\n@@ -179,9 +178,7 @@ sub delete_entry {\n \t\tmy ($ls, $ctx) = command_output_pipe(qw/ls-tree\n \t\t                                     -r --name-only -z/,\n \t\t\t\t                     $tree);\n-\t\tlocal $/ = \"\\0\";\n-\t\twhile (<$ls>) {\n-\t\t\tchomp;\n+\t\twhile (defined($_ = get_record($ls, \"\\0\"))) {\n \t\t\tmy $rmpath = \"$gpath/$_\";\n \t\t\t$self->{gii}->remove($rmpath);\n \t\t\tprint \"\\tD\\t$rmpath\\n\" unless $::_q;\n@@ -247,9 +244,7 @@ sub add_directory {\n \t\tmy ($ls, $ctx) = command_output_pipe(qw/ls-tree\n \t\t                                     -r --name-only -z/,\n \t\t\t\t                     $self->{c});\n-\t\tlocal $/ = \"\\0\";\n-\t\twhile (<$ls>) {\n-\t\t\tchomp;\n+\t\twhile (defined($_ = get_record($ls, \"\\0\"))) {\n \t\t\t$self->{gii}->remove($_);\n \t\t\tprint \"\\tD\\t$_\\n\" unless $::_q;\n \t\t\tpush @deleted_gpath, $gpath;\n-- \nEW\n\n"},{"id":"304908","messageId":"20161026200248.GA28105@starla","threadId":"44290","inReplyTo":"20161014014623.15223-1-e@80x24.org","subject":"Re: [PATCH 0/2] git-svn: implement \"git worktree\" awareness","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2016-10-26T20:02:48Z","receivedAt":"2016-10-26T20:02:53Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Eric Wong <e@80x24.org> wrote:\n> +Cc Jakub since gitweb could probably take advantage of get_record\n> from the first patch, too.  I'm not completely sure about the API\n> for this, though.\n\nJakub: ping?\n\n+Cc: Junio, too.  I'm hoping to have this in 2.11.\n\n> The following changes since commit 3cdd5d19178a54d2e51b5098d43b57571241d0ab:\n> \n>   Sync with maint (2016-10-11 14:55:48 -0700)\n> \n> are available in the git repository at:\n> \n>   git://bogomips.org/git-svn.git svn-wt\n> \n> for you to fetch changes up to 112423eb905cf28c9445781a7647ba590d597ab3:\n> \n>   git-svn: \"git worktree\" awareness (2016-10-14 01:36:12 +0000)\n> \n> ----------------------------------------------------------------\n> Eric Wong (2):\n>       git-svn: reduce scope of input record separator change\n>       git-svn: \"git worktree\" awareness\n> \n>  git-svn.perl              | 13 +++++++------\n>  perl/Git.pm               | 16 +++++++++++++++-\n>  perl/Git/SVN.pm           | 24 +++++++++++++++---------\n>  perl/Git/SVN/Editor.pm    | 12 +++++-------\n>  perl/Git/SVN/Fetcher.pm   | 15 +++++----------\n>  perl/Git/SVN/Migration.pm | 37 ++++++++++++++++++++++---------------\n>  6 files changed, 69 insertions(+), 48 deletions(-)\n"},{"id":"304919","messageId":"xmqq8ttabyjt.fsf@gitster.mtv.corp.google.com","threadId":"44290","inReplyTo":"20161026200248.GA28105@starla","subject":"Re: [PATCH 0/2] git-svn: implement \"git worktree\" awareness","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-26T21:17:10Z","receivedAt":"2016-10-26T21:17:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Wong <e@80x24.org> writes:\n\n> Eric Wong <e@80x24.org> wrote:\n>> +Cc Jakub since gitweb could probably take advantage of get_record\n>> from the first patch, too.  I'm not completely sure about the API\n>> for this, though.\n>\n> Jakub: ping?\n>\n> +Cc: Junio, too.  I'm hoping to have this in 2.11.\n\nI somehow was hoping that I can pull this as part of git-svn updates\nfor the upcoming release without having to even think about it (I\ndid read the patch when they were posted and did not find anything\nwrong with them, fwiw).\n\n>> The following changes since commit 3cdd5d19178a54d2e51b5098d43b57571241d0ab:\n>> \n>>   Sync with maint (2016-10-11 14:55:48 -0700)\n>> \n>> are available in the git repository at:\n>> \n>>   git://bogomips.org/git-svn.git svn-wt\n>> \n>> for you to fetch changes up to 112423eb905cf28c9445781a7647ba590d597ab3:\n>> \n>>   git-svn: \"git worktree\" awareness (2016-10-14 01:36:12 +0000)\n\nThanks.\n"}]}