threads / discuss / 27167

symlinked working tree gotcha

Subject: symlinked working tree gotcha

## tl;dr

4 messages between Apr 24, 2011 and Apr 26, 2011.

replies: 3people: 3as markdown or json

Joey Hess· Apr 24, 2011, 16:58 UTC · lore

joey@gnu:/tmp>mkdir foo joey@gnu:/tmp>cd foo joey@gnu:/tmp/foo>git init Initialized empty Git repository in /tmp/foo/.git/ joey@gnu:/tmp/foo>touch foo joey@gnu:/tmp/foo>git add /tmp/foo/foo joey@gnu:/tmp/foo>cd .. joey@gnu:/tmp>ln -s foo bar joey@gnu:/tmp>cd bar joey@gnu:/tmp/bar>touch bar joey@gnu:/tmp/bar>git add /tmp/bar/bar fatal: '/tmp/bar/bar' is outside repository

Is this a bug or a feature of git? I had some code where I had, lazily, assumed that passing the full path to the file would always work, since it did, in my experience.

-- 
see shy jo
Junio C Hamano· Apr 25, 2011, 18:15 UTC · re: Joey Hess · lore

Re: symlinked working tree gotcha

Joey Hess <joey@kitenet.net> writes:
Show 14 quoted lines
> joey@gnu:/tmp>mkdir foo
> joey@gnu:/tmp>cd foo
> joey@gnu:/tmp/foo>git init
> Initialized empty Git repository in /tmp/foo/.git/
> joey@gnu:/tmp/foo>touch foo
> joey@gnu:/tmp/foo>git add /tmp/foo/foo
> joey@gnu:/tmp/foo>cd ..
> joey@gnu:/tmp>ln -s foo bar
> joey@gnu:/tmp>cd bar
> joey@gnu:/tmp/bar>touch bar
> joey@gnu:/tmp/bar>git add /tmp/bar/bar
> fatal: '/tmp/bar/bar' is outside repository
>
> Is this a bug or a feature of git?
Two 'foo's makes it confusing to read so let's rephrase.
Given this structure:
    /tmp/foo/
    /tmp/foo/.git/
    /tmp/foo/hello
    /tmp/sym@ -> foo

when you refer to /tmp/sym/hello where $(/bin/pwd) is /tmp/foo, should it be considered to be within the bounds of the working tree that is governed by your current $GIT_DIR (which is ".git")?

The answer is "perhaps yes, ideally speaking, but does it really matter in practice, or is it just nice to have?".

I think we do not run realpath to a pathspec given by the end user to canonicalize it. And we cannot blindly run realpath.

Think of this structure (the above with some additions):
    /tmp/foo/
    /tmp/foo/.git/
    /tmp/foo/hello
    /tmp/foo/dir/bye
    /tmp/foo/link@ -> dir
    /tmp/sym@ -> foo

and you refer to /tmp/sym/link/bye from /tmp/foo directory. If we run realpath to the whole thing, we would get /tmp/foo/dir/bye but as far as the repository data is concerned, link/bye is beyond a tracked symbolic link and we should error it out ("git add link/bye" should fail).

If we choose to make your example work, we would need to resolve symbolic links stepwise until we get into the working tree, and then use the remainder without resolving symbolic links, e.g.

 0. We get /tmp/sym/hello  and /tmp/sym/link/bye from the user;
 1. Notice /tmp is a directory and outside the working tree;
 2. Notice /tmp/sym is a symlink; resolve it to get /tmp/foo, notice
    that directory is now within the working tree, and stop resolving
    symbolic links for the remainder;
 3. Append the remainder to come up with /tmp/foo/hello and
   /tmp/foo/link/bye;
 4. Strip /tmp/foo/, to get hello and link/bye as pathspec relative to the
    root of the working tree;
 5. Use them as the pathspec. hello is a valid pathspec within the working
    tree. link/bye is beyond symlink and an error should be reported.

Or something like that. We would also have to deal with "../" in the pathspec, so we cannot just "stop resolving and tack the remainder", but would probably need to check if the directory is within bounds of the working tree in each step.

At least I would say it would be a sensible thing to aim for.
Joey Hess· Apr 25, 2011, 19:09 UTC · re: Junio C Hamano · lore

Re: symlinked working tree gotcha

Junio C Hamano wrote:
Show 12 quoted lines
> Two 'foo's makes it confusing to read so let's rephrase.
> 
> Given this structure:
> 
>     /tmp/foo/
>     /tmp/foo/.git/
>     /tmp/foo/hello
>     /tmp/sym@ -> foo
> 
> when you refer to /tmp/sym/hello where $(/bin/pwd) is /tmp/foo, should it
> be considered to be within the bounds of the working tree that is governed
> by your current $GIT_DIR (which is ".git")?
Hmm, my /bin/pwd does not return "/tmp/foo" when I've cd'd to "/tmp/sym".
> The answer is "perhaps yes, ideally speaking, but does it really matter in
> practice, or is it just nice to have?".

FWIW, my motivation for using the absolute path was that I wanted to always add $GIT_WORK_TREE/hello, but the add could be run when in a subdirectory of the repository, so "git add hello" might not add the right file.

-- 
see shy jo
Jay Soffian· Apr 26, 2011, 03:41 UTC · re: Joey Hess · lore

Re: symlinked working tree gotcha

On Mon, Apr 25, 2011 at 3:09 PM, Joey Hess <joey@kitenet.net> wrote:
> Hmm, my /bin/pwd does not return "/tmp/foo" when I've cd'd to "/tmp/sym".
A pwd misfeature IMO. Try:
$ pwd -P
You can make -P the default in bash with "shopt -s -o physical"
j.

← back to recent threads