mirror of
https://github.com/git/git
synced 2024-10-28 19:25:47 +00:00
Merge branch 'jk/symlinked-dotgitx-cleanup'
Various test and documentation updates about .gitsomething paths that are symlinks. * jk/symlinked-dotgitx-cleanup: docs: document symlink restrictions for dot-files fsck: warn about symlinked dotfiles we'll open with O_NOFOLLOW t0060: test ntfs/hfs-obscured dotfiles t7450: test .gitmodules symlink matching against obscured names t7450: test verify_path() handling of gitmodules t7415: rename to expand scope fsck_tree(): wrap some long lines fsck_tree(): fix shadowed variable t7415: remove out-dated comment about translation
This commit is contained in:
commit
416449eaba
13 changed files with 253 additions and 59 deletions
|
@ -1247,6 +1247,12 @@ to:
|
||||||
[attr]binary -diff -merge -text
|
[attr]binary -diff -merge -text
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
-----
|
||||||
|
|
||||||
|
Git does not follow symbolic links when accessing a `.gitattributes`
|
||||||
|
file in the working tree. This keeps behavior consistent when the file
|
||||||
|
is accessed from the index or a tree versus from the filesystem.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
|
@ -149,6 +149,10 @@ not tracked by Git remain untracked.
|
||||||
To stop tracking a file that is currently tracked, use
|
To stop tracking a file that is currently tracked, use
|
||||||
'git rm --cached'.
|
'git rm --cached'.
|
||||||
|
|
||||||
|
Git does not follow symbolic links when accessing a `.gitignore` file in
|
||||||
|
the working tree. This keeps behavior consistent when the file is
|
||||||
|
accessed from the index or a tree versus from the filesystem.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,13 @@ this would also match the 'Commit Name <commit@email.xx>' above:
|
||||||
Proper Name <proper@email.xx> CoMmIt NaMe <CoMmIt@EmAiL.xX>
|
Proper Name <proper@email.xx> CoMmIt NaMe <CoMmIt@EmAiL.xX>
|
||||||
--
|
--
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
-----
|
||||||
|
|
||||||
|
Git does not follow symbolic links when accessing a `.mailmap` file in
|
||||||
|
the working tree. This keeps behavior consistent when the file is
|
||||||
|
accessed from the index or a tree versus from the filesystem.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,14 @@ submodule.<name>.shallow::
|
||||||
shallow clone (with a history depth of 1) unless the user explicitly
|
shallow clone (with a history depth of 1) unless the user explicitly
|
||||||
asks for a non-shallow clone.
|
asks for a non-shallow clone.
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
-----
|
||||||
|
|
||||||
|
Git does not allow the `.gitmodules` file within a working tree to be a
|
||||||
|
symbolic link, and will refuse to check out such a tree entry. This
|
||||||
|
keeps behavior consistent when the file is accessed from the index or a
|
||||||
|
tree versus from the filesystem, and helps Git reliably enforce security
|
||||||
|
checks of the file contents.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
1
cache.h
1
cache.h
|
@ -1272,6 +1272,7 @@ int is_ntfs_dotgit(const char *name);
|
||||||
int is_ntfs_dotgitmodules(const char *name);
|
int is_ntfs_dotgitmodules(const char *name);
|
||||||
int is_ntfs_dotgitignore(const char *name);
|
int is_ntfs_dotgitignore(const char *name);
|
||||||
int is_ntfs_dotgitattributes(const char *name);
|
int is_ntfs_dotgitattributes(const char *name);
|
||||||
|
int is_ntfs_dotmailmap(const char *name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true iff "str" could be confused as a command-line option when
|
* Returns true iff "str" could be confused as a command-line option when
|
||||||
|
|
84
fsck.c
84
fsck.c
|
@ -558,7 +558,7 @@ static int verify_ordered(unsigned mode1, const char *name1,
|
||||||
return c1 < c2 ? 0 : TREE_UNORDERED;
|
return c1 < c2 ? 0 : TREE_UNORDERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsck_tree(const struct object_id *oid,
|
static int fsck_tree(const struct object_id *tree_oid,
|
||||||
const char *buffer, unsigned long size,
|
const char *buffer, unsigned long size,
|
||||||
struct fsck_options *options)
|
struct fsck_options *options)
|
||||||
{
|
{
|
||||||
|
@ -579,7 +579,9 @@ static int fsck_tree(const struct object_id *oid,
|
||||||
struct name_stack df_dup_candidates = { NULL };
|
struct name_stack df_dup_candidates = { NULL };
|
||||||
|
|
||||||
if (init_tree_desc_gently(&desc, buffer, size)) {
|
if (init_tree_desc_gently(&desc, buffer, size)) {
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_BAD_TREE,
|
||||||
|
"cannot be parsed as a tree");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,11 +591,11 @@ static int fsck_tree(const struct object_id *oid,
|
||||||
while (desc.size) {
|
while (desc.size) {
|
||||||
unsigned short mode;
|
unsigned short mode;
|
||||||
const char *name, *backslash;
|
const char *name, *backslash;
|
||||||
const struct object_id *oid;
|
const struct object_id *entry_oid;
|
||||||
|
|
||||||
oid = tree_entry_extract(&desc, &name, &mode);
|
entry_oid = tree_entry_extract(&desc, &name, &mode);
|
||||||
|
|
||||||
has_null_sha1 |= is_null_oid(oid);
|
has_null_sha1 |= is_null_oid(entry_oid);
|
||||||
has_full_path |= !!strchr(name, '/');
|
has_full_path |= !!strchr(name, '/');
|
||||||
has_empty_name |= !*name;
|
has_empty_name |= !*name;
|
||||||
has_dot |= !strcmp(name, ".");
|
has_dot |= !strcmp(name, ".");
|
||||||
|
@ -603,23 +605,43 @@ static int fsck_tree(const struct object_id *oid,
|
||||||
|
|
||||||
if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name)) {
|
if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name)) {
|
||||||
if (!S_ISLNK(mode))
|
if (!S_ISLNK(mode))
|
||||||
oidset_insert(&options->gitmodules_found, oid);
|
oidset_insert(&options->gitmodules_found,
|
||||||
|
entry_oid);
|
||||||
else
|
else
|
||||||
retval += report(options,
|
retval += report(options,
|
||||||
oid, OBJ_TREE,
|
tree_oid, OBJ_TREE,
|
||||||
FSCK_MSG_GITMODULES_SYMLINK,
|
FSCK_MSG_GITMODULES_SYMLINK,
|
||||||
".gitmodules is a symbolic link");
|
".gitmodules is a symbolic link");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (S_ISLNK(mode)) {
|
||||||
|
if (is_hfs_dotgitignore(name) ||
|
||||||
|
is_ntfs_dotgitignore(name))
|
||||||
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_GITIGNORE_SYMLINK,
|
||||||
|
".gitignore is a symlink");
|
||||||
|
if (is_hfs_dotgitattributes(name) ||
|
||||||
|
is_ntfs_dotgitattributes(name))
|
||||||
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_GITATTRIBUTES_SYMLINK,
|
||||||
|
".gitattributes is a symlink");
|
||||||
|
if (is_hfs_dotmailmap(name) ||
|
||||||
|
is_ntfs_dotmailmap(name))
|
||||||
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_MAILMAP_SYMLINK,
|
||||||
|
".mailmap is a symlink");
|
||||||
|
}
|
||||||
|
|
||||||
if ((backslash = strchr(name, '\\'))) {
|
if ((backslash = strchr(name, '\\'))) {
|
||||||
while (backslash) {
|
while (backslash) {
|
||||||
backslash++;
|
backslash++;
|
||||||
has_dotgit |= is_ntfs_dotgit(backslash);
|
has_dotgit |= is_ntfs_dotgit(backslash);
|
||||||
if (is_ntfs_dotgitmodules(backslash)) {
|
if (is_ntfs_dotgitmodules(backslash)) {
|
||||||
if (!S_ISLNK(mode))
|
if (!S_ISLNK(mode))
|
||||||
oidset_insert(&options->gitmodules_found, oid);
|
oidset_insert(&options->gitmodules_found,
|
||||||
|
entry_oid);
|
||||||
else
|
else
|
||||||
retval += report(options, oid, OBJ_TREE,
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
FSCK_MSG_GITMODULES_SYMLINK,
|
FSCK_MSG_GITMODULES_SYMLINK,
|
||||||
".gitmodules is a symbolic link");
|
".gitmodules is a symbolic link");
|
||||||
}
|
}
|
||||||
|
@ -628,7 +650,9 @@ static int fsck_tree(const struct object_id *oid,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_tree_entry_gently(&desc)) {
|
if (update_tree_entry_gently(&desc)) {
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_BAD_TREE,
|
||||||
|
"cannot be parsed as a tree");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,25 +700,45 @@ static int fsck_tree(const struct object_id *oid,
|
||||||
name_stack_clear(&df_dup_candidates);
|
name_stack_clear(&df_dup_candidates);
|
||||||
|
|
||||||
if (has_null_sha1)
|
if (has_null_sha1)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_NULL_SHA1, "contains entries pointing to null sha1");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_NULL_SHA1,
|
||||||
|
"contains entries pointing to null sha1");
|
||||||
if (has_full_path)
|
if (has_full_path)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_FULL_PATHNAME, "contains full pathnames");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_FULL_PATHNAME,
|
||||||
|
"contains full pathnames");
|
||||||
if (has_empty_name)
|
if (has_empty_name)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_EMPTY_NAME, "contains empty pathname");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_EMPTY_NAME,
|
||||||
|
"contains empty pathname");
|
||||||
if (has_dot)
|
if (has_dot)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_HAS_DOT, "contains '.'");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_HAS_DOT,
|
||||||
|
"contains '.'");
|
||||||
if (has_dotdot)
|
if (has_dotdot)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_HAS_DOTDOT, "contains '..'");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_HAS_DOTDOT,
|
||||||
|
"contains '..'");
|
||||||
if (has_dotgit)
|
if (has_dotgit)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_HAS_DOTGIT, "contains '.git'");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_HAS_DOTGIT,
|
||||||
|
"contains '.git'");
|
||||||
if (has_zero_pad)
|
if (has_zero_pad)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_ZERO_PADDED_FILEMODE, "contains zero-padded file modes");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_ZERO_PADDED_FILEMODE,
|
||||||
|
"contains zero-padded file modes");
|
||||||
if (has_bad_modes)
|
if (has_bad_modes)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_BAD_FILEMODE, "contains bad file modes");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_BAD_FILEMODE,
|
||||||
|
"contains bad file modes");
|
||||||
if (has_dup_entries)
|
if (has_dup_entries)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_DUPLICATE_ENTRIES, "contains duplicate file entries");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_DUPLICATE_ENTRIES,
|
||||||
|
"contains duplicate file entries");
|
||||||
if (not_properly_sorted)
|
if (not_properly_sorted)
|
||||||
retval += report(options, oid, OBJ_TREE, FSCK_MSG_TREE_NOT_SORTED, "not properly sorted");
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
|
FSCK_MSG_TREE_NOT_SORTED,
|
||||||
|
"not properly sorted");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
fsck.h
3
fsck.h
|
@ -67,6 +67,9 @@ enum fsck_msg_type {
|
||||||
FUNC(NUL_IN_COMMIT, WARN) \
|
FUNC(NUL_IN_COMMIT, WARN) \
|
||||||
/* infos (reported as warnings, but ignored by default) */ \
|
/* infos (reported as warnings, but ignored by default) */ \
|
||||||
FUNC(GITMODULES_PARSE, INFO) \
|
FUNC(GITMODULES_PARSE, INFO) \
|
||||||
|
FUNC(GITIGNORE_SYMLINK, INFO) \
|
||||||
|
FUNC(GITATTRIBUTES_SYMLINK, INFO) \
|
||||||
|
FUNC(MAILMAP_SYMLINK, INFO) \
|
||||||
FUNC(BAD_TAG_NAME, INFO) \
|
FUNC(BAD_TAG_NAME, INFO) \
|
||||||
FUNC(MISSING_TAGGER_ENTRY, INFO) \
|
FUNC(MISSING_TAGGER_ENTRY, INFO) \
|
||||||
/* ignored (elevated when requested) */ \
|
/* ignored (elevated when requested) */ \
|
||||||
|
|
5
path.c
5
path.c
|
@ -1493,6 +1493,11 @@ int is_ntfs_dotgitattributes(const char *name)
|
||||||
return is_ntfs_dot_str(name, "gitattributes", "gi7d29");
|
return is_ntfs_dot_str(name, "gitattributes", "gi7d29");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_ntfs_dotmailmap(const char *name)
|
||||||
|
{
|
||||||
|
return is_ntfs_dot_str(name, "mailmap", "maba30");
|
||||||
|
}
|
||||||
|
|
||||||
int looks_like_command_line_option(const char *str)
|
int looks_like_command_line_option(const char *str)
|
||||||
{
|
{
|
||||||
return str && str[0] == '-';
|
return str && str[0] == '-';
|
||||||
|
|
|
@ -172,9 +172,22 @@ static struct test_data dirname_data[] = {
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int is_dotgitmodules(const char *path)
|
static int check_dotfile(const char *x, const char **argv,
|
||||||
|
int (*is_hfs)(const char *),
|
||||||
|
int (*is_ntfs)(const char *))
|
||||||
{
|
{
|
||||||
return is_hfs_dotgitmodules(path) || is_ntfs_dotgitmodules(path);
|
int res = 0, expect = 1;
|
||||||
|
for (; *argv; argv++) {
|
||||||
|
if (!strcmp("--not", *argv))
|
||||||
|
expect = !expect;
|
||||||
|
else if (expect != (is_hfs(*argv) || is_ntfs(*argv)))
|
||||||
|
res = error("'%s' is %s.git%s", *argv,
|
||||||
|
expect ? "not " : "", x);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "ok: '%s' is %s.git%s\n",
|
||||||
|
*argv, expect ? "" : "not ", x);
|
||||||
|
}
|
||||||
|
return !!res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_by_st_size(const void *a, const void *b)
|
static int cmp_by_st_size(const void *a, const void *b)
|
||||||
|
@ -382,17 +395,24 @@ int cmd__path_utils(int argc, const char **argv)
|
||||||
return test_function(dirname_data, posix_dirname, argv[1]);
|
return test_function(dirname_data, posix_dirname, argv[1]);
|
||||||
|
|
||||||
if (argc > 2 && !strcmp(argv[1], "is_dotgitmodules")) {
|
if (argc > 2 && !strcmp(argv[1], "is_dotgitmodules")) {
|
||||||
int res = 0, expect = 1, i;
|
return check_dotfile("modules", argv + 2,
|
||||||
for (i = 2; i < argc; i++)
|
is_hfs_dotgitmodules,
|
||||||
if (!strcmp("--not", argv[i]))
|
is_ntfs_dotgitmodules);
|
||||||
expect = !expect;
|
}
|
||||||
else if (expect != is_dotgitmodules(argv[i]))
|
if (argc > 2 && !strcmp(argv[1], "is_dotgitignore")) {
|
||||||
res = error("'%s' is %s.gitmodules", argv[i],
|
return check_dotfile("ignore", argv + 2,
|
||||||
expect ? "not " : "");
|
is_hfs_dotgitignore,
|
||||||
else
|
is_ntfs_dotgitignore);
|
||||||
fprintf(stderr, "ok: '%s' is %s.gitmodules\n",
|
}
|
||||||
argv[i], expect ? "" : "not ");
|
if (argc > 2 && !strcmp(argv[1], "is_dotgitattributes")) {
|
||||||
return !!res;
|
return check_dotfile("attributes", argv + 2,
|
||||||
|
is_hfs_dotgitattributes,
|
||||||
|
is_ntfs_dotgitattributes);
|
||||||
|
}
|
||||||
|
if (argc > 2 && !strcmp(argv[1], "is_dotmailmap")) {
|
||||||
|
return check_dotfile("mailmap", argv + 2,
|
||||||
|
is_hfs_dotmailmap,
|
||||||
|
is_ntfs_dotmailmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 2 && !strcmp(argv[1], "file-size")) {
|
if (argc > 2 && !strcmp(argv[1], "file-size")) {
|
||||||
|
|
|
@ -468,6 +468,36 @@ test_expect_success 'match .gitmodules' '
|
||||||
.gitmodules,:\$DATA
|
.gitmodules,:\$DATA
|
||||||
'
|
'
|
||||||
|
|
||||||
|
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
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success MINGW 'is_valid_path() on Windows' '
|
test_expect_success MINGW 'is_valid_path() on Windows' '
|
||||||
test-tool path-utils is_valid_path \
|
test-tool path-utils is_valid_path \
|
||||||
win32 \
|
win32 \
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
test_description='check handling of .. in submodule names
|
test_description='check broken or malicious patterns in .git* files
|
||||||
|
|
||||||
Exercise the name-checking function on a variety of names, and then give a
|
Such as:
|
||||||
real-world setup that confirms we catch this in practice.
|
|
||||||
|
- presence of .. in submodule names;
|
||||||
|
Exercise the name-checking function on a variety of names, and then give a
|
||||||
|
real-world setup that confirms we catch this in practice.
|
||||||
|
|
||||||
|
- nested submodule names
|
||||||
|
|
||||||
|
- symlinked .gitmodules, etc
|
||||||
'
|
'
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
. "$TEST_DIRECTORY"/lib-pack.sh
|
. "$TEST_DIRECTORY"/lib-pack.sh
|
||||||
|
@ -132,31 +139,84 @@ test_expect_success 'index-pack --strict works for non-repo pack' '
|
||||||
grep gitmodulesName output
|
grep gitmodulesName output
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'fsck detects symlinked .gitmodules file' '
|
check_dotx_symlink () {
|
||||||
git init symlink &&
|
fsck_must_fail=test_must_fail
|
||||||
(
|
fsck_prefix=error
|
||||||
cd symlink &&
|
refuse_index=t
|
||||||
|
case "$1" in
|
||||||
|
--warning)
|
||||||
|
fsck_must_fail=
|
||||||
|
fsck_prefix=warning
|
||||||
|
refuse_index=
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Make the tree directly to avoid index restrictions.
|
name=$1
|
||||||
#
|
type=$2
|
||||||
# Because symlinks store the target as a blob, choose
|
path=$3
|
||||||
# a pathname that could be parsed as a .gitmodules file
|
dir=symlink-$name-$type
|
||||||
# to trick naive non-symlink-aware checking.
|
|
||||||
tricky="[foo]bar=true" &&
|
|
||||||
content=$(git hash-object -w ../.gitmodules) &&
|
|
||||||
target=$(printf "$tricky" | git hash-object -w --stdin) &&
|
|
||||||
{
|
|
||||||
printf "100644 blob $content\t$tricky\n" &&
|
|
||||||
printf "120000 blob $target\t.gitmodules\n"
|
|
||||||
} | git mktree &&
|
|
||||||
|
|
||||||
# Check not only that we fail, but that it is due to the
|
test_expect_success "set up repo with symlinked $name ($type)" '
|
||||||
# symlink detector; this grep string comes from the config
|
git init $dir &&
|
||||||
# variable name and will not be translated.
|
(
|
||||||
test_must_fail git fsck 2>output &&
|
cd $dir &&
|
||||||
test_i18ngrep gitmodulesSymlink output
|
|
||||||
)
|
# Make the tree directly to avoid index restrictions.
|
||||||
'
|
#
|
||||||
|
# Because symlinks store the target as a blob, choose
|
||||||
|
# a pathname that could be parsed as a .gitmodules file
|
||||||
|
# to trick naive non-symlink-aware checking.
|
||||||
|
tricky="[foo]bar=true" &&
|
||||||
|
content=$(git hash-object -w ../.gitmodules) &&
|
||||||
|
target=$(printf "$tricky" | git hash-object -w --stdin) &&
|
||||||
|
{
|
||||||
|
printf "100644 blob $content\t$tricky\n" &&
|
||||||
|
printf "120000 blob $target\t$path\n"
|
||||||
|
} >bad-tree
|
||||||
|
) &&
|
||||||
|
tree=$(git -C $dir mktree <$dir/bad-tree)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success "fsck detects symlinked $name ($type)" '
|
||||||
|
(
|
||||||
|
cd $dir &&
|
||||||
|
|
||||||
|
# Check not only that we fail, but that it is due to the
|
||||||
|
# symlink detector
|
||||||
|
$fsck_must_fail git fsck 2>output &&
|
||||||
|
grep "$fsck_prefix.*tree $tree: ${name}Symlink" output
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test -n "$refuse_index" &&
|
||||||
|
test_expect_success "refuse to load symlinked $name into index ($type)" '
|
||||||
|
test_must_fail \
|
||||||
|
git -C $dir \
|
||||||
|
-c core.protectntfs \
|
||||||
|
-c core.protecthfs \
|
||||||
|
read-tree $tree 2>err &&
|
||||||
|
grep "invalid path.*$name" err &&
|
||||||
|
git -C $dir ls-files -s >out &&
|
||||||
|
test_must_be_empty out
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
check_dotx_symlink gitmodules vanilla .gitmodules
|
||||||
|
check_dotx_symlink gitmodules ntfs ".gitmodules ."
|
||||||
|
check_dotx_symlink gitmodules hfs ".${u200c}gitmodules"
|
||||||
|
|
||||||
|
check_dotx_symlink --warning gitattributes vanilla .gitattributes
|
||||||
|
check_dotx_symlink --warning gitattributes ntfs ".gitattributes ."
|
||||||
|
check_dotx_symlink --warning gitattributes hfs ".${u200c}gitattributes"
|
||||||
|
|
||||||
|
check_dotx_symlink --warning gitignore vanilla .gitignore
|
||||||
|
check_dotx_symlink --warning gitignore ntfs ".gitignore ."
|
||||||
|
check_dotx_symlink --warning gitignore hfs ".${u200c}gitignore"
|
||||||
|
|
||||||
|
check_dotx_symlink --warning mailmap vanilla .mailmap
|
||||||
|
check_dotx_symlink --warning mailmap ntfs ".mailmap ."
|
||||||
|
check_dotx_symlink --warning mailmap hfs ".${u200c}mailmap"
|
||||||
|
|
||||||
test_expect_success 'fsck detects non-blob .gitmodules' '
|
test_expect_success 'fsck detects non-blob .gitmodules' '
|
||||||
git init non-blob &&
|
git init non-blob &&
|
5
utf8.c
5
utf8.c
|
@ -777,6 +777,11 @@ int is_hfs_dotgitattributes(const char *path)
|
||||||
return is_hfs_dot_str(path, "gitattributes");
|
return is_hfs_dot_str(path, "gitattributes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_hfs_dotmailmap(const char *path)
|
||||||
|
{
|
||||||
|
return is_hfs_dot_str(path, "mailmap");
|
||||||
|
}
|
||||||
|
|
||||||
const char utf8_bom[] = "\357\273\277";
|
const char utf8_bom[] = "\357\273\277";
|
||||||
|
|
||||||
int skip_utf8_bom(char **text, size_t len)
|
int skip_utf8_bom(char **text, size_t len)
|
||||||
|
|
1
utf8.h
1
utf8.h
|
@ -61,6 +61,7 @@ int is_hfs_dotgit(const char *path);
|
||||||
int is_hfs_dotgitmodules(const char *path);
|
int is_hfs_dotgitmodules(const char *path);
|
||||||
int is_hfs_dotgitignore(const char *path);
|
int is_hfs_dotgitignore(const char *path);
|
||||||
int is_hfs_dotgitattributes(const char *path);
|
int is_hfs_dotgitattributes(const char *path);
|
||||||
|
int is_hfs_dotmailmap(const char *path);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ALIGN_LEFT,
|
ALIGN_LEFT,
|
||||||
|
|
Loading…
Reference in a new issue