environment: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'

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> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Tian Yuchen committed Jun 10, 2026 at 20:43 UTC 71386c21dfb7cea181df6707c34cd79b10fc0a2b
5 files changed +48 -19
compat/mingw.c
+1 -1
@@ -3392,7 +3392,7 @@ int is_valid_win32_path(const char *path, int allow_literal_nul)
3392 const char *p = path;
3393 int preceding_space_or_period = 0, i = 0, periods = 0;
3394
3395 - if (!protect_ntfs)
3395 + if (!repo_protect_ntfs(the_repository))
3396 return 1;
3397
3398 skip_dos_drive_prefix((char **)&path);
environment.c
+18 -4
@@ -82,12 +82,10 @@ unsigned long pack_size_limit_cfg;
82 #ifndef PROTECT_HFS_DEFAULT
83 #define PROTECT_HFS_DEFAULT 0
84 #endif
85 -int protect_hfs = PROTECT_HFS_DEFAULT;
85
86 #ifndef PROTECT_NTFS_DEFAULT
87 #define PROTECT_NTFS_DEFAULT 1
88 #endif
90 -int protect_ntfs = PROTECT_NTFS_DEFAULT;
89
90 /*
91 * The character that begins a commented line in user-editable file
@@ -142,6 +140,20 @@ int is_bare_repository(void)
140 return is_bare_repository_cfg && !repo_get_work_tree(the_repository);
141 }
142
143 +int repo_protect_ntfs(struct repository *repo)
144 +{
145 + return repo->gitdir ?
146 + repo_config_values(repo)->protect_ntfs :
147 + PROTECT_NTFS_DEFAULT;
148 +}
149 +
150 +int repo_protect_hfs(struct repository *repo)
151 +{
152 + return repo->gitdir ?
153 + repo_config_values(repo)->protect_hfs :
154 + PROTECT_HFS_DEFAULT;
155 +}
156 +
157 int have_git_dir(void)
158 {
159 return startup_info->have_repository
@@ -541,12 +553,12 @@ int git_default_core_config(const char *var, const char *value,
553 }
554
555 if (!strcmp(var, "core.protecthfs")) {
544 - protect_hfs = git_config_bool(var, value);
556 + cfg->protect_hfs = git_config_bool(var, value);
557 return 0;
558 }
559
560 if (!strcmp(var, "core.protectntfs")) {
549 - protect_ntfs = git_config_bool(var, value);
561 + cfg->protect_ntfs = git_config_bool(var, value);
562 return 0;
563 }
564
@@ -720,5 +732,7 @@ void repo_config_values_init(struct repo_config_values *cfg)
732 {
733 cfg->attributes_file = NULL;
734 cfg->apply_sparse_checkout = 0;
735 + cfg->protect_hfs = PROTECT_HFS_DEFAULT;
736 + cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
737 cfg->branch_track = BRANCH_TRACK_REMOTE;
738 }
environment.h
+10 -2
@@ -91,6 +91,8 @@ struct repo_config_values {
91 /* section "core" config values */
92 char *attributes_file;
93 int apply_sparse_checkout;
94 + int protect_hfs;
95 + int protect_ntfs;
96
97 /* section "branch" config values */
98 enum branch_track branch_track;
@@ -123,6 +125,14 @@ int git_default_config(const char *, const char *,
125 int git_default_core_config(const char *var, const char *value,
126 const struct config_context *ctx, void *cb);
127
128 +/*
129 + * Getters for the `protect_hfs` and `protect_ntfs` fields of `struct repo_config_values`.
130 + * They check `repo->gitdir` to prevent calling repo_config_values()
131 + * before the configuration is loaded or in bare environments.
132 + */
133 +int repo_protect_hfs(struct repository *repo);
134 +int repo_protect_ntfs(struct repository *repo);
135 +
136 void repo_config_values_init(struct repo_config_values *cfg);
137
138 /*
@@ -173,8 +183,6 @@ extern int pack_compression_level;
183 extern unsigned long pack_size_limit_cfg;
184
185 extern int precomposed_unicode;
176 -extern int protect_hfs;
177 -extern int protect_ntfs;
186
187 extern int core_sparse_checkout_cone;
188 extern int sparse_expect_files_outside_of_patterns;
read-cache.c
+4 -3
@@ -1002,7 +1002,7 @@ static enum verify_path_result verify_path_internal(const char *path,
1002 return PATH_OK;
1003 if (is_dir_sep(c)) {
1004 inside:
1005 - if (protect_hfs) {
1005 + if (repo_protect_hfs(the_repository)) {
1006
1007 if (is_hfs_dotgit(path))
1008 return PATH_INVALID;
@@ -1011,7 +1011,7 @@ inside:
1011 return PATH_INVALID;
1012 }
1013 }
1014 - if (protect_ntfs) {
1014 + if (repo_protect_ntfs(the_repository)) {
1015 #if defined GIT_WINDOWS_NATIVE || defined __CYGWIN__
1016 if (c == '\\')
1017 return PATH_INVALID;
@@ -1035,7 +1035,8 @@ inside:
1035 if (c == '\0')
1036 return S_ISDIR(mode) ? PATH_DIR_WITH_SEP :
1037 PATH_INVALID;
1038 - } else if (c == '\\' && protect_ntfs) {
1038 + } else if (c == '\\' &&
1039 + repo_protect_ntfs(the_repository)) {
1040 if (is_ntfs_dotgit(path))
1041 return PATH_INVALID;
1042 if (S_ISLNK(mode)) {
t/helper/test-path-utils.c
+15 -9
@@ -250,6 +250,7 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
250 double m[3][2], v[3][2];
251 uint64_t cumul;
252 double cumul2;
253 + int ntfs, hfs;
254
255 if (argc > 1 && !strcmp(argv[1], "--with-symlink-mode")) {
256 file_mode = 0120000;
@@ -276,8 +277,13 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
277 names[i][--len] = (char)(' ' + (my_random() % ('\x7f' - ' ')));
278 }
279
279 - for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
280 - for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) {
280 + if (!the_repository->gitdir)
281 + the_repository->gitdir = xstrdup(".git");
282 +
283 + for (ntfs = 0; ntfs < 2; ntfs++)
284 + for (hfs = 0; hfs < 2; hfs++) {
285 + repo_config_values(the_repository)->protect_ntfs = ntfs;
286 + repo_config_values(the_repository)->protect_hfs = hfs;
287 cumul = 0;
288 cumul2 = 0;
289 for (i = 0; i < repetitions; i++) {
@@ -285,18 +291,18 @@ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
291 for (j = 0; j < nr; j++)
292 verify_path(names[j], file_mode);
293 end = getnanotime();
288 - printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", protect_ntfs, protect_hfs, (end-begin) / (double)1e6);
294 + printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", ntfs, hfs, (end-begin) / (double)1e6);
295 cumul += end - begin;
296 cumul2 += (end - begin) * (end - begin);
297 }
292 - m[protect_ntfs][protect_hfs] = cumul / (double)repetitions;
293 - v[protect_ntfs][protect_hfs] = my_sqrt(cumul2 / (double)repetitions - m[protect_ntfs][protect_hfs] * m[protect_ntfs][protect_hfs]);
294 - printf("mean: %lfms, stddev: %lfms\n", m[protect_ntfs][protect_hfs] / (double)1e6, v[protect_ntfs][protect_hfs] / (double)1e6);
298 + m[ntfs][hfs] = cumul / (double)repetitions;
299 + v[ntfs][hfs] = my_sqrt(cumul2 / (double)repetitions - m[ntfs][hfs] * m[ntfs][hfs]);
300 + printf("mean: %lfms, stddev: %lfms\n", m[ntfs][hfs] / (double)1e6, v[ntfs][hfs] / (double)1e6);
301 }
302
297 - for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
298 - for (protect_hfs = 0; protect_hfs < 2; protect_hfs++)
299 - printf("ntfs=%d/hfs=%d: %lf%% slower\n", protect_ntfs, protect_hfs, (m[protect_ntfs][protect_hfs] - m[0][0]) * 100 / m[0][0]);
303 + for (ntfs = 0; ntfs < 2; ntfs++)
304 + for (hfs = 0; hfs < 2; hfs++)
305 + printf("ntfs=%d/hfs=%d: %lf%% slower\n", ntfs, hfs, (m[ntfs][hfs] - m[0][0]) * 100 / m[0][0]);
306
307 return 0;
308 }