Merge branch 'ty/migrate-ignorecase'

The global configuration variable 'ignore_case' (representing the
'core.ignorecase' configuration) has been migrated into 'struct
repo_config_values' to tie it to a specific repository instance.

* ty/migrate-ignorecase:
  config: use repo_ignore_case() to access core.ignorecase
  environment: move ignore_case into repo_config_values
main
Junio C Hamano 2026-07-19 10:42:19 -07:00
commit a336bfa205
14 changed files with 43 additions and 28 deletions

View File

@ -4008,7 +4008,7 @@ static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *na
struct cache_entry *ce; struct cache_entry *ce;


ce = index_file_exists(state->repo->index, name->buf, ce = index_file_exists(state->repo->index, name->buf,
name->len, ignore_case); name->len, repo_ignore_case(the_repository));
if (ce && S_ISLNK(ce->ce_mode)) if (ce && S_ISLNK(ce->ce_mode))
return 1; return 1;
} else { } else {

View File

@ -1839,7 +1839,7 @@ static void ref_transaction_rejection_handler(const char *refname,
{ {
struct ref_rejection_data *data = cb_data; struct ref_rejection_data *data = cb_data;


if (err == REF_TRANSACTION_ERROR_CASE_CONFLICT && ignore_case && if (err == REF_TRANSACTION_ERROR_CASE_CONFLICT && repo_ignore_case(the_repository) &&
!data->case_sensitive_msg_shown) { !data->case_sensitive_msg_shown) {
error(_("You're on a case-insensitive filesystem, and the remote you are\n" error(_("You're on a case-insensitive filesystem, and the remote you are\n"
"trying to fetch from has references that only differ in casing. It\n" "trying to fetch from has references that only differ in casing. It\n"

View File

@ -419,7 +419,7 @@ dir_check:
goto act_on_entry; goto act_on_entry;
} }
if (lstat(dst, &st) == 0 && if (lstat(dst, &st) == 0 &&
(!ignore_case || strcasecmp(src, dst))) { (!repo_ignore_case(the_repository) || strcasecmp(src, dst))) {
bad = _("destination exists"); bad = _("destination exists");
if (force) { if (force) {
/* /*

View File

@ -2,6 +2,7 @@


#include "../../git-compat-util.h" #include "../../git-compat-util.h"
#include "../../environment.h" #include "../../environment.h"
#include "../../repository.h"


int win32_has_dos_drive_prefix(const char *path) int win32_has_dos_drive_prefix(const char *path)
{ {
@ -75,7 +76,7 @@ int win32_fspathncmp(const char *a, const char *b, size_t count)
} else if (is_dir_sep(*b)) } else if (is_dir_sep(*b))
return +1; return +1;


diff = ignore_case ? diff = repo_ignore_case(the_repository) ?
(unsigned char)tolower(*a) - (int)(unsigned char)tolower(*b) : (unsigned char)tolower(*a) - (int)(unsigned char)tolower(*b) :
(unsigned char)*a - (int)(unsigned char)*b; (unsigned char)*a - (int)(unsigned char)*b;
if (diff) if (diff)

18
dir.c
View File

@ -126,7 +126,7 @@ int count_slashes(const char *s)


int git_fspathcmp(const char *a, const char *b) int git_fspathcmp(const char *a, const char *b)
{ {
return ignore_case ? strcasecmp(a, b) : strcmp(a, b); return repo_ignore_case(the_repository) ? strcasecmp(a, b) : strcmp(a, b);
} }


int fspatheq(const char *a, const char *b) int fspatheq(const char *a, const char *b)
@ -136,7 +136,7 @@ int fspatheq(const char *a, const char *b)


int git_fspathncmp(const char *a, const char *b, size_t count) int git_fspathncmp(const char *a, const char *b, size_t count)
{ {
return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count); return repo_ignore_case(the_repository) ? strncasecmp(a, b, count) : strncmp(a, b, count);
} }


int paths_collide(const char *a, const char *b) int paths_collide(const char *a, const char *b)
@ -153,7 +153,7 @@ int paths_collide(const char *a, const char *b)


unsigned int fspathhash(const char *str) unsigned int fspathhash(const char *str)
{ {
return ignore_case ? strihash(str) : strhash(str); return repo_ignore_case(the_repository) ? strihash(str) : strhash(str);
} }


int git_fnmatch(const struct pathspec_item *item, int git_fnmatch(const struct pathspec_item *item,
@ -202,7 +202,7 @@ static int fnmatch_icase_mem(const char *pattern, int patternlen,
use_str = str_buf.buf; use_str = str_buf.buf;
} }


if (ignore_case) if (repo_ignore_case(the_repository))
flags |= WM_CASEFOLD; flags |= WM_CASEFOLD;
match_status = wildmatch(use_pat, use_str, flags); match_status = wildmatch(use_pat, use_str, flags);


@ -1851,7 +1851,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir,
struct index_state *istate, struct index_state *istate,
const char *pathname, int len) const char *pathname, int len)
{ {
if (index_file_exists(istate, pathname, len, ignore_case)) if (index_file_exists(istate, pathname, len, repo_ignore_case(the_repository)))
return NULL; return NULL;


ALLOC_GROW(dir->entries, dir->nr+1, dir->internal.alloc); ALLOC_GROW(dir->entries, dir->nr+1, dir->internal.alloc);
@ -1888,7 +1888,7 @@ static enum exist_status directory_exists_in_index_icase(struct index_state *ist
if (index_dir_exists(istate, dirname, len)) if (index_dir_exists(istate, dirname, len))
return index_directory; return index_directory;


ce = index_file_exists(istate, dirname, len, ignore_case); ce = index_file_exists(istate, dirname, len, repo_ignore_case(the_repository));
if (ce && S_ISGITLINK(ce->ce_mode)) if (ce && S_ISGITLINK(ce->ce_mode))
return index_gitdir; return index_gitdir;


@ -1907,7 +1907,7 @@ static enum exist_status directory_exists_in_index(struct index_state *istate,
{ {
int pos; int pos;


if (ignore_case) if (repo_ignore_case(the_repository))
return directory_exists_in_index_icase(istate, dirname, len); return directory_exists_in_index_icase(istate, dirname, len);


pos = index_name_pos(istate, dirname, len); pos = index_name_pos(istate, dirname, len);
@ -2447,7 +2447,7 @@ static enum path_treatment treat_path(struct dir_struct *dir,


/* Always exclude indexed files */ /* Always exclude indexed files */
has_path_in_index = !!index_file_exists(istate, path->buf, path->len, has_path_in_index = !!index_file_exists(istate, path->buf, path->len,
ignore_case); repo_ignore_case(the_repository));
if (dtype != DT_DIR && has_path_in_index) if (dtype != DT_DIR && has_path_in_index)
return path_none; return path_none;


@ -3201,7 +3201,7 @@ static int cmp_icase(char a, char b)
{ {
if (a == b) if (a == b)
return 0; return 0;
if (ignore_case) if (repo_ignore_case(the_repository))
return toupper(a) - toupper(b); return toupper(a) - toupper(b);
return a - b; return a - b;
} }

View File

@ -44,7 +44,6 @@ static int zlib_compression_seen;
int trust_executable_bit = 1; int trust_executable_bit = 1;
int has_symlinks = 1; int has_symlinks = 1;
int minimum_abbrev = 4, default_abbrev = -1; int minimum_abbrev = 4, default_abbrev = -1;
int ignore_case;
int assume_unchanged; int assume_unchanged;
char *git_commit_encoding; char *git_commit_encoding;
char *git_log_output_encoding; char *git_log_output_encoding;
@ -142,6 +141,13 @@ int repo_protect_hfs(struct repository *repo)
PROTECT_HFS_DEFAULT; PROTECT_HFS_DEFAULT;
} }


int repo_ignore_case(struct repository *repo)
{
return (repo && repo->initialized) ?
repo_config_values(repo)->ignore_case :
0;
}

int have_git_dir(void) int have_git_dir(void)
{ {
return startup_info->have_repository return startup_info->have_repository
@ -335,7 +341,7 @@ int git_default_core_config(const char *var, const char *value,
} }


if (!strcmp(var, "core.ignorecase")) { if (!strcmp(var, "core.ignorecase")) {
ignore_case = git_config_bool(var, value); cfg->ignore_case = git_config_bool(var, value);
return 0; return 0;
} }


@ -726,6 +732,7 @@ void repo_config_values_init(struct repo_config_values *cfg)
cfg->apply_sparse_checkout = 0; cfg->apply_sparse_checkout = 0;
cfg->protect_hfs = PROTECT_HFS_DEFAULT; cfg->protect_hfs = PROTECT_HFS_DEFAULT;
cfg->protect_ntfs = PROTECT_NTFS_DEFAULT; cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
cfg->ignore_case = 0;
cfg->branch_track = BRANCH_TRACK_REMOTE; cfg->branch_track = BRANCH_TRACK_REMOTE;
cfg->trust_ctime = 1; cfg->trust_ctime = 1;
cfg->check_stat = 1; cfg->check_stat = 1;

View File

@ -100,6 +100,7 @@ struct repo_config_values {
int warn_on_object_refname_ambiguity; int warn_on_object_refname_ambiguity;
int protect_hfs; int protect_hfs;
int protect_ntfs; int protect_ntfs;
int ignore_case;


/* section "sparse" config values */ /* section "sparse" config values */
int sparse_expect_files_outside_of_patterns; int sparse_expect_files_outside_of_patterns;
@ -143,6 +144,13 @@ int git_default_core_config(const char *var, const char *value,
int repo_protect_hfs(struct repository *repo); int repo_protect_hfs(struct repository *repo);
int repo_protect_ntfs(struct repository *repo); int repo_protect_ntfs(struct repository *repo);


/*
* Getter for the `ignore_case` field of `struct repo_config_values`.
* It checks `repo->initialized` to prevent calling repo_config_values()`
* before the repository setup is fully complete or in non-git environments.
*/
int repo_ignore_case(struct repository *repo);

void repo_config_values_init(struct repo_config_values *cfg); void repo_config_values_init(struct repo_config_values *cfg);


int is_bare_repository(struct repository *repo); int is_bare_repository(struct repository *repo);
@ -173,7 +181,6 @@ int have_git_dir(void);
extern int trust_executable_bit; extern int trust_executable_bit;
extern int has_symlinks; extern int has_symlinks;
extern int minimum_abbrev, default_abbrev; extern int minimum_abbrev, default_abbrev;
extern int ignore_case;
extern int assume_unchanged; extern int assume_unchanged;
extern char *apply_default_whitespace; extern char *apply_default_whitespace;
extern char *apply_default_ignorewhitespace; extern char *apply_default_ignorewhitespace;

View File

@ -453,7 +453,7 @@ static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
* case-insensitive file system, try again using the name-hash * case-insensitive file system, try again using the name-hash
* and dir-name-hash. * and dir-name-hash.
*/ */
if (!nr_in_cone && ignore_case) { if (!nr_in_cone && repo_ignore_case(the_repository)) {
nr_in_cone = handle_using_name_hash_icase(istate, name); nr_in_cone = handle_using_name_hash_icase(istate, name);
if (!nr_in_cone) if (!nr_in_cone)
nr_in_cone = handle_using_dir_name_hash_icase( nr_in_cone = handle_using_dir_name_hash_icase(

View File

@ -126,7 +126,7 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
hashmap_add(&istate->name_hash, &ce->ent); hashmap_add(&istate->name_hash, &ce->ent);
} }


if (ignore_case) if (repo_ignore_case(the_repository))
add_dir_entry(istate, ce); add_dir_entry(istate, ce);
} }


@ -207,7 +207,7 @@ static int lookup_lazy_params(struct index_state *istate)
* code to build the "istate->name_hash". We don't * code to build the "istate->name_hash". We don't
* need the complexity here. * need the complexity here.
*/ */
if (!ignore_case) if (!repo_ignore_case(the_repository))
return 0; return 0;


nr_cpus = online_cpus(); nr_cpus = online_cpus();
@ -651,7 +651,7 @@ void remove_name_hash(struct index_state *istate, struct cache_entry *ce)
ce->ce_flags &= ~CE_HASHED; ce->ce_flags &= ~CE_HASHED;
hashmap_remove(&istate->name_hash, &ce->ent, ce); hashmap_remove(&istate->name_hash, &ce->ent, ce);


if (ignore_case) if (repo_ignore_case(the_repository))
remove_dir_entry(istate, ce); remove_dir_entry(istate, ce);
} }



View File

@ -760,12 +760,12 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
* case of the file being added to the repository matches (is folded into) the existing * case of the file being added to the repository matches (is folded into) the existing
* entry's directory case. * entry's directory case.
*/ */
if (ignore_case) { if (repo_ignore_case(the_repository)) {
adjust_dirname_case(istate, ce->name); adjust_dirname_case(istate, ce->name);
} }
if (!(flags & ADD_CACHE_RENORMALIZE)) { if (!(flags & ADD_CACHE_RENORMALIZE)) {
alias = index_file_exists(istate, ce->name, alias = index_file_exists(istate, ce->name,
ce_namelen(ce), ignore_case); ce_namelen(ce), repo_ignore_case(the_repository));
if (alias && if (alias &&
!ce_stage(alias) && !ce_stage(alias) &&
!ie_match_stat(istate, alias, st, ce_option)) { !ie_match_stat(istate, alias, st, ce_option)) {
@ -786,7 +786,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
} else } else
set_object_name_for_intent_to_add_entry(ce); set_object_name_for_intent_to_add_entry(ce);


if (ignore_case && alias && different_name(ce, alias)) if (repo_ignore_case(the_repository) && alias && different_name(ce, alias))
ce = create_alias_ce(istate, ce, alias); ce = create_alias_ce(istate, ce, alias);
ce->ce_flags |= CE_ADDED; ce->ce_flags |= CE_ADDED;



View File

@ -857,7 +857,7 @@ retry:
} else { } else {
unable_to_lock_message(ref_file.buf, myerr, err); unable_to_lock_message(ref_file.buf, myerr, err);
if (myerr == EEXIST) { if (myerr == EEXIST) {
if (ignore_case && if (repo_ignore_case(the_repository) &&
transaction_has_case_conflicting_update(transaction, update)) { transaction_has_case_conflicting_update(transaction, update)) {
/* /*
* In case-insensitive filesystems, ensure that conflicts within a * In case-insensitive filesystems, ensure that conflicts within a
@ -971,7 +971,7 @@ retry:
* conflicts between 'foo' and 'Foo/bar'. So let's lowercase * conflicts between 'foo' and 'Foo/bar'. So let's lowercase
* the refname. * the refname.
*/ */
if (ignore_case) { if (repo_ignore_case(the_repository)) {
struct strbuf lower = STRBUF_INIT; struct strbuf lower = STRBUF_INIT;


strbuf_addstr(&lower, refname); strbuf_addstr(&lower, refname);

View File

@ -2390,7 +2390,7 @@ static int validate_submodule_encoded_git_dir(char *git_dir, const char *submodu


/* Prevent conflicts on case-folding filesystems */ /* Prevent conflicts on case-folding filesystems */
repo_config_get_bool(the_repository, "core.ignorecase", &config_ignorecase); repo_config_get_bool(the_repository, "core.ignorecase", &config_ignorecase);
if (ignore_case || config_ignorecase) { if (repo_ignore_case(the_repository) || config_ignorecase) {
bool suffixes_match = !strcmp(last_submodule_name, submodule_name); bool suffixes_match = !strcmp(last_submodule_name, submodule_name);
return check_casefolding_conflict(git_dir, submodule_name, return check_casefolding_conflict(git_dir, submodule_name,
suffixes_match); suffixes_match);

View File

@ -218,7 +218,7 @@ int cmd__lazy_init_name_hash(int argc, const char **argv)
/* /*
* istate->dir_hash is only created when ignore_case is set. * istate->dir_hash is only created when ignore_case is set.
*/ */
ignore_case = 1; repo_config_values(the_repository)->ignore_case = 1;


if (dump) { if (dump) {
if (perf || analyze > 0) if (perf || analyze > 0)

View File

@ -2430,7 +2430,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
* *
* Ignore that lstat() if it matches. * Ignore that lstat() if it matches.
*/ */
if (ignore_case && icase_exists(o, name, len, st)) if (repo_ignore_case(the_repository) && icase_exists(o, name, len, st))
return 0; return 0;


if (o->internal.dir && if (o->internal.dir &&