aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config.txt5
-rw-r--r--cache.h1
-rw-r--r--config.c5
-rw-r--r--config.mak.uname1
-rw-r--r--environment.c5
-rw-r--r--read-cache.c3
-rwxr-xr-xt/t1014-read-tree-confusing.sh24
-rw-r--r--t/test-lib.sh6
8 files changed, 45 insertions, 5 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index ab26963d6..0677bd8df 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -234,6 +234,11 @@ core.precomposeunicode::
When false, file names are handled fully transparent by Git,
which is backward compatible with older versions of Git.
+core.protectHFS::
+ If set to true, do not allow checkout of paths that would
+ be considered equivalent to `.git` on an HFS+ filesystem.
+ Defaults to `true` on Mac OS, and `false` elsewhere.
+
core.trustctime::
If false, the ctime differences between the index and the
working tree are ignored; useful when the inode change time
diff --git a/cache.h b/cache.h
index ce377e135..b600a0c3e 100644
--- a/cache.h
+++ b/cache.h
@@ -584,6 +584,7 @@ extern int fsync_object_files;
extern int core_preload_index;
extern int core_apply_sparse_checkout;
extern int precomposed_unicode;
+extern int protect_hfs;
/*
* The character that begins a commented line in user-editable file
diff --git a/config.c b/config.c
index e1d66a145..b519cedc0 100644
--- a/config.c
+++ b/config.c
@@ -881,6 +881,11 @@ static int git_default_core_config(const char *var, const char *value)
return 0;
}
+ if (!strcmp(var, "core.protecthfs")) {
+ protect_hfs = git_config_bool(var, value);
+ return 0;
+ }
+
/* Add other config variables here and to Documentation/config.txt. */
return 0;
}
diff --git a/config.mak.uname b/config.mak.uname
index 82d549e48..23af14883 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -97,6 +97,7 @@ ifeq ($(uname_S),Darwin)
HAVE_DEV_TTY = YesPlease
COMPAT_OBJS += compat/precompose_utf8.o
BASIC_CFLAGS += -DPRECOMPOSE_UNICODE
+ BASIC_CFLAGS += -DPROTECT_HFS_DEFAULT=1
endif
ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease
diff --git a/environment.c b/environment.c
index 0a15349cf..828b574a2 100644
--- a/environment.c
+++ b/environment.c
@@ -63,6 +63,11 @@ int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
struct startup_info *startup_info;
unsigned long pack_size_limit_cfg;
+#ifndef PROTECT_HFS_DEFAULT
+#define PROTECT_HFS_DEFAULT 0
+#endif
+int protect_hfs = PROTECT_HFS_DEFAULT;
+
/*
* The character that begins a commented line in user-editable file
* that is subject to stripspace.
diff --git a/read-cache.c b/read-cache.c
index 122be494f..7f48a08c1 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -14,6 +14,7 @@
#include "resolve-undo.h"
#include "strbuf.h"
#include "varint.h"
+#include "utf8.h"
static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
@@ -786,6 +787,8 @@ int verify_path(const char *path)
return 1;
if (is_dir_sep(c)) {
inside:
+ if (protect_hfs && is_hfs_dotgit(path))
+ return 0;
c = *path++;
if ((c == '.' && !verify_dotfile(path)) ||
is_dir_sep(c) || c == '\0')
diff --git a/t/t1014-read-tree-confusing.sh b/t/t1014-read-tree-confusing.sh
index eff8aedf7..ec310d593 100755
--- a/t/t1014-read-tree-confusing.sh
+++ b/t/t1014-read-tree-confusing.sh
@@ -11,23 +11,39 @@ test_expect_success 'create base tree' '
tree=$(git rev-parse HEAD^{tree})
'
-while read path; do
- test_expect_success "reject $path at end of path" '
+test_expect_success 'enable core.protectHFS for rejection tests' '
+ git config core.protectHFS true
+'
+
+while read path pretty; do
+ : ${pretty:=$path}
+ test_expect_success "reject $pretty at end of path" '
printf "100644 blob %s\t%s" "$blob" "$path" >tree &&
bogus=$(git mktree <tree) &&
test_must_fail git read-tree $bogus
'
- test_expect_success "reject $path as subtree" '
+ test_expect_success "reject $pretty as subtree" '
printf "040000 tree %s\t%s" "$tree" "$path" >tree &&
bogus=$(git mktree <tree) &&
test_must_fail git read-tree $bogus
'
-done <<-\EOF
+done <<-EOF
.
..
.git
.GIT
+${u200c}.Git {u200c}.Git
+.gI${u200c}T .gI{u200c}T
+.GiT${u200c} .GiT{u200c}
EOF
+test_expect_success 'utf-8 paths allowed with core.protectHFS off' '
+ test_when_finished "git read-tree HEAD" &&
+ test_config core.protectHFS false &&
+ printf "100644 blob %s\t%s" "$blob" ".gi${u200c}t" >tree &&
+ ok=$(git mktree <tree) &&
+ git read-tree $ok
+'
+
test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index b25249ec4..d4569f8df 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -154,7 +154,11 @@ _z40=0000000000000000000000000000000000000000
LF='
'
-export _x05 _x40 _z40 LF
+# UTF-8 ZERO WIDTH NON-JOINER, which HFS+ ignores
+# when case-folding filenames
+u200c=$(printf '\342\200\214')
+
+export _x05 _x40 _z40 LF u200c
# Each test should start with something like this, after copyright notices:
#