* [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'
@ 2026-06-06 14:34 Tian Yuchen
2026-06-06 14:34 ` [PATCH v1 0/1] environment: move protect_hfs and protect_ntfs Tian Yuchen
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Tian Yuchen @ 2026-06-06 14:34 UTC (permalink / raw)
To: git
Cc: christian, phillip.wood123, Tian Yuchen, Christian Couder,
Ayush Chandekar, Olamide Caleb Bello
Move the global 'protect_hfs' and 'protect_ntfs' configurations
into the repository-specific 'repo_config_values' struct.
This will help with the elimination of 'the_repository'
For now, associated functions access this configuration by
explicitly falling back to 'the_repository', which needs to
be addressed in the future.
Note: In 't/helper/test-path-utils.c', there is a function
'protect_ntfs_hfs_benchmark()' where these two global
variables are used as loop iterators. New local variables
have been created to replace them.
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com>
Mentored-by: Olamide Caleb Bello <belkid98@gmail.com>
Signed-off-by: Tian Yuchen <cat@malon.dev>
---
compat/mingw.c | 2 +-
environment.c | 8 ++++----
environment.h | 4 ++--
read-cache.c | 7 ++++---
t/helper/test-path-utils.c | 26 ++++++++++++++++----------
5 files changed, 27 insertions(+), 20 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw.c
index aa7525f419..c77696ba8a 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -3392,7 +3392,7 @@ int is_valid_win32_path(const char *path, int allow_literal_nul)
const char *p = path;
int preceding_space_or_period = 0, i = 0, periods = 0;
- if (!protect_ntfs)
+ if (!(the_repository->gitdir ? repo_config_values(the_repository)->protect_ntfs : 1))
return 1;
skip_dos_drive_prefix((char **)&path);
diff --git a/environment.c b/environment.c
index fc3ed8bb1c..0730bfcbba 100644
--- a/environment.c
+++ b/environment.c
@@ -82,12 +82,10 @@ unsigned long pack_size_limit_cfg;
#ifndef PROTECT_HFS_DEFAULT
#define PROTECT_HFS_DEFAULT 0
#endif
-int protect_hfs = PROTECT_HFS_DEFAULT;
#ifndef PROTECT_NTFS_DEFAULT
#define PROTECT_NTFS_DEFAULT 1
#endif
-int protect_ntfs = PROTECT_NTFS_DEFAULT;
/*
* The character that begins a commented line in user-editable file
@@ -541,12 +539,12 @@ int git_default_core_config(const char *var, const char *value,
}
if (!strcmp(var, "core.protecthfs")) {
- protect_hfs = git_config_bool(var, value);
+ cfg->protect_hfs = git_config_bool(var, value);
return 0;
}
if (!strcmp(var, "core.protectntfs")) {
- protect_ntfs = git_config_bool(var, value);
+ cfg->protect_ntfs = git_config_bool(var, value);
return 0;
}
@@ -720,5 +718,7 @@ void repo_config_values_init(struct repo_config_values *cfg)
{
cfg->attributes_file = NULL;
cfg->apply_sparse_checkout = 0;
+ cfg->protect_hfs = PROTECT_HFS_DEFAULT;
+ cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
cfg->branch_track = BRANCH_TRACK_REMOTE;
}
diff --git a/environment.h b/environment.h
index 9eb97b3869..d48fd2719c 100644
--- a/environment.h
+++ b/environment.h
@@ -91,6 +91,8 @@ struct repo_config_values {
/* section "core" config values */
char *attributes_file;
int apply_sparse_checkout;
+ int protect_hfs;
+ int protect_ntfs;
/* section "branch" config values */
enum branch_track branch_track;
@@ -173,8 +175,6 @@ extern int pack_compression_level;
extern unsigned long pack_size_limit_cfg;
extern int precomposed_unicode;
-extern int protect_hfs;
-extern int protect_ntfs;
extern int core_sparse_checkout_cone;
extern int sparse_expect_files_outside_of_patterns;
diff --git a/read-cache.c b/read-cache.c
index 21829102ae..b64a5629ef 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1002,7 +1002,7 @@ static enum verify_path_result verify_path_internal(const char *path,
return PATH_OK;
if (is_dir_sep(c)) {
inside:
- if (protect_hfs) {
+ if ((the_repository->gitdir ? repo_config_values(the_repository)->protect_hfs : 0)) {
if (is_hfs_dotgit(path))
return PATH_INVALID;
@@ -1011,7 +1011,7 @@ static enum verify_path_result verify_path_internal(const char *path,
return PATH_INVALID;
}
}
- if (protect_ntfs) {
+ if ((the_repository->gitdir ? repo_config_values(the_repository)->protect_ntfs : 1)) {
#if defined GIT_WINDOWS_NATIVE || defined __CYGWIN__
if (c == '\\')
return PATH_INVALID;
@@ -1035,7 +1035,8 @@ static enum verify_path_result verify_path_internal(const char *path,
if (c == '\0')
return S_ISDIR(mode) ? PATH_DIR_WITH_SEP :
PATH_INVALID;
- } else if (c == '\\' && protect_ntfs) {
+ } else if (c == '\\' &&
+ (the_repository->gitdir ? repo_config_values(the_repository)->protect_ntfs : 1)) {
if (is_ntfs_dotgit(path))
return PATH_INVALID;
if (S_ISLNK(mode)) {
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index 15eb44485c..4455a68903 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -250,6 +250,7 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
double m[3][2], v[3][2];
uint64_t cumul;
double cumul2;
+ int ntfs, hfs;
if (argc > 1 && !strcmp(argv[1], "--with-symlink-mode")) {
file_mode = 0120000;
@@ -275,9 +276,14 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
while (len > 0)
names[i][--len] = (char)(' ' + (my_random() % ('\x7f' - ' ')));
}
-
- for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
- for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) {
+
+ if (!the_repository->gitdir)
+ the_repository->gitdir = xstrdup(".git");
+
+ for (ntfs = 0; ntfs < 2; ntfs++)
+ for (hfs = 0; hfs < 2; hfs++) {
+ repo_config_values(the_repository)->protect_ntfs = ntfs;
+ repo_config_values(the_repository)->protect_hfs = hfs;
cumul = 0;
cumul2 = 0;
for (i = 0; i < repetitions; i++) {
@@ -285,18 +291,18 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
for (j = 0; j < nr; j++)
verify_path(names[j], file_mode);
end = getnanotime();
- printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", protect_ntfs, protect_hfs, (end-begin) / (double)1e6);
+ printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", ntfs, hfs, (end-begin) / (double)1e6);
cumul += end - begin;
cumul2 += (end - begin) * (end - begin);
}
- m[protect_ntfs][protect_hfs] = cumul / (double)repetitions;
- v[protect_ntfs][protect_hfs] = my_sqrt(cumul2 / (double)repetitions - m[protect_ntfs][protect_hfs] * m[protect_ntfs][protect_hfs]);
- printf("mean: %lfms, stddev: %lfms\n", m[protect_ntfs][protect_hfs] / (double)1e6, v[protect_ntfs][protect_hfs] / (double)1e6);
+ m[ntfs][hfs] = cumul / (double)repetitions;
+ v[ntfs][hfs] = my_sqrt(cumul2 / (double)repetitions - m[ntfs][hfs] * m[ntfs][hfs]);
+ printf("mean: %lfms, stddev: %lfms\n", m[ntfs][hfs] / (double)1e6, v[ntfs][hfs] / (double)1e6);
}
- for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
- for (protect_hfs = 0; protect_hfs < 2; protect_hfs++)
- printf("ntfs=%d/hfs=%d: %lf%% slower\n", protect_ntfs, protect_hfs, (m[protect_ntfs][protect_hfs] - m[0][0]) * 100 / m[0][0]);
+ for (ntfs = 0; ntfs < 2; ntfs++)
+ for (hfs = 0; hfs < 2; hfs++)
+ printf("ntfs=%d/hfs=%d: %lf%% slower\n", ntfs, hfs, (m[ntfs][hfs] - m[0][0]) * 100 / m[0][0]);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v1 0/1] environment: move protect_hfs and protect_ntfs
2026-06-06 14:34 [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Tian Yuchen
@ 2026-06-06 14:34 ` Tian Yuchen
2026-06-09 10:54 ` Christian Couder
2026-06-09 10:20 ` [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Christian Couder
2026-06-10 12:43 ` [PATCH v2 0/1] environment: move protect_hfs and protect_ntfs into repo_config_values Tian Yuchen
2 siblings, 1 reply; 7+ messages in thread
From: Tian Yuchen @ 2026-06-06 14:34 UTC (permalink / raw)
To: git
Cc: christian, phillip.wood123, Tian Yuchen, Christian Couder,
Ayush Chandekar, Olamide Caleb Bello
Hi everyone,
This series continues the ongoing libification effort by moving the
global **filesystem** variables, protect_hfs and protect_ntfs, into
struct repo_config_values.
Place them within the **per-repository** configuration structure
aligns with our goal of removing global states.
RFC Questions:
1. Should we keep PROTECT_HFS_DEFAULT and PROTECT_NTFS_DEFAULT
in repo_config_values_init()?
void repo_config_values_init(struct repo_config_values *cfg)
{
cfg->attributes_file = NULL;
cfg->apply_sparse_checkout = 0;
cfg->protect_hfs = PROTECT_HFS_DEFAULT;
cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
cfg->branch_track = BRANCH_TRACK_REMOTE;
}
Or is it better if they are used anywhere other than in environment.c?
If so...
2. Is it worth introducing a Macro or Getter for safe access?
((the_repository->gitdir ? repo_config_values(the_repository)->protect_hfs : 0))
The current approach looks verbose and lacks readability, and
hard-coded 0 and 1 are used as fallback values. I wonder if a macro or a
getter could be introduced, for example...
#define SAFE_PROTECT_HFS(repo) \
(((repo) && (repo)->gitdir && (repo) == the_repository) ? \
repo_config_values(repo)->protect_hfs : PROTECT_HFS_DEFAULT)
...to improve the coding style a bit. Although I am aware that introducing
new macros is generally frowned upon, I would still like to know which
parts this might make difficult to maintain.
3. Note that Derrick attempted to use get_int_config_global to wrap
this kind of Filesystem Level global variables. This approach bypassed
struct repository, did not actually eliminate global state, and the
reviewer politely rejected it. Nevertheless, I am still curious as
to whether this approach might still be inspiring today.
https://lore.kernel.org/git/a42dd9397d07b2dc4a0d7e75bfe1af2e46cad262.1685716420.git.gitgitgadget@gmail.com/
Thanks!
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com>
Mentored-by: Olamide Caleb Bello <belkid98@gmail.com>
Signed-off-by: Tian Yuchen <cat@malon.dev>
Tian Yuchen (1):
environment.c: move 'protect_hfs' and 'protect_ntfs' into
'repo_config_values'
compat/mingw.c | 2 +-
environment.c | 8 ++++----
environment.h | 4 ++--
read-cache.c | 7 ++++---
t/helper/test-path-utils.c | 26 ++++++++++++++++----------
5 files changed, 27 insertions(+), 20 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'
2026-06-06 14:34 [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Tian Yuchen
2026-06-06 14:34 ` [PATCH v1 0/1] environment: move protect_hfs and protect_ntfs Tian Yuchen
@ 2026-06-09 10:20 ` Christian Couder
2026-06-10 12:43 ` [PATCH v2 0/1] environment: move protect_hfs and protect_ntfs into repo_config_values Tian Yuchen
2 siblings, 0 replies; 7+ messages in thread
From: Christian Couder @ 2026-06-09 10:20 UTC (permalink / raw)
To: Tian Yuchen
Cc: git, christian, phillip.wood123, Ayush Chandekar,
Olamide Caleb Bello
"environment.c:" in the subject could be replaced by just
"environment:". It's a bit shorter and it better describes the area of
the code where the main changes are made, as changes are not just made
in "environment.c" but also in "environment.h".
On Sat, Jun 6, 2026 at 4:34 PM Tian Yuchen <cat@malon.dev> wrote:
>
> Move the global 'protect_hfs' and 'protect_ntfs' configurations
> into the repository-specific 'repo_config_values' struct.
> This will help with the elimination of 'the_repository'
>
> For now, associated functions access this configuration by
> explicitly falling back to 'the_repository', which needs to
> be addressed in the future.
>
> Note: In 't/helper/test-path-utils.c', there is a function
> 'protect_ntfs_hfs_benchmark()' where these two global
> variables are used as loop iterators. New local variables
> have been created to replace them.
> diff --git a/compat/mingw.c b/compat/mingw.c
> index aa7525f419..c77696ba8a 100644
> --- a/compat/mingw.c
> +++ b/compat/mingw.c
> @@ -3392,7 +3392,7 @@ int is_valid_win32_path(const char *path, int allow_literal_nul)
> const char *p = path;
> int preceding_space_or_period = 0, i = 0, periods = 0;
>
> - if (!protect_ntfs)
> + if (!(the_repository->gitdir ? repo_config_values(the_repository)->protect_ntfs : 1))
> return 1;
I think the code would benefit from functions like:
int repo_protect_ntfs(struct repository *repo)
{
return repo->gitdir ?
repo_config_values(repo)->protect_ntfs :
PROTECT_NTFS_DEFAULT;
}
int repo_protect_hfs(struct repository *repo)
{
return repo->gitdir ?
repo_config_values(repo)->protect_hfs :
PROTECT_HFS_DEFAULT;
}
They could be called by passing `the_repository` for now, but perhaps
later in future commits `istate->repo` or something like that could be
passed instead. Also a code comment could explain that the `gitdir`
check prevents calling `repo_config_values()` before config is loaded.
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 0/1] environment: move protect_hfs and protect_ntfs
2026-06-06 14:34 ` [PATCH v1 0/1] environment: move protect_hfs and protect_ntfs Tian Yuchen
@ 2026-06-09 10:54 ` Christian Couder
0 siblings, 0 replies; 7+ messages in thread
From: Christian Couder @ 2026-06-09 10:54 UTC (permalink / raw)
To: Tian Yuchen
Cc: git, christian, phillip.wood123, Ayush Chandekar,
Olamide Caleb Bello
On Sat, Jun 6, 2026 at 4:35 PM Tian Yuchen <cat@malon.dev> wrote:
>
> Hi everyone,
>
> This series continues the ongoing libification effort by moving the
> global **filesystem** variables, protect_hfs and protect_ntfs, into
> struct repo_config_values.
>
> Place them within the **per-repository** configuration structure
> aligns with our goal of removing global states.
>
> RFC Questions:
>
> 1. Should we keep PROTECT_HFS_DEFAULT and PROTECT_NTFS_DEFAULT
> in repo_config_values_init()?
>
> void repo_config_values_init(struct repo_config_values *cfg)
> {
> cfg->attributes_file = NULL;
> cfg->apply_sparse_checkout = 0;
> cfg->protect_hfs = PROTECT_HFS_DEFAULT;
> cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
> cfg->branch_track = BRANCH_TRACK_REMOTE;
> }
>
> Or is it better if they are used anywhere other than in environment.c?
I think it's better to keep them in "environment.c". The
repo_protect_ntfs() and repo_protect_hfs() function I suggest adding
to "environment.c" in my reply to the patch should help with keeping
the macros in "environment.c".
> If so...
> 2. Is it worth introducing a Macro or Getter for safe access?
>
> ((the_repository->gitdir ? repo_config_values(the_repository)->protect_hfs : 0))
Yes, it seems to me that a getter is enough.
> The current approach looks verbose and lacks readability, and
> hard-coded 0 and 1 are used as fallback values. I wonder if a macro or a
> getter could be introduced, for example...
>
> #define SAFE_PROTECT_HFS(repo) \
> (((repo) && (repo)->gitdir && (repo) == the_repository) ? \
> repo_config_values(repo)->protect_hfs : PROTECT_HFS_DEFAULT)
>
> ...to improve the coding style a bit. Although I am aware that introducing
> new macros is generally frowned upon, I would still like to know which
> parts this might make difficult to maintain.
Unless there are features that we really want which a function can't
provide, a function is better as it provides type safety and is
usually easier to maintain.
> 3. Note that Derrick attempted to use get_int_config_global to wrap
> this kind of Filesystem Level global variables. This approach bypassed
> struct repository, did not actually eliminate global state, and the
> reviewer politely rejected it. Nevertheless, I am still curious as
> to whether this approach might still be inspiring today.
>
> https://lore.kernel.org/git/a42dd9397d07b2dc4a0d7e75bfe1af2e46cad262.1685716420.git.gitgitgadget@gmail.com/
To help your reviewers, it might be interesting if you could already
tell why this was rejected by Glen Choo (who reviewed Derrick Stolee's
work then). It seems to me that Glen said that using plain fields in a
struct should be better as long as the fields are always initialized
during the setup process.
And it seems to me that our patch follows the direction that Glen suggested.
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 0/1] environment: move protect_hfs and protect_ntfs into repo_config_values
2026-06-06 14:34 [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Tian Yuchen
2026-06-06 14:34 ` [PATCH v1 0/1] environment: move protect_hfs and protect_ntfs Tian Yuchen
2026-06-09 10:20 ` [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Christian Couder
@ 2026-06-10 12:43 ` Tian Yuchen
2026-06-10 12:43 ` [PATCH v2 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Tian Yuchen
2 siblings, 1 reply; 7+ messages in thread
From: Tian Yuchen @ 2026-06-10 12:43 UTC (permalink / raw)
To: git
Cc: phillip.wood123, Tian Yuchen, Christian Couder, Ayush Chandekar,
Olamide Caleb Bello
Hi everyone,
This series continues the ongoing libification effort by moving the
global filesystem variables, 'protect_hfs' and 'protect_ntfs', into
'struct repo_config_values'.
Place them within the per-repository configuration structure
aligns with our goal of removing global states.
For reviewers familiar with previous libification efforts, Derrick Stolee
attempted to wrap this kind of filesystem-level variable using a
lazy-loaded global accessor get_int_config_global() [1].
However, as Glen Choo pointed out in his review of that series [2],
it is strongly preferred to use plain fields in a repository-scoped
struct over global lazy-loaders, provided those fields are properly
initialized during the setup process.
By moving these variables into repo_config_values and parsing
them eagerly, we successfully tie the filesystem security flags
to the specific repository instance without altering the timing
of configuration warnings or introducing new global states.
Thanks!
Recent related patch (environment.c: migrate 'trust_executable_bit' into 'repo_config_values'): [3]
[1] https://lore.kernel.org/git/a42dd9397d07b2dc4a0d7e75bfe1af2e46cad262.1685716420.git.gitgitgadget@gmail.com/
[2] https://lore.kernel.org/git/kl6lbkhpzujf.fsf@chooglen-macbookpro.roam.corp.google.com/
[3] https://lore.kernel.org/git/20260610093635.139719-1-cat@malon.dev/
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com>
Mentored-by: Olamide Caleb Bello <belkid98@gmail.com>
Signed-off-by: Tian Yuchen <cat@malon.dev>
Tian Yuchen (1):
environment.c: move 'protect_hfs' and 'protect_ntfs' into
'repo_config_values'
compat/mingw.c | 2 +-
environment.c | 22 ++++++++++++++++++----
environment.h | 12 ++++++++++--
read-cache.c | 7 ++++---
t/helper/test-path-utils.c | 24 +++++++++++++++---------
5 files changed, 48 insertions(+), 19 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'
2026-06-10 12:43 ` [PATCH v2 0/1] environment: move protect_hfs and protect_ntfs into repo_config_values Tian Yuchen
@ 2026-06-10 12:43 ` Tian Yuchen
2026-06-10 16:41 ` Junio C Hamano
0 siblings, 1 reply; 7+ messages in thread
From: Tian Yuchen @ 2026-06-10 12:43 UTC (permalink / raw)
To: git
Cc: phillip.wood123, Tian Yuchen, Christian Couder, Ayush Chandekar,
Olamide Caleb Bello
Move the global 'protect_hfs' and 'protect_ntfs' configurations
into the repository-specific 'repo_config_values' struct.
This will help with the elimination of 'the_repository'
To ensure code readability, the getter functions
'repo_protect_hfs()' and 'repo_protect_ntfs()'
have been introduced.
For now, associated functions access this configuration by
explicitly falling back to 'the_repository', which needs to
be addressed in the future.
Note: In 't/helper/test-path-utils.c', there is a function
'protect_ntfs_hfs_benchmark()' where these two global
variables are used as loop iterators. New local variables
have been created to replace them.
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com>
Mentored-by: Olamide Caleb Bello <belkid98@gmail.com>
Signed-off-by: Tian Yuchen <cat@malon.dev>
---
compat/mingw.c | 2 +-
environment.c | 22 ++++++++++++++++++----
environment.h | 12 ++++++++++--
read-cache.c | 7 ++++---
t/helper/test-path-utils.c | 24 +++++++++++++++---------
5 files changed, 48 insertions(+), 19 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw.c
index aa7525f419..af87df77fd 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -3392,7 +3392,7 @@ int is_valid_win32_path(const char *path, int allow_literal_nul)
const char *p = path;
int preceding_space_or_period = 0, i = 0, periods = 0;
- if (!protect_ntfs)
+ if (!repo_protect_ntfs(the_repository))
return 1;
skip_dos_drive_prefix((char **)&path);
diff --git a/environment.c b/environment.c
index fc3ed8bb1c..683fe1b4d3 100644
--- a/environment.c
+++ b/environment.c
@@ -82,12 +82,10 @@ unsigned long pack_size_limit_cfg;
#ifndef PROTECT_HFS_DEFAULT
#define PROTECT_HFS_DEFAULT 0
#endif
-int protect_hfs = PROTECT_HFS_DEFAULT;
#ifndef PROTECT_NTFS_DEFAULT
#define PROTECT_NTFS_DEFAULT 1
#endif
-int protect_ntfs = PROTECT_NTFS_DEFAULT;
/*
* The character that begins a commented line in user-editable file
@@ -142,6 +140,20 @@ int is_bare_repository(void)
return is_bare_repository_cfg && !repo_get_work_tree(the_repository);
}
+int repo_protect_ntfs(struct repository *repo)
+{
+ return repo->gitdir ?
+ repo_config_values(repo)->protect_ntfs :
+ PROTECT_NTFS_DEFAULT;
+}
+
+int repo_protect_hfs(struct repository *repo)
+{
+ return repo->gitdir ?
+ repo_config_values(repo)->protect_hfs :
+ PROTECT_HFS_DEFAULT;
+}
+
int have_git_dir(void)
{
return startup_info->have_repository
@@ -541,12 +553,12 @@ int git_default_core_config(const char *var, const char *value,
}
if (!strcmp(var, "core.protecthfs")) {
- protect_hfs = git_config_bool(var, value);
+ cfg->protect_hfs = git_config_bool(var, value);
return 0;
}
if (!strcmp(var, "core.protectntfs")) {
- protect_ntfs = git_config_bool(var, value);
+ cfg->protect_ntfs = git_config_bool(var, value);
return 0;
}
@@ -720,5 +732,7 @@ void repo_config_values_init(struct repo_config_values *cfg)
{
cfg->attributes_file = NULL;
cfg->apply_sparse_checkout = 0;
+ cfg->protect_hfs = PROTECT_HFS_DEFAULT;
+ cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
cfg->branch_track = BRANCH_TRACK_REMOTE;
}
diff --git a/environment.h b/environment.h
index 9eb97b3869..fdd9775900 100644
--- a/environment.h
+++ b/environment.h
@@ -91,6 +91,8 @@ struct repo_config_values {
/* section "core" config values */
char *attributes_file;
int apply_sparse_checkout;
+ int protect_hfs;
+ int protect_ntfs;
/* section "branch" config values */
enum branch_track branch_track;
@@ -123,6 +125,14 @@ int git_default_config(const char *, const char *,
int git_default_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);
+/*
+ * Getters for the `protect_hfs` and `protect_ntfs` fields of `struct repo_config_values`.
+ * They check `repo->gitdir` to prevent calling repo_config_values()
+ * before the configuration is loaded or in bare environments.
+ */
+int repo_protect_hfs(struct repository *repo);
+int repo_protect_ntfs(struct repository *repo);
+
void repo_config_values_init(struct repo_config_values *cfg);
/*
@@ -173,8 +183,6 @@ extern int pack_compression_level;
extern unsigned long pack_size_limit_cfg;
extern int precomposed_unicode;
-extern int protect_hfs;
-extern int protect_ntfs;
extern int core_sparse_checkout_cone;
extern int sparse_expect_files_outside_of_patterns;
diff --git a/read-cache.c b/read-cache.c
index 21829102ae..2c6a60c756 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1002,7 +1002,7 @@ static enum verify_path_result verify_path_internal(const char *path,
return PATH_OK;
if (is_dir_sep(c)) {
inside:
- if (protect_hfs) {
+ if (repo_protect_hfs(the_repository)) {
if (is_hfs_dotgit(path))
return PATH_INVALID;
@@ -1011,7 +1011,7 @@ static enum verify_path_result verify_path_internal(const char *path,
return PATH_INVALID;
}
}
- if (protect_ntfs) {
+ if (repo_protect_ntfs(the_repository)) {
#if defined GIT_WINDOWS_NATIVE || defined __CYGWIN__
if (c == '\\')
return PATH_INVALID;
@@ -1035,7 +1035,8 @@ static enum verify_path_result verify_path_internal(const char *path,
if (c == '\0')
return S_ISDIR(mode) ? PATH_DIR_WITH_SEP :
PATH_INVALID;
- } else if (c == '\\' && protect_ntfs) {
+ } else if (c == '\\' &&
+ repo_protect_ntfs(the_repository)) {
if (is_ntfs_dotgit(path))
return PATH_INVALID;
if (S_ISLNK(mode)) {
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index 15eb44485c..f77b3f9d70 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -250,6 +250,7 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
double m[3][2], v[3][2];
uint64_t cumul;
double cumul2;
+ int ntfs, hfs;
if (argc > 1 && !strcmp(argv[1], "--with-symlink-mode")) {
file_mode = 0120000;
@@ -276,8 +277,13 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
names[i][--len] = (char)(' ' + (my_random() % ('\x7f' - ' ')));
}
- for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
- for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) {
+ if (!the_repository->gitdir)
+ the_repository->gitdir = xstrdup(".git");
+
+ for (ntfs = 0; ntfs < 2; ntfs++)
+ for (hfs = 0; hfs < 2; hfs++) {
+ repo_config_values(the_repository)->protect_ntfs = ntfs;
+ repo_config_values(the_repository)->protect_hfs = hfs;
cumul = 0;
cumul2 = 0;
for (i = 0; i < repetitions; i++) {
@@ -285,18 +291,18 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
for (j = 0; j < nr; j++)
verify_path(names[j], file_mode);
end = getnanotime();
- printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", protect_ntfs, protect_hfs, (end-begin) / (double)1e6);
+ printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", ntfs, hfs, (end-begin) / (double)1e6);
cumul += end - begin;
cumul2 += (end - begin) * (end - begin);
}
- m[protect_ntfs][protect_hfs] = cumul / (double)repetitions;
- v[protect_ntfs][protect_hfs] = my_sqrt(cumul2 / (double)repetitions - m[protect_ntfs][protect_hfs] * m[protect_ntfs][protect_hfs]);
- printf("mean: %lfms, stddev: %lfms\n", m[protect_ntfs][protect_hfs] / (double)1e6, v[protect_ntfs][protect_hfs] / (double)1e6);
+ m[ntfs][hfs] = cumul / (double)repetitions;
+ v[ntfs][hfs] = my_sqrt(cumul2 / (double)repetitions - m[ntfs][hfs] * m[ntfs][hfs]);
+ printf("mean: %lfms, stddev: %lfms\n", m[ntfs][hfs] / (double)1e6, v[ntfs][hfs] / (double)1e6);
}
- for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
- for (protect_hfs = 0; protect_hfs < 2; protect_hfs++)
- printf("ntfs=%d/hfs=%d: %lf%% slower\n", protect_ntfs, protect_hfs, (m[protect_ntfs][protect_hfs] - m[0][0]) * 100 / m[0][0]);
+ for (ntfs = 0; ntfs < 2; ntfs++)
+ for (hfs = 0; hfs < 2; hfs++)
+ printf("ntfs=%d/hfs=%d: %lf%% slower\n", ntfs, hfs, (m[ntfs][hfs] - m[0][0]) * 100 / m[0][0]);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'
2026-06-10 12:43 ` [PATCH v2 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Tian Yuchen
@ 2026-06-10 16:41 ` Junio C Hamano
0 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2026-06-10 16:41 UTC (permalink / raw)
To: Tian Yuchen
Cc: git, phillip.wood123, Christian Couder, Ayush Chandekar,
Olamide Caleb Bello
Tian Yuchen <cat@malon.dev> writes:
> +int repo_protect_ntfs(struct repository *repo)
> +{
> + return repo->gitdir ?
> + repo_config_values(repo)->protect_ntfs :
> + PROTECT_NTFS_DEFAULT;
> +}
> +
> +int repo_protect_hfs(struct repository *repo)
> +{
> + return repo->gitdir ?
> + repo_config_values(repo)->protect_hfs :
> + PROTECT_HFS_DEFAULT;
> +}
> ...
> @@ -123,6 +125,14 @@ int git_default_config(const char *, const char *,
> int git_default_core_config(const char *var, const char *value,
> const struct config_context *ctx, void *cb);
>
> +/*
> + * Getters for the `protect_hfs` and `protect_ntfs` fields of `struct repo_config_values`.
> + * They check `repo->gitdir` to prevent calling repo_config_values()
> + * before the configuration is loaded or in bare environments.
> + */
> +int repo_protect_hfs(struct repository *repo);
> +int repo_protect_ntfs(struct repository *repo);
I briefly wondered what *should* happen when repo->gitdir is not
ready, as it feels almost a bug for a caller to call these two
functions before the repository is ready to be used.
When repo is not ready, these return their respective default
values. That's like the original code using the initial value of
these global variables.
IOW, this rewrite is bug-for-bug compatible, which is good.
Shall we declare victory and mark the topic for 'next' now?
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-10 16:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-06 14:34 [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Tian Yuchen
2026-06-06 14:34 ` [PATCH v1 0/1] environment: move protect_hfs and protect_ntfs Tian Yuchen
2026-06-09 10:54 ` Christian Couder
2026-06-09 10:20 ` [PATCH v1 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Christian Couder
2026-06-10 12:43 ` [PATCH v2 0/1] environment: move protect_hfs and protect_ntfs into repo_config_values Tian Yuchen
2026-06-10 12:43 ` [PATCH v2 1/1] environment.c: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values' Tian Yuchen
2026-06-10 16:41 ` Junio C Hamano
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.