Incorporating Torsten suggestions and some documentation: --- Documentation/config.txt | 12 ++++++++++++ builtin/init-db.c | 4 +++- config.c | 5 +++++ environment.c | 1 + refs.c | 26 +++++++++++++++++++++++--- 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 040197b..c0a6c5c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -2077,6 +2077,18 @@ receive.shallowupdate:: If set to true, .git/shallow can be updated when new refs require new shallow roots. Otherwise those refs are rejected. +refs.ignorecase:: + If true, this option prevents the creation of ref names + that differ in case only. For example, if a branch Foo exists, + `git checkout -b foo` would fail. This is the case + across ref hierarchies, so `git tag foo` would also fail. + This option is useful on filesystems that are not case + sensitive. ++ +The default is false, except linkgit:git-clone[1] or linkgit:git-init[1] +will probe and set refs.ignorecase true if appropriate when the repository +is created. refs.ignorecase will also be true if core.ignorecase is true. + remote.pushdefault:: The remote to push to by default. Overrides `branch.<name>.remote` for all branches, and is overridden by diff --git a/builtin/init-db.c b/builtin/init-db.c index c7c76bb..7c6931b 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -288,8 +288,10 @@ static int create_default_files(const char *template_path) /* Check if the filesystem is case-insensitive */ path[len] = 0; strcpy(path + len, "CoNfIg"); - if (!access(path, F_OK)) + if (!access(path, F_OK)) { git_config_set("core.ignorecase", "true"); + git_config_set("refs.ignorecase", "true"); + } probe_utf8_pathname_composition(path, len); } diff --git a/config.c b/config.c index 314d8ee..797391a 100644 --- a/config.c +++ b/config.c @@ -702,6 +702,11 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "refs.ignorecase")) { + refs_ignore_case = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "core.attributesfile")) return git_config_pathname(&git_attributes_file, var, value); diff --git a/environment.c b/environment.c index 4a3437d..2eced48 100644 --- a/environment.c +++ b/environment.c @@ -18,6 +18,7 @@ int check_stat = 1; int has_symlinks = 1; int minimum_abbrev = 4, default_abbrev = 7; int ignore_case; +int refs_ignore_case = -1; int assume_unchanged; int prefer_symlink_refs; int is_bare_repository_cfg = -1; /* unspecified */ diff --git a/refs.c b/refs.c index 89228e2..1915ec2 100644 --- a/refs.c +++ b/refs.c @@ -359,16 +359,26 @@ struct string_slice { const char *str; }; -static int ref_entry_cmp_sslice(const void *key_, const void *ent_) +static int ref_entry_ncmp(const void *key_, const void *ent_, int (*cmp_fn)(const char *, const char *, size_t)) { const struct string_slice *key = key_; const struct ref_entry *ent = *(const struct ref_entry * const *)ent_; - int cmp = strncmp(key->str, ent->name, key->len); + int cmp = cmp_fn(key->str, ent->name, key->len); if (cmp) return cmp; return '\0' - (unsigned char)ent->name[key->len]; } +static int ref_entry_cmp_sslice(const void *key_, const void *ent_) +{ + return ref_entry_ncmp(key_, ent_, strncmp); +} + +static int ref_entry_casecmp_sslice(const void *key_, const void *ent_) +{ + return ref_entry_ncmp(key_, ent_, strncasecmp); +} + /* * Return the index of the entry with the given refname from the * ref_dir (non-recursively), sorting dir if necessary. Return -1 if @@ -378,6 +388,7 @@ static int search_ref_dir(struct ref_dir *dir, const char *refname, size_t len) { struct ref_entry **r; struct string_slice key; + int (*cmp_fn)(const void *, const void *); if (refname == NULL || !dir->nr) return -1; @@ -385,8 +396,17 @@ static int search_ref_dir(struct ref_dir *dir, const char *refname, size_t len) sort_ref_dir(dir); key.len = len; key.str = refname; + + if(refs_ignore_case < 0) + refs_ignore_case = ignore_case; + + if(ignore_case) + cmp_fn = ref_entry_casecmp_sslice; + else + cmp_fn = ref_entry_cmp_sslice; + r = bsearch(&key, dir->entries, dir->nr, sizeof(*dir->entries), - ref_entry_cmp_sslice); + cmp_fn); if (r == NULL) return -1; -- -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html