The prefix_path_gently() function currently applies real_path to
everything if given an absolute path, dereferencing symlinks both
outside and inside the work tree.
This causes most high-level functions to misbehave when acting on
symlinks given via absolute paths. For example
$ git add /dir/repo/symlink
attempts to add the target of the symlink rather than the symlink
itself, which is usually not what the user intends to do.
In order to manipulate symlinks in the work tree using absolute paths,
symlinks should only be dereferenced outside the work tree.
Modify the prefix_path_gently() to first normalize the path in order to
make sure path levels are separated by '/', then pass the result to
'abspath_part_inside_repo' to find the part inside the work tree
(without dereferencing any symlinks inside the work tree).
For absolute paths, prefix_path_gently() did not, nor does now do, any
actual prefixing, hence the result from abspath_part_in_repo() is
returned as-is.
Fixes t0060-82 and t3004-5.
Signed-off-by: Martin Erik Werner <martinerikwerner@gmail.com>
Reviewed-by: Duy Nguyen <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
One edge-case that isn't currently checked in the tests is the beginning
of the path matching the work tree, despite the target not actually
being the work tree, for example:
path = /dir/repoa
work_tree = /dir/repo
should fail since the path is outside the repo. However, if /dir/repoa
is in fact a symlink that points to /dir/repo, it should instead
succeed.
Add two tests covering these cases, since they might be potential
regression points.
Signed-off-by: Martin Erik Werner <martinerikwerner@gmail.com>
Reviewed-by: Duy Nguyen <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The current behaviour of prefix_path is to return an empty string if
prefixing and absolute path that only contains exactly the work tree.
This behaviour is a potential regression point.
Signed-off-by: Martin Erik Werner <martinerikwerner@gmail.com>
Reviewed-by: Duy Nguyen <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When symlinks in the working tree are manipulated using the absolute
path, git dereferences them, and tries to manipulate the link target
instead.
This applies to most high-level commands but prefix_path is the common
denominator for all of them.
Add a known-breakage tests using the prefix_path function, which
currently uses real_path, causing the dereference.
Signed-off-by: Martin Erik Werner <martinerikwerner@gmail.com>
Reviewed-by: Duy Nguyen <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* jx/relative-path-regression-fix:
Use simpler relative_path when set_git_dir
relative_path should honor dos-drive-prefix
test: use unambigous leading path (/foo) for MSYS
mingw_path was introduced in abd4284 to output a mangled path as it is
passed as an argument to main(). But the name is misleading because
mangling does not come from MinGW, but from MSYS [1]. As abd4284 does not
introduce any MSYS or MinGW specific code but just prints out argv[2] as
it is passed to main(), give the function the more generic and less
confusing name "print_path".
[1] http://www.mingw.org/wiki/Posix_path_conversion
Signed-off-by: Sebastian Schuberth <sschuberth@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Tvangeste found that the "relative_path" function could not work
properly on Windows if "in" and "prefix" have DOS drive prefix
(such as "C:/windows"). ($gmane/234434)
E.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
should return "C:/a/b", but returns "../../C:/a/b", which is wrong.
So make relative_path honor DOS drive prefix, and add test cases
for it in t0060.
Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
In test cases for relative_path, path with one leading character
(such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
such DOS drive on MSYS platform. Use an umambigous leading path
"/foo" instead.
Also change two leading slashes (//) to three leading slashes (///),
otherwize it will be recognized as UNC name on MSYS platform.
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Acked-by: Sebastian Schuberth <sschuberth@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Some test cases are skipped on Windows by marking with POSIX prereq.
This is because arguments look like absolute paths (such as /a/b)
for regular Windows programs (*.exe executables, no bash scripts)
are changed to Windows paths (like C:/msysgit/a/b).
There is no cygpath nor equivalent on msysGit, but it is easy to
write one. New subcommand "mingw_path" is added in test-path-utils,
so that we can get the expected absolute paths on Windows. E.g.
COMMAND LINE Linux output Windows output
================================== ============ ===============
test-path-utils mingw_path / / C:/msysgit
test-path-utils mingw_path /a/b/ /a/b/ C:/msysgit/a/b/
With this utility, most skipped test cases in t0060 can be turned on
to be tested correctly on Windows.
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Original design of relative_path() is simple, just strip the prefix
(*base) from the absolute path (*abs).
In most cases, we need a real relative path, such as: ../foo,
../../bar. That's why there is another reimplementation
(path_relative()) in quote.c.
Borrow some codes from path_relative() in quote.c to refactor
relative_path() in path.c, so that it could return real relative
path, and user can reuse this function without reimplementing
his/her own. The function path_relative() in quote.c will be
substituted, and I would use the new relative_path() function when
implementing the interactive git-clean later.
Different results for relative_path() before and after this refactor:
abs path base path relative (original) relative (refactor)
======== ========= =================== ===================
/a/b /a/b . ./
/a/b/ /a/b . ./
/a /a/b/ /a ../
/ /a/b/ / ../../
/a/c /a/b/ /a/c ../c
/x/y /a/b/ /x/y ../../x/y
a/b/ a/b/ . ./
a/b/ a/b . ./
a a/b a ../
x/y a/b/ x/y ../../x/y
a/c a/b a/c ../c
(empty) (null) (empty) ./
(empty) (empty) (empty) ./
(empty) /a/b (empty) ./
(null) (null) (null) ./
(null) (empty) (null) ./
(null) /a/b (segfault) ./
You may notice that return value "." has been changed to "./".
It is because:
* Function quote_path_relative() in quote.c will show the relative
path as "./" if abs(in) and base(prefix) are the same.
* Function relative_path() is called only once (in setup.c), and
it will be OK for the return value as "./" instead of ".".
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Add subcommand "relative_path" in test-path-utils, and add test cases
in t0060.
Johannes tested an earlier version of this patch on Windows, and
found that some relative_path tests should be skipped on
Windows. This is because the bash on Windows rewrites arguments of
regular Windows programs, such as git and the test helpers, if the
arguments look like absolute POSIX paths. As a consequence, the
actual tests performed are not what the tests scripts expect.
The tests that need *not* be skipped are those where the two paths passed
to 'test-path-utils relative_path' have the same prefix and the result is
expected to be a relative path. This is because the rewriting changes
"/a/b" to "D:/Src/MSysGit/a/b", and when both inputs are extended the same
way, this just cancels out in the relative path computation.
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Move the responsibility for normalizing prefixes from
longest_ancestor_length() to its callers. Use slightly different
normalizations at the two callers:
In setup_git_directory_gently_1(), use the old normalization, which
ignores paths that are not usable. In the next commit we will change
this caller to also resolve symlinks in the paths from
GIT_CEILING_DIRECTORIES as part of the normalization.
In "test-path-utils longest_ancestor_length", use the old
normalization, but die() if any paths are unusable. Also change t0060
to only pass normalized paths to the test program (no empty entries or
non-absolute paths, strip trailing slashes from the paths, and remove
tests that thereby become redundant).
The point of this change is to reduce the scope of the ancestor_length
tests in t0060 from testing normalization+longest_prefix to testing
only mostly longest_prefix. This is necessary because when
setup_git_directory_gently_1() starts resolving symlinks as part of
its normalization, it will not be reasonable to do the same in the
test suite, because that would make the test results depend on the
contents of the root directory of the filesystem on which the test is
run. HOWEVER: under Windows, bash mangles arguments that look like
absolute POSIX paths into DOS paths. So we have to retain the level
of normalization done by normalize_path_copy() to convert the
bash-mangled DOS paths (which contain backslashes) into paths that use
forward slashes.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Jeff King <peff@peff.net>
Only the first half of the test works only on POSIX, the second half
passes on Windows as well.
A later test "real path removes other extra slashes" looks very similar,
but it does not make sense to split it in the same way: When two slashes
are prepended in front of an absolute DOS-style path on Windows, the
meaning of the path is changed (//server/share style), so that the test
cannot pass on Windows.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Acked-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Adjusted for Windows by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The change has two points:
1. Do not strip off a leading slash, because that erroneously turns an
absolute path into a relative path.
2. Do not remove slashes from groups of multiple slashes; instead let
chdir() handle them. It could be, for example, that it wants to
leave leading double-slashes alone.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
There is currently a bug: if passed an absolute top-level path that
doesn't exist (e.g., "/foo") it incorrectly interprets the path as a
relative path (e.g., returns "$(pwd)/foo"). So mark the test as
failing.
These tests are skipped on Windows because test-path-utils operates on
a DOS-style absolute path even if a POSIX style absolute path is
passed as argument.
Adjusted for Windows by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Some platforms like to stick extra whitespace in the output
of "wc -c"; using the result without quotes gets the shell
to collapse the whitespace.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Since the MSYS bash mangles absolute paths that it passes as command line
arguments to non-MSYS progams (such as git or test-path-utils), we have to
bend over backwards to squeeze some usefulness out of the existing tests.
In particular, a set of path normalization tests is added that test
relative paths. Some paths in the ancestor path tests are adjusted to help
MSYS bash's path mangling heuristics.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
The function strip_path_suffix() will try to strip a given suffix from
a given path. The suffix must start at a directory boundary (i.e. "core"
is not a path suffix of "libexec/git-core", but "git-core" is).
Arbitrary runs of directory separators ("slashes") are assumed identical.
Example:
strip_path_suffix("C:\\msysgit/\\libexec\\git-core",
"libexec///git-core", &prefix)
will set prefix to "C:\\msysgit" and return 0.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This changes the test-path-utils utility to invoke normalize_path_copy()
instead of normalize_absolute_path() because the latter is about to be
removed.
The test cases in t0060 are adjusted in two regards:
- normalize_path_copy() more often leaves a trailing slash in the result.
This has no negative side effects because the new user of this function,
longest_ancester_length(), already accounts for this behavior.
- The function can fail.
The tests uncover a flaw in normalize_path_copy(): If there are
sufficiently many '..' path components so that the root is reached, such as
in "/d1/s1/../../d2", then the leading slash was lost. This manifested
itself that (assuming there is a repository at /tmp/foo)
$ git add /d1/../tmp/foo/some-file
reported 'pathspec is outside repository'. This is now fixed.
Moreover, the test case descriptions of t0060 now include the test data and
expected outcome.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Make git recognize a new environment variable that prevents it from
chdir'ing up into specified directories when looking for a GIT_DIR.
Useful for avoiding slow network directories.
For example, I use git in an environment where homedirs are automounted
and "ls /home/nonexistent" takes about 9 seconds. Setting
GIT_CEILING_DIRS="/home" allows "git help -a" (for bash completion) and
"git symbolic-ref" (for my shell prompt) to run in a reasonable time.
Signed-off-by: David Reiss <dreiss@facebook.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
normalize_absolute_path removes several oddities form absolute paths,
giving nice clean paths like "/dir/sub1/sub2". Also add a test case
for this utility, based on a new test program (in the style of test-sha1).
Signed-off-by: David Reiss <dreiss@facebook.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>