Commit 1ac10aae by Vicent Martí

Merge pull request #1408 from arrbee/refactor-iterators

Refactor iterators
parents b70bf922 62beacd3
...@@ -119,7 +119,7 @@ void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf); ...@@ -119,7 +119,7 @@ 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) #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; ssize_t idx = (ssize_t)buf->size - 1;
while (idx >= 0 && buf->ptr[idx] == ch) idx--; while (idx >= 0 && buf->ptr[idx] == ch) idx--;
...@@ -127,18 +127,17 @@ GIT_INLINE(ssize_t) git_buf_rfind_next(git_buf *buf, char ch) ...@@ -127,18 +127,17 @@ GIT_INLINE(ssize_t) git_buf_rfind_next(git_buf *buf, char ch)
return 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; 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; 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; void *found = memchr(buf->ptr, ch, buf->size);
while (idx < buf->size && buf->ptr[idx] != ch) idx++; return found ? (ssize_t)((const char *)found - buf->ptr) : -1;
return (idx == buf->size) ? -1 : (ssize_t)idx;
} }
/* Remove whitespace from the end of the buffer */ /* Remove whitespace from the end of the buffer */
......
...@@ -456,7 +456,7 @@ static int checkout_action( ...@@ -456,7 +456,7 @@ static int checkout_action(
while (1) { while (1) {
if (!wd) if (!wd)
return checkout_action_no_wd(data, delta); return checkout_action_no_wd(data, delta);
cmp = strcomp(wd->path, delta->old_file.path); cmp = strcomp(wd->path, delta->old_file.path);
/* 1. wd before delta ("a/a" before "a/b") /* 1. wd before delta ("a/a" before "a/b")
...@@ -473,9 +473,9 @@ static int checkout_action( ...@@ -473,9 +473,9 @@ static int checkout_action(
if (cmp == 0) { if (cmp == 0) {
if (wd->mode == GIT_FILEMODE_TREE) { if (wd->mode == GIT_FILEMODE_TREE) {
/* case 2 - entry prefixed by workdir 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; goto fail;
*wditem_ptr = wd; *wditem_ptr = wd;
continue; continue;
} }
...@@ -484,14 +484,14 @@ static int checkout_action( ...@@ -484,14 +484,14 @@ static int checkout_action(
if (delta->old_file.path[strlen(wd->path)] == '/') { if (delta->old_file.path[strlen(wd->path)] == '/') {
act = checkout_action_with_wd_blocker(data, delta, wd); act = checkout_action_with_wd_blocker(data, delta, wd);
*wditem_ptr = *wditem_ptr =
git_iterator_advance(workdir, &wd) ? NULL : wd; git_iterator_advance(&wd, workdir) ? NULL : wd;
return act; return act;
} }
} }
/* case 1 - handle wd item (if it matches pathspec) */ /* case 1 - handle wd item (if it matches pathspec) */
if (checkout_action_wd_only(data, workdir, wd, pathspec) < 0 || if (checkout_action_wd_only(data, workdir, wd, pathspec) < 0 ||
git_iterator_advance(workdir, &wd) < 0) git_iterator_advance(&wd, workdir) < 0)
goto fail; goto fail;
*wditem_ptr = wd; *wditem_ptr = wd;
...@@ -501,7 +501,7 @@ static int checkout_action( ...@@ -501,7 +501,7 @@ static int checkout_action(
if (cmp == 0) { if (cmp == 0) {
/* case 4 */ /* case 4 */
act = checkout_action_with_wd(data, delta, wd); 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; return act;
} }
...@@ -514,7 +514,7 @@ static int checkout_action( ...@@ -514,7 +514,7 @@ static int checkout_action(
if (delta->status == GIT_DELTA_TYPECHANGE) { if (delta->status == GIT_DELTA_TYPECHANGE) {
if (delta->old_file.mode == GIT_FILEMODE_TREE) { if (delta->old_file.mode == GIT_FILEMODE_TREE) {
act = checkout_action_with_wd(data, delta, wd); 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; wd = NULL;
*wditem_ptr = wd; *wditem_ptr = wd;
return act; return act;
...@@ -525,7 +525,7 @@ static int checkout_action( ...@@ -525,7 +525,7 @@ static int checkout_action(
delta->old_file.mode == GIT_FILEMODE_COMMIT) delta->old_file.mode == GIT_FILEMODE_COMMIT)
{ {
act = checkout_action_with_wd(data, delta, wd); act = checkout_action_with_wd(data, delta, wd);
if (git_iterator_advance(workdir, &wd) < 0) if (git_iterator_advance(&wd, workdir) < 0)
wd = NULL; wd = NULL;
*wditem_ptr = wd; *wditem_ptr = wd;
return act; return act;
...@@ -554,7 +554,7 @@ static int checkout_remaining_wd_items( ...@@ -554,7 +554,7 @@ static int checkout_remaining_wd_items(
while (wd && !error) { while (wd && !error) {
if (!(error = checkout_action_wd_only(data, workdir, wd, spec))) if (!(error = checkout_action_wd_only(data, workdir, wd, spec)))
error = git_iterator_advance(workdir, &wd); error = git_iterator_advance(&wd, workdir);
} }
return error; return error;
...@@ -578,7 +578,7 @@ static int checkout_get_actions( ...@@ -578,7 +578,7 @@ static int checkout_get_actions(
git_pathspec_init(&pathspec, &data->opts.paths, &pathpool) < 0) git_pathspec_init(&pathspec, &data->opts.paths, &pathpool) < 0)
return -1; return -1;
if ((error = git_iterator_current(workdir, &wditem)) < 0) if ((error = git_iterator_current(&wditem, workdir)) < 0)
goto fail; goto fail;
deltas = &data->diff->deltas; deltas = &data->diff->deltas;
...@@ -1134,16 +1134,17 @@ static int checkout_data_init( ...@@ -1134,16 +1134,17 @@ static int checkout_data_init(
if ((error = git_config_refresh(cfg)) < 0) if ((error = git_config_refresh(cfg)) < 0)
goto cleanup; goto cleanup;
if (git_iterator_inner_type(target) == GIT_ITERATOR_TYPE_INDEX) { /* if we are checking out the index, don't reload,
/* if we are iterating over the index, don't reload */ * otherwise get index and force reload
data->index = git_iterator_index_get_index(target); */
if ((data->index = git_iterator_get_index(target)) != NULL) {
GIT_REFCOUNT_INC(data->index); GIT_REFCOUNT_INC(data->index);
} else { } else {
/* otherwise, grab and reload the index */ /* otherwise, grab and reload the index */
if ((error = git_repository_index(&data->index, data->repo)) < 0 || if ((error = git_repository_index(&data->index, data->repo)) < 0 ||
(error = git_index_read(data->index)) < 0) (error = git_index_read(data->index)) < 0)
goto cleanup; goto cleanup;
/* clear the REUC when doing a tree or commit checkout */ /* clear the REUC when doing a tree or commit checkout */
git_index_reuc_clear(data->index); git_index_reuc_clear(data->index);
} }
...@@ -1241,16 +1242,15 @@ int git_checkout_iterator( ...@@ -1241,16 +1242,15 @@ int git_checkout_iterator(
GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE; GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE;
if ((error = git_iterator_reset(target, data.pfx, data.pfx)) < 0 || 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 || &workdir, data.repo, iterflags | GIT_ITERATOR_DONT_AUTOEXPAND,
(error = git_iterator_for_tree_range( data.pfx, data.pfx)) < 0 ||
(error = git_iterator_for_tree(
&baseline, data.opts.baseline, iterflags, data.pfx, data.pfx)) < 0) &baseline, data.opts.baseline, iterflags, data.pfx, data.pfx)) < 0)
goto cleanup; goto cleanup;
/* Handle case insensitivity for baseline if necessary */ /* Should not have case insensitivity mismatch */
if (git_iterator_ignore_case(workdir) != git_iterator_ignore_case(baseline)) assert(git_iterator_ignore_case(workdir) == git_iterator_ignore_case(baseline));
if ((error = git_iterator_spoolandsort_push(baseline, true)) < 0)
goto cleanup;
/* Generate baseline-to-target diff which will include an entry for /* Generate baseline-to-target diff which will include an entry for
* every possible update that might need to be made. * every possible update that might need to be made.
...@@ -1321,7 +1321,7 @@ int git_checkout_index( ...@@ -1321,7 +1321,7 @@ int git_checkout_index(
return error; return error;
GIT_REFCOUNT_INC(index); 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); error = git_checkout_iterator(index_i, opts);
git_iterator_free(index_i); git_iterator_free(index_i);
...@@ -1348,7 +1348,7 @@ int git_checkout_tree( ...@@ -1348,7 +1348,7 @@ int git_checkout_tree(
return -1; 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); error = git_checkout_iterator(tree_i, opts);
git_iterator_free(tree_i); git_iterator_free(tree_i);
...@@ -1369,7 +1369,7 @@ int git_checkout_head( ...@@ -1369,7 +1369,7 @@ int git_checkout_head(
return error; return error;
if (!(error = checkout_lookup_head_tree(&head, repo)) && 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); error = git_checkout_iterator(head_i, opts);
git_iterator_free(head_i); git_iterator_free(head_i);
......
...@@ -623,18 +623,13 @@ int git_diff__from_iterators( ...@@ -623,18 +623,13 @@ int git_diff__from_iterators(
goto fail; goto fail;
if (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) { if (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) {
/* If either iterator does not have ignore_case set, then we will if (git_iterator_set_ignore_case(old_iter, true) < 0 ||
* spool its data, sort it icase, and use that for the merge join git_iterator_set_ignore_case(new_iter, true) < 0)
* 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)
goto fail; goto fail;
} }
if (git_iterator_current(old_iter, &oitem) < 0 || if (git_iterator_current(&oitem, old_iter) < 0 ||
git_iterator_current(new_iter, &nitem) < 0) git_iterator_current(&nitem, new_iter) < 0)
goto fail; goto fail;
/* run iterators building diffs */ /* run iterators building diffs */
...@@ -666,12 +661,12 @@ int git_diff__from_iterators( ...@@ -666,12 +661,12 @@ int git_diff__from_iterators(
if (S_ISDIR(nitem->mode) && if (S_ISDIR(nitem->mode) &&
!(diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS)) !(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; goto fail;
} }
} }
if (git_iterator_advance(old_iter, &oitem) < 0) if (git_iterator_advance(&oitem, old_iter) < 0)
goto fail; goto fail;
} }
...@@ -699,7 +694,7 @@ int git_diff__from_iterators( ...@@ -699,7 +694,7 @@ int git_diff__from_iterators(
/* do not advance into directories that contain a .git file */ /* do not advance into directories that contain a .git file */
if (!contains_oitem && recurse_untracked) { if (!contains_oitem && recurse_untracked) {
git_buf *full = NULL; 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; goto fail;
if (git_path_contains_dir(full, DOT_GIT)) if (git_path_contains_dir(full, DOT_GIT))
recurse_untracked = false; recurse_untracked = false;
...@@ -713,9 +708,19 @@ int git_diff__from_iterators( ...@@ -713,9 +708,19 @@ int git_diff__from_iterators(
git_iterator_current_is_ignored(new_iter)) git_iterator_current_is_ignored(new_iter))
git_buf_sets(&ignore_prefix, nitem->path); git_buf_sets(&ignore_prefix, nitem->path);
if (git_iterator_advance_into_directory(new_iter, &nitem) < 0) /* advance into directory */
goto fail; 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; continue;
} }
} }
...@@ -736,7 +741,7 @@ int git_diff__from_iterators( ...@@ -736,7 +741,7 @@ int git_diff__from_iterators(
* skip the file. * skip the file.
*/ */
else if (delta_type == GIT_DELTA_IGNORED) { 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; goto fail;
continue; /* ignored parent directory, so skip completely */ continue; /* ignored parent directory, so skip completely */
} }
...@@ -765,7 +770,7 @@ int git_diff__from_iterators( ...@@ -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; goto fail;
} }
...@@ -775,11 +780,10 @@ int git_diff__from_iterators( ...@@ -775,11 +780,10 @@ int git_diff__from_iterators(
else { else {
assert(oitem && nitem && cmp == 0); assert(oitem && nitem && cmp == 0);
if (maybe_modified( if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 ||
old_iter, oitem, new_iter, nitem, diff) < 0 || git_iterator_advance(&oitem, old_iter) < 0 ||
git_iterator_advance(old_iter, &oitem) < 0 || git_iterator_advance(&nitem, new_iter) < 0)
git_iterator_advance(new_iter, &nitem) < 0) goto fail;
goto fail;
} }
} }
...@@ -800,7 +804,7 @@ fail: ...@@ -800,7 +804,7 @@ 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 = git_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)
...@@ -817,8 +821,8 @@ int git_diff_tree_to_tree( ...@@ -817,8 +821,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, old_tree, 0, pfx, pfx), git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
git_iterator_for_tree_range(&b, new_tree, 0, pfx, pfx) git_iterator_for_tree(&b, new_tree, 0, pfx, pfx)
); );
return error; return error;
...@@ -839,8 +843,8 @@ int git_diff_tree_to_index( ...@@ -839,8 +843,8 @@ int git_diff_tree_to_index(
return error; return error;
DIFF_FROM_ITERATORS( DIFF_FROM_ITERATORS(
git_iterator_for_tree_range(&a, old_tree, 0, pfx, pfx), git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
git_iterator_for_index_range(&b, index, 0, pfx, pfx) git_iterator_for_index(&b, index, 0, pfx, pfx)
); );
return error; return error;
...@@ -860,8 +864,9 @@ int git_diff_index_to_workdir( ...@@ -860,8 +864,9 @@ int git_diff_index_to_workdir(
return error; return error;
DIFF_FROM_ITERATORS( DIFF_FROM_ITERATORS(
git_iterator_for_index_range(&a, index, 0, pfx, pfx), git_iterator_for_index(&a, index, 0, pfx, pfx),
git_iterator_for_workdir_range(&b, repo, 0, pfx, pfx) git_iterator_for_workdir(
&b, repo, GIT_ITERATOR_DONT_AUTOEXPAND, pfx, pfx)
); );
return error; return error;
...@@ -879,8 +884,9 @@ int git_diff_tree_to_workdir( ...@@ -879,8 +884,9 @@ int git_diff_tree_to_workdir(
assert(diff && repo); assert(diff && repo);
DIFF_FROM_ITERATORS( DIFF_FROM_ITERATORS(
git_iterator_for_tree_range(&a, old_tree, 0, pfx, pfx), git_iterator_for_tree(&a, old_tree, 0, pfx, pfx),
git_iterator_for_workdir_range(&b, repo, 0, pfx, pfx) git_iterator_for_workdir(
&b, repo, GIT_ITERATOR_DONT_AUTOEXPAND, pfx, pfx)
); );
return error; return error;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
#include "hashsig.h" #include "hashsig.h"
#include "fileops.h" #include "fileops.h"
#include "util.h"
typedef uint32_t hashsig_t; typedef uint32_t hashsig_t;
typedef uint64_t hashsig_state; typedef uint64_t hashsig_state;
...@@ -19,7 +20,7 @@ typedef uint64_t hashsig_state; ...@@ -19,7 +20,7 @@ typedef uint64_t hashsig_state;
#define HASHSIG_HEAP_SIZE ((1 << 7) - 1) #define HASHSIG_HEAP_SIZE ((1 << 7) - 1)
typedef int (GIT_STDLIB_CALL *hashsig_cmp)(const void *a, const void *b); typedef int (*hashsig_cmp)(const void *a, const void *b, void *);
typedef struct { typedef struct {
int size, asize; int size, asize;
...@@ -53,15 +54,17 @@ static void hashsig_heap_init(hashsig_heap *h, hashsig_cmp cmp) ...@@ -53,15 +54,17 @@ static void hashsig_heap_init(hashsig_heap *h, hashsig_cmp cmp)
h->cmp = cmp; h->cmp = cmp;
} }
static int GIT_STDLIB_CALL hashsig_cmp_max(const void *a, const void *b) static int hashsig_cmp_max(const void *a, const void *b, void *payload)
{ {
hashsig_t av = *(const hashsig_t *)a, bv = *(const hashsig_t *)b; hashsig_t av = *(const hashsig_t *)a, bv = *(const hashsig_t *)b;
GIT_UNUSED(payload);
return (av < bv) ? -1 : (av > bv) ? 1 : 0; return (av < bv) ? -1 : (av > bv) ? 1 : 0;
} }
static int GIT_STDLIB_CALL hashsig_cmp_min(const void *a, const void *b) static int hashsig_cmp_min(const void *a, const void *b, void *payload)
{ {
hashsig_t av = *(const hashsig_t *)a, bv = *(const hashsig_t *)b; hashsig_t av = *(const hashsig_t *)a, bv = *(const hashsig_t *)b;
GIT_UNUSED(payload);
return (av > bv) ? -1 : (av < bv) ? 1 : 0; return (av > bv) ? -1 : (av < bv) ? 1 : 0;
} }
...@@ -69,7 +72,7 @@ static void hashsig_heap_up(hashsig_heap *h, int el) ...@@ -69,7 +72,7 @@ static void hashsig_heap_up(hashsig_heap *h, int el)
{ {
int parent_el = HEAP_PARENT_OF(el); int parent_el = HEAP_PARENT_OF(el);
while (el > 0 && h->cmp(&h->values[parent_el], &h->values[el]) > 0) { while (el > 0 && h->cmp(&h->values[parent_el], &h->values[el], NULL) > 0) {
hashsig_t t = h->values[el]; hashsig_t t = h->values[el];
h->values[el] = h->values[parent_el]; h->values[el] = h->values[parent_el];
h->values[parent_el] = t; h->values[parent_el] = t;
...@@ -92,10 +95,10 @@ static void hashsig_heap_down(hashsig_heap *h, int el) ...@@ -92,10 +95,10 @@ static void hashsig_heap_down(hashsig_heap *h, int el)
lv = h->values[lel]; lv = h->values[lel];
rv = h->values[rel]; rv = h->values[rel];
if (h->cmp(&v, &lv) < 0 && h->cmp(&v, &rv) < 0) if (h->cmp(&v, &lv, NULL) < 0 && h->cmp(&v, &rv, NULL) < 0)
break; break;
swapel = (h->cmp(&lv, &rv) < 0) ? lel : rel; swapel = (h->cmp(&lv, &rv, NULL) < 0) ? lel : rel;
h->values[el] = h->values[swapel]; h->values[el] = h->values[swapel];
h->values[swapel] = v; h->values[swapel] = v;
...@@ -107,13 +110,13 @@ static void hashsig_heap_down(hashsig_heap *h, int el) ...@@ -107,13 +110,13 @@ static void hashsig_heap_down(hashsig_heap *h, int el)
static void hashsig_heap_sort(hashsig_heap *h) static void hashsig_heap_sort(hashsig_heap *h)
{ {
/* only need to do this at the end for signature comparison */ /* only need to do this at the end for signature comparison */
qsort(h->values, h->size, sizeof(hashsig_t), h->cmp); git__qsort_r(h->values, h->size, sizeof(hashsig_t), h->cmp, NULL);
} }
static void hashsig_heap_insert(hashsig_heap *h, hashsig_t val) static void hashsig_heap_insert(hashsig_heap *h, hashsig_t val)
{ {
/* if heap is full, pop top if new element should replace it */ /* if heap is full, pop top if new element should replace it */
if (h->size == h->asize && h->cmp(&val, &h->values[0]) > 0) { if (h->size == h->asize && h->cmp(&val, &h->values[0], NULL) > 0) {
h->size--; h->size--;
h->values[0] = h->values[h->size]; h->values[0] = h->values[h->size];
hashsig_heap_down(h, 0); hashsig_heap_down(h, 0);
...@@ -343,7 +346,7 @@ static int hashsig_heap_compare(const hashsig_heap *a, const hashsig_heap *b) ...@@ -343,7 +346,7 @@ static int hashsig_heap_compare(const hashsig_heap *a, const hashsig_heap *b)
/* hash heaps are sorted - just look for overlap vs total */ /* hash heaps are sorted - just look for overlap vs total */
for (i = 0, j = 0; i < a->size && j < b->size; ) { for (i = 0, j = 0; i < a->size && j < b->size; ) {
cmp = a->cmp(&a->values[i], &b->values[j]); cmp = a->cmp(&a->values[i], &b->values[j], NULL);
if (cmp < 0) if (cmp < 0)
++i; ++i;
......
...@@ -1679,54 +1679,3 @@ git_repository *git_index_owner(const git_index *index) ...@@ -1679,54 +1679,3 @@ git_repository *git_index_owner(const git_index *index)
{ {
return INDEX_OWNER(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
}
...@@ -50,7 +50,4 @@ extern int git_index_entry__cmp_icase(const void *a, const void *b); ...@@ -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 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 #endif
...@@ -12,11 +12,6 @@ ...@@ -12,11 +12,6 @@
#include "vector.h" #include "vector.h"
#include "buffer.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 struct git_iterator git_iterator;
typedef enum { typedef enum {
...@@ -24,20 +19,26 @@ typedef enum { ...@@ -24,20 +19,26 @@ typedef enum {
GIT_ITERATOR_TYPE_TREE = 1, GIT_ITERATOR_TYPE_TREE = 1,
GIT_ITERATOR_TYPE_INDEX = 2, GIT_ITERATOR_TYPE_INDEX = 2,
GIT_ITERATOR_TYPE_WORKDIR = 3, GIT_ITERATOR_TYPE_WORKDIR = 3,
GIT_ITERATOR_TYPE_SPOOLANDSORT = 4
} git_iterator_type_t; } git_iterator_type_t;
typedef enum { typedef enum {
GIT_ITERATOR_IGNORE_CASE = (1 << 0), /* ignore_case */ /** ignore case for entry sort order */
GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1), /* force ignore_case off */ GIT_ITERATOR_IGNORE_CASE = (1 << 0),
/** force case sensitivity for entry sort order */
GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1),
/** return tree items in addition to blob items */
GIT_ITERATOR_INCLUDE_TREES = (1 << 2),
/** don't flatten trees, requiring advance_into (implies INCLUDE_TREES) */
GIT_ITERATOR_DONT_AUTOEXPAND = (1 << 3),
} git_iterator_flag_t; } git_iterator_flag_t;
typedef struct { typedef struct {
int (*current)(git_iterator *, const git_index_entry **); int (*current)(const git_index_entry **, git_iterator *);
int (*at_end)(git_iterator *); int (*advance)(const git_index_entry **, git_iterator *);
int (*advance)(git_iterator *, const git_index_entry **); int (*advance_into)(const git_index_entry **, git_iterator *);
int (*seek)(git_iterator *, const char *prefix); int (*seek)(git_iterator *, const char *prefix);
int (*reset)(git_iterator *, const char *start, const char *end); int (*reset)(git_iterator *, const char *start, const char *end);
int (*at_end)(git_iterator *);
void (*free)(git_iterator *); void (*free)(git_iterator *);
} git_iterator_callbacks; } git_iterator_callbacks;
...@@ -52,86 +53,92 @@ struct git_iterator { ...@@ -52,86 +53,92 @@ struct git_iterator {
}; };
extern int git_iterator_for_nothing( 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 /* tree iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value * 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_iterator **out,
git_tree *tree, git_tree *tree,
git_iterator_flag_t flags, git_iterator_flag_t flags,
const char *start, const char *start,
const char *end); 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 /* index iterators will take the ignore_case value from the index; the
* ignore_case flags are not used * ignore_case flags are not used
*/ */
extern int git_iterator_for_index_range( extern int git_iterator_for_index(
git_iterator **out, git_iterator **out,
git_index *index, git_index *index,
git_iterator_flag_t flags, git_iterator_flag_t flags,
const char *start, const char *start,
const char *end); 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 /* workdir iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value * 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_iterator **out,
git_repository *repo, git_repository *repo,
git_iterator_flag_t flags, git_iterator_flag_t flags,
const char *start, const char *start,
const char *end); 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); extern void git_iterator_free(git_iterator *iter);
/* Spool all iterator values, resort with alternative ignore_case value /* Return a git_index_entry structure for the current value the iterator
* and replace callbacks with spoolandsort alternates. * is looking at or NULL if the iterator is at the end.
*/ *
extern int git_iterator_spoolandsort_push(git_iterator *iter, bool ignore_case); * 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
/* Restore original callbacks - not required in most circumstances */ * you can use `git_iterator_current_oid()` to calculate it on demand).
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.
* *
* You do not need to free the entry. It is still "owned" by the iterator. * 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 * Once you call `git_iterator_advance()` then the old entry is no longer
* no longer guaranteed to be valid. * guaranteed to be valid - it may be freed or just overwritten in place.
*/ */
GIT_INLINE(int) git_iterator_current( GIT_INLINE(int) git_iterator_current(
git_iterator *iter, const git_index_entry **entry) const git_index_entry **entry, git_iterator *iter)
{ {
return iter->cb->current(iter, entry); return iter->cb->current(entry, iter);
} }
GIT_INLINE(int) git_iterator_at_end(git_iterator *iter) /**
* Advance to the next item for the iterator.
*
* If GIT_ITERATOR_INCLUDE_TREES is set, this may be a tree item. If
* GIT_ITERATOR_DONT_AUTOEXPAND is set, calling this again when on a tree
* item will skip over all the items under that tree.
*/
GIT_INLINE(int) git_iterator_advance(
const git_index_entry **entry, git_iterator *iter)
{ {
return iter->cb->at_end(iter); return iter->cb->advance(entry, iter);
} }
GIT_INLINE(int) git_iterator_advance( /**
git_iterator *iter, const git_index_entry **entry) * Iterate into a tree item (when GIT_ITERATOR_DONT_AUTOEXPAND is set).
*
* git_iterator_advance() steps through all items being iterated over
* (either with or without trees, depending on GIT_ITERATOR_INCLUDE_TREES),
* but if GIT_ITERATOR_DONT_AUTOEXPAND is set, it will skip to the next
* sibling of a tree instead of going to the first child of the tree. In
* that case, use this function to advance to the first child of the tree.
*
* If the current item is not a tree, this is a no-op.
*
* For working directory iterators only, a tree (i.e. directory) can be
* empty. In that case, this function returns GIT_ENOTFOUND and does not
* advance. That can't happen for tree and index iterators.
*/
GIT_INLINE(int) git_iterator_advance_into(
const git_index_entry **entry, git_iterator *iter)
{ {
return iter->cb->advance(iter, entry); return iter->cb->advance_into(entry, iter);
} }
GIT_INLINE(int) git_iterator_seek( GIT_INLINE(int) git_iterator_seek(
...@@ -146,6 +153,11 @@ GIT_INLINE(int) git_iterator_reset( ...@@ -146,6 +153,11 @@ GIT_INLINE(int) git_iterator_reset(
return iter->cb->reset(iter, start, end); 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) GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter)
{ {
return iter->type; return iter->type;
...@@ -166,47 +178,28 @@ GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter) ...@@ -166,47 +178,28 @@ GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter)
return ((iter->flags & GIT_ITERATOR_IGNORE_CASE) != 0); return ((iter->flags & GIT_ITERATOR_IGNORE_CASE) != 0);
} }
extern int git_iterator_set_ignore_case(git_iterator *iter, bool ignore_case);
extern int git_iterator_current_tree_entry( extern int git_iterator_current_tree_entry(
git_iterator *iter, const git_tree_entry **tree_entry); const git_tree_entry **entry_out, git_iterator *iter);
extern int git_iterator_current_parent_tree( extern int git_iterator_current_parent_tree(
git_iterator *iter, const char *parent_path, const git_tree **tree_ptr); const git_tree **tree_out, 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.
*
* Workdir iterators do not automatically descend into directories (so that
* when comparing two iterator entries you can detect a newly created
* directory in the workdir). As a result, you may get S_ISDIR items from
* a workdir iterator. If you wish to iterate over the contents of the
* directories you encounter, then call this function when you encounter
* a directory.
*
* If there are no files in the directory, this will end up acting like a
* regular advance and will skip past the directory, so you should be
* prepared for that case.
*
* 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_cmp( extern int git_iterator_cmp(
git_iterator *iter, const char *path_prefix); git_iterator *iter, const char *path_prefix);
/** /**
* Get the full path of the current item from a workdir iterator. * Get full path of the current item from a workdir iterator. This will
* This will return NULL for a non-workdir iterator. * 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( 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);
extern git_iterator_type_t git_iterator_inner_type(git_iterator *iter); /* Return index pointer if index iterator, else NULL */
extern git_index *git_iterator_get_index(git_iterator *iter);
#endif #endif
...@@ -625,7 +625,7 @@ int git_note_iterator_new( ...@@ -625,7 +625,7 @@ int git_note_iterator_new(
if (error < 0) if (error < 0)
goto cleanup; 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); git_iterator_free(*it);
cleanup: cleanup:
...@@ -643,7 +643,7 @@ int git_note_next( ...@@ -643,7 +643,7 @@ int git_note_next(
int error; int error;
const git_index_entry *item; const git_index_entry *item;
if ((error = git_iterator_current(it, &item)) < 0) if ((error = git_iterator_current(&item, it)) < 0)
goto exit; goto exit;
if (item != NULL) { if (item != NULL) {
...@@ -651,7 +651,7 @@ int git_note_next( ...@@ -651,7 +651,7 @@ int git_note_next(
error = process_entry_path(item->path, annotated_id); error = process_entry_path(item->path, annotated_id);
if (error >= 0) if (error >= 0)
error = git_iterator_advance(it, NULL); error = git_iterator_advance(NULL, it);
} else { } else {
error = GIT_ITEROVER; error = GIT_ITEROVER;
} }
......
...@@ -32,14 +32,13 @@ typedef int git_file; ...@@ -32,14 +32,13 @@ typedef int git_file;
* Standard POSIX Methods * Standard POSIX Methods
* *
* All the methods starting with the `p_` prefix are * All the methods starting with the `p_` prefix are
* direct ports of the standard POSIX methods. * direct ports of the standard POSIX methods.
* *
* Some of the methods are slightly wrapped to provide * Some of the methods are slightly wrapped to provide
* saner defaults. Some of these methods are emulated * saner defaults. Some of these methods are emulated
* in Windows platforns. * in Windows platforns.
* *
* Use your manpages to check the docs on these. * Use your manpages to check the docs on these.
* Straightforward
*/ */
extern int p_read(git_file fd, void *buf, size_t cnt); extern int p_read(git_file fd, void *buf, size_t cnt);
......
...@@ -1135,10 +1135,10 @@ static int load_submodule_config_from_index( ...@@ -1135,10 +1135,10 @@ static int load_submodule_config_from_index(
const git_index_entry *entry; const git_index_entry *entry;
if ((error = git_repository_index__weakptr(&index, repo)) < 0 || 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; return error;
error = git_iterator_current(i, &entry); error = git_iterator_current(&entry, i);
while (!error && entry != NULL) { while (!error && entry != NULL) {
...@@ -1154,7 +1154,7 @@ static int load_submodule_config_from_index( ...@@ -1154,7 +1154,7 @@ static int load_submodule_config_from_index(
git_oid_cpy(gitmodules_oid, &entry->oid); git_oid_cpy(gitmodules_oid, &entry->oid);
} }
error = git_iterator_advance(i, &entry); error = git_iterator_advance(&entry, i);
} }
git_iterator_free(i); git_iterator_free(i);
...@@ -1173,12 +1173,12 @@ static int load_submodule_config_from_head( ...@@ -1173,12 +1173,12 @@ 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, head)) < 0) { if ((error = git_iterator_for_tree(&i, head, 0, NULL, NULL)) < 0) {
git_tree_free(head); git_tree_free(head);
return error; return error;
} }
error = git_iterator_current(i, &entry); error = git_iterator_current(&entry, i);
while (!error && entry != NULL) { while (!error && entry != NULL) {
...@@ -1195,7 +1195,7 @@ static int load_submodule_config_from_head( ...@@ -1195,7 +1195,7 @@ static int load_submodule_config_from_head(
git_oid_cpy(gitmodules_oid, &entry->oid); git_oid_cpy(gitmodules_oid, &entry->oid);
} }
error = git_iterator_advance(i, &entry); error = git_iterator_advance(&entry, i);
} }
git_iterator_free(i); git_iterator_free(i);
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#endif #endif
static int binsearch( static int binsearch(
void **dst, const void *x, size_t size, git__tsort_r_cmp cmp, void *payload) void **dst, const void *x, size_t size, git__sort_r_cmp cmp, void *payload)
{ {
int l, c, r; int l, c, r;
void *lx, *cx; void *lx, *cx;
...@@ -71,7 +71,7 @@ static int binsearch( ...@@ -71,7 +71,7 @@ static int binsearch(
/* Binary insertion sort, but knowing that the first "start" entries are sorted. Used in timsort. */ /* Binary insertion sort, but knowing that the first "start" entries are sorted. Used in timsort. */
static void bisort( static void bisort(
void **dst, size_t start, size_t size, git__tsort_r_cmp cmp, void *payload) void **dst, size_t start, size_t size, git__sort_r_cmp cmp, void *payload)
{ {
size_t i; size_t i;
void *x; void *x;
...@@ -102,7 +102,7 @@ struct tsort_run { ...@@ -102,7 +102,7 @@ struct tsort_run {
struct tsort_store { struct tsort_store {
size_t alloc; size_t alloc;
git__tsort_r_cmp cmp; git__sort_r_cmp cmp;
void *payload; void *payload;
void **storage; void **storage;
}; };
...@@ -334,7 +334,7 @@ static ssize_t collapse(void **dst, struct tsort_run *stack, ssize_t stack_curr, ...@@ -334,7 +334,7 @@ static ssize_t collapse(void **dst, struct tsort_run *stack, ssize_t stack_curr,
while (0) while (0)
void git__tsort_r( void git__tsort_r(
void **dst, size_t size, git__tsort_r_cmp cmp, void *payload) void **dst, size_t size, git__sort_r_cmp cmp, void *payload)
{ {
struct tsort_store _store, *store = &_store; struct tsort_store _store, *store = &_store;
struct tsort_run run_stack[128]; struct tsort_run run_stack[128];
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define INCLUDE_posix__w32_h__ #define INCLUDE_posix__w32_h__
#include <stdio.h> #include <stdio.h>
#include <sys/param.h>
#define p_lstat(p,b) lstat(p,b) #define p_lstat(p,b) lstat(p,b)
#define p_readlink(a, b, c) readlink(a, b, c) #define p_readlink(a, b, c) readlink(a, b, c)
......
...@@ -607,3 +607,55 @@ size_t git__unescape(char *str) ...@@ -607,3 +607,55 @@ size_t git__unescape(char *str)
return (pos - str); return (pos - str);
} }
#if defined(GIT_WIN32) || defined(BSD)
typedef struct {
git__sort_r_cmp cmp;
void *payload;
} git__qsort_r_glue;
static int GIT_STDLIB_CALL git__qsort_r_glue_cmp(
void *payload, const void *a, const void *b)
{
git__qsort_r_glue *glue = payload;
return glue->cmp(a, b, glue->payload);
}
#endif
void git__qsort_r(
void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload)
{
#if defined(__MINGW32__)
git__insertsort_r(els, nel, elsize, NULL, cmp, payload);
#elif defined(GIT_WIN32)
git__qsort_r_glue glue = { cmp, payload };
qsort_s(els, nel, elsize, git__qsort_r_glue_cmp, &glue);
#elif defined(BSD)
git__qsort_r_glue glue = { cmp, payload };
qsort_r(els, nel, elsize, &glue, git__qsort_r_glue_cmp);
#else
qsort_r(els, nel, elsize, cmp, payload);
#endif
}
void git__insertsort_r(
void *els, size_t nel, size_t elsize, void *swapel,
git__sort_r_cmp cmp, void *payload)
{
uint8_t *base = els, *end = els + nel * elsize;
uint8_t *i, *j;
bool freeswap = !swapel;
if (freeswap)
swapel = git__malloc(elsize);
for (i = base + elsize; i < end; i += elsize)
for (j = i; j > base && cmp(j, j - elsize, payload) < 0; j -= elsize) {
memcpy(swapel, j, elsize);
memcpy(j, j - elsize, elsize);
memcpy(j - elsize, swapel, elsize);
}
if (freeswap)
git__free(swapel);
}
...@@ -146,11 +146,17 @@ typedef int (*git__tsort_cmp)(const void *a, const void *b); ...@@ -146,11 +146,17 @@ typedef int (*git__tsort_cmp)(const void *a, const void *b);
extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp); extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp);
typedef int (*git__tsort_r_cmp)(const void *a, const void *b, void *payload); typedef int (*git__sort_r_cmp)(const void *a, const void *b, void *payload);
extern void git__tsort_r( extern void git__tsort_r(
void **dst, size_t size, git__tsort_r_cmp cmp, void *payload); void **dst, size_t size, git__sort_r_cmp cmp, void *payload);
extern void git__qsort_r(
void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload);
extern void git__insertsort_r(
void *els, size_t nel, size_t elsize, void *swapel,
git__sort_r_cmp cmp, void *payload);
/** /**
* @param position If non-NULL, this will be set to the position where the * @param position If non-NULL, this will be set to the position where the
......
...@@ -35,26 +35,26 @@ static void tree_iterator_test( ...@@ -35,26 +35,26 @@ 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( cl_git_pass(git_iterator_for_tree(
&i, t, GIT_ITERATOR_DONT_IGNORE_CASE, start, end)); &i, t, GIT_ITERATOR_DONT_IGNORE_CASE, start, end));
/* test loop */ /* test loop */
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
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)); cl_git_pass(git_iterator_advance(&entry, i));
} }
/* test reset */ /* test reset */
cl_git_pass(git_iterator_reset(i, NULL, NULL)); cl_git_pass(git_iterator_reset(i, NULL, NULL));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
while (entry != NULL) { while (entry != NULL) {
if (expected_values != NULL) if (expected_values != NULL)
cl_assert_equal_s(expected_values[count_post_reset], entry->path); cl_assert_equal_s(expected_values[count_post_reset], entry->path);
count_post_reset++; count_post_reset++;
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(&entry, i));
} }
git_iterator_free(i); git_iterator_free(i);
...@@ -261,30 +261,30 @@ static void check_tree_entry( ...@@ -261,30 +261,30 @@ static void check_tree_entry(
const git_tree *tree; const git_tree *tree;
git_buf path = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT;
cl_git_pass(git_iterator_current_tree_entry(i, &te)); cl_git_pass(git_iterator_current_tree_entry(&te, i));
cl_assert(te); cl_assert(te);
cl_assert(git_oid_streq(&te->oid, oid) == 0); cl_assert(git_oid_streq(&te->oid, oid) == 0);
cl_git_pass(git_iterator_current(i, &ie)); cl_git_pass(git_iterator_current(&ie, i));
cl_git_pass(git_buf_sets(&path, ie->path)); cl_git_pass(git_buf_sets(&path, ie->path));
if (oid_p) { if (oid_p) {
git_buf_rtruncate_at_char(&path, '/'); git_buf_rtruncate_at_char(&path, '/');
cl_git_pass(git_iterator_current_parent_tree(i, path.ptr, &tree)); cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr));
cl_assert(tree); cl_assert(tree);
cl_assert(git_oid_streq(git_tree_id(tree), oid_p) == 0); cl_assert(git_oid_streq(git_tree_id(tree), oid_p) == 0);
} }
if (oid_pp) { if (oid_pp) {
git_buf_rtruncate_at_char(&path, '/'); git_buf_rtruncate_at_char(&path, '/');
cl_git_pass(git_iterator_current_parent_tree(i, path.ptr, &tree)); cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr));
cl_assert(tree); cl_assert(tree);
cl_assert(git_oid_streq(git_tree_id(tree), oid_pp) == 0); cl_assert(git_oid_streq(git_tree_id(tree), oid_pp) == 0);
} }
if (oid_ppp) { if (oid_ppp) {
git_buf_rtruncate_at_char(&path, '/'); git_buf_rtruncate_at_char(&path, '/');
cl_git_pass(git_iterator_current_parent_tree(i, path.ptr, &tree)); cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr));
cl_assert(tree); cl_assert(tree);
cl_assert(git_oid_streq(git_tree_id(tree), oid_ppp) == 0); cl_assert(git_oid_streq(git_tree_id(tree), oid_ppp) == 0);
} }
...@@ -305,9 +305,9 @@ void test_diff_iterator__tree_special_functions(void) ...@@ -305,9 +305,9 @@ 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( cl_git_pass(git_iterator_for_tree(
&i, t, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); &i, t, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
while (entry != NULL) { while (entry != NULL) {
if (strcmp(entry->path, "sub/file") == 0) { if (strcmp(entry->path, "sub/file") == 0) {
...@@ -339,7 +339,7 @@ void test_diff_iterator__tree_special_functions(void) ...@@ -339,7 +339,7 @@ void test_diff_iterator__tree_special_functions(void)
rootoid, NULL); rootoid, NULL);
} }
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(&entry, i));
} }
cl_assert_equal_i(4, cases); cl_assert_equal_i(4, cases);
...@@ -364,8 +364,8 @@ static void index_iterator_test( ...@@ -364,8 +364,8 @@ static void index_iterator_test(
git_repository *repo = cl_git_sandbox_init(sandbox); git_repository *repo = cl_git_sandbox_init(sandbox);
cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_repository_index(&index, repo));
cl_git_pass(git_iterator_for_index_range(&i, index, 0, start, end)); cl_git_pass(git_iterator_for_index(&i, index, 0, start, end));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
while (entry != NULL) { while (entry != NULL) {
if (expected_names != NULL) if (expected_names != NULL)
...@@ -378,7 +378,7 @@ static void index_iterator_test( ...@@ -378,7 +378,7 @@ static void index_iterator_test(
} }
count++; count++;
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(&entry, i));
} }
git_iterator_free(i); git_iterator_free(i);
...@@ -538,14 +538,15 @@ static void workdir_iterator_test( ...@@ -538,14 +538,15 @@ static void workdir_iterator_test(
int count = 0, count_all = 0, count_all_post_reset = 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, 0, start, end)); cl_git_pass(git_iterator_for_workdir(
cl_git_pass(git_iterator_current(i, &entry)); &i, repo, GIT_ITERATOR_DONT_AUTOEXPAND, start, end));
cl_git_pass(git_iterator_current(&entry, i));
while (entry != NULL) { while (entry != NULL) {
int ignored = git_iterator_current_is_ignored(i); int ignored = git_iterator_current_is_ignored(i);
if (S_ISDIR(entry->mode)) { if (S_ISDIR(entry->mode)) {
cl_git_pass(git_iterator_advance_into_directory(i, &entry)); cl_git_pass(git_iterator_advance_into(&entry, i));
continue; continue;
} }
...@@ -559,22 +560,22 @@ static void workdir_iterator_test( ...@@ -559,22 +560,22 @@ static void workdir_iterator_test(
count++; count++;
count_all++; count_all++;
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(&entry, i));
} }
cl_git_pass(git_iterator_reset(i, NULL, NULL)); cl_git_pass(git_iterator_reset(i, NULL, NULL));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
while (entry != NULL) { while (entry != NULL) {
if (S_ISDIR(entry->mode)) { if (S_ISDIR(entry->mode)) {
cl_git_pass(git_iterator_advance_into_directory(i, &entry)); cl_git_pass(git_iterator_advance_into(&entry, i));
continue; continue;
} }
if (expected_names != NULL) if (expected_names != NULL)
cl_assert_equal_s( cl_assert_equal_s(
expected_names[count_all_post_reset], entry->path); expected_names[count_all_post_reset], entry->path);
count_all_post_reset++; count_all_post_reset++;
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(&entry, i));
} }
git_iterator_free(i); git_iterator_free(i);
...@@ -735,9 +736,9 @@ void test_diff_iterator__workdir_builtin_ignores(void) ...@@ -735,9 +736,9 @@ void test_diff_iterator__workdir_builtin_ignores(void)
cl_git_pass(p_mkdir("attr/sub/sub/.git", 0777)); cl_git_pass(p_mkdir("attr/sub/sub/.git", 0777));
cl_git_mkfile("attr/sub/.git", "whatever"); cl_git_mkfile("attr/sub/.git", "whatever");
cl_git_pass( cl_git_pass(git_iterator_for_workdir(
git_iterator_for_workdir_range(&i, repo, 0, "dir", "sub/sub/file")); &i, repo, GIT_ITERATOR_DONT_AUTOEXPAND, "dir", "sub/sub/file"));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
for (idx = 0; entry != NULL; ++idx) { for (idx = 0; entry != NULL; ++idx) {
int ignored = git_iterator_current_is_ignored(i); int ignored = git_iterator_current_is_ignored(i);
...@@ -746,9 +747,9 @@ void test_diff_iterator__workdir_builtin_ignores(void) ...@@ -746,9 +747,9 @@ void test_diff_iterator__workdir_builtin_ignores(void)
cl_assert_(ignored == expected[idx].ignored, expected[idx].path); cl_assert_(ignored == expected[idx].ignored, expected[idx].path);
if (!ignored && S_ISDIR(entry->mode)) if (!ignored && S_ISDIR(entry->mode))
cl_git_pass(git_iterator_advance_into_directory(i, &entry)); cl_git_pass(git_iterator_advance_into(&entry, i));
else else
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(&entry, i));
} }
cl_assert(expected[idx].path == NULL); cl_assert(expected[idx].path == NULL);
...@@ -764,17 +765,14 @@ static void check_wd_first_through_third_range( ...@@ -764,17 +765,14 @@ static void check_wd_first_through_third_range(
int idx; int idx;
static const char *expected[] = { "FIRST", "second", "THIRD", NULL }; static const char *expected[] = { "FIRST", "second", "THIRD", NULL };
cl_git_pass(git_iterator_for_workdir_range( cl_git_pass(git_iterator_for_workdir(
&i, repo, GIT_ITERATOR_IGNORE_CASE, start, end)); &i, repo, GIT_ITERATOR_IGNORE_CASE, start, end));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
for (idx = 0; entry != NULL; ++idx) { for (idx = 0; entry != NULL; ++idx) {
cl_assert_equal_s(expected[idx], entry->path); cl_assert_equal_s(expected[idx], entry->path);
if (S_ISDIR(entry->mode)) cl_git_pass(git_iterator_advance(&entry, i));
cl_git_pass(git_iterator_advance_into_directory(i, &entry));
else
cl_git_pass(git_iterator_advance(i, &entry));
} }
cl_assert(expected[idx] == NULL); cl_assert(expected[idx] == NULL);
...@@ -817,16 +815,16 @@ static void check_tree_range( ...@@ -817,16 +815,16 @@ static void check_tree_range(
cl_git_pass(git_repository_head_tree(&head, repo)); cl_git_pass(git_repository_head_tree(&head, repo));
cl_git_pass(git_iterator_for_tree_range( cl_git_pass(git_iterator_for_tree(
&i, head, &i, head,
ignore_case ? GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE, ignore_case ? GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE,
start, end)); start, end));
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
for (count = 0; entry != NULL; ) { for (count = 0; entry != NULL; ) {
++count; ++count;
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(&entry, i));
} }
cl_assert_equal_i(expected_count, count); cl_assert_equal_i(expected_count, count);
...@@ -882,15 +880,15 @@ static void check_index_range( ...@@ -882,15 +880,15 @@ static void check_index_range(
if (ignore_case != is_ignoring_case) if (ignore_case != is_ignoring_case)
cl_git_pass(git_index_set_caps(index, caps ^ GIT_INDEXCAP_IGNORE_CASE)); cl_git_pass(git_index_set_caps(index, caps ^ GIT_INDEXCAP_IGNORE_CASE));
cl_git_pass(git_iterator_for_index_range(&i, index, 0, start, end)); cl_git_pass(git_iterator_for_index(&i, index, 0, start, end));
cl_assert(git_iterator_ignore_case(i) == ignore_case); cl_assert(git_iterator_ignore_case(i) == ignore_case);
cl_git_pass(git_iterator_current(i, &entry)); cl_git_pass(git_iterator_current(&entry, i));
for (count = 0; entry != NULL; ) { for (count = 0; entry != NULL; ) {
++count; ++count;
cl_git_pass(git_iterator_advance(i, &entry)); cl_git_pass(git_iterator_advance(&entry, i));
} }
cl_assert_equal_i(expected_count, count); cl_assert_equal_i(expected_count, count);
......
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = false
Unnamed repository; edit this file 'description' to name the repository.
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
0000000000000000000000000000000000000000 76d6e1d231b1085fcce151427e9899335de74be6 Russell Belfer <rb@github.com> 1359157123 -0800 commit (initial): initial commit
0000000000000000000000000000000000000000 76d6e1d231b1085fcce151427e9899335de74be6 Russell Belfer <rb@github.com> 1359157123 -0800 commit (initial): initial commit
76d6e1d231b1085fcce151427e9899335de74be6
...@@ -274,6 +274,7 @@ void test_status_worktree__issue_592(void) ...@@ -274,6 +274,7 @@ void test_status_worktree__issue_592(void)
repo = cl_git_sandbox_init("issue_592"); repo = cl_git_sandbox_init("issue_592");
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "l.txt")); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "l.txt"));
cl_git_pass(p_unlink(git_buf_cstr(&path))); cl_git_pass(p_unlink(git_buf_cstr(&path)));
cl_assert(!git_path_exists("issue_592/l.txt"));
cl_git_pass(git_status_foreach(repo, cb_status__check_592, "l.txt")); cl_git_pass(git_status_foreach(repo, cb_status__check_592, "l.txt"));
...@@ -288,6 +289,7 @@ void test_status_worktree__issue_592_2(void) ...@@ -288,6 +289,7 @@ void test_status_worktree__issue_592_2(void)
repo = cl_git_sandbox_init("issue_592"); repo = cl_git_sandbox_init("issue_592");
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c/a.txt")); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c/a.txt"));
cl_git_pass(p_unlink(git_buf_cstr(&path))); cl_git_pass(p_unlink(git_buf_cstr(&path)));
cl_assert(!git_path_exists("issue_592/c/a.txt"));
cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt")); cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt"));
...@@ -303,6 +305,7 @@ void test_status_worktree__issue_592_3(void) ...@@ -303,6 +305,7 @@ void test_status_worktree__issue_592_3(void)
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c")); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c"));
cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
cl_assert(!git_path_exists("issue_592/c/a.txt"));
cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt")); cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt"));
......
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