Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Kelley <phkelley@hotmail.com>2012-09-17 23:42:41 +0400
committerPhilip Kelley <phkelley@hotmail.com>2012-09-17 23:42:41 +0400
commitec40b7f99f7f7161b0a1b24f1d8a934ec0eaacb1 (patch)
tree59744c10038258c3993a4eb1b1dfc3896c35b97a /src/iterator.c
parente8776d30f7edb570f435cf746d712c696b862bdd (diff)
Support for core.ignorecase
Diffstat (limited to 'src/iterator.c')
-rw-r--r--src/iterator.c189
1 files changed, 177 insertions, 12 deletions
diff --git a/src/iterator.c b/src/iterator.c
index e30e11220..e52554d4f 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -17,6 +17,7 @@
(P)->base.type = GIT_ITERATOR_ ## NAME_UC; \
(P)->base.start = start ? git__strdup(start) : NULL; \
(P)->base.end = end ? git__strdup(end) : NULL; \
+ (P)->base.ignore_case = 0; \
(P)->base.current = NAME_LC ## _iterator__current; \
(P)->base.at_end = NAME_LC ## _iterator__at_end; \
(P)->base.advance = NAME_LC ## _iterator__advance; \
@@ -336,7 +337,7 @@ static int index_iterator__current(
if (ie != NULL &&
ii->base.end != NULL &&
- git__prefixcmp(ie->path, ii->base.end) > 0)
+ ITERATOR_PREFIXCMP(ii->base, ie->path, ii->base.end) > 0)
{
ii->current = git_index_entrycount(ii->index);
ie = NULL;
@@ -401,6 +402,7 @@ int git_iterator_for_index_range(
if ((error = git_repository_index(&ii->index, repo)) < 0)
git__free(ii);
else {
+ ii->base.ignore_case = ii->index->ignore_case;
ii->current = start ? git_index__prefix_position(ii->index, start) : 0;
*iter = (git_iterator *)ii;
}
@@ -428,12 +430,30 @@ typedef struct {
int is_ignored;
} workdir_iterator;
-static workdir_iterator_frame *workdir_iterator__alloc_frame(void)
+static int git_path_with_stat_cmp_case(const void *a, const void *b)
+{
+ const git_path_with_stat *path_with_stat_a = a;
+ const git_path_with_stat *path_with_stat_b = b;
+
+ return strcmp(path_with_stat_a->path, path_with_stat_b->path);
+}
+
+static int git_path_with_stat_cmp_icase(const void *a, const void *b)
+{
+ const git_path_with_stat *path_with_stat_a = a;
+ const git_path_with_stat *path_with_stat_b = b;
+
+ return strcasecmp(path_with_stat_a->path, path_with_stat_b->path);
+}
+
+static workdir_iterator_frame *workdir_iterator__alloc_frame(workdir_iterator *wi)
{
workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame));
+ git_vector_cmp entry_compare = CASESELECT(wi->base.ignore_case, git_path_with_stat_cmp_icase, git_path_with_stat_cmp_case);
+
if (wf == NULL)
return NULL;
- if (git_vector_init(&wf->entries, 0, git_path_with_stat_cmp) != 0) {
+ if (git_vector_init(&wf->entries, 0, entry_compare) != 0) {
git__free(wf);
return NULL;
}
@@ -453,16 +473,22 @@ static void workdir_iterator__free_frame(workdir_iterator_frame *wf)
static int workdir_iterator__update_entry(workdir_iterator *wi);
-static int workdir_iterator__entry_cmp(const void *prefix, const void *item)
+static int workdir_iterator__entry_cmp_case(const void *prefix, const void *item)
{
const git_path_with_stat *ps = item;
return git__prefixcmp((const char *)prefix, ps->path);
}
+static int workdir_iterator__entry_cmp_icase(const void *prefix, const void *item)
+{
+ const git_path_with_stat *ps = item;
+ return git__prefixcmp_icase((const char *)prefix, ps->path);
+}
+
static int workdir_iterator__expand_dir(workdir_iterator *wi)
{
int error;
- workdir_iterator_frame *wf = workdir_iterator__alloc_frame();
+ workdir_iterator_frame *wf = workdir_iterator__alloc_frame(wi);
GITERR_CHECK_ALLOC(wf);
error = git_path_dirload_with_stat(wi->path.ptr, wi->root_len, &wf->entries);
@@ -476,12 +502,15 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
if (!wi->stack)
wf->start = wi->base.start;
else if (wi->stack->start &&
- git__prefixcmp(wi->stack->start, wi->path.ptr + wi->root_len) == 0)
+ ITERATOR_PREFIXCMP(wi->base, wi->stack->start, wi->path.ptr + wi->root_len) == 0)
wf->start = wi->stack->start;
if (wf->start)
git_vector_bsearch3(
- &wf->index, &wf->entries, workdir_iterator__entry_cmp, wf->start);
+ &wf->index,
+ &wf->entries,
+ CASESELECT(wi->base.ignore_case, workdir_iterator__entry_cmp_icase, workdir_iterator__entry_cmp_case),
+ wf->start);
wf->next = wi->stack;
wi->stack = wf;
@@ -526,8 +555,8 @@ static int workdir_iterator__advance(
next = git_vector_get(&wf->entries, ++wf->index);
if (next != NULL) {
/* match git's behavior of ignoring anything named ".git" */
- if (strcmp(next->path, DOT_GIT "/") == 0 ||
- strcmp(next->path, DOT_GIT) == 0)
+ if (STRCMP_CASESELECT(wi->base.ignore_case, next->path, DOT_GIT "/") == 0 ||
+ STRCMP_CASESELECT(wi->base.ignore_case, next->path, DOT_GIT) == 0)
continue;
/* else found a good entry */
break;
@@ -604,13 +633,14 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
return -1;
if (wi->base.end &&
- git__prefixcmp(wi->path.ptr + wi->root_len, wi->base.end) > 0)
+ ITERATOR_PREFIXCMP(wi->base, wi->path.ptr + wi->root_len, wi->base.end) > 0)
return 0;
wi->entry.path = ps->path;
/* skip over .git entry */
- if (strcmp(ps->path, DOT_GIT "/") == 0 || strcmp(ps->path, DOT_GIT) == 0)
+ if (STRCMP_CASESELECT(wi->base.ignore_case, ps->path, DOT_GIT "/") == 0 ||
+ STRCMP_CASESELECT(wi->base.ignore_case, ps->path, DOT_GIT) == 0)
return workdir_iterator__advance((git_iterator *)wi, NULL);
/* if there is an error processing the entry, treat as ignored */
@@ -656,6 +686,7 @@ int git_iterator_for_workdir_range(
{
int error;
workdir_iterator *wi;
+ git_index *index;
assert(iter && repo);
@@ -666,6 +697,17 @@ int git_iterator_for_workdir_range(
wi->repo = repo;
+ if ((error = git_repository_index(&index, repo)) < 0) {
+ git__free(wi);
+ return error;
+ }
+
+ /* Set the ignore_case flag for the workdir iterator to match
+ * that of the index. */
+ wi->base.ignore_case = index->ignore_case;
+
+ git_index_free(index);
+
if (git_buf_sets(&wi->path, git_repository_workdir(repo)) < 0 ||
git_path_to_dir(&wi->path) < 0 ||
git_ignore__for_path(repo, "", &wi->ignores) < 0)
@@ -690,6 +732,129 @@ int git_iterator_for_workdir_range(
return error;
}
+typedef struct {
+ git_iterator base;
+ git_iterator *wrapped;
+ git_vector entries;
+ git_vector_cmp comparer;
+ git_pool entry_pool;
+ git_pool string_pool;
+ unsigned int position;
+} spoolandsort_iterator;
+
+static int spoolandsort_iterator__current(
+ git_iterator *self, const git_index_entry **entry)
+{
+ spoolandsort_iterator *si = (spoolandsort_iterator *)self;
+
+ if (si->position < si->entries.length)
+ *entry = (const git_index_entry *)git_vector_get_const(&si->entries, si->position);
+ else
+ *entry = NULL;
+
+ return 0;
+}
+
+static int spoolandsort_iterator__at_end(git_iterator *self)
+{
+ spoolandsort_iterator *si = (spoolandsort_iterator *)self;
+
+ return 0 == si->entries.length || si->entries.length - 1 <= si->position;
+}
+
+static int spoolandsort_iterator__advance(
+ git_iterator *self, const git_index_entry **entry)
+{
+ spoolandsort_iterator *si = (spoolandsort_iterator *)self;
+
+ if (si->position < si->entries.length)
+ *entry = (const git_index_entry *)git_vector_get_const(&si->entries, ++si->position);
+ else
+ *entry = NULL;
+
+ return 0;
+}
+
+static int spoolandsort_iterator__seek(git_iterator *self, const char *prefix)
+{
+ GIT_UNUSED(self);
+ GIT_UNUSED(prefix);
+
+ return -1;
+}
+
+static int spoolandsort_iterator__reset(git_iterator *self)
+{
+ spoolandsort_iterator *si = (spoolandsort_iterator *)self;
+
+ si->position = 0;
+
+ return 0;
+}
+
+static void spoolandsort_iterator__free(git_iterator *self)
+{
+ spoolandsort_iterator *si = (spoolandsort_iterator *)self;
+
+ git_pool_clear(&si->string_pool);
+ git_pool_clear(&si->entry_pool);
+ git_vector_free(&si->entries);
+ git_iterator_free(si->wrapped);
+}
+
+int git_iterator_spoolandsort_range(
+ git_iterator **iter,
+ git_iterator *towrap,
+ git_vector_cmp comparer,
+ bool ignore_case,
+ const char *start,
+ const char *end)
+{
+ spoolandsort_iterator *si;
+ const git_index_entry *item;
+
+ assert(iter && towrap && comparer);
+
+ ITERATOR_BASE_INIT(si, spoolandsort, SPOOLANDSORT);
+ si->base.ignore_case = ignore_case;
+ si->wrapped = towrap;
+ si->comparer = comparer;
+ si->position = 0;
+
+ if (git_vector_init(&si->entries, 16, si->comparer) < 0 ||
+ git_iterator_current(towrap, &item) < 0 ||
+ git_pool_init(&si->entry_pool, sizeof(git_index_entry), 0) ||
+ git_pool_init(&si->string_pool, 1, 0))
+ {
+ git__free(si);
+ return -1;
+ }
+
+ while (item)
+ {
+ git_index_entry *clone = git_pool_malloc(&si->entry_pool, 1);
+ memcpy(clone, item, sizeof(git_index_entry));
+
+ if (item->path)
+ {
+ clone->path = git_pool_strdup(&si->string_pool, item->path);
+ }
+
+ git_vector_insert(&si->entries, clone);
+
+ if (git_iterator_advance(towrap, &item) < 0)
+ {
+ git__free(si);
+ return -1;
+ }
+ }
+
+ git_vector_sort(&si->entries);
+
+ *iter = (git_iterator *)si;
+
+ return 0;
+}
int git_iterator_current_tree_entry(
git_iterator *iter, const git_tree_entry **tree_entry)
@@ -737,6 +902,6 @@ int git_iterator_cmp(
if (!path_prefix)
return -1;
- return git__prefixcmp(entry->path, path_prefix);
+ return ITERATOR_PREFIXCMP(*iter, entry->path, path_prefix);
}