Commit 55325efa by Vicent Martí

Merge pull request #1133 from arrbee/more-iterator-cleanup

More iterator cleanup
parents 4cbe9a1b 91e7d263
...@@ -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 ||
...@@ -759,8 +760,8 @@ fail: ...@@ -759,8 +760,8 @@ fail:
git_iterator *a = NULL, *b = NULL; \ git_iterator *a = NULL, *b = NULL; \
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; \
...@@ -29,6 +29,25 @@ ...@@ -29,6 +29,25 @@
return -1; \ return -1; \
} while (0) } while (0)
static int iterator__reset_range(
git_iterator *iter, const char *start, const char *end)
{
if (start) {
if (iter->start)
git__free(iter->start);
iter->start = git__strdup(start);
GITERR_CHECK_ALLOC(iter->start);
}
if (end) {
if (iter->end)
git__free(iter->end);
iter->end = git__strdup(end);
GITERR_CHECK_ALLOC(iter->end);
}
return 0;
}
static int empty_iterator__no_item( static int empty_iterator__no_item(
git_iterator *iter, const git_index_entry **entry) git_iterator *iter, const git_index_entry **entry)
...@@ -44,16 +63,16 @@ static int empty_iterator__at_end(git_iterator *iter) ...@@ -44,16 +63,16 @@ static int empty_iterator__at_end(git_iterator *iter)
return 1; return 1;
} }
static int empty_iterator__noop(git_iterator *iter) static int empty_iterator__reset(
git_iterator *iter, const char *start, const char *end)
{ {
GIT_UNUSED(iter); GIT_UNUSED(iter); GIT_UNUSED(start); GIT_UNUSED(end);
return 0; return 0;
} }
static int empty_iterator__seek(git_iterator *iter, const char *prefix) static int empty_iterator__seek(git_iterator *iter, const char *prefix)
{ {
GIT_UNUSED(iter); GIT_UNUSED(iter); GIT_UNUSED(prefix);
GIT_UNUSED(prefix);
return -1; return -1;
} }
...@@ -72,7 +91,7 @@ int git_iterator_for_nothing(git_iterator **iter) ...@@ -72,7 +91,7 @@ int git_iterator_for_nothing(git_iterator **iter)
i->at_end = empty_iterator__at_end; i->at_end = empty_iterator__at_end;
i->advance = empty_iterator__no_item; i->advance = empty_iterator__no_item;
i->seek = empty_iterator__seek; i->seek = empty_iterator__seek;
i->reset = empty_iterator__noop; i->reset = empty_iterator__reset;
i->free = empty_iterator__free; i->free = empty_iterator__free;
*iter = i; *iter = i;
...@@ -91,17 +110,15 @@ struct tree_iterator_frame { ...@@ -91,17 +110,15 @@ 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;
bool path_has_filename; bool path_has_filename;
} tree_iterator; } tree_iterator;
static const git_tree_entry *tree_iterator__tree_entry(tree_iterator *ti) GIT_INLINE(const git_tree_entry *)tree_iterator__tree_entry(tree_iterator *ti)
{ {
return (ti->stack == NULL) ? NULL : return git_tree_entry_byindex(ti->stack->tree, ti->stack->index);
git_tree_entry_byindex(ti->stack->tree, ti->stack->index);
} }
static char *tree_iterator__current_filename( static char *tree_iterator__current_filename(
...@@ -116,25 +133,34 @@ static char *tree_iterator__current_filename( ...@@ -116,25 +133,34 @@ static char *tree_iterator__current_filename(
return ti->path.ptr; return ti->path.ptr;
} }
static void tree_iterator__pop_frame(tree_iterator *ti) static void tree_iterator__free_frame(tree_iterator_frame *tf)
{ {
tree_iterator_frame *tf = ti->stack; if (!tf)
ti->stack = tf->next; return;
if (ti->stack != NULL) { git_tree_free(tf->tree);
git_tree_free(tf->tree); /* don't free the initial tree */
ti->stack->prev = NULL; /* disconnect prev */
}
git__free(tf); git__free(tf);
} }
static int tree_iterator__to_end(tree_iterator *ti) static bool tree_iterator__pop_frame(tree_iterator *ti)
{ {
while (ti->stack && ti->stack->next) tree_iterator_frame *tf = ti->stack;
tree_iterator__pop_frame(ti);
if (ti->stack) /* don't free the initial tree/frame */
ti->stack->index = git_tree_entrycount(ti->stack->tree); if (!tf->next)
return false;
ti->stack = tf->next;
ti->stack->prev = NULL;
tree_iterator__free_frame(tf);
return true;
}
static int tree_iterator__to_end(tree_iterator *ti)
{
while (tree_iterator__pop_frame(ti)) /* pop all */;
ti->stack->index = git_tree_entrycount(ti->stack->tree);
return 0; return 0;
} }
...@@ -205,7 +231,7 @@ static int tree_iterator__expand_tree(tree_iterator *ti) ...@@ -205,7 +231,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;
...@@ -247,12 +273,13 @@ static int tree_iterator__advance( ...@@ -247,12 +273,13 @@ static int tree_iterator__advance(
ti->path_has_filename = false; ti->path_has_filename = false;
} }
while (ti->stack != NULL) { while (1) {
te = git_tree_entry_byindex(ti->stack->tree, ++ti->stack->index); te = git_tree_entry_byindex(ti->stack->tree, ++ti->stack->index);
if (te != NULL) if (te != NULL)
break; break;
tree_iterator__pop_frame(ti); if (!tree_iterator__pop_frame(ti))
break; /* no frames left to pop */
git_buf_rtruncate_at_char(&ti->path, '/'); git_buf_rtruncate_at_char(&ti->path, '/');
} }
...@@ -279,30 +306,36 @@ static int tree_iterator__seek(git_iterator *self, const char *prefix) ...@@ -279,30 +306,36 @@ static int tree_iterator__seek(git_iterator *self, const char *prefix)
static void tree_iterator__free(git_iterator *self) static void tree_iterator__free(git_iterator *self)
{ {
tree_iterator *ti = (tree_iterator *)self; tree_iterator *ti = (tree_iterator *)self;
while (ti->stack != NULL)
tree_iterator__pop_frame(ti); while (tree_iterator__pop_frame(ti)) /* pop all */;
tree_iterator__free_frame(ti->stack);
ti->stack = ti->tail = NULL;
git_buf_free(&ti->path); git_buf_free(&ti->path);
} }
static int tree_iterator__reset(git_iterator *self) static int tree_iterator__reset(
git_iterator *self, const char *start, const char *end)
{ {
tree_iterator *ti = (tree_iterator *)self; tree_iterator *ti = (tree_iterator *)self;
while (ti->stack && ti->stack->next) while (tree_iterator__pop_frame(ti)) /* pop all */;
tree_iterator__pop_frame(ti);
if (ti->stack) if (iterator__reset_range(self, start, end) < 0)
ti->stack->index = return -1;
git_tree__prefix_position(ti->stack->tree, ti->base.start);
ti->stack->index =
git_tree__prefix_position(ti->stack->tree, ti->base.start);
git_buf_clear(&ti->path); git_buf_clear(&ti->path);
ti->path_has_filename = false;
return tree_iterator__expand_tree(ti); return tree_iterator__expand_tree(ti);
} }
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)
...@@ -313,9 +346,12 @@ int git_iterator_for_tree_range( ...@@ -313,9 +346,12 @@ int git_iterator_for_tree_range(
if (tree == NULL) if (tree == NULL)
return git_iterator_for_nothing(iter); return git_iterator_for_nothing(iter);
if ((error = git_tree__dup(&tree, tree)) < 0)
return error;
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)
...@@ -396,9 +432,12 @@ static int index_iterator__seek(git_iterator *self, const char *prefix) ...@@ -396,9 +432,12 @@ static int index_iterator__seek(git_iterator *self, const char *prefix)
return -1; return -1;
} }
static int index_iterator__reset(git_iterator *self) static int index_iterator__reset(
git_iterator *self, const char *start, const char *end)
{ {
index_iterator *ii = (index_iterator *)self; index_iterator *ii = (index_iterator *)self;
if (iterator__reset_range(self, start, end) < 0)
return -1;
ii->current = ii->base.start ? ii->current = ii->base.start ?
git_index__prefix_position(ii->index, ii->base.start) : 0; git_index__prefix_position(ii->index, ii->base.start) : 0;
index_iterator__skip_conflicts(ii); index_iterator__skip_conflicts(ii);
...@@ -424,9 +463,10 @@ int git_iterator_for_index_range( ...@@ -424,9 +463,10 @@ 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, NULL, NULL);
*iter = (git_iterator *)ii; *iter = (git_iterator *)ii;
...@@ -456,36 +496,19 @@ struct workdir_iterator_frame { ...@@ -456,36 +496,19 @@ struct workdir_iterator_frame {
workdir_iterator_frame *next; workdir_iterator_frame *next;
git_vector entries; git_vector entries;
size_t index; size_t index;
char *start;
}; };
typedef struct { typedef struct {
git_iterator base; git_iterator base;
git_repository *repo;
size_t root_len;
workdir_iterator_frame *stack; workdir_iterator_frame *stack;
int (*entrycmp)(const void *pfx, const void *item);
git_ignores ignores; git_ignores ignores;
git_index_entry entry; git_index_entry entry;
git_buf path; git_buf path;
size_t root_len;
int is_ignored; int is_ignored;
} workdir_iterator; } workdir_iterator;
static int git_path_with_stat_cmp_case(const void *a, const void *b)
{
const git_path_with_stat *path_with_stat_a = a;
const git_path_with_stat *path_with_stat_b = b;
return strcmp(path_with_stat_a->path, path_with_stat_b->path);
}
static int git_path_with_stat_cmp_icase(const void *a, const void *b)
{
const git_path_with_stat *path_with_stat_a = a;
const git_path_with_stat *path_with_stat_b = b;
return strcasecmp(path_with_stat_a->path, path_with_stat_b->path);
}
GIT_INLINE(bool) path_is_dotgit(const git_path_with_stat *ps) GIT_INLINE(bool) path_is_dotgit(const git_path_with_stat *ps)
{ {
if (!ps) if (!ps)
...@@ -494,26 +517,34 @@ GIT_INLINE(bool) path_is_dotgit(const git_path_with_stat *ps) ...@@ -494,26 +517,34 @@ GIT_INLINE(bool) path_is_dotgit(const git_path_with_stat *ps)
const char *path = ps->path; const char *path = ps->path;
size_t len = ps->path_len; size_t len = ps->path_len;
return len >= 4 && if (len < 4)
tolower(path[len - 1]) == 't' && return false;
tolower(path[len - 2]) == 'i' && if (path[len - 1] == '/')
tolower(path[len - 3]) == 'g' && len--;
path[len - 4] == '.' && if (tolower(path[len - 1]) != 't' ||
(len == 4 || path[len - 5] == '/'); tolower(path[len - 2]) != 'i' ||
tolower(path[len - 3]) != 'g' ||
tolower(path[len - 4]) != '.')
return false;
return (len == 4 || path[len - 5] == '/');
} }
} }
static workdir_iterator_frame *workdir_iterator__alloc_frame(workdir_iterator *wi) static workdir_iterator_frame *workdir_iterator__alloc_frame(
workdir_iterator *wi)
{ {
workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame)); workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame));
git_vector_cmp entry_compare = CASESELECT(wi->base.ignore_case, git_path_with_stat_cmp_icase, git_path_with_stat_cmp_case); git_vector_cmp entry_compare = CASESELECT(wi->base.ignore_case,
git_path_with_stat_cmp_icase, git_path_with_stat_cmp);
if (wf == NULL) if (wf == NULL)
return NULL; return NULL;
if (git_vector_init(&wf->entries, 0, entry_compare) != 0) { if (git_vector_init(&wf->entries, 0, entry_compare) != 0) {
git__free(wf); git__free(wf);
return NULL; return NULL;
} }
return wf; return wf;
} }
...@@ -530,16 +561,32 @@ static void workdir_iterator__free_frame(workdir_iterator_frame *wf) ...@@ -530,16 +561,32 @@ static void workdir_iterator__free_frame(workdir_iterator_frame *wf)
static int workdir_iterator__update_entry(workdir_iterator *wi); static int workdir_iterator__update_entry(workdir_iterator *wi);
static int workdir_iterator__entry_cmp_case(const void *prefix, const void *item) static int workdir_iterator__entry_cmp_case(const void *pfx, const void *item)
{ {
const git_path_with_stat *ps = item; const git_path_with_stat *ps = item;
return git__prefixcmp((const char *)prefix, ps->path); return git__prefixcmp((const char *)pfx, ps->path);
} }
static int workdir_iterator__entry_cmp_icase(const void *prefix, const void *item) static int workdir_iterator__entry_cmp_icase(const void *pfx, const void *item)
{ {
const git_path_with_stat *ps = item; const git_path_with_stat *ps = item;
return git__prefixcmp_icase((const char *)prefix, ps->path); return git__prefixcmp_icase((const char *)pfx, ps->path);
}
static void workdir_iterator__seek_frame_start(
workdir_iterator *wi, workdir_iterator_frame *wf)
{
if (!wf)
return;
if (wi->base.start)
git_vector_bsearch3(
&wf->index, &wf->entries, wi->entrycmp, wi->base.start);
else
wf->index = 0;
if (path_is_dotgit(git_vector_get(&wf->entries, wf->index)))
wf->index++;
} }
static int workdir_iterator__expand_dir(workdir_iterator *wi) static int workdir_iterator__expand_dir(workdir_iterator *wi)
...@@ -548,39 +595,26 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi) ...@@ -548,39 +595,26 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
workdir_iterator_frame *wf = workdir_iterator__alloc_frame(wi); workdir_iterator_frame *wf = workdir_iterator__alloc_frame(wi);
GITERR_CHECK_ALLOC(wf); GITERR_CHECK_ALLOC(wf);
error = git_path_dirload_with_stat(wi->path.ptr, wi->root_len, &wf->entries); error = git_path_dirload_with_stat(
wi->path.ptr, wi->root_len, wi->base.ignore_case,
wi->base.start, wi->base.end, &wf->entries);
if (error < 0 || wf->entries.length == 0) { if (error < 0 || wf->entries.length == 0) {
workdir_iterator__free_frame(wf); workdir_iterator__free_frame(wf);
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
} }
git_vector_sort(&wf->entries); workdir_iterator__seek_frame_start(wi, wf);
if (!wi->stack)
wf->start = wi->base.start;
else if (wi->stack->start &&
ITERATOR_PREFIXCMP(wi->base, wi->stack->start, wi->path.ptr + wi->root_len) == 0)
wf->start = wi->stack->start;
if (wf->start)
git_vector_bsearch3(
&wf->index,
&wf->entries,
CASESELECT(wi->base.ignore_case, workdir_iterator__entry_cmp_icase, workdir_iterator__entry_cmp_case),
wf->start);
if (path_is_dotgit(git_vector_get(&wf->entries, wf->index)))
wf->index++;
wf->next = wi->stack;
wi->stack = wf;
/* only push new ignores if this is not top level directory */ /* only push new ignores if this is not top level directory */
if (wi->stack->next != NULL) { if (wi->stack != NULL) {
ssize_t slash_pos = git_buf_rfind_next(&wi->path, '/'); ssize_t slash_pos = git_buf_rfind_next(&wi->path, '/');
(void)git_ignore__push_dir(&wi->ignores, &wi->path.ptr[slash_pos + 1]); (void)git_ignore__push_dir(&wi->ignores, &wi->path.ptr[slash_pos + 1]);
} }
wf->next = wi->stack;
wi->stack = wf;
return workdir_iterator__update_entry(wi); return workdir_iterator__update_entry(wi);
} }
...@@ -611,8 +645,10 @@ static int workdir_iterator__advance( ...@@ -611,8 +645,10 @@ static int workdir_iterator__advance(
if (wi->entry.path == NULL) if (wi->entry.path == NULL)
return 0; return 0;
while ((wf = wi->stack) != NULL) { while (1) {
wf = wi->stack;
next = git_vector_get(&wf->entries, ++wf->index); next = git_vector_get(&wf->entries, ++wf->index);
if (next != NULL) { if (next != NULL) {
/* match git's behavior of ignoring anything named ".git" */ /* match git's behavior of ignoring anything named ".git" */
if (path_is_dotgit(next)) if (path_is_dotgit(next))
...@@ -621,15 +657,15 @@ static int workdir_iterator__advance( ...@@ -621,15 +657,15 @@ static int workdir_iterator__advance(
break; break;
} }
/* pop workdir directory stack */ /* pop stack if anything is left to pop */
wi->stack = wf->next; if (!wf->next) {
workdir_iterator__free_frame(wf);
git_ignore__pop_dir(&wi->ignores);
if (wi->stack == NULL) {
memset(&wi->entry, 0, sizeof(wi->entry)); memset(&wi->entry, 0, sizeof(wi->entry));
return 0; return 0;
} }
wi->stack = wf->next;
workdir_iterator__free_frame(wf);
git_ignore__pop_dir(&wi->ignores);
} }
error = workdir_iterator__update_entry(wi); error = workdir_iterator__update_entry(wi);
...@@ -650,18 +686,24 @@ static int workdir_iterator__seek(git_iterator *self, const char *prefix) ...@@ -650,18 +686,24 @@ static int workdir_iterator__seek(git_iterator *self, const char *prefix)
return 0; return 0;
} }
static int workdir_iterator__reset(git_iterator *self) static int workdir_iterator__reset(
git_iterator *self, const char *start, const char *end)
{ {
workdir_iterator *wi = (workdir_iterator *)self; workdir_iterator *wi = (workdir_iterator *)self;
while (wi->stack != NULL && wi->stack->next != NULL) { while (wi->stack != NULL && wi->stack->next != NULL) {
workdir_iterator_frame *wf = wi->stack; workdir_iterator_frame *wf = wi->stack;
wi->stack = wf->next; wi->stack = wf->next;
workdir_iterator__free_frame(wf); workdir_iterator__free_frame(wf);
git_ignore__pop_dir(&wi->ignores); git_ignore__pop_dir(&wi->ignores);
} }
if (wi->stack)
wi->stack->index = 0; if (iterator__reset_range(self, start, end) < 0)
return 0; return -1;
workdir_iterator__seek_frame_start(wi, wi->stack);
return workdir_iterator__update_entry(wi);
} }
static void workdir_iterator__free(git_iterator *self) static void workdir_iterator__free(git_iterator *self)
...@@ -680,7 +722,8 @@ static void workdir_iterator__free(git_iterator *self) ...@@ -680,7 +722,8 @@ static void workdir_iterator__free(git_iterator *self)
static int workdir_iterator__update_entry(workdir_iterator *wi) static int workdir_iterator__update_entry(workdir_iterator *wi)
{ {
git_path_with_stat *ps = git_vector_get(&wi->stack->entries, wi->stack->index); git_path_with_stat *ps =
git_vector_get(&wi->stack->entries, wi->stack->index);
git_buf_truncate(&wi->path, wi->root_len); git_buf_truncate(&wi->path, wi->root_len);
memset(&wi->entry, 0, sizeof(wi->entry)); memset(&wi->entry, 0, sizeof(wi->entry));
...@@ -691,8 +734,8 @@ static int workdir_iterator__update_entry(workdir_iterator *wi) ...@@ -691,8 +734,8 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
if (git_buf_put(&wi->path, ps->path, ps->path_len) < 0) if (git_buf_put(&wi->path, ps->path, ps->path_len) < 0)
return -1; return -1;
if (wi->base.end && if (wi->base.end && ITERATOR_PREFIXCMP(
ITERATOR_PREFIXCMP(wi->base, wi->path.ptr + wi->root_len, wi->base.end) > 0) wi->base, wi->path.ptr + wi->root_len, wi->base.end) > 0)
return 0; return 0;
wi->entry.path = ps->path; wi->entry.path = ps->path;
...@@ -716,7 +759,7 @@ static int workdir_iterator__update_entry(workdir_iterator *wi) ...@@ -716,7 +759,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,10 +793,10 @@ int git_iterator_for_workdir_range( ...@@ -750,10 +793,10 @@ 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_iterator_free((git_iterator *)wi);
return error; return error;
} }
...@@ -769,6 +812,8 @@ int git_iterator_for_workdir_range( ...@@ -769,6 +812,8 @@ int git_iterator_for_workdir_range(
} }
wi->root_len = wi->path.size; wi->root_len = wi->path.size;
wi->entrycmp = wi->base.ignore_case ?
workdir_iterator__entry_cmp_icase : workdir_iterator__entry_cmp_case;
if ((error = workdir_iterator__expand_dir(wi)) < 0) { if ((error = workdir_iterator__expand_dir(wi)) < 0) {
if (error == GIT_ENOTFOUND) if (error == GIT_ENOTFOUND)
...@@ -837,10 +882,13 @@ static int spoolandsort_iterator__seek(git_iterator *self, const char *prefix) ...@@ -837,10 +882,13 @@ static int spoolandsort_iterator__seek(git_iterator *self, const char *prefix)
return -1; return -1;
} }
static int spoolandsort_iterator__reset(git_iterator *self) static int spoolandsort_iterator__reset(
git_iterator *self, const char *start, const char *end)
{ {
spoolandsort_iterator *si = (spoolandsort_iterator *)self; spoolandsort_iterator *si = (spoolandsort_iterator *)self;
GIT_UNUSED(start); GIT_UNUSED(end);
si->position = 0; si->position = 0;
return 0; return 0;
......
...@@ -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 *, const char *start, const char *end);
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,
...@@ -124,9 +126,10 @@ GIT_INLINE(int) git_iterator_seek( ...@@ -124,9 +126,10 @@ GIT_INLINE(int) git_iterator_seek(
return iter->seek(iter, prefix); return iter->seek(iter, prefix);
} }
GIT_INLINE(int) git_iterator_reset(git_iterator *iter) GIT_INLINE(int) git_iterator_reset(
git_iterator *iter, const char *start, const char *end)
{ {
return iter->reset(iter); return iter->reset(iter, start, end);
} }
GIT_INLINE(void) git_iterator_free(git_iterator *iter) GIT_INLINE(void) git_iterator_free(git_iterator *iter)
...@@ -149,6 +152,11 @@ GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter) ...@@ -149,6 +152,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) {
......
...@@ -770,18 +770,30 @@ int git_path_dirload( ...@@ -770,18 +770,30 @@ int git_path_dirload(
int git_path_with_stat_cmp(const void *a, const void *b) int git_path_with_stat_cmp(const void *a, const void *b)
{ {
const git_path_with_stat *psa = a, *psb = b; const git_path_with_stat *psa = a, *psb = b;
return git__strcmp_cb(psa->path, psb->path); return strcmp(psa->path, psb->path);
}
int git_path_with_stat_cmp_icase(const void *a, const void *b)
{
const git_path_with_stat *psa = a, *psb = b;
return strcasecmp(psa->path, psb->path);
} }
int git_path_dirload_with_stat( int git_path_dirload_with_stat(
const char *path, const char *path,
size_t prefix_len, size_t prefix_len,
bool ignore_case,
const char *start_stat,
const char *end_stat,
git_vector *contents) git_vector *contents)
{ {
int error; int error;
unsigned int i; unsigned int i;
git_path_with_stat *ps; git_path_with_stat *ps;
git_buf full = GIT_BUF_INIT; git_buf full = GIT_BUF_INIT;
int (*strncomp)(const char *a, const char *b, size_t sz);
size_t start_len = start_stat ? strlen(start_stat) : 0;
size_t end_len = end_stat ? strlen(end_stat) : 0, cmp_len;
if (git_buf_set(&full, path, prefix_len) < 0) if (git_buf_set(&full, path, prefix_len) < 0)
return -1; return -1;
...@@ -793,11 +805,23 @@ int git_path_dirload_with_stat( ...@@ -793,11 +805,23 @@ int git_path_dirload_with_stat(
return error; return error;
} }
strncomp = ignore_case ? git__strncasecmp : git__strncmp;
/* stat struct at start of git_path_with_stat, so shift path text */
git_vector_foreach(contents, i, ps) { git_vector_foreach(contents, i, ps) {
size_t path_len = strlen((char *)ps); size_t path_len = strlen((char *)ps);
memmove(ps->path, ps, path_len + 1); memmove(ps->path, ps, path_len + 1);
ps->path_len = path_len; ps->path_len = path_len;
}
git_vector_foreach(contents, i, ps) {
/* skip if before start_stat or after end_stat */
cmp_len = min(start_len, ps->path_len);
if (cmp_len && strncomp(ps->path, start_stat, cmp_len) < 0)
continue;
cmp_len = min(end_len, ps->path_len);
if (cmp_len && strncomp(ps->path, end_stat, cmp_len) > 0)
continue;
if ((error = git_buf_joinpath(&full, full.ptr, ps->path)) < 0 || if ((error = git_buf_joinpath(&full, full.ptr, ps->path)) < 0 ||
(error = git_path_lstat(full.ptr, &ps->st)) < 0) (error = git_path_lstat(full.ptr, &ps->st)) < 0)
...@@ -806,11 +830,14 @@ int git_path_dirload_with_stat( ...@@ -806,11 +830,14 @@ int git_path_dirload_with_stat(
git_buf_truncate(&full, prefix_len); git_buf_truncate(&full, prefix_len);
if (S_ISDIR(ps->st.st_mode)) { if (S_ISDIR(ps->st.st_mode)) {
ps->path[path_len] = '/'; ps->path[ps->path_len++] = '/';
ps->path[path_len + 1] = '\0'; ps->path[ps->path_len] = '\0';
} }
} }
/* sort now that directory suffix is added */
git_vector_sort(contents);
git_buf_free(&full); git_buf_free(&full);
return error; return error;
......
...@@ -321,18 +321,33 @@ typedef struct { ...@@ -321,18 +321,33 @@ typedef struct {
} git_path_with_stat; } git_path_with_stat;
extern int git_path_with_stat_cmp(const void *a, const void *b); extern int git_path_with_stat_cmp(const void *a, const void *b);
extern int git_path_with_stat_cmp_icase(const void *a, const void *b);
/** /**
* Load all directory entries along with stat info into a vector. * Load all directory entries along with stat info into a vector.
* *
* This is just like git_path_dirload except that each entry in the * This adds four things on top of plain `git_path_dirload`:
* vector is a git_path_with_stat structure that contains both the *
* path and the stat info, plus directories will have a / suffixed * 1. Each entry in the vector is a `git_path_with_stat` struct that
* to their path name. * contains both the path and the stat info
* 2. The entries will be sorted alphabetically
* 3. Entries that are directories will be suffixed with a '/'
* 4. Optionally, you can be a start and end prefix and only elements
* after the start and before the end (inclusively) will be stat'ed.
*
* @param path The directory to read from
* @param prefix_len The trailing part of path to prefix to entry paths
* @param ignore_case How to sort and compare paths with start/end limits
* @param start_stat As optimization, only stat values after this prefix
* @param end_stat As optimization, only stat values before this prefix
* @param contents Vector to fill with git_path_with_stat structures
*/ */
extern int git_path_dirload_with_stat( extern int git_path_dirload_with_stat(
const char *path, const char *path,
size_t prefix_len, size_t prefix_len,
bool ignore_case,
const char *start_stat,
const char *end_stat,
git_vector *contents); git_vector *contents);
#endif #endif
...@@ -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)
...@@ -296,6 +301,9 @@ int git_tree__prefix_position(git_tree *tree, const char *path) ...@@ -296,6 +301,9 @@ int git_tree__prefix_position(git_tree *tree, const char *path)
struct tree_key_search ksearch; struct tree_key_search ksearch;
size_t at_pos; size_t at_pos;
if (!path)
return 0;
ksearch.filename = path; ksearch.filename = path;
ksearch.filename_len = strlen(path); ksearch.filename_len = strlen(path);
......
...@@ -29,6 +29,10 @@ struct git_treebuilder { ...@@ -29,6 +29,10 @@ struct git_treebuilder {
git_vector entries; git_vector entries;
}; };
GIT_INLINE(int) git_tree__dup(git_tree **dest, git_tree *source)
{
return git_object__dup((git_object **)dest, (git_object *)source);
}
GIT_INLINE(bool) git_tree_entry__is_tree(const struct git_tree_entry *e) GIT_INLINE(bool) git_tree_entry__is_tree(const struct git_tree_entry *e)
{ {
......
...@@ -199,9 +199,17 @@ int git__strncmp(const char *a, const char *b, size_t sz) ...@@ -199,9 +199,17 @@ int git__strncmp(const char *a, const char *b, size_t sz)
int git__strncasecmp(const char *a, const char *b, size_t sz) int git__strncasecmp(const char *a, const char *b, size_t sz)
{ {
while (sz && *a && *b && tolower(*a) == tolower(*b)) int al, bl;
while (sz && *a && *b) {
al = (unsigned char)tolower(*a);
bl = (unsigned char)tolower(*b);
if (al != bl)
break;
--sz, ++a, ++b; --sz, ++a, ++b;
return !sz ? 0 : (tolower(*a) - tolower(*b)); }
return !sz ? 0 : al - bl;
} }
void git__strntolower(char *str, size_t len) void git__strntolower(char *str, size_t len)
......
...@@ -31,25 +31,35 @@ static void tree_iterator_test( ...@@ -31,25 +31,35 @@ static void tree_iterator_test(
git_tree *t; git_tree *t;
git_iterator *i; git_iterator *i;
const git_index_entry *entry; const git_index_entry *entry;
int count = 0; int count = 0, count_post_reset = 0;
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));
/* test loop */
cl_git_pass(git_iterator_current(i, &entry));
while (entry != NULL) { while (entry != NULL) {
if (expected_values != NULL) if (expected_values != NULL)
cl_assert_equal_s(expected_values[count], entry->path); cl_assert_equal_s(expected_values[count], entry->path);
count++; count++;
cl_git_pass(git_iterator_advance(i, &entry));
}
/* test reset */
cl_git_pass(git_iterator_reset(i, NULL, NULL));
cl_git_pass(git_iterator_current(i, &entry));
while (entry != NULL) {
if (expected_values != NULL)
cl_assert_equal_s(expected_values[count_post_reset], entry->path);
count_post_reset++;
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(i, &entry));
} }
git_iterator_free(i); git_iterator_free(i);
cl_assert(expected_count == count); cl_assert_equal_i(expected_count, count);
cl_assert_equal_i(count, count_post_reset);
git_tree_free(t); git_tree_free(t);
} }
...@@ -294,7 +304,7 @@ void test_diff_iterator__tree_special_functions(void) ...@@ -294,7 +304,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) {
...@@ -520,7 +530,7 @@ static void workdir_iterator_test( ...@@ -520,7 +530,7 @@ static void workdir_iterator_test(
{ {
git_iterator *i; git_iterator *i;
const git_index_entry *entry; const git_index_entry *entry;
int count = 0, count_all = 0; int count = 0, count_all = 0, count_all_post_reset = 0;
git_repository *repo = cl_git_sandbox_init(sandbox); git_repository *repo = cl_git_sandbox_init(sandbox);
cl_git_pass(git_iterator_for_workdir_range(&i, repo, start, end)); cl_git_pass(git_iterator_for_workdir_range(&i, repo, start, end));
...@@ -547,10 +557,26 @@ static void workdir_iterator_test( ...@@ -547,10 +557,26 @@ static void workdir_iterator_test(
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(i, &entry));
} }
cl_git_pass(git_iterator_reset(i, NULL, NULL));
cl_git_pass(git_iterator_current(i, &entry));
while (entry != NULL) {
if (S_ISDIR(entry->mode)) {
cl_git_pass(git_iterator_advance_into_directory(i, &entry));
continue;
}
if (expected_names != NULL)
cl_assert_equal_s(
expected_names[count_all_post_reset], entry->path);
count_all_post_reset++;
cl_git_pass(git_iterator_advance(i, &entry));
}
git_iterator_free(i); git_iterator_free(i);
cl_assert_equal_i(expected_count,count); cl_assert_equal_i(expected_count, count);
cl_assert_equal_i(expected_count + expected_ignores, count_all); cl_assert_equal_i(expected_count + expected_ignores, count_all);
cl_assert_equal_i(count_all, count_all_post_reset);
} }
void test_diff_iterator__workdir_0(void) void test_diff_iterator__workdir_0(void)
......
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