Re: git's fascination with absolute paths
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:47:56
Junio C Hamano [off-list ref] writes:
Not really. The scripts can work with ".." just fine, as long as they
know how to use "cd_to_topdir" and "rev-parse --show-prefix" correctly.
While I do not necessarily agree with the original claim that hiding
higher level of hierarchies are "standard" practice in UNIX (it instead
falls into "an unusual set-up that is permitted but you have to be
careful" category), I don't think it is fundamental that we need read
access all the way up to the root level. It is only that getcwd(3) does.
At the basic level, work tree and index operations operate relative to the root
of the work tree. Originally, almost no privision was made to run from a
subdirectory of a work tree (you were expected to run from the top-level,
having ./.git as the meta information sture), and we didn't have to run
any getcwd(3). Later we added "look at parent directories until we find
the one that has .git subdirectory, while remembering how many levels we
went up", in order to support operations from a subdirectory of a work
tree. The commands chdir up to the root of the work tree and would use
the path they climbed as a pathspec to limit the scope of their operation.
While "counting how many levels we went up" can be expressed by a sequence
of "../", turning it to the directory prefix means at some point you would
need to do what getcwd(3) does. It wants to be able to read ".." to give
you an absolute path.
By rewriting that part of the "root-level-discovery" code to do something
like
- while test -d .git is not true:
- stat(".") to get the inum;
- chdir(".."); and
- opendir(".") and readdir() to find where we were;
while going up every level, you should be able to construct the prefix
without being to able to read all the way up to the filesystem root. You
only need to be able to read your work tree.
Admittedly the code complexity got worse later when we added support for
GIT_WORK_TREE and also GIT_CEILING_DIRECTORIES, as they fundamentally need
to know where you are relative to the root of the filesystem tree and need
a working getcwd(3) support, which J Chapman's set-up refuses to give.
Also I wouldn't be surprised if the support for these two features cheat
in order to reduce code complexity by always using absolute paths even in
places where a path relative to the root of the work tree might have
sufficed.Clarificaiton. The above, like many other messages from me, was not meant as a justification, but a mere explanation of the historical fact. IOW, don't get me wrong by interpreting that I am not interested in seeing a solution that does not use absolute paths. While I think the original "higher levels in the filesystems may not be accessible" is a rather unusual set-up, making paths absolute and relying on being able to always do so have another drawback in a not-so-unusual setup. A work tree that is shallow (say, has only one t/ subdirectory and short filenames) may not be usable if it is so deep in the filesystem hierarchy that the result of getcwd(3) exceeds PATH_MAX. The "hand roll what getcwd(3) did in traditional UNIX while looking for the root level of the work tree" approach I outlined in the previous message will be a way to fix such a use case; as long as the deepest level of your work tree relative to the root of the work tree does not exceed PATH_MAX, you'll be Ok. We have a few known issues in the GIT_WORK_TREE (IIRC, it has a funny interaction with alias expansion). When we reexamine the codepath that the introduction of the feature needed to touch, I would love to see us at least try to see if it is feasible to redo this without calling getcwd(3) when no GIT_WORK_TREE (or core.worktree) is set.