Put hooks in place for precompose in dirload fn This doesn't actual do string precompose but it puts the hooks in place into the iterators and the git_path_dirload function so that the actual precompose work is ready to go.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
diff --git a/src/config_cache.c b/src/config_cache.c
index 84de3a5..6808521 100644
--- a/src/config_cache.c
+++ b/src/config_cache.c
@@ -67,6 +67,7 @@ static struct map_data _cvar_maps[] = {
{"core.ignorestat", NULL, 0, GIT_IGNORESTAT_DEFAULT },
{"core.trustctime", NULL, 0, GIT_TRUSTCTIME_DEFAULT },
{"core.abbrev", _cvar_map_int, 1, GIT_ABBREV_DEFAULT },
+ {"core.precomposeunicode", NULL, 0, GIT_PRECOMPOSE_DEFAULT },
};
int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar)
diff --git a/src/iterator.c b/src/iterator.c
index bdc98d2..9467904 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -986,7 +986,10 @@ static int fs_iterator__expand_dir(fs_iterator *fi)
GITERR_CHECK_ALLOC(ff);
error = git_path_dirload_with_stat(
- fi->path.ptr, fi->root_len, iterator__ignore_case(fi),
+ fi->path.ptr, fi->root_len,
+ (iterator__ignore_case(fi) ? GIT_PATH_DIRLOAD_IGNORE_CASE : 0) |
+ (iterator__flag(fi, PRECOMPOSE_UNICODE) ?
+ GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE : 0),
fi->base.start, fi->base.end, &ff->entries);
if (error < 0) {
@@ -1356,6 +1359,15 @@ int git_iterator_for_workdir_ext(
return error;
}
+ /* try to look up precompose and set flag if appropriate */
+ {
+ int precompose = 0;
+ if (git_repository__cvar(&precompose, repo, GIT_CVAR_PRECOMPOSE) < 0)
+ giterr_clear();
+ else if (precompose)
+ wi->fi.base.flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE;
+ }
+
return fs_iterator__initialize(out, &wi->fi, repo_workdir);
}
diff --git a/src/iterator.h b/src/iterator.h
index ea88fa6..751e139 100644
--- a/src/iterator.h
+++ b/src/iterator.h
@@ -24,13 +24,15 @@ typedef enum {
typedef enum {
/** ignore case for entry sort order */
- GIT_ITERATOR_IGNORE_CASE = (1 << 0),
+ GIT_ITERATOR_IGNORE_CASE = (1u << 0),
/** force case sensitivity for entry sort order */
- GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1),
+ GIT_ITERATOR_DONT_IGNORE_CASE = (1u << 1),
/** return tree items in addition to blob items */
- GIT_ITERATOR_INCLUDE_TREES = (1 << 2),
+ GIT_ITERATOR_INCLUDE_TREES = (1u << 2),
/** don't flatten trees, requiring advance_into (implies INCLUDE_TREES) */
- GIT_ITERATOR_DONT_AUTOEXPAND = (1 << 3),
+ GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3),
+ /** convert precomposed unicode to decomposed unicode */
+ GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
} git_iterator_flag_t;
typedef struct {
diff --git a/src/path.c b/src/path.c
index 9d8e903..c4ab571 100644
--- a/src/path.c
+++ b/src/path.c
@@ -781,6 +781,7 @@ int git_path_dirload(
const char *path,
size_t prefix_len,
size_t alloc_extra,
+ unsigned int flags,
git_vector *contents)
{
int error, need_slash;
@@ -816,6 +817,12 @@ int git_path_dirload(
entry_len = strlen(de->d_name);
+ /* if we read decomposed unicode and precompose flag is set,
+ * then precompose it now so app code sees it as precomposed
+ */
+ if ((flags & GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE) != 0) {
+ }
+
entry_path = git__malloc(
path_len + need_slash + entry_len + 1 + alloc_extra);
GITERR_CHECK_ALLOC(entry_path);
@@ -858,7 +865,7 @@ int git_path_with_stat_cmp_icase(const void *a, const void *b)
int git_path_dirload_with_stat(
const char *path,
size_t prefix_len,
- bool ignore_case,
+ unsigned int flags,
const char *start_stat,
const char *end_stat,
git_vector *contents)
@@ -875,13 +882,14 @@ int git_path_dirload_with_stat(
return -1;
error = git_path_dirload(
- path, prefix_len, sizeof(git_path_with_stat) + 1, contents);
+ path, prefix_len, sizeof(git_path_with_stat) + 1, flags, contents);
if (error < 0) {
git_buf_free(&full);
return error;
}
- strncomp = ignore_case ? git__strncasecmp : git__strncmp;
+ strncomp = (flags & GIT_PATH_DIRLOAD_IGNORE_CASE) != 0 ?
+ git__strncasecmp : git__strncmp;
/* stat struct at start of git_path_with_stat, so shift path text */
git_vector_foreach(contents, i, ps) {
diff --git a/src/path.h b/src/path.h
index b2899e9..feacc99 100644
--- a/src/path.h
+++ b/src/path.h
@@ -290,6 +290,11 @@ extern int git_path_walk_up(
int (*fn)(void *state, git_buf *),
void *state);
+enum {
+ GIT_PATH_DIRLOAD_IGNORE_CASE = (1u << 0),
+ GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE = (1u << 1),
+};
+
/**
* Load all directory entries (except '.' and '..') into a vector.
*
@@ -310,6 +315,7 @@ extern int git_path_dirload(
const char *path,
size_t prefix_len,
size_t alloc_extra,
+ unsigned int flags,
git_vector *contents);
@@ -336,7 +342,7 @@ extern int git_path_with_stat_cmp_icase(const void *a, const void *b);
*
* @param path The directory to read from
* @param prefix_len The trailing part of path to prefix to entry paths
- * @param ignore_case How to sort and compare paths with start/end limits
+ * @param flags GIT_PATH_DIRLOAD flags from above
* @param start_stat As optimization, only stat values after this prefix
* @param end_stat As optimization, only stat values before this prefix
* @param contents Vector to fill with git_path_with_stat structures
@@ -344,7 +350,7 @@ extern int git_path_with_stat_cmp_icase(const void *a, const void *b);
extern int git_path_dirload_with_stat(
const char *path,
size_t prefix_len,
- bool ignore_case,
+ unsigned int flags,
const char *start_stat,
const char *end_stat,
git_vector *contents);
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 0ba711e..715b311 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -458,17 +458,23 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter)
static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter)
{
- int error = 0;
+ int error = 0, t;
git_buf path = GIT_BUF_INIT;
+ git_iterator_flag_t flags = 0;
git_iterator *fsit = NULL;
const git_index_entry *entry = NULL;
if (!backend->path) /* do nothing if no path for loose refs */
return 0;
+ if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_IGNORECASE) && t)
+ flags |= GIT_ITERATOR_IGNORE_CASE;
+ if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_PRECOMPOSE) && t)
+ flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE;
+
if ((error = git_buf_printf(&path, "%s/refs", backend->path)) < 0 ||
(error = git_iterator_for_filesystem(
- &fsit, git_buf_cstr(&path), 0, NULL, NULL)) < 0) {
+ &fsit, git_buf_cstr(&path), flags, NULL, NULL)) < 0) {
git_buf_free(&path);
return error;
}
diff --git a/src/repository.h b/src/repository.h
index 12dc50d..832df3b 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -37,6 +37,7 @@ typedef enum {
GIT_CVAR_IGNORESTAT, /* core.ignorestat */
GIT_CVAR_TRUSTCTIME, /* core.trustctime */
GIT_CVAR_ABBREV, /* core.abbrev */
+ GIT_CVAR_PRECOMPOSE, /* core.precomposeunicode */
GIT_CVAR_CACHE_MAX
} git_cvar_cached;
@@ -86,6 +87,8 @@ typedef enum {
GIT_TRUSTCTIME_DEFAULT = GIT_CVAR_TRUE,
/* core.abbrev */
GIT_ABBREV_DEFAULT = 7,
+ /* core.precomposeunicode */
+ GIT_PRECOMPOSE_DEFAULT = GIT_CVAR_FALSE,
} git_cvar_value;