From: Junio C Hamano Date: Thu, 16 Dec 2010 20:49:48 +0000 (-0800) Subject: Merge branch 'nd/maint-relative' X-Git-Tag: v1.7.4-rc0~36 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/20cb8e202520173727f3ea060e1eca035b32e2b7?hp=-c Merge branch 'nd/maint-relative' * nd/maint-relative: get_cwd_relative(): do not misinterpret root path --- 20cb8e202520173727f3ea060e1eca035b32e2b7 diff --combined dir.c index 852e60f2a8,ee9299db05..38f3e3eb97 --- a/dir.c +++ b/dir.c @@@ -18,22 -18,6 +18,22 @@@ static int read_directory_recursive(str int check_only, const struct path_simplify *simplify); static int get_dtype(struct dirent *de, const char *path, int len); +/* helper string functions with support for the ignore_case flag */ +int strcmp_icase(const char *a, const char *b) +{ + return ignore_case ? strcasecmp(a, b) : strcmp(a, b); +} + +int strncmp_icase(const char *a, const char *b, size_t count) +{ + return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count); +} + +int fnmatch_icase(const char *pattern, const char *string, int flags) +{ + return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0)); +} + static int common_prefix(const char **pathspec) { const char *path, *slash, *next; @@@ -107,30 -91,16 +107,30 @@@ static int match_one(const char *match if (!*match) return MATCHED_RECURSIVELY; - for (;;) { - unsigned char c1 = *match; - unsigned char c2 = *name; - if (c1 == '\0' || is_glob_special(c1)) - break; - if (c1 != c2) - return 0; - match++; - name++; - namelen--; + if (ignore_case) { + for (;;) { + unsigned char c1 = tolower(*match); + unsigned char c2 = tolower(*name); + if (c1 == '\0' || is_glob_special(c1)) + break; + if (c1 != c2) + return 0; + match++; + name++; + namelen--; + } + } else { + for (;;) { + unsigned char c1 = *match; + unsigned char c2 = *name; + if (c1 == '\0' || is_glob_special(c1)) + break; + if (c1 != c2) + return 0; + match++; + name++; + namelen--; + } } @@@ -139,8 -109,8 +139,8 @@@ * we need to match by fnmatch */ matchlen = strlen(match); - if (strncmp(match, name, matchlen)) - return !fnmatch(match, name, 0) ? MATCHED_FNMATCH : 0; + if (strncmp_icase(match, name, matchlen)) + return !fnmatch_icase(match, name, 0) ? MATCHED_FNMATCH : 0; if (namelen == matchlen) return MATCHED_EXACTLY; @@@ -262,7 -232,7 +262,7 @@@ int add_excludes_from_file_to_list(cons { struct stat st; int fd, i; - size_t size; + size_t size = 0; char *buf, *entry; fd = open(fname, O_RDONLY); @@@ -390,8 -360,7 +390,8 @@@ int excluded_from_list(const char *path if (x->flags & EXC_FLAG_MUSTBEDIR) { if (!dtype) { - if (!prefixcmp(pathname, exclude)) + if (!prefixcmp(pathname, exclude) && + pathname[x->patternlen] == '/') return to_exclude; else continue; @@@ -405,14 -374,14 +405,14 @@@ if (x->flags & EXC_FLAG_NODIR) { /* match basename */ if (x->flags & EXC_FLAG_NOWILDCARD) { - if (!strcmp(exclude, basename)) + if (!strcmp_icase(exclude, basename)) return to_exclude; } else if (x->flags & EXC_FLAG_ENDSWITH) { if (x->patternlen - 1 <= pathlen && - !strcmp(exclude + 1, pathname + pathlen - x->patternlen + 1)) + !strcmp_icase(exclude + 1, pathname + pathlen - x->patternlen + 1)) return to_exclude; } else { - if (fnmatch(exclude, basename, 0) == 0) + if (fnmatch_icase(exclude, basename, 0) == 0) return to_exclude; } } @@@ -427,14 -396,14 +427,14 @@@ if (pathlen < baselen || (baselen && pathname[baselen-1] != '/') || - strncmp(pathname, x->base, baselen)) + strncmp_icase(pathname, x->base, baselen)) continue; if (x->flags & EXC_FLAG_NOWILDCARD) { - if (!strcmp(exclude, pathname + baselen)) + if (!strcmp_icase(exclude, pathname + baselen)) return to_exclude; } else { - if (fnmatch(exclude, pathname+baselen, + if (fnmatch_icase(exclude, pathname+baselen, FNM_PATHNAME) == 0) return to_exclude; } @@@ -484,7 -453,7 +484,7 @@@ static struct dir_entry *dir_add_name(s return dir->entries[dir->nr++] = dir_entry_new(pathname, len); } -static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len) +struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len) { if (!cache_name_is_other(pathname, len)) return NULL; @@@ -496,42 -465,9 +496,42 @@@ enum exist_status { index_nonexistent = 0, index_directory, - index_gitdir, + index_gitdir }; +/* + * Do not use the alphabetically stored index to look up + * the directory name; instead, use the case insensitive + * name hash. + */ +static enum exist_status directory_exists_in_index_icase(const char *dirname, int len) +{ + struct cache_entry *ce = index_name_exists(&the_index, dirname, len + 1, ignore_case); + unsigned char endchar; + + if (!ce) + return index_nonexistent; + endchar = ce->name[len]; + + /* + * The cache_entry structure returned will contain this dirname + * and possibly additional path components. + */ + if (endchar == '/') + return index_directory; + + /* + * If there are no additional path components, then this cache_entry + * represents a submodule. Submodules, despite being directories, + * are stored in the cache without a closing slash. + */ + if (!endchar && S_ISGITLINK(ce->ce_mode)) + return index_gitdir; + + /* This should never be hit, but it exists just in case. */ + return index_nonexistent; +} + /* * The index sorts alphabetically by entry name, which * means that a gitlink sorts as '\0' at the end, while @@@ -541,12 -477,7 +541,12 @@@ */ static enum exist_status directory_exists_in_index(const char *dirname, int len) { - int pos = cache_name_pos(dirname, len); + int pos; + + if (ignore_case) + return directory_exists_in_index_icase(dirname, len); + + pos = cache_name_pos(dirname, len); if (pos < 0) pos = -pos-1; while (pos < active_nr) { @@@ -602,7 -533,7 +602,7 @@@ enum directory_treatment { show_directory, ignore_directory, - recurse_into_directory, + recurse_into_directory }; static enum directory_treatment treat_directory(struct dir_struct *dir, @@@ -753,7 -684,7 +753,7 @@@ static int get_dtype(struct dirent *de enum path_treatment { path_ignored, path_handled, - path_recurse, + path_recurse }; static enum path_treatment treat_one_path(struct dir_struct *dir, @@@ -1033,6 -964,12 +1033,12 @@@ char *get_relative_cwd(char *buffer, in case '/': return cwd + 1; default: + /* + * dir can end with a path separator when it's root + * directory. Return proper prefix in that case. + */ + if (dir[-1] == '/') + return cwd; return NULL; } }