Skip to content

Commit

Permalink
Merge pull request libgit2#1408 from arrbee/refactor-iterators
Browse files Browse the repository at this point in the history
Refactor iterators
  • Loading branch information
Vicent Martí committed Mar 12, 2013
2 parents 316cfe9 + 858210e commit 2178db8
Show file tree
Hide file tree
Showing 51 changed files with 1,704 additions and 766 deletions.
11 changes: 5 additions & 6 deletions src/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,25 @@ void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf);

#define git_buf_PUTS(buf, str) git_buf_put(buf, str, sizeof(str) - 1)

GIT_INLINE(ssize_t) git_buf_rfind_next(git_buf *buf, char ch)
GIT_INLINE(ssize_t) git_buf_rfind_next(const git_buf *buf, char ch)
{
ssize_t idx = (ssize_t)buf->size - 1;
while (idx >= 0 && buf->ptr[idx] == ch) idx--;
while (idx >= 0 && buf->ptr[idx] != ch) idx--;
return idx;
}

GIT_INLINE(ssize_t) git_buf_rfind(git_buf *buf, char ch)
GIT_INLINE(ssize_t) git_buf_rfind(const git_buf *buf, char ch)
{
ssize_t idx = (ssize_t)buf->size - 1;
while (idx >= 0 && buf->ptr[idx] != ch) idx--;
return idx;
}

GIT_INLINE(ssize_t) git_buf_find(git_buf *buf, char ch)
GIT_INLINE(ssize_t) git_buf_find(const git_buf *buf, char ch)
{
size_t idx = 0;
while (idx < buf->size && buf->ptr[idx] != ch) idx++;
return (idx == buf->size) ? -1 : (ssize_t)idx;
void *found = memchr(buf->ptr, ch, buf->size);
return found ? (ssize_t)((const char *)found - buf->ptr) : -1;
}

/* Remove whitespace from the end of the buffer */
Expand Down
48 changes: 24 additions & 24 deletions src/checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -1241,16 +1242,15 @@ 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(
&workdir, data.repo, iterflags, data.pfx, data.pfx)) < 0 ||
(error = git_iterator_for_tree_range(
(error = git_iterator_for_workdir(
&workdir, data.repo, iterflags | GIT_ITERATOR_DONT_AUTOEXPAND,
data.pfx, data.pfx)) < 0 ||
(error = git_iterator_for_tree(
&baseline, data.opts.baseline, iterflags, data.pfx, data.pfx)) < 0)
goto cleanup;

/* Handle case insensitivity for baseline if necessary */
if (git_iterator_ignore_case(workdir) != git_iterator_ignore_case(baseline))
if ((error = git_iterator_spoolandsort_push(baseline, true)) < 0)
goto cleanup;
/* Should not have case insensitivity mismatch */
assert(git_iterator_ignore_case(workdir) == git_iterator_ignore_case(baseline));

/* Generate baseline-to-target diff which will include an entry for
* every possible update that might need to be made.
Expand Down Expand Up @@ -1321,7 +1321,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);
Expand All @@ -1348,7 +1348,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);
Expand All @@ -1369,7 +1369,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);
Expand Down
66 changes: 36 additions & 30 deletions src/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,18 +623,13 @@ int git_diff__from_iterators(
goto fail;

if (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) {
/* If either iterator does not have ignore_case set, then we will
* spool its data, sort it icase, and use that for the merge join
* with the other iterator which was icase sorted. This call is
* a no-op on an iterator that already matches "ignore_case".
*/
if (git_iterator_spoolandsort_push(old_iter, true) < 0 ||
git_iterator_spoolandsort_push(new_iter, true) < 0)
if (git_iterator_set_ignore_case(old_iter, true) < 0 ||
git_iterator_set_ignore_case(new_iter, true) < 0)
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 */
Expand Down Expand Up @@ -666,12 +661,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;
}

Expand Down Expand Up @@ -699,7 +694,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;
Expand All @@ -713,9 +708,19 @@ 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)
goto fail;
/* advance into directory */
error = git_iterator_advance_into(&nitem, new_iter);

/* if directory is empty, can't advance into it, so skip */
if (error == GIT_ENOTFOUND) {
giterr_clear();
error = git_iterator_advance(&nitem, new_iter);

git_buf_clear(&ignore_prefix);
}

if (error < 0)
goto fail;
continue;
}
}
Expand All @@ -736,7 +741,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 */
}
Expand Down Expand Up @@ -765,7 +770,7 @@ int git_diff__from_iterators(
}
}

if (git_iterator_advance(new_iter, &nitem) < 0)
if (git_iterator_advance(&nitem, new_iter) < 0)
goto fail;
}

Expand All @@ -775,11 +780,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;
}
}

Expand All @@ -800,7 +804,7 @@ int git_diff__from_iterators(
git_iterator *a = NULL, *b = NULL; \
char *pfx = opts ? git_pathspec_prefix(&opts->pathspec) : NULL; \
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 = git_diff__from_iterators(diff, repo, a, b, opts); \
git__free(pfx); git_iterator_free(a); git_iterator_free(b); \
} while (0)
Expand All @@ -817,8 +821,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;
Expand All @@ -839,8 +843,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;
Expand All @@ -860,8 +864,9 @@ 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, GIT_ITERATOR_DONT_AUTOEXPAND, pfx, pfx)
);

return error;
Expand All @@ -879,8 +884,9 @@ 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, GIT_ITERATOR_DONT_AUTOEXPAND, pfx, pfx)
);

return error;
Expand Down
Loading

0 comments on commit 2178db8

Please sign in to comment.