2008-05-20 14:48:54 +08:00
|
|
|
#!/bin/sh
|
|
|
|
#
|
|
|
|
# Copyright (c) 2008 David Reiss
|
|
|
|
#
|
|
|
|
|
|
|
|
test_description='Test various path utilities'
|
|
|
|
|
2022-07-01 18:37:33 +08:00
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
2008-05-20 14:48:54 +08:00
|
|
|
. ./test-lib.sh
|
|
|
|
|
2009-03-12 05:15:10 +08:00
|
|
|
norm_path() {
|
2018-03-24 15:44:49 +08:00
|
|
|
expected=$(test-tool path-utils print_path "$2")
|
2023-02-07 06:44:31 +08:00
|
|
|
test_expect_success $3 "normalize path: $1 => $2" "
|
|
|
|
echo '$expected' >expect &&
|
|
|
|
test-tool path-utils normalize_path_copy '$1' >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
"
|
2008-05-20 14:48:54 +08:00
|
|
|
}
|
|
|
|
|
2013-06-25 23:53:42 +08:00
|
|
|
relative_path() {
|
2018-03-24 15:44:49 +08:00
|
|
|
expected=$(test-tool path-utils print_path "$3")
|
2023-02-07 06:44:31 +08:00
|
|
|
test_expect_success $4 "relative path: $1 $2 => $3" "
|
|
|
|
echo '$expected' >expect &&
|
|
|
|
test-tool path-utils relative_path '$1' '$2' >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
"
|
2013-06-25 23:53:42 +08:00
|
|
|
}
|
|
|
|
|
2016-04-16 08:50:12 +08:00
|
|
|
test_submodule_relative_url() {
|
|
|
|
test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
|
2023-02-07 06:44:31 +08:00
|
|
|
echo '$4' >expect &&
|
|
|
|
test-tool submodule resolve-relative-url '$1' '$2' '$3' >actual &&
|
|
|
|
test_cmp expect actual
|
2016-04-16 08:50:12 +08:00
|
|
|
"
|
|
|
|
}
|
|
|
|
|
2014-11-30 16:24:31 +08:00
|
|
|
test_git_path() {
|
|
|
|
test_expect_success "git-path $1 $2 => $3" "
|
|
|
|
$1 git rev-parse --git-path $2 >actual &&
|
|
|
|
echo $3 >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
"
|
|
|
|
}
|
|
|
|
|
2009-03-12 05:15:10 +08:00
|
|
|
# On Windows, we are using MSYS's bash, which mangles the paths.
|
|
|
|
# Absolute paths are anchored at the MSYS installation directory,
|
|
|
|
# which means that the path / accounts for this many characters:
|
2018-03-24 15:44:49 +08:00
|
|
|
rootoff=$(test-tool path-utils normalize_path_copy / | wc -c)
|
2009-03-12 05:15:10 +08:00
|
|
|
# Account for the trailing LF:
|
2009-03-23 14:22:29 +08:00
|
|
|
if test $rootoff = 2; then
|
2009-03-12 05:15:10 +08:00
|
|
|
rootoff= # we are on Unix
|
|
|
|
else
|
|
|
|
rootoff=$(($rootoff-1))
|
mingw: accomodate t0060-path-utils for MSYS2
On Windows, there are no POSIX paths, only Windows ones (an absolute
Windows path looks like "C:\Program Files\Git\ReleaseNotes.html", under
most circumstances, forward slashes are also allowed and synonymous to
backslashes).
So when a POSIX shell (such as MSYS2's Bash, which is used by Git for
Windows to execute all those shell scripts that are part of Git) passes
a POSIX path to test-path-utils.exe (which is not POSIX-aware), the path
is translated into a Windows path. For example, /etc/profile becomes
C:/Program Files/Git/etc/profile.
This path translation poses a problem when passing the root directory as
parameter to test-path-utils.exe, as it is not well defined whether the
translated root directory should end in a slash or not. MSys1 stripped
the trailing slash, but MSYS2 does not.
Originally, the Git for Windows project patched MSYS2's runtime to
accomodate Git's regression test, but we really should do it the other
way round.
To work with both of MSys1's and MSYS2's behaviors, we simply test what
the current system does in the beginning of t0060-path-utils.sh and then
adjust the expected longest ancestor length accordingly.
It looks quite a bit tricky what we actually do in this patch: first, we
adjust the expected length for the trailing slash we did not originally
expect (subtracting one). So far, so good.
But now comes the part where things work in a surprising way: when the
expected length was 0, the prefix to match is the root directory. If the
root directory is converted into a path with a trailing slash, however,
we know that the logic in longest_ancestor_length() cannot match: to
avoid partial matches of the last directory component, it verifies that
the character after the matching prefix is a slash (but because the
slash was part of the matching prefix, the next character cannot be a
slash). So the return value is -1. Alas, this is exactly what the
expected length is after subtracting the value of $rootslash! So we skip
adding the $rootoff value in that case (and only in that case).
Directories other than the root directory are handled fine (as they are
specified without a trailing slash, something not possible for the root
directory, and MSYS2 converts them into Windows paths that also lack
trailing slashes), therefore we do not need any more special handling.
Thanks to Ray Donnelly for his patient help with this issue.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-28 00:19:40 +08:00
|
|
|
# In MSYS2, the root directory "/" is translated into a Windows
|
|
|
|
# directory *with* trailing slash. Let's test for that and adjust
|
|
|
|
# our expected longest ancestor length accordingly.
|
2018-03-24 15:44:49 +08:00
|
|
|
case "$(test-tool path-utils print_path /)" in
|
mingw: accomodate t0060-path-utils for MSYS2
On Windows, there are no POSIX paths, only Windows ones (an absolute
Windows path looks like "C:\Program Files\Git\ReleaseNotes.html", under
most circumstances, forward slashes are also allowed and synonymous to
backslashes).
So when a POSIX shell (such as MSYS2's Bash, which is used by Git for
Windows to execute all those shell scripts that are part of Git) passes
a POSIX path to test-path-utils.exe (which is not POSIX-aware), the path
is translated into a Windows path. For example, /etc/profile becomes
C:/Program Files/Git/etc/profile.
This path translation poses a problem when passing the root directory as
parameter to test-path-utils.exe, as it is not well defined whether the
translated root directory should end in a slash or not. MSys1 stripped
the trailing slash, but MSYS2 does not.
Originally, the Git for Windows project patched MSYS2's runtime to
accomodate Git's regression test, but we really should do it the other
way round.
To work with both of MSys1's and MSYS2's behaviors, we simply test what
the current system does in the beginning of t0060-path-utils.sh and then
adjust the expected longest ancestor length accordingly.
It looks quite a bit tricky what we actually do in this patch: first, we
adjust the expected length for the trailing slash we did not originally
expect (subtracting one). So far, so good.
But now comes the part where things work in a surprising way: when the
expected length was 0, the prefix to match is the root directory. If the
root directory is converted into a path with a trailing slash, however,
we know that the logic in longest_ancestor_length() cannot match: to
avoid partial matches of the last directory component, it verifies that
the character after the matching prefix is a slash (but because the
slash was part of the matching prefix, the next character cannot be a
slash). So the return value is -1. Alas, this is exactly what the
expected length is after subtracting the value of $rootslash! So we skip
adding the $rootoff value in that case (and only in that case).
Directories other than the root directory are handled fine (as they are
specified without a trailing slash, something not possible for the root
directory, and MSYS2 converts them into Windows paths that also lack
trailing slashes), therefore we do not need any more special handling.
Thanks to Ray Donnelly for his patient help with this issue.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-28 00:19:40 +08:00
|
|
|
*/) rootslash=1;;
|
|
|
|
*) rootslash=0;;
|
|
|
|
esac
|
2009-03-12 05:15:10 +08:00
|
|
|
fi
|
|
|
|
|
2008-05-20 14:49:26 +08:00
|
|
|
ancestor() {
|
2009-03-12 05:15:10 +08:00
|
|
|
# We do some math with the expected ancestor length.
|
|
|
|
expected=$3
|
Fix `GIT_CEILING_DIRECTORIES` with `C:\` and the likes
When determining the length of the longest ancestor of a given path with
respect to to e.g. `GIT_CEILING_DIRECTORIES`, we special-case the root
directory by returning 0 (i.e. we pretend that the path `/` does not end
in a slash by virtually stripping it).
That is the correct behavior because when normalizing paths, the root
directory is special: all other directory paths have their trailing
slash stripped, but not the root directory's path (because it would
become the empty string, which is not a legal path).
However, this special-casing of the root directory in
`longest_ancestor_length()` completely forgets about Windows-style root
directories, e.g. `C:\`. These _also_ get normalized with a trailing
slash (because `C:` would actually refer to the current directory on
that drive, not necessarily to its root directory).
In fc56c7b34b (mingw: accomodate t0060-path-utils for MSYS2,
2016-01-27), we almost got it right. We noticed that
`longest_ancestor_length()` expects a slash _after_ the matched prefix,
and if the prefix already ends in a slash, the normalized path won't
ever match and -1 is returned.
But then that commit went astray: The correct fix is not to adjust the
_tests_ to expect an incorrect -1 when that function is fed a prefix
that ends in a slash, but instead to treat such a prefix as if the
trailing slash had been removed.
Likewise, that function needs to handle the case where it is fed a path
that ends in a slash (not only a prefix that ends in a slash): if it
matches the prefix (plus trailing slash), we still need to verify that
the path does not end there, otherwise the prefix is not actually an
ancestor of the path but identical to it (and we need to return -1 in
that case).
With these two adjustments, we no longer need to play games in t0060
where we only add `$rootoff` if the passed prefix is different from the
MSYS2 pseudo root, instead we also add it for the MSYS2 pseudo root
itself. We do have to be careful to skip that logic entirely for Windows
paths, though, because they do are not subject to that MSYS2 pseudo root
treatment.
This patch fixes the scenario where a user has set
`GIT_CEILING_DIRECTORIES=C:\`, which would be ignored otherwise.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2022-03-24 06:00:41 +08:00
|
|
|
case "$rootoff,$expected,$2" in
|
|
|
|
*,*,//*) ;; # leave UNC paths alone
|
|
|
|
[0-9]*,[0-9]*,/*)
|
|
|
|
# On Windows, expect MSYS2 pseudo root translation for
|
|
|
|
# Unix-style absolute paths
|
|
|
|
expected=$(($expected-$rootslash+$rootoff))
|
|
|
|
;;
|
|
|
|
esac
|
2023-02-07 06:44:31 +08:00
|
|
|
test_expect_success $4 "longest ancestor: $1 $2 => $expected" "
|
|
|
|
echo '$expected' >expect &&
|
|
|
|
test-tool path-utils longest_ancestor_length '$1' '$2' >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
"
|
2008-05-20 14:49:26 +08:00
|
|
|
}
|
|
|
|
|
2013-06-25 23:53:57 +08:00
|
|
|
# Some absolute path tests should be skipped on Windows due to path mangling
|
|
|
|
# on POSIX-style absolute paths
|
2009-03-12 05:15:10 +08:00
|
|
|
case $(uname -s) in
|
|
|
|
*MINGW*)
|
|
|
|
;;
|
2017-07-03 22:41:37 +08:00
|
|
|
*CYGWIN*)
|
|
|
|
;;
|
2009-03-12 05:15:10 +08:00
|
|
|
*)
|
|
|
|
test_set_prereq POSIX
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
2018-03-24 15:44:49 +08:00
|
|
|
test_expect_success basename 'test-tool path-utils basename'
|
|
|
|
test_expect_success dirname 'test-tool path-utils dirname'
|
2016-01-12 15:57:57 +08:00
|
|
|
|
2009-03-12 05:15:10 +08:00
|
|
|
norm_path "" ""
|
|
|
|
norm_path . ""
|
|
|
|
norm_path ./ ""
|
|
|
|
norm_path ./. ""
|
|
|
|
norm_path ./.. ++failed++
|
|
|
|
norm_path ../. ++failed++
|
|
|
|
norm_path ./../.// ++failed++
|
|
|
|
norm_path dir/.. ""
|
|
|
|
norm_path dir/sub/../.. ""
|
|
|
|
norm_path dir/sub/../../.. ++failed++
|
|
|
|
norm_path dir dir
|
|
|
|
norm_path dir// dir/
|
|
|
|
norm_path ./dir dir
|
|
|
|
norm_path dir/. dir/
|
|
|
|
norm_path dir///./ dir/
|
|
|
|
norm_path dir//sub/.. dir/
|
|
|
|
norm_path dir/sub/../ dir/
|
|
|
|
norm_path dir/sub/../. dir/
|
|
|
|
norm_path dir/s1/../s2/ dir/s2/
|
|
|
|
norm_path d1/s1///s2/..//../s3/ d1/s3/
|
|
|
|
norm_path d1/s1//../s2/../../d2 d2
|
|
|
|
norm_path d1/.../d2 d1/.../d2
|
|
|
|
norm_path d1/..././../d2 d1/d2
|
|
|
|
|
2013-06-25 23:53:57 +08:00
|
|
|
norm_path / /
|
2009-03-12 05:15:10 +08:00
|
|
|
norm_path // / POSIX
|
|
|
|
norm_path /// / POSIX
|
2013-06-25 23:53:57 +08:00
|
|
|
norm_path /. /
|
2009-03-12 05:15:10 +08:00
|
|
|
norm_path /./ / POSIX
|
|
|
|
norm_path /./.. ++failed++ POSIX
|
2013-06-25 23:53:57 +08:00
|
|
|
norm_path /../. ++failed++
|
2009-03-12 05:15:10 +08:00
|
|
|
norm_path /./../.// ++failed++ POSIX
|
|
|
|
norm_path /dir/.. / POSIX
|
|
|
|
norm_path /dir/sub/../.. / POSIX
|
|
|
|
norm_path /dir/sub/../../.. ++failed++ POSIX
|
2013-06-25 23:53:57 +08:00
|
|
|
norm_path /dir /dir
|
|
|
|
norm_path /dir// /dir/
|
|
|
|
norm_path /./dir /dir
|
|
|
|
norm_path /dir/. /dir/
|
|
|
|
norm_path /dir///./ /dir/
|
|
|
|
norm_path /dir//sub/.. /dir/
|
|
|
|
norm_path /dir/sub/../ /dir/
|
2009-03-12 05:15:10 +08:00
|
|
|
norm_path //dir/sub/../. /dir/ POSIX
|
2013-06-25 23:53:57 +08:00
|
|
|
norm_path /dir/s1/../s2/ /dir/s2/
|
|
|
|
norm_path /d1/s1///s2/..//../s3/ /d1/s3/
|
|
|
|
norm_path /d1/s1//../s2/../../d2 /d2
|
|
|
|
norm_path /d1/.../d2 /d1/.../d2
|
|
|
|
norm_path /d1/..././../d2 /d1/d2
|
2008-05-20 14:48:54 +08:00
|
|
|
|
2008-05-20 14:49:26 +08:00
|
|
|
ancestor / / -1
|
|
|
|
ancestor /foo / 0
|
|
|
|
ancestor /foo /fo -1
|
|
|
|
ancestor /foo /foo -1
|
|
|
|
ancestor /foo /bar -1
|
|
|
|
ancestor /foo /foo/bar -1
|
2012-10-29 00:16:25 +08:00
|
|
|
ancestor /foo /foo:/bar -1
|
|
|
|
ancestor /foo /:/foo:/bar 0
|
|
|
|
ancestor /foo /foo:/:/bar 0
|
|
|
|
ancestor /foo /:/bar:/foo 0
|
2008-05-20 14:49:26 +08:00
|
|
|
ancestor /foo/bar / 0
|
|
|
|
ancestor /foo/bar /fo -1
|
|
|
|
ancestor /foo/bar /foo 4
|
|
|
|
ancestor /foo/bar /foo/ba -1
|
|
|
|
ancestor /foo/bar /:/fo 0
|
|
|
|
ancestor /foo/bar /foo:/foo/ba 4
|
|
|
|
ancestor /foo/bar /bar -1
|
2012-10-29 00:16:25 +08:00
|
|
|
ancestor /foo/bar /fo -1
|
|
|
|
ancestor /foo/bar /foo:/bar 4
|
|
|
|
ancestor /foo/bar /:/foo:/bar 4
|
|
|
|
ancestor /foo/bar /foo:/:/bar 4
|
|
|
|
ancestor /foo/bar /:/bar:/fo 0
|
|
|
|
ancestor /foo/bar /:/bar 0
|
|
|
|
ancestor /foo/bar /foo 4
|
|
|
|
ancestor /foo/bar /foo:/bar 4
|
|
|
|
ancestor /foo/bar /bar -1
|
2008-05-20 14:49:26 +08:00
|
|
|
|
Fix `GIT_CEILING_DIRECTORIES` with `C:\` and the likes
When determining the length of the longest ancestor of a given path with
respect to to e.g. `GIT_CEILING_DIRECTORIES`, we special-case the root
directory by returning 0 (i.e. we pretend that the path `/` does not end
in a slash by virtually stripping it).
That is the correct behavior because when normalizing paths, the root
directory is special: all other directory paths have their trailing
slash stripped, but not the root directory's path (because it would
become the empty string, which is not a legal path).
However, this special-casing of the root directory in
`longest_ancestor_length()` completely forgets about Windows-style root
directories, e.g. `C:\`. These _also_ get normalized with a trailing
slash (because `C:` would actually refer to the current directory on
that drive, not necessarily to its root directory).
In fc56c7b34b (mingw: accomodate t0060-path-utils for MSYS2,
2016-01-27), we almost got it right. We noticed that
`longest_ancestor_length()` expects a slash _after_ the matched prefix,
and if the prefix already ends in a slash, the normalized path won't
ever match and -1 is returned.
But then that commit went astray: The correct fix is not to adjust the
_tests_ to expect an incorrect -1 when that function is fed a prefix
that ends in a slash, but instead to treat such a prefix as if the
trailing slash had been removed.
Likewise, that function needs to handle the case where it is fed a path
that ends in a slash (not only a prefix that ends in a slash): if it
matches the prefix (plus trailing slash), we still need to verify that
the path does not end there, otherwise the prefix is not actually an
ancestor of the path but identical to it (and we need to return -1 in
that case).
With these two adjustments, we no longer need to play games in t0060
where we only add `$rootoff` if the passed prefix is different from the
MSYS2 pseudo root, instead we also add it for the MSYS2 pseudo root
itself. We do have to be careful to skip that logic entirely for Windows
paths, though, because they do are not subject to that MSYS2 pseudo root
treatment.
This patch fixes the scenario where a user has set
`GIT_CEILING_DIRECTORIES=C:\`, which would be ignored otherwise.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2022-03-24 06:00:41 +08:00
|
|
|
# Windows-specific: DOS drives, network shares
|
|
|
|
ancestor C:/Users/me C:/ 2 MINGW
|
|
|
|
ancestor D:/Users/me C:/ -1 MINGW
|
|
|
|
ancestor //server/share/my-directory //server/share/ 14 MINGW
|
|
|
|
|
2009-02-20 03:10:49 +08:00
|
|
|
test_expect_success 'strip_path_suffix' '
|
2023-02-07 06:44:31 +08:00
|
|
|
echo c:/msysgit >expect &&
|
|
|
|
test-tool path-utils strip_path_suffix \
|
|
|
|
c:/msysgit/libexec//git-core libexec/git-core >actual &&
|
|
|
|
test_cmp expect actual
|
2009-02-20 03:10:49 +08:00
|
|
|
'
|
2012-09-07 06:40:57 +08:00
|
|
|
|
2012-09-07 06:40:59 +08:00
|
|
|
test_expect_success 'absolute path rejects the empty string' '
|
2018-03-24 15:44:49 +08:00
|
|
|
test_must_fail test-tool path-utils absolute_path ""
|
2012-09-07 06:40:58 +08:00
|
|
|
'
|
|
|
|
|
mingw: handle `subst`-ed "DOS drives"
Over a decade ago, in 25fe217b86c (Windows: Treat Windows style path
names., 2008-03-05), Git was taught to handle absolute Windows paths,
i.e. paths that start with a drive letter and a colon.
Unbeknownst to us, while drive letters of physical drives are limited to
letters of the English alphabet, there is a way to assign virtual drive
letters to arbitrary directories, via the `subst` command, which is
_not_ limited to English letters.
It is therefore possible to have absolute Windows paths of the form
`1:\what\the\hex.txt`. Even "better": pretty much arbitrary Unicode
letters can also be used, e.g. `ä:\tschibät.sch`.
While it can be sensibly argued that users who set up such funny drive
letters really seek adverse consequences, the Windows Operating System
is known to be a platform where many users are at the mercy of
administrators who have their very own idea of what constitutes a
reasonable setup.
Therefore, let's just make sure that such funny paths are still
considered absolute paths by Git, on Windows.
In addition to Unicode characters, pretty much any character is a valid
drive letter, as far as `subst` is concerned, even `:` and `"` or even a
space character. While it is probably the opposite of smart to use them,
let's safeguard `is_dos_drive_prefix()` against all of them.
Note: `[::1]:repo` is a valid URL, but not a valid path on Windows.
As `[` is now considered a valid drive letter, we need to be very
careful to avoid misinterpreting such a string as valid local path in
`url_is_local_not_ssh()`. To do that, we use the just-introduced
function `is_valid_path()` (which will label the string as invalid file
name because of the colon characters).
This fixes CVE-2019-1351.
Reported-by: Nicolas Joly <Nicolas.Joly@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-06 06:09:10 +08:00
|
|
|
test_expect_success MINGW '<drive-letter>:\\abc is an absolute path' '
|
|
|
|
for letter in : \" C Z 1 ä
|
|
|
|
do
|
|
|
|
path=$letter:\\abc &&
|
2019-12-05 05:21:20 +08:00
|
|
|
absolute="$(test-tool path-utils absolute_path "$path")" &&
|
mingw: handle `subst`-ed "DOS drives"
Over a decade ago, in 25fe217b86c (Windows: Treat Windows style path
names., 2008-03-05), Git was taught to handle absolute Windows paths,
i.e. paths that start with a drive letter and a colon.
Unbeknownst to us, while drive letters of physical drives are limited to
letters of the English alphabet, there is a way to assign virtual drive
letters to arbitrary directories, via the `subst` command, which is
_not_ limited to English letters.
It is therefore possible to have absolute Windows paths of the form
`1:\what\the\hex.txt`. Even "better": pretty much arbitrary Unicode
letters can also be used, e.g. `ä:\tschibät.sch`.
While it can be sensibly argued that users who set up such funny drive
letters really seek adverse consequences, the Windows Operating System
is known to be a platform where many users are at the mercy of
administrators who have their very own idea of what constitutes a
reasonable setup.
Therefore, let's just make sure that such funny paths are still
considered absolute paths by Git, on Windows.
In addition to Unicode characters, pretty much any character is a valid
drive letter, as far as `subst` is concerned, even `:` and `"` or even a
space character. While it is probably the opposite of smart to use them,
let's safeguard `is_dos_drive_prefix()` against all of them.
Note: `[::1]:repo` is a valid URL, but not a valid path on Windows.
As `[` is now considered a valid drive letter, we need to be very
careful to avoid misinterpreting such a string as valid local path in
`url_is_local_not_ssh()`. To do that, we use the just-introduced
function `is_valid_path()` (which will label the string as invalid file
name because of the colon characters).
This fixes CVE-2019-1351.
Reported-by: Nicolas Joly <Nicolas.Joly@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-06 06:09:10 +08:00
|
|
|
test "$path" = "$absolute" || return 1
|
|
|
|
done
|
|
|
|
'
|
|
|
|
|
2012-09-07 06:41:01 +08:00
|
|
|
test_expect_success 'real path rejects the empty string' '
|
2018-03-24 15:44:49 +08:00
|
|
|
test_must_fail test-tool path-utils real_path ""
|
2012-09-07 06:41:00 +08:00
|
|
|
'
|
|
|
|
|
2012-09-09 23:42:20 +08:00
|
|
|
test_expect_success POSIX 'real path works on absolute paths 1' '
|
2023-02-07 06:44:31 +08:00
|
|
|
echo / >expect &&
|
|
|
|
test-tool path-utils real_path "/" >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
2012-09-07 06:41:02 +08:00
|
|
|
nopath="hopefully-absent-path" &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "/$nopath" >expect &&
|
|
|
|
test-tool path-utils real_path "/$nopath" >actual &&
|
|
|
|
test_cmp expect actual
|
2012-09-09 23:42:20 +08:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'real path works on absolute paths 2' '
|
2012-09-07 06:41:02 +08:00
|
|
|
# Find an existing top-level directory for the remaining tests:
|
|
|
|
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "$d" >expect &&
|
|
|
|
test-tool path-utils real_path "$d" >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
nopath="hopefully-absent-path" &&
|
|
|
|
echo "$d/$nopath" >expect &&
|
|
|
|
test-tool path-utils real_path "$d/$nopath" >actual &&
|
|
|
|
test_cmp expect actual
|
2012-09-07 06:41:02 +08:00
|
|
|
'
|
|
|
|
|
2012-09-07 06:41:04 +08:00
|
|
|
test_expect_success POSIX 'real path removes extra leading slashes' '
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "/" >expect &&
|
|
|
|
test-tool path-utils real_path "///" >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
2012-09-07 06:41:04 +08:00
|
|
|
nopath="hopefully-absent-path" &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "/$nopath" >expect &&
|
|
|
|
test-tool path-utils real_path "///$nopath" >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
2012-09-07 06:41:04 +08:00
|
|
|
# Find an existing top-level directory for the remaining tests:
|
|
|
|
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "$d" >expect &&
|
|
|
|
test-tool path-utils real_path "//$d" >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
echo "$d/$nopath" >expect &&
|
|
|
|
test-tool path-utils real_path "//$d/$nopath" >actual &&
|
|
|
|
test_cmp expect actual
|
2012-09-07 06:41:04 +08:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'real path removes other extra slashes' '
|
|
|
|
# Find an existing top-level directory for the remaining tests:
|
|
|
|
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "$d" >expect &&
|
|
|
|
test-tool path-utils real_path "$d///" >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
nopath="hopefully-absent-path" &&
|
|
|
|
echo "$d/$nopath" >expect &&
|
|
|
|
test-tool path-utils real_path "$d///$nopath" >actual &&
|
|
|
|
test_cmp expect actual
|
2012-09-07 06:41:04 +08:00
|
|
|
'
|
|
|
|
|
2012-09-07 06:41:02 +08:00
|
|
|
test_expect_success SYMLINKS 'real path works on symlinks' '
|
2012-09-07 06:40:57 +08:00
|
|
|
mkdir first &&
|
|
|
|
ln -s ../.git first/.git &&
|
|
|
|
mkdir second &&
|
|
|
|
ln -s ../first second/other &&
|
|
|
|
mkdir third &&
|
tests: fix broken &&-chains in `$(...)` command substitutions
The top-level &&-chain checker built into t/test-lib.sh causes tests to
magically exit with code 117 if the &&-chain is broken. However, it has
the shortcoming that the magic does not work within `{...}` groups,
`(...)` subshells, `$(...)` substitutions, or within bodies of compound
statements, such as `if`, `for`, `while`, `case`, etc. `chainlint.sed`
partly fills in the gap by catching broken &&-chains in `(...)`
subshells, but bugs can still lurk behind broken &&-chains in the other
cases.
Fix broken &&-chains in `$(...)` command substitutions in order to
reduce the number of possible lurking bugs.
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Reviewed-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-12-09 13:11:07 +08:00
|
|
|
dir="$(cd .git && pwd -P)" &&
|
2012-09-07 06:40:57 +08:00
|
|
|
dir2=third/../second/other/.git &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "$dir" >expect &&
|
|
|
|
test-tool path-utils real_path $dir2 >actual &&
|
|
|
|
test_cmp expect actual &&
|
2012-09-07 06:40:57 +08:00
|
|
|
file="$dir"/index &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "$file" >expect &&
|
|
|
|
test-tool path-utils real_path $dir2/index >actual &&
|
|
|
|
test_cmp expect actual &&
|
2012-09-07 06:40:57 +08:00
|
|
|
basename=blub &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "$dir/$basename" >expect &&
|
|
|
|
test-tool -C .git path-utils real_path "$basename" >actual &&
|
|
|
|
test_cmp expect actual &&
|
2012-09-07 06:40:57 +08:00
|
|
|
ln -s ../first/file .git/syml &&
|
tests: fix broken &&-chains in `$(...)` command substitutions
The top-level &&-chain checker built into t/test-lib.sh causes tests to
magically exit with code 117 if the &&-chain is broken. However, it has
the shortcoming that the magic does not work within `{...}` groups,
`(...)` subshells, `$(...)` substitutions, or within bodies of compound
statements, such as `if`, `for`, `while`, `case`, etc. `chainlint.sed`
partly fills in the gap by catching broken &&-chains in `(...)`
subshells, but bugs can still lurk behind broken &&-chains in the other
cases.
Fix broken &&-chains in `$(...)` command substitutions in order to
reduce the number of possible lurking bugs.
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Reviewed-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-12-09 13:11:07 +08:00
|
|
|
sym="$(cd first && pwd -P)"/file &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "$sym" >expect &&
|
|
|
|
test-tool path-utils real_path "$dir2/syml" >actual &&
|
|
|
|
test_cmp expect actual
|
2012-09-07 06:40:57 +08:00
|
|
|
'
|
|
|
|
|
2014-02-04 22:25:20 +08:00
|
|
|
test_expect_success SYMLINKS 'prefix_path works with absolute paths to work tree symlinks' '
|
2014-02-04 22:25:16 +08:00
|
|
|
ln -s target symlink &&
|
2023-02-07 06:44:31 +08:00
|
|
|
echo "symlink" >expect &&
|
|
|
|
test-tool path-utils prefix_path prefix "$(pwd)/symlink" >actual &&
|
|
|
|
test_cmp expect actual
|
2014-02-04 22:25:16 +08:00
|
|
|
'
|
|
|
|
|
2014-02-04 22:25:17 +08:00
|
|
|
test_expect_success 'prefix_path works with only absolute path to work tree' '
|
|
|
|
echo "" >expected &&
|
2018-03-24 15:44:49 +08:00
|
|
|
test-tool path-utils prefix_path prefix "$(pwd)" >actual &&
|
2014-02-04 22:25:17 +08:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2014-02-04 22:25:18 +08:00
|
|
|
test_expect_success 'prefix_path rejects absolute path to dir with same beginning as work tree' '
|
2018-03-24 15:44:49 +08:00
|
|
|
test_must_fail test-tool path-utils prefix_path prefix "$(pwd)a"
|
2014-02-04 22:25:18 +08:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success SYMLINKS 'prefix_path works with absolute path to a symlink to work tree having same beginning as work tree' '
|
|
|
|
git init repo &&
|
|
|
|
ln -s repo repolink &&
|
2023-02-07 06:44:30 +08:00
|
|
|
echo "a" >expect &&
|
|
|
|
repo_path="$(cd repo && pwd)" &&
|
|
|
|
test-tool -C repo path-utils prefix_path prefix "$repo_path/../repolink/a" >actual &&
|
|
|
|
test_cmp expect actual
|
2014-02-04 22:25:18 +08:00
|
|
|
'
|
|
|
|
|
2013-10-14 10:29:38 +08:00
|
|
|
relative_path /foo/a/b/c/ /foo/a/b/ c/
|
|
|
|
relative_path /foo/a/b/c/ /foo/a/b c/
|
|
|
|
relative_path /foo/a//b//c/ ///foo/a/b// c/ POSIX
|
|
|
|
relative_path /foo/a/b /foo/a/b ./
|
|
|
|
relative_path /foo/a/b/ /foo/a/b ./
|
|
|
|
relative_path /foo/a /foo/a/b ../
|
|
|
|
relative_path / /foo/a/b/ ../../../
|
|
|
|
relative_path /foo/a/c /foo/a/b/ ../c
|
|
|
|
relative_path /foo/a/c /foo/a/b ../c
|
|
|
|
relative_path /foo/x/y /foo/a/b/ ../../x/y
|
|
|
|
relative_path /foo/a/b "<empty>" /foo/a/b
|
|
|
|
relative_path /foo/a/b "<null>" /foo/a/b
|
|
|
|
relative_path foo/a/b/c/ foo/a/b/ c/
|
|
|
|
relative_path foo/a/b/c/ foo/a/b c/
|
|
|
|
relative_path foo/a/b//c foo/a//b c
|
|
|
|
relative_path foo/a/b/ foo/a/b/ ./
|
|
|
|
relative_path foo/a/b/ foo/a/b ./
|
|
|
|
relative_path foo/a foo/a/b ../
|
|
|
|
relative_path foo/x/y foo/a/b ../../x/y
|
|
|
|
relative_path foo/a/c foo/a/b ../c
|
2013-10-14 10:29:39 +08:00
|
|
|
relative_path foo/a/b /foo/x/y foo/a/b
|
|
|
|
relative_path /foo/a/b foo/x/y /foo/a/b
|
|
|
|
relative_path d:/a/b D:/a/c ../b MINGW
|
|
|
|
relative_path C:/a/b D:/a/c C:/a/b MINGW
|
2013-10-14 10:29:38 +08:00
|
|
|
relative_path foo/a/b "<empty>" foo/a/b
|
|
|
|
relative_path foo/a/b "<null>" foo/a/b
|
|
|
|
relative_path "<empty>" /foo/a/b ./
|
|
|
|
relative_path "<empty>" "<empty>" ./
|
|
|
|
relative_path "<empty>" "<null>" ./
|
|
|
|
relative_path "<null>" "<empty>" ./
|
|
|
|
relative_path "<null>" "<null>" ./
|
|
|
|
relative_path "<null>" /foo/a/b ./
|
2013-06-25 23:53:42 +08:00
|
|
|
|
2014-11-30 16:24:31 +08:00
|
|
|
test_git_path A=B info/grafts .git/info/grafts
|
|
|
|
test_git_path GIT_GRAFT_FILE=foo info/grafts foo
|
|
|
|
test_git_path GIT_GRAFT_FILE=foo info/////grafts foo
|
|
|
|
test_git_path GIT_INDEX_FILE=foo index foo
|
|
|
|
test_git_path GIT_INDEX_FILE=foo index/foo .git/index/foo
|
|
|
|
test_git_path GIT_INDEX_FILE=foo index2 .git/index2
|
|
|
|
test_expect_success 'setup fake objects directory foo' 'mkdir foo'
|
|
|
|
test_git_path GIT_OBJECT_DIRECTORY=foo objects foo
|
|
|
|
test_git_path GIT_OBJECT_DIRECTORY=foo objects/foo foo/foo
|
|
|
|
test_git_path GIT_OBJECT_DIRECTORY=foo objects2 .git/objects2
|
$GIT_COMMON_DIR: a new environment variable
This variable is intended to support multiple working directories
attached to a repository. Such a repository may have a main working
directory, created by either "git init" or "git clone" and one or more
linked working directories. These working directories and the main
repository share the same repository directory.
In linked working directories, $GIT_COMMON_DIR must be defined to point
to the real repository directory and $GIT_DIR points to an unused
subdirectory inside $GIT_COMMON_DIR. File locations inside the
repository are reorganized from the linked worktree view point:
- worktree-specific such as HEAD, logs/HEAD, index, other top-level
refs and unrecognized files are from $GIT_DIR.
- the rest like objects, refs, info, hooks, packed-refs, shallow...
are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's
a separate patch)
Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse
--git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR"
business.
The redirection is done by git_path(), git_pathdup() and
strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR,
not the other way around in case a developer adds a new
worktree-specific file and it's accidentally promoted to be shared
across repositories (this includes unknown files added by third party
commands)
The list of known files that belong to $GIT_DIR are:
ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG
BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD
MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD
REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD
next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/*
shallow_*
Path mapping is NOT done for git_path_submodule(). Multi-checkouts are
not supported as submodules.
Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-30 16:24:36 +08:00
|
|
|
test_expect_success 'setup common repository' 'git --git-dir=bar init'
|
|
|
|
test_git_path GIT_COMMON_DIR=bar index .git/index
|
2019-10-28 20:57:18 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar index.lock .git/index.lock
|
$GIT_COMMON_DIR: a new environment variable
This variable is intended to support multiple working directories
attached to a repository. Such a repository may have a main working
directory, created by either "git init" or "git clone" and one or more
linked working directories. These working directories and the main
repository share the same repository directory.
In linked working directories, $GIT_COMMON_DIR must be defined to point
to the real repository directory and $GIT_DIR points to an unused
subdirectory inside $GIT_COMMON_DIR. File locations inside the
repository are reorganized from the linked worktree view point:
- worktree-specific such as HEAD, logs/HEAD, index, other top-level
refs and unrecognized files are from $GIT_DIR.
- the rest like objects, refs, info, hooks, packed-refs, shallow...
are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's
a separate patch)
Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse
--git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR"
business.
The redirection is done by git_path(), git_pathdup() and
strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR,
not the other way around in case a developer adds a new
worktree-specific file and it's accidentally promoted to be shared
across repositories (this includes unknown files added by third party
commands)
The list of known files that belong to $GIT_DIR are:
ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG
BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD
MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD
REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD
next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/*
shallow_*
Path mapping is NOT done for git_path_submodule(). Multi-checkouts are
not supported as submodules.
Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-30 16:24:36 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar HEAD .git/HEAD
|
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/HEAD .git/logs/HEAD
|
2019-10-28 20:57:18 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/HEAD.lock .git/logs/HEAD.lock
|
2015-09-01 10:13:11 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/refs/bisect/foo .git/logs/refs/bisect/foo
|
path.c: don't call the match function without value in trie_find()
'logs/refs' is not a working tree-specific path, but since commit
b9317d55a3 (Make sure refs/rewritten/ is per-worktree, 2019-03-07)
'git rev-parse --git-path' has been returning a bogus path if a
trailing '/' is present:
$ git -C WT/ rev-parse --git-path logs/refs --git-path logs/refs/
/home/szeder/src/git/.git/logs/refs
/home/szeder/src/git/.git/worktrees/WT/logs/refs/
We use a trie data structure to efficiently decide whether a path
belongs to the common dir or is working tree-specific. As it happens
b9317d55a3 triggered a bug that is as old as the trie implementation
itself, added in 4e09cf2acf (path: optimize common dir checking,
2015-08-31).
- According to the comment describing trie_find(), it should only
call the given match function 'fn' for a "/-or-\0-terminated
prefix of the key for which the trie contains a value". This is
not true: there are three places where trie_find() calls the match
function, but one of them is missing the check for value's
existence.
- b9317d55a3 added two new keys to the trie: 'logs/refs/rewritten'
and 'logs/refs/worktree', next to the already existing
'logs/refs/bisect'. This resulted in a trie node with the path
'logs/refs/', which didn't exist before, and which doesn't have a
value attached. A query for 'logs/refs/' finds this node and then
hits that one callsite of the match function which doesn't check
for the value's existence, and thus invokes the match function
with NULL as value.
- When the match function check_common() is invoked with a NULL
value, it returns 0, which indicates that the queried path doesn't
belong to the common directory, ultimately resulting the bogus
path shown above.
Add the missing condition to trie_find() so it will never invoke the
match function with a non-existing value. check_common() will then no
longer have to check that it got a non-NULL value, so remove that
condition.
I believe that there are no other paths that could cause similar bogus
output. AFAICT the only other key resulting in the match function
being called with a NULL value is 'co' (because of the keys 'common'
and 'config'). However, as they are not in a directory that belongs
to the common directory the resulting working tree-specific path is
expected.
Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-10-22 00:00:43 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/refs bar/logs/refs
|
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/refs/ bar/logs/refs/
|
2015-09-01 10:13:11 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/refs/bisec/foo bar/logs/refs/bisec/foo
|
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/refs/bisec bar/logs/refs/bisec
|
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/refs/bisectfoo bar/logs/refs/bisectfoo
|
$GIT_COMMON_DIR: a new environment variable
This variable is intended to support multiple working directories
attached to a repository. Such a repository may have a main working
directory, created by either "git init" or "git clone" and one or more
linked working directories. These working directories and the main
repository share the same repository directory.
In linked working directories, $GIT_COMMON_DIR must be defined to point
to the real repository directory and $GIT_DIR points to an unused
subdirectory inside $GIT_COMMON_DIR. File locations inside the
repository are reorganized from the linked worktree view point:
- worktree-specific such as HEAD, logs/HEAD, index, other top-level
refs and unrecognized files are from $GIT_DIR.
- the rest like objects, refs, info, hooks, packed-refs, shallow...
are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's
a separate patch)
Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse
--git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR"
business.
The redirection is done by git_path(), git_pathdup() and
strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR,
not the other way around in case a developer adds a new
worktree-specific file and it's accidentally promoted to be shared
across repositories (this includes unknown files added by third party
commands)
The list of known files that belong to $GIT_DIR are:
ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG
BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD
MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD
REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD
next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/*
shallow_*
Path mapping is NOT done for git_path_submodule(). Multi-checkouts are
not supported as submodules.
Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-30 16:24:36 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar objects bar/objects
|
|
|
|
test_git_path GIT_COMMON_DIR=bar objects/bar bar/objects/bar
|
|
|
|
test_git_path GIT_COMMON_DIR=bar info/exclude bar/info/exclude
|
|
|
|
test_git_path GIT_COMMON_DIR=bar info/grafts bar/info/grafts
|
2014-11-30 16:24:55 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar info/sparse-checkout .git/info/sparse-checkout
|
2015-09-01 10:13:10 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar info//sparse-checkout .git/info//sparse-checkout
|
$GIT_COMMON_DIR: a new environment variable
This variable is intended to support multiple working directories
attached to a repository. Such a repository may have a main working
directory, created by either "git init" or "git clone" and one or more
linked working directories. These working directories and the main
repository share the same repository directory.
In linked working directories, $GIT_COMMON_DIR must be defined to point
to the real repository directory and $GIT_DIR points to an unused
subdirectory inside $GIT_COMMON_DIR. File locations inside the
repository are reorganized from the linked worktree view point:
- worktree-specific such as HEAD, logs/HEAD, index, other top-level
refs and unrecognized files are from $GIT_DIR.
- the rest like objects, refs, info, hooks, packed-refs, shallow...
are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's
a separate patch)
Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse
--git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR"
business.
The redirection is done by git_path(), git_pathdup() and
strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR,
not the other way around in case a developer adds a new
worktree-specific file and it's accidentally promoted to be shared
across repositories (this includes unknown files added by third party
commands)
The list of known files that belong to $GIT_DIR are:
ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG
BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD
MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD
REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD
next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/*
shallow_*
Path mapping is NOT done for git_path_submodule(). Multi-checkouts are
not supported as submodules.
Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-30 16:24:36 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar remotes/bar bar/remotes/bar
|
|
|
|
test_git_path GIT_COMMON_DIR=bar branches/bar bar/branches/bar
|
2020-11-19 07:44:21 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar logs/refs/heads/main bar/logs/refs/heads/main
|
|
|
|
test_git_path GIT_COMMON_DIR=bar refs/heads/main bar/refs/heads/main
|
2015-09-01 10:13:11 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar refs/bisect/foo .git/refs/bisect/foo
|
$GIT_COMMON_DIR: a new environment variable
This variable is intended to support multiple working directories
attached to a repository. Such a repository may have a main working
directory, created by either "git init" or "git clone" and one or more
linked working directories. These working directories and the main
repository share the same repository directory.
In linked working directories, $GIT_COMMON_DIR must be defined to point
to the real repository directory and $GIT_DIR points to an unused
subdirectory inside $GIT_COMMON_DIR. File locations inside the
repository are reorganized from the linked worktree view point:
- worktree-specific such as HEAD, logs/HEAD, index, other top-level
refs and unrecognized files are from $GIT_DIR.
- the rest like objects, refs, info, hooks, packed-refs, shallow...
are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's
a separate patch)
Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse
--git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR"
business.
The redirection is done by git_path(), git_pathdup() and
strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR,
not the other way around in case a developer adds a new
worktree-specific file and it's accidentally promoted to be shared
across repositories (this includes unknown files added by third party
commands)
The list of known files that belong to $GIT_DIR are:
ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG
BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD
MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD
REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD
next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/*
shallow_*
Path mapping is NOT done for git_path_submodule(). Multi-checkouts are
not supported as submodules.
Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-30 16:24:36 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar hooks/me bar/hooks/me
|
|
|
|
test_git_path GIT_COMMON_DIR=bar config bar/config
|
|
|
|
test_git_path GIT_COMMON_DIR=bar packed-refs bar/packed-refs
|
|
|
|
test_git_path GIT_COMMON_DIR=bar shallow bar/shallow
|
2018-09-30 03:10:23 +08:00
|
|
|
test_git_path GIT_COMMON_DIR=bar common bar/common
|
|
|
|
test_git_path GIT_COMMON_DIR=bar common/file bar/common/file
|
2014-11-30 16:24:31 +08:00
|
|
|
|
2016-10-19 04:06:07 +08:00
|
|
|
# In the tests below, $(pwd) must be used because it is a native path on
|
|
|
|
# Windows and avoids MSYS's path mangling (which simplifies "foo/../bar" and
|
|
|
|
# strips the dot from trailing "/.").
|
2016-04-16 08:50:12 +08:00
|
|
|
|
|
|
|
test_submodule_relative_url "../" "../foo" "../submodule" "../../submodule"
|
|
|
|
test_submodule_relative_url "../" "../foo/bar" "../submodule" "../../foo/submodule"
|
|
|
|
test_submodule_relative_url "../" "../foo/submodule" "../submodule" "../../foo/submodule"
|
|
|
|
test_submodule_relative_url "../" "./foo" "../submodule" "../submodule"
|
|
|
|
test_submodule_relative_url "../" "./foo/bar" "../submodule" "../foo/submodule"
|
|
|
|
test_submodule_relative_url "../../../" "../foo/bar" "../sub/a/b/c" "../../../../foo/sub/a/b/c"
|
2016-10-19 04:06:07 +08:00
|
|
|
test_submodule_relative_url "../" "$(pwd)/addtest" "../repo" "$(pwd)/repo"
|
2016-04-16 08:50:12 +08:00
|
|
|
test_submodule_relative_url "../" "foo/bar" "../submodule" "../foo/submodule"
|
|
|
|
test_submodule_relative_url "../" "foo" "../submodule" "../submodule"
|
|
|
|
|
|
|
|
test_submodule_relative_url "(null)" "../foo/bar" "../sub/a/b/c" "../foo/sub/a/b/c"
|
2016-10-11 01:56:11 +08:00
|
|
|
test_submodule_relative_url "(null)" "../foo/bar" "../sub/a/b/c/" "../foo/sub/a/b/c"
|
2016-10-11 01:56:10 +08:00
|
|
|
test_submodule_relative_url "(null)" "../foo/bar/" "../sub/a/b/c" "../foo/sub/a/b/c"
|
2016-04-16 08:50:12 +08:00
|
|
|
test_submodule_relative_url "(null)" "../foo/bar" "../submodule" "../foo/submodule"
|
|
|
|
test_submodule_relative_url "(null)" "../foo/submodule" "../submodule" "../foo/submodule"
|
|
|
|
test_submodule_relative_url "(null)" "../foo" "../submodule" "../submodule"
|
|
|
|
test_submodule_relative_url "(null)" "./foo/bar" "../submodule" "foo/submodule"
|
|
|
|
test_submodule_relative_url "(null)" "./foo" "../submodule" "submodule"
|
|
|
|
test_submodule_relative_url "(null)" "//somewhere else/repo" "../subrepo" "//somewhere else/subrepo"
|
2018-08-15 02:59:06 +08:00
|
|
|
test_submodule_relative_url "(null)" "//somewhere else/repo" "../../subrepo" "//subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "//somewhere else/repo" "../../../subrepo" "/subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "//somewhere else/repo" "../../../../subrepo" "subrepo"
|
2016-10-19 04:06:07 +08:00
|
|
|
test_submodule_relative_url "(null)" "$(pwd)/subsuper_update_r" "../subsubsuper_update_r" "$(pwd)/subsubsuper_update_r"
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)/super_update_r2" "../subsuper_update_r" "$(pwd)/subsuper_update_r"
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)/." "../." "$(pwd)/."
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)" "./." "$(pwd)/."
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)/addtest" "../repo" "$(pwd)/repo"
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)" "./å äö" "$(pwd)/å äö"
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)/." "../submodule" "$(pwd)/submodule"
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)/submodule" "../submodule" "$(pwd)/submodule"
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)/home2/../remote" "../bundle1" "$(pwd)/home2/../bundle1"
|
|
|
|
test_submodule_relative_url "(null)" "$(pwd)/submodule_update_repo" "./." "$(pwd)/submodule_update_repo/."
|
2016-04-16 08:50:12 +08:00
|
|
|
test_submodule_relative_url "(null)" "file:///tmp/repo" "../subrepo" "file:///tmp/subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "foo/bar" "../submodule" "foo/submodule"
|
|
|
|
test_submodule_relative_url "(null)" "foo" "../submodule" "submodule"
|
|
|
|
test_submodule_relative_url "(null)" "helper:://hostname/repo" "../subrepo" "helper:://hostname/subrepo"
|
2018-08-15 02:59:06 +08:00
|
|
|
test_submodule_relative_url "(null)" "helper:://hostname/repo" "../../subrepo" "helper:://subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "helper:://hostname/repo" "../../../subrepo" "helper::/subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "helper:://hostname/repo" "../../../../subrepo" "helper::subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "helper:://hostname/repo" "../../../../../subrepo" "helper:subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "helper:://hostname/repo" "../../../../../../subrepo" ".:subrepo"
|
2016-04-16 08:50:12 +08:00
|
|
|
test_submodule_relative_url "(null)" "ssh://hostname/repo" "../subrepo" "ssh://hostname/subrepo"
|
2018-08-15 02:59:06 +08:00
|
|
|
test_submodule_relative_url "(null)" "ssh://hostname/repo" "../../subrepo" "ssh://subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "ssh://hostname/repo" "../../../subrepo" "ssh:/subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "ssh://hostname/repo" "../../../../subrepo" "ssh:subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "ssh://hostname/repo" "../../../../../subrepo" ".:subrepo"
|
2016-04-16 08:50:12 +08:00
|
|
|
test_submodule_relative_url "(null)" "ssh://hostname:22/repo" "../subrepo" "ssh://hostname:22/subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "user@host:path/to/repo" "../subrepo" "user@host:path/to/subrepo"
|
|
|
|
test_submodule_relative_url "(null)" "user@host:repo" "../subrepo" "user@host:subrepo"
|
2018-08-15 02:59:06 +08:00
|
|
|
test_submodule_relative_url "(null)" "user@host:repo" "../../subrepo" ".:subrepo"
|
2016-04-16 08:50:12 +08:00
|
|
|
|
2018-05-13 04:16:51 +08:00
|
|
|
test_expect_success 'match .gitmodules' '
|
2018-05-29 16:09:58 +08:00
|
|
|
test-tool path-utils is_dotgitmodules \
|
2018-05-13 04:16:51 +08:00
|
|
|
.gitmodules \
|
|
|
|
\
|
|
|
|
.git${u200c}modules \
|
|
|
|
\
|
|
|
|
.Gitmodules \
|
|
|
|
.gitmoduleS \
|
|
|
|
\
|
|
|
|
".gitmodules " \
|
|
|
|
".gitmodules." \
|
|
|
|
".gitmodules " \
|
|
|
|
".gitmodules. " \
|
|
|
|
".gitmodules ." \
|
|
|
|
".gitmodules.." \
|
|
|
|
".gitmodules " \
|
|
|
|
".gitmodules. " \
|
|
|
|
".gitmodules . " \
|
|
|
|
".gitmodules ." \
|
|
|
|
\
|
|
|
|
".Gitmodules " \
|
|
|
|
".Gitmodules." \
|
|
|
|
".Gitmodules " \
|
|
|
|
".Gitmodules. " \
|
|
|
|
".Gitmodules ." \
|
|
|
|
".Gitmodules.." \
|
|
|
|
".Gitmodules " \
|
|
|
|
".Gitmodules. " \
|
|
|
|
".Gitmodules . " \
|
|
|
|
".Gitmodules ." \
|
|
|
|
\
|
|
|
|
GITMOD~1 \
|
|
|
|
gitmod~1 \
|
|
|
|
GITMOD~2 \
|
|
|
|
gitmod~3 \
|
|
|
|
GITMOD~4 \
|
|
|
|
\
|
|
|
|
"GITMOD~1 " \
|
|
|
|
"gitmod~2." \
|
|
|
|
"GITMOD~3 " \
|
|
|
|
"gitmod~4. " \
|
|
|
|
"GITMOD~1 ." \
|
|
|
|
"gitmod~2 " \
|
|
|
|
"GITMOD~3. " \
|
|
|
|
"gitmod~4 . " \
|
|
|
|
\
|
|
|
|
GI7EBA~1 \
|
|
|
|
gi7eba~9 \
|
|
|
|
\
|
|
|
|
GI7EB~10 \
|
|
|
|
GI7EB~11 \
|
|
|
|
GI7EB~99 \
|
|
|
|
GI7EB~10 \
|
|
|
|
GI7E~100 \
|
|
|
|
GI7E~101 \
|
|
|
|
GI7E~999 \
|
|
|
|
~1000000 \
|
|
|
|
~9999999 \
|
|
|
|
\
|
2019-08-28 18:22:17 +08:00
|
|
|
.gitmodules:\$DATA \
|
|
|
|
"gitmod~4 . :\$DATA" \
|
|
|
|
\
|
2018-05-13 04:16:51 +08:00
|
|
|
--not \
|
|
|
|
".gitmodules x" \
|
|
|
|
".gitmodules .x" \
|
|
|
|
\
|
|
|
|
" .gitmodules" \
|
|
|
|
\
|
|
|
|
..gitmodules \
|
|
|
|
\
|
|
|
|
gitmodules \
|
|
|
|
\
|
|
|
|
.gitmodule \
|
|
|
|
\
|
|
|
|
".gitmodules x " \
|
|
|
|
".gitmodules .x" \
|
|
|
|
\
|
|
|
|
GI7EBA~ \
|
|
|
|
GI7EBA~0 \
|
|
|
|
GI7EBA~~1 \
|
|
|
|
GI7EBA~X \
|
|
|
|
Gx7EBA~1 \
|
|
|
|
GI7EBX~1 \
|
|
|
|
\
|
|
|
|
GI7EB~1 \
|
|
|
|
GI7EB~01 \
|
2019-08-28 18:22:17 +08:00
|
|
|
GI7EB~1X \
|
|
|
|
\
|
|
|
|
.gitmodules,:\$DATA
|
2018-05-13 04:16:51 +08:00
|
|
|
'
|
|
|
|
|
t0060: test ntfs/hfs-obscured dotfiles
We have tests that cover various filesystem-specific spellings of
".gitmodules", because we need to reliably identify that path for some
security checks. These are from dc2d9ba318 (is_{hfs,ntfs}_dotgitmodules:
add tests, 2018-05-12), with the actual code coming from e7cb0b4455
(is_ntfs_dotgit: match other .git files, 2018-05-11) and 0fc333ba20
(is_hfs_dotgit: match other .git files, 2018-05-02).
Those latter two commits also added similar matching functions for
.gitattributes and .gitignore. These ended up not being used in the
final series, and are currently dead code. But in preparation for them
being used in some fsck checks, let's make sure they actually work by
throwing a few basic tests at them. Likewise, let's cover .mailmap
(which does need matching code added).
I didn't bother with the whole battery of tests that we cover for
.gitmodules. These functions are all based on the same generic matcher,
so it's sufficient to test most of the corner cases just once.
Note that the ntfs magic prefix names in the tests come from the
algorithm described in e7cb0b4455 (and are different for each file).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-05-04 04:43:22 +08:00
|
|
|
test_expect_success 'match .gitattributes' '
|
|
|
|
test-tool path-utils is_dotgitattributes \
|
|
|
|
.gitattributes \
|
|
|
|
.git${u200c}attributes \
|
|
|
|
.Gitattributes \
|
|
|
|
.gitattributeS \
|
|
|
|
GITATT~1 \
|
|
|
|
GI7D29~1
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'match .gitignore' '
|
|
|
|
test-tool path-utils is_dotgitignore \
|
|
|
|
.gitignore \
|
|
|
|
.git${u200c}ignore \
|
|
|
|
.Gitignore \
|
|
|
|
.gitignorE \
|
|
|
|
GITIGN~1 \
|
|
|
|
GI250A~1
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'match .mailmap' '
|
|
|
|
test-tool path-utils is_dotmailmap \
|
|
|
|
.mailmap \
|
|
|
|
.mail${u200c}map \
|
|
|
|
.Mailmap \
|
|
|
|
.mailmaP \
|
|
|
|
MAILMA~1 \
|
|
|
|
MABA30~1
|
|
|
|
'
|
|
|
|
|
mingw: refuse to access paths with trailing spaces or periods
When creating a directory on Windows whose path ends in a space or a
period (or chains thereof), the Win32 API "helpfully" trims those. For
example, `mkdir("abc ");` will return success, but actually create a
directory called `abc` instead.
This stems back to the DOS days, when all file names had exactly 8
characters plus exactly 3 characters for the file extension, and the
only way to have shorter names was by padding with spaces.
Sadly, this "helpful" behavior is a bit inconsistent: after a successful
`mkdir("abc ");`, a `mkdir("abc /def")` will actually _fail_ (because
the directory `abc ` does not actually exist).
Even if it would work, we now have a serious problem because a Git
repository could contain directories `abc` and `abc `, and on Windows,
they would be "merged" unintentionally.
As these paths are illegal on Windows, anyway, let's disallow any
accesses to such paths on that Operating System.
For practical reasons, this behavior is still guarded by the
config setting `core.protectNTFS`: it is possible (and at least two
regression tests make use of it) to create commits without involving the
worktree. In such a scenario, it is of course possible -- even on
Windows -- to create such file names.
Among other consequences, this patch disallows submodules' paths to end
in spaces on Windows (which would formerly have confused Git enough to
try to write into incorrect paths, anyway).
While this patch does not fix a vulnerability on its own, it prevents an
attack vector that was exploited in demonstrations of a number of
recently-fixed security bugs.
The regression test added to `t/t7417-submodule-path-url.sh` reflects
that attack vector.
Note that we have to adjust the test case "prevent git~1 squatting on
Windows" in `t/t7415-submodule-names.sh` because of a very subtle issue.
It tries to clone two submodules whose names differ only in a trailing
period character, and as a consequence their git directories differ in
the same way. Previously, when Git tried to clone the second submodule,
it thought that the git directory already existed (because on Windows,
when you create a directory with the name `b.` it actually creates `b`),
but with this patch, the first submodule's clone will fail because of
the illegal name of the git directory. Therefore, when cloning the
second submodule, Git will take a different code path: a fresh clone
(without an existing git directory). Both code paths fail to clone the
second submodule, both because the the corresponding worktree directory
exists and is not empty, but the error messages are worded differently.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-05 19:27:53 +08:00
|
|
|
test_expect_success MINGW 'is_valid_path() on Windows' '
|
2019-12-22 06:05:01 +08:00
|
|
|
test-tool path-utils is_valid_path \
|
mingw: refuse to access paths with trailing spaces or periods
When creating a directory on Windows whose path ends in a space or a
period (or chains thereof), the Win32 API "helpfully" trims those. For
example, `mkdir("abc ");` will return success, but actually create a
directory called `abc` instead.
This stems back to the DOS days, when all file names had exactly 8
characters plus exactly 3 characters for the file extension, and the
only way to have shorter names was by padding with spaces.
Sadly, this "helpful" behavior is a bit inconsistent: after a successful
`mkdir("abc ");`, a `mkdir("abc /def")` will actually _fail_ (because
the directory `abc ` does not actually exist).
Even if it would work, we now have a serious problem because a Git
repository could contain directories `abc` and `abc `, and on Windows,
they would be "merged" unintentionally.
As these paths are illegal on Windows, anyway, let's disallow any
accesses to such paths on that Operating System.
For practical reasons, this behavior is still guarded by the
config setting `core.protectNTFS`: it is possible (and at least two
regression tests make use of it) to create commits without involving the
worktree. In such a scenario, it is of course possible -- even on
Windows -- to create such file names.
Among other consequences, this patch disallows submodules' paths to end
in spaces on Windows (which would formerly have confused Git enough to
try to write into incorrect paths, anyway).
While this patch does not fix a vulnerability on its own, it prevents an
attack vector that was exploited in demonstrations of a number of
recently-fixed security bugs.
The regression test added to `t/t7417-submodule-path-url.sh` reflects
that attack vector.
Note that we have to adjust the test case "prevent git~1 squatting on
Windows" in `t/t7415-submodule-names.sh` because of a very subtle issue.
It tries to clone two submodules whose names differ only in a trailing
period character, and as a consequence their git directories differ in
the same way. Previously, when Git tried to clone the second submodule,
it thought that the git directory already existed (because on Windows,
when you create a directory with the name `b.` it actually creates `b`),
but with this patch, the first submodule's clone will fail because of
the illegal name of the git directory. Therefore, when cloning the
second submodule, Git will take a different code path: a fresh clone
(without an existing git directory). Both code paths fail to clone the
second submodule, both because the the corresponding worktree directory
exists and is not empty, but the error messages are worded differently.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-05 19:27:53 +08:00
|
|
|
win32 \
|
|
|
|
"win32 x" \
|
|
|
|
../hello.txt \
|
mingw: refuse to access paths with illegal characters
Certain characters are not admissible in file names on Windows, even if
Cygwin/MSYS2 (and therefore, Git for Windows' Bash) pretend that they
are, e.g. `:`, `<`, `>`, etc
Let's disallow those characters explicitly in Windows builds of Git.
Note: just like trailing spaces or periods, it _is_ possible on Windows
to create commits adding files with such illegal characters, as long as
the operation leaves the worktree untouched. To allow for that, we
continue to guard `is_valid_win32_path()` behind the config setting
`core.protectNTFS`, so that users _can_ continue to do that, as long as
they turn the protections off via that config setting.
Among other problems, this prevents Git from trying to write to an "NTFS
Alternate Data Stream" (which refers to metadata stored alongside a
file, under a special name: "<filename>:<stream-name>"). This fix
therefore also prevents an attack vector that was exploited in
demonstrations of a number of recently-fixed security bugs.
Further reading on illegal characters in Win32 filenames:
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-05 19:44:21 +08:00
|
|
|
C:\\git \
|
2019-12-22 06:05:01 +08:00
|
|
|
comm \
|
|
|
|
conout.c \
|
mingw: do not treat `COM0` as a reserved file name
In 4dc42c6c186 (mingw: refuse paths containing reserved names,
2019-12-21), we started disallowing file names that are reserved, e.g.
`NUL`, `CONOUT$`, etc.
This included `COM<n>` where `<n>` is a digit. Unfortunately, this
includes `COM0` but only `COM1`, ..., `COM9` are reserved, according to
the official documentation, `COM0` is mentioned in the "NT Namespaces"
section but it is explicitly _omitted_ from the list of reserved names:
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
Tests corroborate this: it is totally possible to write a file called
`com0.c` on Windows 10, but not `com1.c`.
So let's tighten the code to disallow only the reserved `COM<n>` file
names, but to allow `COM0` again.
This fixes https://github.com/git-for-windows/git/issues/2470.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-09 02:06:49 +08:00
|
|
|
com0.c \
|
2019-12-22 06:05:01 +08:00
|
|
|
lptN \
|
mingw: refuse to access paths with trailing spaces or periods
When creating a directory on Windows whose path ends in a space or a
period (or chains thereof), the Win32 API "helpfully" trims those. For
example, `mkdir("abc ");` will return success, but actually create a
directory called `abc` instead.
This stems back to the DOS days, when all file names had exactly 8
characters plus exactly 3 characters for the file extension, and the
only way to have shorter names was by padding with spaces.
Sadly, this "helpful" behavior is a bit inconsistent: after a successful
`mkdir("abc ");`, a `mkdir("abc /def")` will actually _fail_ (because
the directory `abc ` does not actually exist).
Even if it would work, we now have a serious problem because a Git
repository could contain directories `abc` and `abc `, and on Windows,
they would be "merged" unintentionally.
As these paths are illegal on Windows, anyway, let's disallow any
accesses to such paths on that Operating System.
For practical reasons, this behavior is still guarded by the
config setting `core.protectNTFS`: it is possible (and at least two
regression tests make use of it) to create commits without involving the
worktree. In such a scenario, it is of course possible -- even on
Windows -- to create such file names.
Among other consequences, this patch disallows submodules' paths to end
in spaces on Windows (which would formerly have confused Git enough to
try to write into incorrect paths, anyway).
While this patch does not fix a vulnerability on its own, it prevents an
attack vector that was exploited in demonstrations of a number of
recently-fixed security bugs.
The regression test added to `t/t7417-submodule-path-url.sh` reflects
that attack vector.
Note that we have to adjust the test case "prevent git~1 squatting on
Windows" in `t/t7415-submodule-names.sh` because of a very subtle issue.
It tries to clone two submodules whose names differ only in a trailing
period character, and as a consequence their git directories differ in
the same way. Previously, when Git tried to clone the second submodule,
it thought that the git directory already existed (because on Windows,
when you create a directory with the name `b.` it actually creates `b`),
but with this patch, the first submodule's clone will fail because of
the illegal name of the git directory. Therefore, when cloning the
second submodule, Git will take a different code path: a fresh clone
(without an existing git directory). Both code paths fail to clone the
second submodule, both because the the corresponding worktree directory
exists and is not empty, but the error messages are worded differently.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-05 19:27:53 +08:00
|
|
|
\
|
|
|
|
--not \
|
|
|
|
"win32 " \
|
|
|
|
"win32 /x " \
|
|
|
|
"win32." \
|
|
|
|
"win32 . ." \
|
mingw: refuse to access paths with illegal characters
Certain characters are not admissible in file names on Windows, even if
Cygwin/MSYS2 (and therefore, Git for Windows' Bash) pretend that they
are, e.g. `:`, `<`, `>`, etc
Let's disallow those characters explicitly in Windows builds of Git.
Note: just like trailing spaces or periods, it _is_ possible on Windows
to create commits adding files with such illegal characters, as long as
the operation leaves the worktree untouched. To allow for that, we
continue to guard `is_valid_win32_path()` behind the config setting
`core.protectNTFS`, so that users _can_ continue to do that, as long as
they turn the protections off via that config setting.
Among other problems, this prevents Git from trying to write to an "NTFS
Alternate Data Stream" (which refers to metadata stored alongside a
file, under a special name: "<filename>:<stream-name>"). This fix
therefore also prevents an attack vector that was exploited in
demonstrations of a number of recently-fixed security bugs.
Further reading on illegal characters in Win32 filenames:
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-05 19:44:21 +08:00
|
|
|
.../hello.txt \
|
2019-12-22 06:05:01 +08:00
|
|
|
colon:test \
|
|
|
|
"AUX.c" \
|
|
|
|
"abc/conOut\$ .xyz/test" \
|
|
|
|
lpt8 \
|
mingw: do not treat `COM0` as a reserved file name
In 4dc42c6c186 (mingw: refuse paths containing reserved names,
2019-12-21), we started disallowing file names that are reserved, e.g.
`NUL`, `CONOUT$`, etc.
This included `COM<n>` where `<n>` is a digit. Unfortunately, this
includes `COM0` but only `COM1`, ..., `COM9` are reserved, according to
the official documentation, `COM0` is mentioned in the "NT Namespaces"
section but it is explicitly _omitted_ from the list of reserved names:
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
Tests corroborate this: it is totally possible to write a file called
`com0.c` on Windows 10, but not `com1.c`.
So let's tighten the code to disallow only the reserved `COM<n>` file
names, but to allow `COM0` again.
This fixes https://github.com/git-for-windows/git/issues/2470.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-09 02:06:49 +08:00
|
|
|
com9.c \
|
2019-12-22 06:05:01 +08:00
|
|
|
"lpt*" \
|
|
|
|
Nul \
|
|
|
|
"PRN./abc"
|
2018-05-13 04:16:51 +08:00
|
|
|
'
|
|
|
|
|
2021-07-25 06:06:49 +08:00
|
|
|
test_lazy_prereq RUNTIME_PREFIX '
|
|
|
|
test true = "$RUNTIME_PREFIX"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_lazy_prereq CAN_EXEC_IN_PWD '
|
|
|
|
cp "$GIT_EXEC_PATH"/git$X ./ &&
|
|
|
|
./git rev-parse
|
|
|
|
'
|
|
|
|
|
2022-05-13 06:32:15 +08:00
|
|
|
test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'RUNTIME_PREFIX works' '
|
2021-07-25 06:06:49 +08:00
|
|
|
mkdir -p pretend/bin pretend/libexec/git-core &&
|
|
|
|
echo "echo HERE" | write_script pretend/libexec/git-core/git-here &&
|
|
|
|
cp "$GIT_EXEC_PATH"/git$X pretend/bin/ &&
|
|
|
|
GIT_EXEC_PATH= ./pretend/bin/git here >actual &&
|
|
|
|
echo HERE >expect &&
|
interpolate_path(): allow specifying paths relative to the runtime prefix
Ever since Git learned to detect its install location at runtime, there
was the slightly awkward problem that it was impossible to specify paths
relative to said location.
For example, if a version of Git was shipped with custom SSL
certificates to use, there was no portable way to specify
`http.sslCAInfo`.
In Git for Windows, the problem was "solved" for years by interpreting
paths starting with a slash as relative to the runtime prefix.
However, this is not correct: such paths _are_ legal on Windows, and
they are interpreted as absolute paths in the same drive as the current
directory.
After a lengthy discussion, and an even lengthier time to mull over the
problem and its best solution, and then more discussions, we eventually
decided to introduce support for the magic sequence `%(prefix)/`. If a
path starts with this, the remainder is interpreted as relative to the
detected (runtime) prefix. If built without runtime prefix support, Git
will simply interpolate the compiled-in prefix.
If a user _wants_ to specify a path starting with the magic sequence,
they can prefix the magic sequence with `./` and voilà, the path won't
be expanded.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-25 06:06:53 +08:00
|
|
|
test_cmp expect actual'
|
|
|
|
|
2022-05-13 06:32:15 +08:00
|
|
|
test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works' '
|
interpolate_path(): allow specifying paths relative to the runtime prefix
Ever since Git learned to detect its install location at runtime, there
was the slightly awkward problem that it was impossible to specify paths
relative to said location.
For example, if a version of Git was shipped with custom SSL
certificates to use, there was no portable way to specify
`http.sslCAInfo`.
In Git for Windows, the problem was "solved" for years by interpreting
paths starting with a slash as relative to the runtime prefix.
However, this is not correct: such paths _are_ legal on Windows, and
they are interpreted as absolute paths in the same drive as the current
directory.
After a lengthy discussion, and an even lengthier time to mull over the
problem and its best solution, and then more discussions, we eventually
decided to introduce support for the magic sequence `%(prefix)/`. If a
path starts with this, the remainder is interpreted as relative to the
detected (runtime) prefix. If built without runtime prefix support, Git
will simply interpolate the compiled-in prefix.
If a user _wants_ to specify a path starting with the magic sequence,
they can prefix the magic sequence with `./` and voilà, the path won't
be expanded.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-25 06:06:53 +08:00
|
|
|
mkdir -p pretend/bin &&
|
|
|
|
cp "$GIT_EXEC_PATH"/git$X pretend/bin/ &&
|
|
|
|
git config yes.path "%(prefix)/yes" &&
|
|
|
|
GIT_EXEC_PATH= ./pretend/bin/git config --path yes.path >actual &&
|
|
|
|
echo "$(pwd)/pretend/yes" >expect &&
|
2021-07-25 06:06:49 +08:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2008-05-20 14:48:54 +08:00
|
|
|
test_done
|