Commit 9950d27a by Russell Belfer

Clean up iterator APIs

This removes the need to explicitly pass the repo into iterators
where the repo is implied by the other parameters.  This moves
the repo to be owned by the parent struct.  Also, this has some
iterator related updates to the internal diff API to lay the
groundwork for checkout improvements.
parent 4cbe9a1b
...@@ -81,6 +81,14 @@ GIT_INLINE(void) git_tree_free(git_tree *tree) ...@@ -81,6 +81,14 @@ GIT_INLINE(void) git_tree_free(git_tree *tree)
GIT_EXTERN(const git_oid *) git_tree_id(const git_tree *tree); GIT_EXTERN(const git_oid *) git_tree_id(const git_tree *tree);
/** /**
* Get the repository that contains the tree.
*
* @param tree A previously loaded tree.
* @return Repository that contains this tree.
*/
GIT_EXTERN(git_repository *) git_tree_owner(const git_tree *tree);
/**
* Get the number of entries listed in a tree * Get the number of entries listed in a tree
* *
* @param tree a previously loaded tree. * @param tree a previously loaded tree.
......
...@@ -448,8 +448,7 @@ static int checkout_get_actions( ...@@ -448,8 +448,7 @@ static int checkout_get_actions(
!(error == GIT_ENOTFOUND || error == GIT_EORPHANEDHEAD)) !(error == GIT_ENOTFOUND || error == GIT_EORPHANEDHEAD))
return -1; return -1;
if ((error = git_iterator_for_tree_range( if ((error = git_iterator_for_tree_range(&hiter, head, pfx, pfx)) < 0)
&hiter, data->repo, head, pfx, pfx)) < 0)
goto fail; goto fail;
if ((diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 && if ((diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 &&
......
...@@ -570,7 +570,7 @@ static int diff_list_init_from_iterators( ...@@ -570,7 +570,7 @@ static int diff_list_init_from_iterators(
return 0; return 0;
} }
static int diff_from_iterators( int git_diff__from_iterators(
git_diff_list **diff_ptr, git_diff_list **diff_ptr,
git_repository *repo, git_repository *repo,
git_iterator *old_iter, git_iterator *old_iter,
...@@ -610,9 +610,10 @@ static int diff_from_iterators( ...@@ -610,9 +610,10 @@ static int diff_from_iterators(
/* run iterators building diffs */ /* run iterators building diffs */
while (oitem || nitem) { while (oitem || nitem) {
int cmp = oitem ? (nitem ? diff->entrycomp(oitem, nitem) : -1) : 1;
/* create DELETED records for old items not matched in new */ /* create DELETED records for old items not matched in new */
if (oitem && (!nitem || diff->entrycomp(oitem, nitem) < 0)) { if (cmp < 0) {
if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0) if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0)
goto fail; goto fail;
...@@ -637,7 +638,7 @@ static int diff_from_iterators( ...@@ -637,7 +638,7 @@ static int diff_from_iterators(
/* create ADDED, TRACKED, or IGNORED records for new items not /* create ADDED, TRACKED, or IGNORED records for new items not
* matched in old (and/or descend into directories as needed) * matched in old (and/or descend into directories as needed)
*/ */
else if (nitem && (!oitem || diff->entrycomp(oitem, nitem) > 0)) { else if (cmp > 0) {
git_delta_t delta_type = GIT_DELTA_UNTRACKED; git_delta_t delta_type = GIT_DELTA_UNTRACKED;
/* check if contained in ignored parent directory */ /* check if contained in ignored parent directory */
...@@ -733,7 +734,7 @@ static int diff_from_iterators( ...@@ -733,7 +734,7 @@ static int diff_from_iterators(
* (or ADDED and DELETED pair if type changed) * (or ADDED and DELETED pair if type changed)
*/ */
else { else {
assert(oitem && nitem && diff->entrycomp(oitem, nitem) == 0); assert(oitem && nitem && cmp == 0);
if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 || if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 ||
git_iterator_advance(old_iter, &oitem) < 0 || git_iterator_advance(old_iter, &oitem) < 0 ||
...@@ -760,7 +761,7 @@ fail: ...@@ -760,7 +761,7 @@ fail:
char *pfx = opts ? git_pathspec_prefix(&opts->pathspec) : NULL; \ char *pfx = opts ? git_pathspec_prefix(&opts->pathspec) : NULL; \
GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); \ GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); \
if (!(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \ if (!(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \
error = diff_from_iterators(diff, repo, a, b, opts); \ error = git_diff__from_iterators(diff, repo, a, b, opts); \
git__free(pfx); git_iterator_free(a); git_iterator_free(b); \ git__free(pfx); git_iterator_free(a); git_iterator_free(b); \
} while (0) } while (0)
...@@ -776,8 +777,8 @@ int git_diff_tree_to_tree( ...@@ -776,8 +777,8 @@ int git_diff_tree_to_tree(
assert(diff && repo); assert(diff && repo);
DIFF_FROM_ITERATORS( DIFF_FROM_ITERATORS(
git_iterator_for_tree_range(&a, repo, old_tree, pfx, pfx), git_iterator_for_tree_range(&a, old_tree, pfx, pfx),
git_iterator_for_tree_range(&b, repo, new_tree, pfx, pfx) git_iterator_for_tree_range(&b, new_tree, pfx, pfx)
); );
return error; return error;
...@@ -798,7 +799,7 @@ int git_diff_index_to_tree( ...@@ -798,7 +799,7 @@ int git_diff_index_to_tree(
return error; return error;
DIFF_FROM_ITERATORS( DIFF_FROM_ITERATORS(
git_iterator_for_tree_range(&a, repo, old_tree, pfx, pfx), git_iterator_for_tree_range(&a, old_tree, pfx, pfx),
git_iterator_for_index_range(&b, index, pfx, pfx) git_iterator_for_index_range(&b, index, pfx, pfx)
); );
...@@ -838,7 +839,7 @@ int git_diff_workdir_to_tree( ...@@ -838,7 +839,7 @@ int git_diff_workdir_to_tree(
assert(diff && repo); assert(diff && repo);
DIFF_FROM_ITERATORS( DIFF_FROM_ITERATORS(
git_iterator_for_tree_range(&a, repo, old_tree, pfx, pfx), git_iterator_for_tree_range(&a, old_tree, pfx, pfx),
git_iterator_for_workdir_range(&b, repo, pfx, pfx) git_iterator_for_workdir_range(&b, repo, pfx, pfx)
); );
......
...@@ -61,6 +61,12 @@ extern bool git_diff_delta__should_skip( ...@@ -61,6 +61,12 @@ extern bool git_diff_delta__should_skip(
extern int git_diff__oid_for_file( extern int git_diff__oid_for_file(
git_repository *, const char *, uint16_t, git_off_t, git_oid *); git_repository *, const char *, uint16_t, git_off_t, git_oid *);
extern int git_diff__from_iterators(
git_diff_list **diff_ptr,
git_repository *repo,
git_iterator *old_iter,
git_iterator *new_iter,
const git_diff_options *opts);
#endif #endif
...@@ -1641,8 +1641,7 @@ int git_index_read_tree_match( ...@@ -1641,8 +1641,7 @@ int git_index_read_tree_match(
pfx = git_pathspec_prefix(strspec); pfx = git_pathspec_prefix(strspec);
if ((error = git_iterator_for_tree_range( if ((error = git_iterator_for_tree_range(&iter, tree, pfx, pfx)) < 0 ||
&iter, INDEX_OWNER(index), tree, pfx, pfx)) < 0 ||
(error = git_iterator_current(iter, &entry)) < 0) (error = git_iterator_current(iter, &entry)) < 0)
goto cleanup; goto cleanup;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
(P)->base.type = GIT_ITERATOR_ ## NAME_UC; \ (P)->base.type = GIT_ITERATOR_ ## NAME_UC; \
(P)->base.start = start ? git__strdup(start) : NULL; \ (P)->base.start = start ? git__strdup(start) : NULL; \
(P)->base.end = end ? git__strdup(end) : NULL; \ (P)->base.end = end ? git__strdup(end) : NULL; \
(P)->base.ignore_case = 0; \ (P)->base.ignore_case = false; \
(P)->base.current = NAME_LC ## _iterator__current; \ (P)->base.current = NAME_LC ## _iterator__current; \
(P)->base.at_end = NAME_LC ## _iterator__at_end; \ (P)->base.at_end = NAME_LC ## _iterator__at_end; \
(P)->base.advance = NAME_LC ## _iterator__advance; \ (P)->base.advance = NAME_LC ## _iterator__advance; \
...@@ -91,7 +91,6 @@ struct tree_iterator_frame { ...@@ -91,7 +91,6 @@ struct tree_iterator_frame {
typedef struct { typedef struct {
git_iterator base; git_iterator base;
git_repository *repo;
tree_iterator_frame *stack, *tail; tree_iterator_frame *stack, *tail;
git_index_entry entry; git_index_entry entry;
git_buf path; git_buf path;
...@@ -205,7 +204,7 @@ static int tree_iterator__expand_tree(tree_iterator *ti) ...@@ -205,7 +204,7 @@ static int tree_iterator__expand_tree(tree_iterator *ti)
git__prefixcmp(ti->path.ptr, ti->base.end) > 0) git__prefixcmp(ti->path.ptr, ti->base.end) > 0)
return tree_iterator__to_end(ti); return tree_iterator__to_end(ti);
if ((error = git_tree_lookup(&subtree, ti->repo, &te->oid)) < 0) if ((error = git_tree_lookup(&subtree, ti->base.repo, &te->oid)) < 0)
return error; return error;
relpath = NULL; relpath = NULL;
...@@ -302,7 +301,6 @@ static int tree_iterator__reset(git_iterator *self) ...@@ -302,7 +301,6 @@ static int tree_iterator__reset(git_iterator *self)
int git_iterator_for_tree_range( int git_iterator_for_tree_range(
git_iterator **iter, git_iterator **iter,
git_repository *repo,
git_tree *tree, git_tree *tree,
const char *start, const char *start,
const char *end) const char *end)
...@@ -315,7 +313,7 @@ int git_iterator_for_tree_range( ...@@ -315,7 +313,7 @@ int git_iterator_for_tree_range(
ITERATOR_BASE_INIT(ti, tree, TREE); ITERATOR_BASE_INIT(ti, tree, TREE);
ti->repo = repo; ti->base.repo = git_tree_owner(tree);
ti->stack = ti->tail = tree_iterator__alloc_frame(tree, ti->base.start); ti->stack = ti->tail = tree_iterator__alloc_frame(tree, ti->base.start);
if ((error = tree_iterator__expand_tree(ti)) < 0) if ((error = tree_iterator__expand_tree(ti)) < 0)
...@@ -424,6 +422,7 @@ int git_iterator_for_index_range( ...@@ -424,6 +422,7 @@ int git_iterator_for_index_range(
ITERATOR_BASE_INIT(ii, index, INDEX); ITERATOR_BASE_INIT(ii, index, INDEX);
ii->index = index; ii->index = index;
ii->base.repo = git_index_owner(index);
ii->base.ignore_case = ii->index->ignore_case; ii->base.ignore_case = ii->index->ignore_case;
index_iterator__reset((git_iterator *)ii); index_iterator__reset((git_iterator *)ii);
...@@ -461,7 +460,6 @@ struct workdir_iterator_frame { ...@@ -461,7 +460,6 @@ struct workdir_iterator_frame {
typedef struct { typedef struct {
git_iterator base; git_iterator base;
git_repository *repo;
size_t root_len; size_t root_len;
workdir_iterator_frame *stack; workdir_iterator_frame *stack;
git_ignores ignores; git_ignores ignores;
...@@ -716,7 +714,7 @@ static int workdir_iterator__update_entry(workdir_iterator *wi) ...@@ -716,7 +714,7 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
/* detect submodules */ /* detect submodules */
if (S_ISDIR(wi->entry.mode)) { if (S_ISDIR(wi->entry.mode)) {
int res = git_submodule_lookup(NULL, wi->repo, wi->entry.path); int res = git_submodule_lookup(NULL, wi->base.repo, wi->entry.path);
bool is_submodule = (res == 0); bool is_submodule = (res == 0);
if (res == GIT_ENOTFOUND) if (res == GIT_ENOTFOUND)
giterr_clear(); giterr_clear();
...@@ -750,7 +748,7 @@ int git_iterator_for_workdir_range( ...@@ -750,7 +748,7 @@ int git_iterator_for_workdir_range(
return error; return error;
ITERATOR_BASE_INIT(wi, workdir, WORKDIR); ITERATOR_BASE_INIT(wi, workdir, WORKDIR);
wi->repo = repo; wi->base.repo = repo;
if ((error = git_repository_index__weakptr(&index, repo)) < 0) { if ((error = git_repository_index__weakptr(&index, repo)) < 0) {
git__free(wi); git__free(wi);
......
...@@ -28,32 +28,33 @@ typedef enum { ...@@ -28,32 +28,33 @@ typedef enum {
struct git_iterator { struct git_iterator {
git_iterator_type_t type; git_iterator_type_t type;
git_repository *repo;
char *start; char *start;
char *end; char *end;
bool ignore_case;
int (*current)(git_iterator *, const git_index_entry **); int (*current)(git_iterator *, const git_index_entry **);
int (*at_end)(git_iterator *); int (*at_end)(git_iterator *);
int (*advance)(git_iterator *, const git_index_entry **); int (*advance)(git_iterator *, const git_index_entry **);
int (*seek)(git_iterator *, const char *prefix); int (*seek)(git_iterator *, const char *prefix);
int (*reset)(git_iterator *); int (*reset)(git_iterator *);
void (*free)(git_iterator *); void (*free)(git_iterator *);
unsigned int ignore_case:1;
}; };
extern int git_iterator_for_nothing(git_iterator **iter); extern int git_iterator_for_nothing(git_iterator **iter);
extern int git_iterator_for_tree_range( extern int git_iterator_for_tree_range(
git_iterator **iter, git_repository *repo, git_tree *tree, git_iterator **iter, git_tree *tree,
const char *start, const char *end); const char *start, const char *end);
GIT_INLINE(int) git_iterator_for_tree( GIT_INLINE(int) git_iterator_for_tree(
git_iterator **iter, git_repository *repo, git_tree *tree) git_iterator **iter, git_tree *tree)
{ {
return git_iterator_for_tree_range(iter, repo, tree, NULL, NULL); return git_iterator_for_tree_range(iter, tree, NULL, NULL);
} }
extern int git_iterator_for_index_range( extern int git_iterator_for_index_range(
git_iterator **iter, git_index *index, git_iterator **iter, git_index *index, const char *start, const char *end);
const char *start, const char *end);
GIT_INLINE(int) git_iterator_for_index( GIT_INLINE(int) git_iterator_for_index(
git_iterator **iter, git_index *index) git_iterator **iter, git_index *index)
...@@ -90,7 +91,8 @@ GIT_INLINE(int) git_iterator_spoolandsort( ...@@ -90,7 +91,8 @@ GIT_INLINE(int) git_iterator_spoolandsort(
git_iterator **iter, git_iterator *towrap, git_iterator **iter, git_iterator *towrap,
git_vector_cmp comparer, bool ignore_case) git_vector_cmp comparer, bool ignore_case)
{ {
return git_iterator_spoolandsort_range(iter, towrap, comparer, ignore_case, NULL, NULL); return git_iterator_spoolandsort_range(
iter, towrap, comparer, ignore_case, NULL, NULL);
} }
/* Entry is not guaranteed to be fully populated. For a tree iterator, /* Entry is not guaranteed to be fully populated. For a tree iterator,
...@@ -149,6 +151,11 @@ GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter) ...@@ -149,6 +151,11 @@ GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter)
return iter->type; return iter->type;
} }
GIT_INLINE(git_repository *) git_iterator_owner(git_iterator *iter)
{
return iter->repo;
}
extern int git_iterator_current_tree_entry( extern int git_iterator_current_tree_entry(
git_iterator *iter, const git_tree_entry **tree_entry); git_iterator *iter, const git_tree_entry **tree_entry);
......
...@@ -593,7 +593,7 @@ int git_note_foreach( ...@@ -593,7 +593,7 @@ int git_note_foreach(
if (!(error = retrieve_note_tree_and_commit( if (!(error = retrieve_note_tree_and_commit(
&tree, &commit, repo, &notes_ref)) && &tree, &commit, repo, &notes_ref)) &&
!(error = git_iterator_for_tree(&iter, repo, tree))) !(error = git_iterator_for_tree(&iter, tree)))
error = git_iterator_current(iter, &item); error = git_iterator_current(iter, &item);
while (!error && item) { while (!error && item) {
......
...@@ -1156,7 +1156,7 @@ static int load_submodule_config_from_head( ...@@ -1156,7 +1156,7 @@ static int load_submodule_config_from_head(
if ((error = git_repository_head_tree(&head, repo)) < 0) if ((error = git_repository_head_tree(&head, repo)) < 0)
return error; return error;
if ((error = git_iterator_for_tree(&i, repo, head)) < 0) { if ((error = git_iterator_for_tree(&i, head)) < 0) {
git_tree_free(head); git_tree_free(head);
return error; return error;
} }
......
...@@ -207,9 +207,14 @@ void git_tree__free(git_tree *tree) ...@@ -207,9 +207,14 @@ void git_tree__free(git_tree *tree)
git__free(tree); git__free(tree);
} }
const git_oid *git_tree_id(const git_tree *c) const git_oid *git_tree_id(const git_tree *t)
{ {
return git_object_id((const git_object *)c); return git_object_id((const git_object *)t);
}
git_repository *git_tree_owner(const git_tree *t)
{
return git_object_owner((const git_object *)t);
} }
git_filemode_t git_tree_entry_filemode(const git_tree_entry *entry) git_filemode_t git_tree_entry_filemode(const git_tree_entry *entry)
......
...@@ -35,7 +35,7 @@ static void tree_iterator_test( ...@@ -35,7 +35,7 @@ static void tree_iterator_test(
git_repository *repo = cl_git_sandbox_init(sandbox); git_repository *repo = cl_git_sandbox_init(sandbox);
cl_assert(t = resolve_commit_oid_to_tree(repo, treeish)); cl_assert(t = resolve_commit_oid_to_tree(repo, treeish));
cl_git_pass(git_iterator_for_tree_range(&i, repo, t, start, end)); cl_git_pass(git_iterator_for_tree_range(&i, t, start, end));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(i, &entry));
while (entry != NULL) { while (entry != NULL) {
...@@ -294,7 +294,7 @@ void test_diff_iterator__tree_special_functions(void) ...@@ -294,7 +294,7 @@ void test_diff_iterator__tree_special_functions(void)
repo, "24fa9a9fc4e202313e24b648087495441dab432b"); repo, "24fa9a9fc4e202313e24b648087495441dab432b");
cl_assert(t != NULL); cl_assert(t != NULL);
cl_git_pass(git_iterator_for_tree_range(&i, repo, t, NULL, NULL)); cl_git_pass(git_iterator_for_tree_range(&i, t, NULL, NULL));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(i, &entry));
while (entry != NULL) { while (entry != NULL) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment