diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/checkout.c | 39 | ||||
-rw-r--r-- | src/diff.c | 41 | ||||
-rw-r--r-- | src/index.c | 51 | ||||
-rw-r--r-- | src/index.h | 3 | ||||
-rw-r--r-- | src/iterator.c | 257 | ||||
-rw-r--r-- | src/iterator.h | 97 | ||||
-rw-r--r-- | src/notes.c | 6 | ||||
-rw-r--r-- | src/submodule.c | 12 |
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); |