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.thie...@gmail.com>
---
 .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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to