summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/checkout.c39
-rw-r--r--src/diff.c41
-rw-r--r--src/index.c51
-rw-r--r--src/index.h3
-rw-r--r--src/iterator.c257
-rw-r--r--src/iterator.h97
-rw-r--r--src/notes.c6
-rw-r--r--src/submodule.c12
8 files changed, 233 insertions, 273 deletions
diff --git a/src/checkout.c b/src/checkout.c
index 19ac913d3..0be87b4a3 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -456,7 +456,7 @@ static int checkout_action(
while (1) {
if (!wd)
return checkout_action_no_wd(data, delta);
-
+
cmp = strcomp(wd->path, delta->old_file.path);
/* 1. wd before delta ("a/a" before "a/b")
@@ -473,9 +473,9 @@ static int checkout_action(
if (cmp == 0) {
if (wd->mode == GIT_FILEMODE_TREE) {
/* case 2 - entry prefixed by workdir tree */
- if (git_iterator_advance_into_directory(workdir, &wd) < 0)
+ if (git_iterator_advance_into(&wd, workdir) < 0)
goto fail;
-
+
*wditem_ptr = wd;
continue;
}
@@ -484,14 +484,14 @@ static int checkout_action(
if (delta->old_file.path[strlen(wd->path)] == '/') {
act = checkout_action_with_wd_blocker(data, delta, wd);
*wditem_ptr =
- git_iterator_advance(workdir, &wd) ? NULL : wd;
+ git_iterator_advance(&wd, workdir) ? NULL : wd;
return act;
}
}
/* case 1 - handle wd item (if it matches pathspec) */
if (checkout_action_wd_only(data, workdir, wd, pathspec) < 0 ||
- git_iterator_advance(workdir, &wd) < 0)
+ git_iterator_advance(&wd, workdir) < 0)
goto fail;
*wditem_ptr = wd;
@@ -501,7 +501,7 @@ static int checkout_action(
if (cmp == 0) {
/* case 4 */
act = checkout_action_with_wd(data, delta, wd);
- *wditem_ptr = git_iterator_advance(workdir, &wd) ? NULL : wd;
+ *wditem_ptr = git_iterator_advance(&wd, workdir) ? NULL : wd;
return act;
}
@@ -514,7 +514,7 @@ static int checkout_action(
if (delta->status == GIT_DELTA_TYPECHANGE) {
if (delta->old_file.mode == GIT_FILEMODE_TREE) {
act = checkout_action_with_wd(data, delta, wd);
- if (git_iterator_advance_into_directory(workdir, &wd) < 0)
+ if (git_iterator_advance_into(&wd, workdir) < 0)
wd = NULL;
*wditem_ptr = wd;
return act;
@@ -525,7 +525,7 @@ static int checkout_action(
delta->old_file.mode == GIT_FILEMODE_COMMIT)
{
act = checkout_action_with_wd(data, delta, wd);
- if (git_iterator_advance(workdir, &wd) < 0)
+ if (git_iterator_advance(&wd, workdir) < 0)
wd = NULL;
*wditem_ptr = wd;
return act;
@@ -554,7 +554,7 @@ static int checkout_remaining_wd_items(
while (wd && !error) {
if (!(error = checkout_action_wd_only(data, workdir, wd, spec)))
- error = git_iterator_advance(workdir, &wd);
+ error = git_iterator_advance(&wd, workdir);
}
return error;
@@ -578,7 +578,7 @@ static int checkout_get_actions(
git_pathspec_init(&pathspec, &data->opts.paths, &pathpool) < 0)
return -1;
- if ((error = git_iterator_current(workdir, &wditem)) < 0)
+ if ((error = git_iterator_current(&wditem, workdir)) < 0)
goto fail;
deltas = &data->diff->deltas;
@@ -1134,16 +1134,17 @@ static int checkout_data_init(
if ((error = git_config_refresh(cfg)) < 0)
goto cleanup;
- if (git_iterator_inner_type(target) == GIT_ITERATOR_TYPE_INDEX) {
- /* if we are iterating over the index, don't reload */
- data->index = git_iterator_index_get_index(target);
+ /* if we are checking out the index, don't reload,
+ * otherwise get index and force reload
+ */
+ if ((data->index = git_iterator_get_index(target)) != NULL) {
GIT_REFCOUNT_INC(data->index);
} else {
/* otherwise, grab and reload the index */
if ((error = git_repository_index(&data->index, data->repo)) < 0 ||
(error = git_index_read(data->index)) < 0)
goto cleanup;
-
+
/* clear the REUC when doing a tree or commit checkout */
git_index_reuc_clear(data->index);
}
@@ -1241,9 +1242,9 @@ int git_checkout_iterator(
GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE;
if ((error = git_iterator_reset(target, data.pfx, data.pfx)) < 0 ||
- (error = git_iterator_for_workdir_range(
+ (error = git_iterator_for_workdir(
&workdir, data.repo, iterflags, data.pfx, data.pfx)) < 0 ||
- (error = git_iterator_for_tree_range(
+ (error = git_iterator_for_tree(
&baseline, data.opts.baseline, iterflags, data.pfx, data.pfx)) < 0)
goto cleanup;
@@ -1321,7 +1322,7 @@ int git_checkout_index(
return error;
GIT_REFCOUNT_INC(index);
- if (!(error = git_iterator_for_index(&index_i, index)))
+ if (!(error = git_iterator_for_index(&index_i, index, 0, NULL, NULL)))
error = git_checkout_iterator(index_i, opts);
git_iterator_free(index_i);
@@ -1348,7 +1349,7 @@ int git_checkout_tree(
return -1;
}
- if (!(error = git_iterator_for_tree(&tree_i, tree)))
+ if (!(error = git_iterator_for_tree(&tree_i, tree, 0, NULL, NULL)))
error = git_checkout_iterator(tree_i, opts);
git_iterator_free(tree_i);
@@ -1369,7 +1370,7 @@ int git_checkout_head(
return error;
if (!(error = checkout_lookup_head_tree(&head, repo)) &&
- !(error = git_iterator_for_tree(&head_i, head)))
+ !(error = git_iterator_for_tree(&head_i, head, 0, NULL, NULL)))
error = git_checkout_iterator(head_i, opts);
git_iterator_free(head_i);
diff --git a/src/diff.c b/src/diff.c
index 0861b13eb..c0f8ee689 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -630,8 +630,8 @@ int git_diff__from_iterators(
goto fail;
}
- if (git_iterator_current(old_iter, &oitem) < 0 ||
- git_iterator_current(new_iter, &nitem) < 0)
+ if (git_iterator_current(&oitem, old_iter) < 0 ||
+ git_iterator_current(&nitem, new_iter) < 0)
goto fail;
/* run iterators building diffs */
@@ -663,12 +663,12 @@ int git_diff__from_iterators(
if (S_ISDIR(nitem->mode) &&
!(diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS))
{
- if (git_iterator_advance(new_iter, &nitem) < 0)
+ if (git_iterator_advance(&nitem, new_iter) < 0)
goto fail;
}
}
- if (git_iterator_advance(old_iter, &oitem) < 0)
+ if (git_iterator_advance(&oitem, old_iter) < 0)
goto fail;
}
@@ -696,7 +696,7 @@ int git_diff__from_iterators(
/* do not advance into directories that contain a .git file */
if (!contains_oitem && recurse_untracked) {
git_buf *full = NULL;
- if (git_iterator_current_workdir_path(new_iter, &full) < 0)
+ if (git_iterator_current_workdir_path(&full, new_iter) < 0)
goto fail;
if (git_path_contains_dir(full, DOT_GIT))
recurse_untracked = false;
@@ -710,7 +710,7 @@ int git_diff__from_iterators(
git_iterator_current_is_ignored(new_iter))
git_buf_sets(&ignore_prefix, nitem->path);
- if (git_iterator_advance_into_directory(new_iter, &nitem) < 0)
+ if (git_iterator_advance_into(&nitem, new_iter) < 0)
goto fail;
continue;
@@ -733,7 +733,7 @@ int git_diff__from_iterators(
* skip the file.
*/
else if (delta_type == GIT_DELTA_IGNORED) {
- if (git_iterator_advance(new_iter, &nitem) < 0)
+ if (git_iterator_advance(&nitem, new_iter) < 0)
goto fail;
continue; /* ignored parent directory, so skip completely */
}
@@ -762,7 +762,7 @@ int git_diff__from_iterators(
}
}
- if (git_iterator_advance(new_iter, &nitem) < 0)
+ if (git_iterator_advance(&nitem, new_iter) < 0)
goto fail;
}
@@ -772,11 +772,10 @@ int git_diff__from_iterators(
else {
assert(oitem && nitem && cmp == 0);
- if (maybe_modified(
- old_iter, oitem, new_iter, nitem, diff) < 0 ||
- git_iterator_advance(old_iter, &oitem) < 0 ||
- git_iterator_advance(new_iter, &nitem) < 0)
- goto fail;
+ if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 ||
+ git_iterator_advance(&oitem, old_iter) < 0 ||
+ git_iterator_advance(&nitem, new_iter) < 0)
+ goto fail;
}
}
@@ -814,8 +813,8 @@ int git_diff_tree_to_tree(
assert(diff && repo);
DIFF_FROM_ITERATORS(
- git_iterator_for_tree_range(&a, old_tree, 0, pfx, pfx),
- git_iterator_for_tree_range(&b, new_tree, 0, pfx, pfx)
+ git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
+ git_iterator_for_tree(&b, new_tree, 0, pfx, pfx)
);
return error;
@@ -836,8 +835,8 @@ int git_diff_tree_to_index(
return error;
DIFF_FROM_ITERATORS(
- git_iterator_for_tree_range(&a, old_tree, 0, pfx, pfx),
- git_iterator_for_index_range(&b, index, 0, pfx, pfx)
+ git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
+ git_iterator_for_index(&b, index, 0, pfx, pfx)
);
return error;
@@ -857,8 +856,8 @@ int git_diff_index_to_workdir(
return error;
DIFF_FROM_ITERATORS(
- git_iterator_for_index_range(&a, index, 0, pfx, pfx),
- git_iterator_for_workdir_range(&b, repo, 0, pfx, pfx)
+ git_iterator_for_index(&a, index, 0, pfx, pfx),
+ git_iterator_for_workdir(&b, repo, 0, pfx, pfx)
);
return error;
@@ -876,8 +875,8 @@ int git_diff_tree_to_workdir(
assert(diff && repo);
DIFF_FROM_ITERATORS(
- git_iterator_for_tree_range(&a, old_tree, 0, pfx, pfx),
- git_iterator_for_workdir_range(&b, repo, 0, pfx, pfx)
+ git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
+ git_iterator_for_workdir(&b, repo, 0, pfx, pfx)
);
return error;
diff --git a/src/index.c b/src/index.c
index 4deafd77f..1ca3b16b2 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1679,54 +1679,3 @@ git_repository *git_index_owner(const git_index *index)
{
return INDEX_OWNER(index);
}
-
-int git_index_read_tree_match(
- git_index *index, git_tree *tree, git_strarray *strspec)
-{
-#if 0
- git_iterator *iter = NULL;
- const git_index_entry *entry;
- char *pfx = NULL;
- git_vector pathspec = GIT_VECTOR_INIT;
- git_pool pathpool = GIT_POOL_INIT_STRINGPOOL;
-#endif
-
- if (!git_pathspec_is_interesting(strspec))
- return git_index_read_tree(index, tree);
-
- return git_index_read_tree(index, tree);
-
-#if 0
- /* The following loads the matches into the index, but doesn't
- * erase obsoleted entries (e.g. you load a blob at "a/b" which
- * should obsolete a blob at "a/b/c/d" since b is no longer a tree)
- */
-
- if (git_pathspec_init(&pathspec, strspec, &pathpool) < 0)
- return -1;
-
- pfx = git_pathspec_prefix(strspec);
-
- if ((error = git_iterator_for_tree_range(&iter, tree, pfx, pfx)) < 0 ||
- (error = git_iterator_current(iter, &entry)) < 0)
- goto cleanup;
-
- while (entry != NULL) {
- if (git_pathspec_match_path(
- &pathspec, entry->path, false, false, NULL) &&
- (error = git_index_add(index, entry)) < 0)
- goto cleanup;
-
- if ((error = git_iterator_advance(iter, &entry)) < 0)
- goto cleanup;
- }
-
-cleanup:
- git_iterator_free(iter);
- git_pathspec_free(&pathspec);
- git_pool_clear(&pathpool);
- git__free(pfx);
-
- return error;
-#endif
-}
diff --git a/src/index.h b/src/index.h
index 2beaa6375..9498907b6 100644
--- a/src/index.h
+++ b/src/index.h
@@ -50,7 +50,4 @@ extern int git_index_entry__cmp_icase(const void *a, const void *b);
extern void git_index__set_ignore_case(git_index *index, bool ignore_case);
-extern int git_index_read_tree_match(
- git_index *index, git_tree *tree, git_strarray *strspec);
-
#endif
diff --git a/src/iterator.c b/src/iterator.c
index 8ad639d6b..2832e4ac2 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -14,13 +14,16 @@
#define ITERATOR_SET_CB(P,NAME_LC) do { \
(P)->cb.current = NAME_LC ## _iterator__current; \
- (P)->cb.at_end = NAME_LC ## _iterator__at_end; \
(P)->cb.advance = NAME_LC ## _iterator__advance; \
(P)->cb.seek = NAME_LC ## _iterator__seek; \
(P)->cb.reset = NAME_LC ## _iterator__reset; \
+ (P)->cb.at_end = NAME_LC ## _iterator__at_end; \
(P)->cb.free = NAME_LC ## _iterator__free; \
} while (0)
+#define ITERATOR_CASE_FLAGS \
+ (GIT_ITERATOR_IGNORE_CASE | GIT_ITERATOR_DONT_IGNORE_CASE)
+
#define ITERATOR_BASE_INIT(P,NAME_LC,NAME_UC) do { \
(P) = git__calloc(1, sizeof(NAME_LC ## _iterator)); \
GITERR_CHECK_ALLOC(P); \
@@ -32,8 +35,17 @@
if ((start && !(P)->base.start) || (end && !(P)->base.end)) { \
git__free(P); return -1; } \
(P)->base.prefixcomp = git__prefixcmp; \
+ (P)->base.flags = flags & ~ITERATOR_CASE_FLAGS; \
} while (0)
+#define iterator__flag(I,F) ((((git_iterator *)(I))->flags & (F)) != 0)
+#define iterator__ignore_case(I) iterator__flag(I,GIT_ITERATOR_IGNORE_CASE)
+
+#define iterator__end(I) ((git_iterator *)(I))->end
+#define iterator__past_end(I,PATH) \
+ (iterator__end(I) && ((git_iterator *)(I))->prefixcomp((PATH),iterator__end(I)) > 0)
+
+
static int iterator__reset_range(
git_iterator *iter, const char *start, const char *end)
{
@@ -82,18 +94,13 @@ static int iterator_update_ignore_case(
return error;
}
-static int empty_iterator__no_item(
- git_iterator *iter, const git_index_entry **entry)
-{
- GIT_UNUSED(iter);
- *entry = NULL;
- return 0;
-}
-static int empty_iterator__at_end(git_iterator *iter)
+static int empty_iterator__noop(
+ const git_index_entry **entry, git_iterator *iter)
{
GIT_UNUSED(iter);
- return 1;
+ if (entry) *entry = NULL;
+ return 0;
}
static int empty_iterator__reset(
@@ -109,6 +116,12 @@ static int empty_iterator__seek(git_iterator *iter, const char *prefix)
return -1;
}
+static int empty_iterator__at_end(git_iterator *iter)
+{
+ GIT_UNUSED(iter);
+ return 1;
+}
+
static void empty_iterator__free(git_iterator *iter)
{
GIT_UNUSED(iter);
@@ -119,20 +132,22 @@ typedef struct {
git_iterator_callbacks cb;
} empty_iterator;
-int git_iterator_for_nothing(git_iterator **iter, git_iterator_flag_t flags)
+int git_iterator_for_nothing(
+ git_iterator **iter,
+ git_iterator_flag_t flags,
+ const char *start,
+ const char *end)
{
empty_iterator *i = git__calloc(1, sizeof(empty_iterator));
GITERR_CHECK_ALLOC(i);
- i->base.type = GIT_ITERATOR_TYPE_EMPTY;
- i->base.cb = &i->cb;
- i->base.flags = flags;
- i->cb.current = empty_iterator__no_item;
- i->cb.at_end = empty_iterator__at_end;
- i->cb.advance = empty_iterator__no_item;
- i->cb.seek = empty_iterator__seek;
- i->cb.reset = empty_iterator__reset;
- i->cb.free = empty_iterator__free;
+#define empty_iterator__current empty_iterator__noop
+#define empty_iterator__advance empty_iterator__noop
+
+ ITERATOR_BASE_INIT(i, empty, EMPTY);
+
+ if ((flags & GIT_ITERATOR_IGNORE_CASE) != 0)
+ i->base.flags |= GIT_ITERATOR_IGNORE_CASE;
*iter = (git_iterator *)i;
@@ -144,9 +159,10 @@ typedef struct tree_iterator_frame tree_iterator_frame;
struct tree_iterator_frame {
tree_iterator_frame *next, *prev;
git_tree *tree;
- char *start;
+ const char *start;
size_t startlen;
size_t index;
+ /* secondary tree index for case-insensitive sort */
void **icase_map;
void *icase_data[GIT_FLEX_ARRAY];
};
@@ -163,12 +179,15 @@ typedef struct {
GIT_INLINE(const git_tree_entry *)tree_iterator__tree_entry(tree_iterator *ti)
{
tree_iterator_frame *tf = ti->stack;
+ size_t entries = git_tree_entrycount(tf->tree), idx = tf->index;
- if (tf->index >= git_tree_entrycount(tf->tree))
+ if (idx >= entries)
return NULL;
- return git_tree_entry_byindex(
- tf->tree, tf->icase_map ? (size_t)tf->icase_map[tf->index] : tf->index);
+ if (tf->icase_map)
+ idx = (size_t)tf->icase_map[idx];
+
+ return git_tree_entry_byindex(tf->tree, idx);
}
static char *tree_iterator__current_filename(
@@ -218,7 +237,7 @@ static int tree_iterator__to_end(tree_iterator *ti)
}
static int tree_iterator__current(
- git_iterator *self, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *self)
{
tree_iterator *ti = (tree_iterator *)self;
const git_tree_entry *te = tree_iterator__tree_entry(ti);
@@ -236,7 +255,7 @@ static int tree_iterator__current(
if (ti->entry.path == NULL)
return -1;
- if (ti->base.end && ti->base.prefixcomp(ti->entry.path, ti->base.end) > 0)
+ if (iterator__past_end(ti, ti->entry.path))
return tree_iterator__to_end(ti);
if (entry)
@@ -290,26 +309,35 @@ static void tree_iterator__frame_seek_start(tree_iterator_frame *tf)
}
}
-static tree_iterator_frame *tree_iterator__alloc_frame(
- tree_iterator *ti, git_tree *tree, char *start)
+static int tree_iterator__push_frame(
+ tree_iterator *ti, git_tree *tree, const char *start)
{
size_t i, max_i = git_tree_entrycount(tree);
tree_iterator_frame *tf =
git__calloc(1, sizeof(tree_iterator_frame) + max_i * sizeof(void *));
- if (!tf)
- return NULL;
+ GITERR_CHECK_ALLOC(tf);
- tf->tree = tree;
+ tf->tree = tree;
+
+ tf->next = ti->stack;
+ ti->stack = tf;
+ if (tf->next)
+ tf->next->prev = tf;
+ else
+ ti->tail = tf;
if (start && *start) {
- tf->start = start;
+ tf->start = start;
tf->startlen = strlen(start);
}
+ ti->path_has_filename = false;
+
if (!max_i)
- return tf;
+ return 0;
- if ((ti->base.flags & GIT_ITERATOR_IGNORE_CASE) != 0) {
+ /* build secondary index if iterator is case-insensitive */
+ if (iterator__ignore_case(ti)) {
tf->icase_map = tf->icase_data;
for (i = 0; i < max_i; ++i)
@@ -321,7 +349,7 @@ static tree_iterator_frame *tree_iterator__alloc_frame(
tree_iterator__frame_seek_start(tf);
- return tf;
+ return 0;
}
static int tree_iterator__expand_tree(tree_iterator *ti)
@@ -329,16 +357,13 @@ static int tree_iterator__expand_tree(tree_iterator *ti)
int error;
git_tree *subtree;
const git_tree_entry *te = tree_iterator__tree_entry(ti);
- tree_iterator_frame *tf;
- char *relpath;
+ const char *relpath;
while (te != NULL && git_tree_entry__is_tree(te)) {
- if (git_buf_joinpath(&ti->path, ti->path.ptr, te->filename) < 0)
- return -1;
+ relpath = tree_iterator__current_filename(ti, te);
/* check that we have not passed the range end */
- if (ti->base.end != NULL &&
- ti->base.prefixcomp(ti->path.ptr, ti->base.end) > 0)
+ if (iterator__past_end(ti, relpath))
return tree_iterator__to_end(ti);
if ((error = git_tree_lookup(&subtree, ti->base.repo, &te->oid)) < 0)
@@ -354,12 +379,8 @@ static int tree_iterator__expand_tree(tree_iterator *ti)
relpath = ti->stack->start + te->filename_len + 1;
}
- if ((tf = tree_iterator__alloc_frame(ti, subtree, relpath)) == NULL)
- return -1;
-
- tf->next = ti->stack;
- ti->stack = tf;
- tf->next->prev = tf;
+ if ((error = tree_iterator__push_frame(ti, subtree, relpath)) < 0)
+ return error;
te = tree_iterator__tree_entry(ti);
}
@@ -368,9 +389,8 @@ static int tree_iterator__expand_tree(tree_iterator *ti)
}
static int tree_iterator__advance(
- git_iterator *self, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *self)
{
- int error = 0;
tree_iterator *ti = (tree_iterator *)self;
const git_tree_entry *te = NULL;
@@ -394,13 +414,13 @@ static int tree_iterator__advance(
git_buf_rtruncate_at_char(&ti->path, '/');
}
- if (te && git_tree_entry__is_tree(te))
- error = tree_iterator__expand_tree(ti);
-
- if (!error)
- error = tree_iterator__current(self, entry);
+ if (te && git_tree_entry__is_tree(te)) {
+ int error = tree_iterator__expand_tree(ti);
+ if (error < 0)
+ return error;
+ }
- return error;
+ return tree_iterator__current(entry, self);
}
static int tree_iterator__seek(git_iterator *self, const char *prefix)
@@ -444,7 +464,7 @@ static int tree_iterator__reset(
return tree_iterator__expand_tree(ti);
}
-int git_iterator_for_tree_range(
+int git_iterator_for_tree(
git_iterator **iter,
git_tree *tree,
git_iterator_flag_t flags,
@@ -455,7 +475,7 @@ int git_iterator_for_tree_range(
tree_iterator *ti;
if (tree == NULL)
- return git_iterator_for_nothing(iter, flags);
+ return git_iterator_for_nothing(iter, flags, start, end);
if ((error = git_tree__dup(&tree, tree)) < 0)
return error;
@@ -464,11 +484,10 @@ int git_iterator_for_tree_range(
ti->base.repo = git_tree_owner(tree);
- if ((error = iterator_update_ignore_case((git_iterator *)ti, flags)) < 0)
+ if ((error = iterator_update_ignore_case((git_iterator *)ti, flags)) < 0 ||
+ (error = tree_iterator__push_frame(ti, tree, ti->base.start)) < 0)
goto fail;
- ti->stack = ti->tail = tree_iterator__alloc_frame(ti, tree, ti->base.start);
-
if ((error = tree_iterator__expand_tree(ti)) < 0)
goto fail;
@@ -489,7 +508,7 @@ typedef struct {
} index_iterator;
static int index_iterator__current(
- git_iterator *self, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *self)
{
index_iterator *ii = (index_iterator *)self;
const git_index_entry *ie = git_index_get_byindex(ii->index, ii->current);
@@ -506,18 +525,15 @@ static int index_iterator__at_end(git_iterator *self)
return (ii->current >= git_index_entrycount(ii->index));
}
-static void index_iterator__skip_conflicts(
- index_iterator *ii)
+static void index_iterator__skip_conflicts(index_iterator *ii)
{
size_t entrycount = git_index_entrycount(ii->index);
- const git_index_entry *ie;
+ const git_index_entry *ie = NULL;
while (ii->current < entrycount) {
ie = git_index_get_byindex(ii->index, ii->current);
- if (ie == NULL ||
- (ii->base.end != NULL &&
- ii->base.prefixcomp(ie->path, ii->base.end) > 0)) {
+ if (ie != NULL && iterator__past_end(ii, ie->path)) {
ii->current = entrycount;
break;
}
@@ -530,7 +546,7 @@ static void index_iterator__skip_conflicts(
}
static int index_iterator__advance(
- git_iterator *self, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *self)
{
index_iterator *ii = (index_iterator *)self;
@@ -539,7 +555,7 @@ static int index_iterator__advance(
index_iterator__skip_conflicts(ii);
- return index_iterator__current(self, entry);
+ return index_iterator__current(entry, self);
}
static int index_iterator__seek(git_iterator *self, const char *prefix)
@@ -554,11 +570,15 @@ static int index_iterator__reset(
git_iterator *self, const char *start, const char *end)
{
index_iterator *ii = (index_iterator *)self;
+
if (iterator__reset_range(self, start, end) < 0)
return -1;
+
ii->current = ii->base.start ?
git_index__prefix_position(ii->index, ii->base.start) : 0;
+
index_iterator__skip_conflicts(ii);
+
return 0;
}
@@ -569,7 +589,7 @@ static void index_iterator__free(git_iterator *self)
ii->index = NULL;
}
-int git_iterator_for_index_range(
+int git_iterator_for_index(
git_iterator **iter,
git_index *index,
git_iterator_flag_t flags,
@@ -583,10 +603,12 @@ int git_iterator_for_index_range(
ITERATOR_BASE_INIT(ii, index, INDEX);
ii->base.repo = git_index_owner(index);
+
if (index->ignore_case) {
ii->base.flags |= GIT_ITERATOR_IGNORE_CASE;
ii->base.prefixcomp = git__prefixcmp_icase;
}
+
ii->index = index;
GIT_REFCOUNT_INC(index);
@@ -643,7 +665,7 @@ static workdir_iterator_frame *workdir_iterator__alloc_frame(
{
workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame));
git_vector_cmp entry_compare = CASESELECT(
- (wi->base.flags & GIT_ITERATOR_IGNORE_CASE) != 0,
+ iterator__ignore_case(wi),
git_path_with_stat_cmp_icase, git_path_with_stat_cmp);
if (wf == NULL)
@@ -706,7 +728,7 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
error = git_path_dirload_with_stat(
wi->path.ptr, wi->root_len,
- (wi->base.flags & GIT_ITERATOR_IGNORE_CASE) != 0,
+ iterator__ignore_case(wi),
wi->base.start, wi->base.end, &wf->entries);
if (error < 0 || wf->entries.length == 0) {
@@ -729,10 +751,11 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
}
static int workdir_iterator__current(
- git_iterator *self, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *self)
{
workdir_iterator *wi = (workdir_iterator *)self;
- *entry = (wi->entry.path == NULL) ? NULL : &wi->entry;
+ if (entry)
+ *entry = (wi->entry.path == NULL) ? NULL : &wi->entry;
return 0;
}
@@ -742,7 +765,7 @@ static int workdir_iterator__at_end(git_iterator *self)
}
static int workdir_iterator__advance(
- git_iterator *self, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *self)
{
int error;
workdir_iterator *wi = (workdir_iterator *)self;
@@ -781,7 +804,7 @@ static int workdir_iterator__advance(
error = workdir_iterator__update_entry(wi);
if (!error && entry != NULL)
- error = workdir_iterator__current(self, entry);
+ error = workdir_iterator__current(entry, self);
return error;
}
@@ -832,6 +855,7 @@ static void workdir_iterator__free(git_iterator *self)
static int workdir_iterator__update_entry(workdir_iterator *wi)
{
+ int error = 0;
git_path_with_stat *ps =
git_vector_get(&wi->stack->entries, wi->stack->index);
@@ -841,19 +865,18 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
if (!ps)
return 0;
+ /* skip over .git entries */
+ if (path_is_dotgit(ps))
+ return workdir_iterator__advance(NULL, (git_iterator *)wi);
+
if (git_buf_put(&wi->path, ps->path, ps->path_len) < 0)
return -1;
- if (wi->base.end &&
- wi->base.prefixcomp(wi->path.ptr + wi->root_len, wi->base.end) > 0)
+ if (iterator__past_end(wi, wi->path.ptr + wi->root_len))
return 0;
wi->entry.path = ps->path;
- /* skip over .git entries */
- if (path_is_dotgit(ps))
- return workdir_iterator__advance((git_iterator *)wi, NULL);
-
wi->is_ignored = -1;
git_index_entry__init_from_stat(&wi->entry, &ps->st);
@@ -867,26 +890,28 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
return 0;
}
+ /* if this isn't a tree, then we're done */
+ if (wi->entry.mode != GIT_FILEMODE_TREE)
+ return 0;
+
/* detect submodules */
- if (S_ISDIR(wi->entry.mode)) {
- int res = git_submodule_lookup(NULL, wi->base.repo, wi->entry.path);
- bool is_submodule = (res == 0);
- if (res == GIT_ENOTFOUND)
- giterr_clear();
-
- /* if submodule, mark as GITLINK and remove trailing slash */
- if (is_submodule) {
- size_t len = strlen(wi->entry.path);
- assert(wi->entry.path[len - 1] == '/');
- wi->entry.path[len - 1] = '\0';
- wi->entry.mode = S_IFGITLINK;
- }
+
+ error = git_submodule_lookup(NULL, wi->base.repo, wi->entry.path);
+ if (error == GIT_ENOTFOUND)
+ giterr_clear();
+
+ /* if submodule, mark as GITLINK and remove trailing slash */
+ if (!error) {
+ size_t len = strlen(wi->entry.path);
+ assert(wi->entry.path[len - 1] == '/');
+ wi->entry.path[len - 1] = '\0';
+ wi->entry.mode = S_IFGITLINK;
}
return 0;
}
-int git_iterator_for_workdir_range(
+int git_iterator_for_workdir(
git_iterator **iter,
git_repository *repo,
git_iterator_flag_t flags,
@@ -917,7 +942,7 @@ int git_iterator_for_workdir_range(
}
wi->root_len = wi->path.size;
- wi->entrycmp = (wi->base.flags & GIT_ITERATOR_IGNORE_CASE) != 0 ?
+ wi->entrycmp = iterator__ignore_case(wi) ?
workdir_iterator__entry_cmp_icase : workdir_iterator__entry_cmp_case;
if ((error = workdir_iterator__expand_dir(wi)) < 0) {
@@ -949,7 +974,7 @@ typedef struct {
} spoolandsort_callbacks;
static int spoolandsort_iterator__current(
- git_iterator *self, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *self)
{
spoolandsort_callbacks *scb = (spoolandsort_callbacks *)self->cb;
@@ -967,7 +992,7 @@ static int spoolandsort_iterator__at_end(git_iterator *self)
}
static int spoolandsort_iterator__advance(
- git_iterator *self, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *self)
{
spoolandsort_callbacks *scb = (spoolandsort_callbacks *)self->cb;
@@ -1053,7 +1078,7 @@ int git_iterator_spoolandsort_push(git_iterator *iter, bool ignore_case)
if (git_vector_init(&scb->entries, 16, entrycomp) < 0 ||
git_pool_init(&scb->entry_pool, sizeof(git_index_entry), 0) < 0 ||
git_pool_init(&scb->string_pool, 1, 0) < 0 ||
- git_iterator_current(iter, &item) < 0)
+ git_iterator_current(&item, iter) < 0)
goto fail;
while (item) {
@@ -1072,7 +1097,7 @@ int git_iterator_spoolandsort_push(git_iterator *iter, bool ignore_case)
if (git_vector_insert(&scb->entries, clone) < 0)
goto fail;
- if (git_iterator_advance(iter, &item) < 0)
+ if (git_iterator_advance(&item, iter) < 0)
goto fail;
}
@@ -1105,7 +1130,7 @@ void git_iterator_free(git_iterator *iter)
git__free(iter);
}
-git_index *git_iterator_index_get_index(git_iterator *iter)
+git_index *git_iterator_get_index(git_iterator *iter)
{
if (iter->type == GIT_ITERATOR_TYPE_INDEX)
return ((index_iterator *)iter)->index;
@@ -1126,7 +1151,7 @@ git_iterator_type_t git_iterator_inner_type(git_iterator *iter)
}
int git_iterator_current_tree_entry(
- git_iterator *iter, const git_tree_entry **tree_entry)
+ const git_tree_entry **tree_entry, git_iterator *iter)
{
*tree_entry = (iter->type != GIT_ITERATOR_TYPE_TREE) ? NULL :
tree_iterator__tree_entry((tree_iterator *)iter);
@@ -1134,9 +1159,9 @@ int git_iterator_current_tree_entry(
}
int git_iterator_current_parent_tree(
+ const git_tree **tree_ptr,
git_iterator *iter,
- const char *parent_path,
- const git_tree **tree_ptr)
+ const char *parent_path)
{
tree_iterator *ti = (tree_iterator *)iter;
tree_iterator_frame *tf;
@@ -1177,24 +1202,24 @@ notfound:
return 0;
}
-int git_iterator_current_is_ignored(git_iterator *iter)
+bool git_iterator_current_is_ignored(git_iterator *iter)
{
workdir_iterator *wi = (workdir_iterator *)iter;
if (iter->type != GIT_ITERATOR_TYPE_WORKDIR)
- return 0;
+ return false;
if (wi->is_ignored != -1)
- return wi->is_ignored;
+ return (bool)(wi->is_ignored != 0);
if (git_ignore__lookup(&wi->ignores, wi->entry.path, &wi->is_ignored) < 0)
- wi->is_ignored = 1;
+ wi->is_ignored = true;
- return wi->is_ignored;
+ return (bool)wi->is_ignored;
}
-int git_iterator_advance_into_directory(
- git_iterator *iter, const git_index_entry **entry)
+int git_iterator_advance_into(
+ const git_index_entry **entry, git_iterator *iter)
{
workdir_iterator *wi = (workdir_iterator *)iter;
@@ -1205,10 +1230,10 @@ int git_iterator_advance_into_directory(
{
if (workdir_iterator__expand_dir(wi) < 0)
/* if error loading or if empty, skip the directory. */
- return workdir_iterator__advance(iter, entry);
+ return workdir_iterator__advance(entry, iter);
}
- return entry ? git_iterator_current(iter, entry) : 0;
+ return entry ? git_iterator_current(entry, iter) : 0;
}
int git_iterator_cmp(git_iterator *iter, const char *path_prefix)
@@ -1216,7 +1241,7 @@ int git_iterator_cmp(git_iterator *iter, const char *path_prefix)
const git_index_entry *entry;
/* a "done" iterator is after every prefix */
- if (git_iterator_current(iter, &entry) < 0 ||
+ if (git_iterator_current(&entry, iter) < 0 ||
entry == NULL)
return 1;
@@ -1227,7 +1252,7 @@ int git_iterator_cmp(git_iterator *iter, const char *path_prefix)
return iter->prefixcomp(entry->path, path_prefix);
}
-int git_iterator_current_workdir_path(git_iterator *iter, git_buf **path)
+int git_iterator_current_workdir_path(git_buf **path, git_iterator *iter)
{
workdir_iterator *wi = (workdir_iterator *)iter;
diff --git a/src/iterator.h b/src/iterator.h
index a9bccfca8..feb0c2271 100644
--- a/src/iterator.h
+++ b/src/iterator.h
@@ -12,11 +12,6 @@
#include "vector.h"
#include "buffer.h"
-#define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) \
- (((ITER).flags & GIT_ITERATOR_IGNORE_CASE) != 0 ? \
- git__prefixcmp_icase((STR), (PREFIX)) : \
- git__prefixcmp((STR), (PREFIX)))
-
typedef struct git_iterator git_iterator;
typedef enum {
@@ -28,16 +23,18 @@ typedef enum {
} git_iterator_type_t;
typedef enum {
- GIT_ITERATOR_IGNORE_CASE = (1 << 0), /* ignore_case */
- GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1), /* force ignore_case off */
+ /** ignore case for entry sort order */
+ GIT_ITERATOR_IGNORE_CASE = (1 << 0),
+ /** force case sensitivity for entry sort order */
+ GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1),
} git_iterator_flag_t;
typedef struct {
- int (*current)(git_iterator *, const git_index_entry **);
- int (*at_end)(git_iterator *);
- int (*advance)(git_iterator *, const git_index_entry **);
+ int (*current)(const git_index_entry **, git_iterator *);
+ int (*advance)(const git_index_entry **, git_iterator *);
int (*seek)(git_iterator *, const char *prefix);
int (*reset)(git_iterator *, const char *start, const char *end);
+ int (*at_end)(git_iterator *);
void (*free)(git_iterator *);
} git_iterator_callbacks;
@@ -52,53 +49,41 @@ struct git_iterator {
};
extern int git_iterator_for_nothing(
- git_iterator **out, git_iterator_flag_t flags);
+ git_iterator **out,
+ git_iterator_flag_t flags,
+ const char *start,
+ const char *end);
/* tree iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value
*/
-extern int git_iterator_for_tree_range(
+extern int git_iterator_for_tree(
git_iterator **out,
git_tree *tree,
git_iterator_flag_t flags,
const char *start,
const char *end);
-GIT_INLINE(int) git_iterator_for_tree(git_iterator **out, git_tree *tree)
-{
- return git_iterator_for_tree_range(out, tree, 0, NULL, NULL);
-}
-
/* index iterators will take the ignore_case value from the index; the
* ignore_case flags are not used
*/
-extern int git_iterator_for_index_range(
+extern int git_iterator_for_index(
git_iterator **out,
git_index *index,
git_iterator_flag_t flags,
const char *start,
const char *end);
-GIT_INLINE(int) git_iterator_for_index(git_iterator **out, git_index *index)
-{
- return git_iterator_for_index_range(out, index, 0, NULL, NULL);
-}
-
/* workdir iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value
*/
-extern int git_iterator_for_workdir_range(
+extern int git_iterator_for_workdir(
git_iterator **out,
git_repository *repo,
git_iterator_flag_t flags,
const char *start,
const char *end);
-GIT_INLINE(int) git_iterator_for_workdir(git_iterator **out, git_repository *repo)
-{
- return git_iterator_for_workdir_range(out, repo, 0, NULL, NULL);
-}
-
extern void git_iterator_free(git_iterator *iter);
/* Spool all iterator values, resort with alternative ignore_case value
@@ -109,29 +94,27 @@ extern int git_iterator_spoolandsort_push(git_iterator *iter, bool ignore_case);
/* Restore original callbacks - not required in most circumstances */
extern void git_iterator_spoolandsort_pop(git_iterator *iter);
-/* Entry is not guaranteed to be fully populated. For a tree iterator,
- * we will only populate the mode, oid and path, for example. For a workdir
- * iterator, we will not populate the oid.
+/* Return a git_index_entry structure for the current value the iterator
+ * is looking at or NULL if the iterator is at the end.
+ *
+ * The entry may noy be fully populated. Tree iterators will only have a
+ * value mode, OID, and path. Workdir iterators will not have an OID (but
+ * you can use `git_iterator_current_oid()` to calculate it on demand).
*
* You do not need to free the entry. It is still "owned" by the iterator.
- * Once you call `git_iterator_advance`, then content of the old entry is
- * no longer guaranteed to be valid.
+ * Once you call `git_iterator_advance()` then the old entry is no longer
+ * guaranteed to be valid - it may be freed or just overwritten in place.
*/
GIT_INLINE(int) git_iterator_current(
- git_iterator *iter, const git_index_entry **entry)
-{
- return iter->cb->current(iter, entry);
-}
-
-GIT_INLINE(int) git_iterator_at_end(git_iterator *iter)
+ const git_index_entry **entry, git_iterator *iter)
{
- return iter->cb->at_end(iter);
+ return iter->cb->current(entry, iter);
}
GIT_INLINE(int) git_iterator_advance(
- git_iterator *iter, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *iter)
{
- return iter->cb->advance(iter, entry);
+ return iter->cb->advance(entry, iter);
}
GIT_INLINE(int) git_iterator_seek(
@@ -146,6 +129,11 @@ GIT_INLINE(int) git_iterator_reset(
return iter->cb->reset(iter, start, end);
}
+GIT_INLINE(int) git_iterator_at_end(git_iterator *iter)
+{
+ return iter->cb->at_end(iter);
+}
+
GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter)
{
return iter->type;
@@ -167,15 +155,15 @@ GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter)
}
extern int git_iterator_current_tree_entry(
- git_iterator *iter, const git_tree_entry **tree_entry);
+ const git_tree_entry **tree_entry, git_iterator *iter);
extern int git_iterator_current_parent_tree(
- git_iterator *iter, const char *parent_path, const git_tree **tree_ptr);
+ const git_tree **tree_ptr, git_iterator *iter, const char *parent_path);
-extern int git_iterator_current_is_ignored(git_iterator *iter);
+extern bool git_iterator_current_is_ignored(git_iterator *iter);
/**
- * Iterate into a workdir directory.
+ * Iterate into a directory.
*
* Workdir iterators do not automatically descend into directories (so that
* when comparing two iterator entries you can detect a newly created
@@ -191,21 +179,22 @@ extern int git_iterator_current_is_ignored(git_iterator *iter);
* On non-workdir iterators or if not pointing at a directory, this is a
* no-op and will not advance the iterator.
*/
-extern int git_iterator_advance_into_directory(
- git_iterator *iter, const git_index_entry **entry);
+extern int git_iterator_advance_into(
+ const git_index_entry **entry, git_iterator *iter);
extern int git_iterator_cmp(
git_iterator *iter, const char *path_prefix);
/**
- * Get the full path of the current item from a workdir iterator.
- * This will return NULL for a non-workdir iterator.
+ * Get full path of the current item from a workdir iterator. This will
+ * return NULL for a non-workdir iterator. The git_buf is still owned by
+ * the iterator; this is exposed just for efficiency.
*/
extern int git_iterator_current_workdir_path(
- git_iterator *iter, git_buf **path);
-
+ git_buf **path, git_iterator *iter);
-extern git_index *git_iterator_index_get_index(git_iterator *iter);
+/* Return index pointer if index iterator, else NULL */
+extern git_index *git_iterator_get_index(git_iterator *iter);
extern git_iterator_type_t git_iterator_inner_type(git_iterator *iter);
diff --git a/src/notes.c b/src/notes.c
index a1a47d989..ef48ac88e 100644
--- a/src/notes.c
+++ b/src/notes.c
@@ -625,7 +625,7 @@ int git_note_iterator_new(
if (error < 0)
goto cleanup;
- if ((error = git_iterator_for_tree(it, tree)) < 0)
+ if ((error = git_iterator_for_tree(it, tree, 0, NULL, NULL)) < 0)
git_iterator_free(*it);
cleanup:
@@ -643,7 +643,7 @@ int git_note_next(
int error;
const git_index_entry *item;
- if ((error = git_iterator_current(it, &item)) < 0)
+ if ((error = git_iterator_current(&item, it)) < 0)
goto exit;
if (item != NULL) {
@@ -651,7 +651,7 @@ int git_note_next(
error = process_entry_path(item->path, annotated_id);
if (error >= 0)
- error = git_iterator_advance(it, NULL);
+ error = git_iterator_advance(NULL, it);
} else {
error = GIT_ITEROVER;
}
diff --git a/src/submodule.c b/src/submodule.c
index 359306498..c02061376 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -1135,10 +1135,10 @@ static int load_submodule_config_from_index(
const git_index_entry *entry;
if ((error = git_repository_index__weakptr(&index, repo)) < 0 ||
- (error = git_iterator_for_index(&i, index)) < 0)
+ (error = git_iterator_for_index(&i, index, 0, NULL, NULL)) < 0)
return error;
- error = git_iterator_current(i, &entry);
+ error = git_iterator_current(&entry, i);
while (!error && entry != NULL) {
@@ -1154,7 +1154,7 @@ static int load_submodule_config_from_index(
git_oid_cpy(gitmodules_oid, &entry->oid);
}
- error = git_iterator_advance(i, &entry);
+ error = git_iterator_advance(&entry, i);
}
git_iterator_free(i);
@@ -1173,12 +1173,12 @@ static int load_submodule_config_from_head(
if ((error = git_repository_head_tree(&head, repo)) < 0)
return error;
- if ((error = git_iterator_for_tree(&i, head)) < 0) {
+ if ((error = git_iterator_for_tree(&i, head, 0, NULL, NULL)) < 0) {
git_tree_free(head);
return error;
}
- error = git_iterator_current(i, &entry);
+ error = git_iterator_current(&entry, i);
while (!error && entry != NULL) {
@@ -1195,7 +1195,7 @@ static int load_submodule_config_from_head(
git_oid_cpy(gitmodules_oid, &entry->oid);
}
- error = git_iterator_advance(i, &entry);
+ error = git_iterator_advance(&entry, i);
}
git_iterator_free(i);