Add a test case for deep symlinking into a repo, which breaks with the
old relative output of --show-cdup.
Signed-off-by: Steven Grimm <redacted>
---
I have a symlink pointing to a subdirectory of a repo of mine. If I cd
to that symlink, some shell-script git commands don't work. Shell scripts
use the PWD environment variable as the working directory, and the chain
of "../"s from git-rev-parse --show-cdup just peels entries off that
variable. That's fine when PWD is a real path, but not so great when it's
a reference to a symlink from an outside directory.
A typical failure case:
$ git clone git://whatever.git foobar
$ ln -s foobar/src/tools/misc/myapp myapp
$ cd myapp
$ git pull
fatal: Not a git repository
This patch adds a test for the problem (fails in the current git build)
and a proposed fix: making git-rev-parse --show-cdup output an absolute
path. It's possible that'll break something somewhere, but all the tests
in the test suite pass, so I think the breakage can't be *too* severe if
there's any at all.
builtin-rev-parse.c | 18 +++++++++---------
t/t6102-rev-parse-cdup.sh | 24 ++++++++++++++++++++++++
2 files changed, 33 insertions(+), 9 deletions(-)
create mode 100755 t/t6102-rev-parse-cdup.sh
@@ -320,15 +320,15 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)continue;}if(!strcmp(arg,"--show-cdup")){-constchar*pfx=prefix;-while(pfx){-pfx=strchr(pfx,'/');-if(pfx){-pfx++;-printf("../");-}-}-putchar('\n');+charcwd[PATH_MAX];+/*+*Theprefixcomputationdoeschdir("..")untilit+*reachesthetoplevel,sothecurrentdirectory+*isactuallythethingwewanttooutput.+*/+if(!getcwd(cwd,PATH_MAX))+die("unable to get current working directory");+printf("%s/\n",cwd);continue;}if(!strcmp(arg,"--git-dir")){
@@ -0,0 +1,24 @@+#!/bin/sh+#+# Copyright (c) 2007 Steven Grimm+#++test_description='Test git-rev-parse --show-cdup'++../test-lib.sh+.../t6000lib.sh# t6xxx specific functions++# Make a subdirectory and a symbolic link pointing to it from outside the repo.+mkdirsubdir+ln-s`pwd`/subdir/tmp/git-test.$$+cd/tmp/git-test.$$++test_expect_success'shell pwd references symlink'"pwd | grep git-test.$$"+test_expect_success'cdup goes to top level of repo''+cd`git-rev-parse--show-cdup`&&+test-d.git'++rm/tmp/git-test.$$++test_done+
From: Alex Riesen <hidden> Date: 2016-06-15 22:43:07
On 4/26/07, koreth@midwinter.com [off-list ref] wrote:
I have a symlink pointing to a subdirectory of a repo of mine. If I cd
to that symlink, some shell-script git commands don't work. Shell scripts
use the PWD environment variable as the working directory, and the chain
of "../"s from git-rev-parse --show-cdup just peels entries off that
variable. That's fine when PWD is a real path, but not so great when it's
a reference to a symlink from an outside directory.
Your implementation will fail if cwd is longer than PATH_MAX.
Does not happen often, though.
A typical failure case:
$ git clone git://whatever.git foobar
$ ln -s foobar/src/tools/misc/myapp myapp
$ cd myapp
Which is a strange thing to do. What is that for?
myapp is kind of outside the git repo foobar.
From: Steven Grimm <hidden> Date: 2016-06-15 22:43:07
Alex Riesen wrote:
Your implementation will fail if cwd is longer than PATH_MAX.
Does not happen often, though.
That limitation is already littered through the code, e.g. in setup.c
which would already be failing in the existing implementation. Actually
setup.c goes one better: is_inside_git_dir() hardwires a 1024-character
limit into the code rather than using PATH_MAX. I didn't think I was
introducing a new limit here.
quoted
A typical failure case:
$ git clone git://whatever.git foobar
$ ln -s foobar/src/tools/misc/myapp myapp
$ cd myapp
Which is a strange thing to do. What is that for?
myapp is kind of outside the git repo foobar.
For convenience, mostly; obviously that example was a bit contrived but
I do have several symlinks to subdirectories of my repository and it's
faster to type "cd ~/xyz" than "cd ~/repo/src/server/xyz" all the time.
And as you say, you're only "kind of" outside the repo when going
through the symlink; one could argue that cd-ing into a symlink should
be the semantic equivalent of cd-ing into the thing the link points to,
and that's certainly the way I use it.
But actually my big objection isn't that it fails, per se, but rather
that it fails inconsistently. All the C commands work just fine since
they do getcwd() which returns the real path. It's only the shell
scripts that fail, e.g. git-pull. With the existing implementation I
have to remember which commands are shell scripts and which are C
programs, so I can do "cd `/bin/pwd`" to reset my $PWD before running
any of the former.
That was actually my initial approach to fixing this -- I put "cd
`/bin/pwd`" at the top of the "cd_to_toplevel" function in
git-sh-setup.sh. But it felt cleaner to make git-rev-parse return the
actual correct path so it'd work for shell scripts that didn't happen to
use git-sh-setup.sh. I'm happy to go either way, or of course to keep
this as a local modification if folks find it too distasteful to include
in the official source.
-Steve
Signed-off-by: Steven Grimm <redacted>
---
Is the +1 really needed? The existing code is doing this in other places
but I'm not sure it's necessary since we're also doing sizeof(buffer)-1
in the getcwd() call. I figured it was best to be consistent with the
existing code, e.g. setup_git_directory_gently().
setup.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
From: Alex Riesen <hidden> Date: 2016-06-15 22:43:07
On 4/26/07, Steven Grimm [off-list ref] wrote:
Alex Riesen wrote:
quoted
Your implementation will fail if cwd is longer than PATH_MAX.
Does not happen often, though.
That limitation is already littered through the code, e.g. in setup.c
which would already be failing in the existing implementation. Actually
setup.c goes one better: is_inside_git_dir() hardwires a 1024-character
limit into the code rather than using PATH_MAX. I didn't think I was
introducing a new limit here.
It is yet another place to fix when it breaks.
quoted
quoted
A typical failure case:
$ git clone git://whatever.git foobar
$ ln -s foobar/src/tools/misc/myapp myapp
$ cd myapp
Which is a strange thing to do. What is that for?
myapp is kind of outside the git repo foobar.
For convenience, mostly; obviously that example was a bit contrived but
I do have several symlinks to subdirectories of my repository and it's
faster to type "cd ~/xyz" than "cd ~/repo/src/server/xyz" all the time.
Can't you use your shells variables or aliases (which is even faster to
type)?
That was actually my initial approach to fixing this -- I put "cd
`/bin/pwd`" at the top of the "cd_to_toplevel" function in
git-sh-setup.sh. But it felt cleaner to make git-rev-parse return the
actual correct path so it'd work for shell scripts that didn't happen to
use git-sh-setup.sh. I'm happy to go either way, or of course to keep
this as a local modification if folks find it too distasteful to include
in the official source.
I'm not really objecting. It's just a bit unusual so I suspect unusual
problems coming out of it. Kind of when you try running with your
eyes closed.