If "core.ignorecase" is true, "git blame" fails when the given path differs to the real path in case sensitivity. Signed-off-by: Ralf Thielow <ralf.thielow@xxxxxxxxx> --- .gitignore | 1 + Makefile | 3 +++ builtin/blame.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ test-path-ignorecase.c | 27 +++++++++++++++++++++++ 4 Dateien geändert, 89 Zeilen hinzugefügt(+) create mode 100644 test-path-ignorecase.c diff --git a/.gitignore b/.gitignore index bb5c91e..65ab9f6 100644 --- a/.gitignore +++ b/.gitignore @@ -195,6 +195,7 @@ /test-sigchain /test-subprocess /test-svn-fe +/test-path-ignorecase /common-cmds.h *.tar.gz *.dsc diff --git a/Makefile b/Makefile index 6b0c961..dbdd214 100644 --- a/Makefile +++ b/Makefile @@ -503,6 +503,7 @@ TEST_PROGRAMS_NEED_X += test-sha1 TEST_PROGRAMS_NEED_X += test-sigchain TEST_PROGRAMS_NEED_X += test-subprocess TEST_PROGRAMS_NEED_X += test-svn-fe +TEST_PROGRAMS_NEED_X += test-path-ignorecase TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X)) @@ -2562,6 +2563,8 @@ test-parse-options$X: parse-options.o parse-options-cb.o test-svn-fe$X: vcs-svn/lib.a +test-path-ignorecase$X: builtin/blame.o + .PRECIOUS: $(TEST_OBJS) test-%$X: test-%.o GIT-LDFLAGS $(GITLIBS) diff --git a/builtin/blame.c b/builtin/blame.c index 0d50273..895f665 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -1937,6 +1937,61 @@ static int has_string_in_work_tree(const char *path) return !lstat(path, &st); } +const char* get_path_ignorecase(const char *path) +{ + struct strbuf res = STRBUF_INIT; + struct strbuf p = STRBUF_INIT; + int offset = 0; + + if (!ignore_case || has_string_in_work_tree(path)) + return path; + + for (;;) { + char c = path[offset++]; + + if (is_dir_sep(c) || c == '\0') { + DIR *dir; + + if (res.len) + dir = opendir(res.buf); + else + dir = opendir("."); + + if (dir != NULL) { + for (;;) { + struct dirent *ent = readdir(dir); + + if (ent == NULL ) + break; + + if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name)) + continue; + + if (!strcmp(p.buf, ent->d_name)) + break; + + if (!strcasecmp(p.buf, ent->d_name)) { + strbuf_release(&p); + strbuf_add(&p, ent->d_name, strlen(ent->d_name)); + break; + } + } + closedir(dir); + } + + strbuf_addch(&p, c); + strbuf_addbuf(&res, &p); + strbuf_release(&p); + } else { + strbuf_addch(&p, c); + } + + if (c == '\0') + break; + } + return res.buf; +} + static unsigned parse_score(const char *arg) { char *end; @@ -2448,6 +2503,7 @@ parse_done: /* FALLTHROUGH */ case 1: /* (1a) */ path = add_prefix(prefix, argv[--argc]); + path = get_path_ignorecase(path); argv[argc] = NULL; break; default: @@ -2457,8 +2513,10 @@ parse_done: if (argc < 2) usage_with_options(blame_opt_usage, options); path = add_prefix(prefix, argv[argc - 1]); + path = get_path_ignorecase(path); if (argc == 3 && !has_string_in_work_tree(path)) { /* (2b) */ path = add_prefix(prefix, argv[1]); + path = get_path_ignorecase(path); argv[1] = argv[2]; } argv[argc - 1] = "--"; diff --git a/test-path-ignorecase.c b/test-path-ignorecase.c new file mode 100644 index 0000000..1f17f5c --- /dev/null +++ b/test-path-ignorecase.c @@ -0,0 +1,27 @@ +#include "cache.h" + +static const char *usage_msg = "\n" + "test-similar-path <path>...\n"; +const char* get_path_ignorecase(const char *path); + +int main(int argc, char **argv) +{ + char *p; + const char *np; + + if (argc != 2) { + usage(usage_msg); + return 1; + } + + argv++; + p = *argv; + + ignore_case = 1; + + np = get_path_ignorecase(p); + + printf("%s\n", np); + + return 0; +} -- 1.7.12.1.gfe115d7 -- 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