Diff iterators

This refactors the diff output code so that an iterator object
can be used to traverse and generate the diffs, instead of just
the `foreach()` style with callbacks.  The code has been rearranged
so that the two styles can still share most functions.

This also replaces `GIT_REVWALKOVER` with `GIT_ITEROVER` and uses
that as a common error code for marking the end of iteration when
using a iterator style of object.
This commit is contained in:
Russell Belfer 2012-08-30 14:24:16 -07:00
parent 4d3834038b
commit f335ecd6e1
25 changed files with 1492 additions and 578 deletions

View File

@ -169,7 +169,7 @@ enum {
GIT_DIFF_LINE_CONTEXT = ' ', GIT_DIFF_LINE_CONTEXT = ' ',
GIT_DIFF_LINE_ADDITION = '+', GIT_DIFF_LINE_ADDITION = '+',
GIT_DIFF_LINE_DELETION = '-', GIT_DIFF_LINE_DELETION = '-',
GIT_DIFF_LINE_ADD_EOFNL = '\n', /**< DEPRECATED */ GIT_DIFF_LINE_ADD_EOFNL = '\n', /**< DEPRECATED - will not be returned */
GIT_DIFF_LINE_DEL_EOFNL = '\0', /**< LF was removed at end of file */ GIT_DIFF_LINE_DEL_EOFNL = '\0', /**< LF was removed at end of file */
/* The following values will only be sent to a `git_diff_data_fn` when /* The following values will only be sent to a `git_diff_data_fn` when
@ -197,6 +197,11 @@ typedef int (*git_diff_data_fn)(
const char *content, const char *content,
size_t content_len); size_t content_len);
/**
* The diff iterator object is used to scan a diff list.
*/
typedef struct git_diff_iterator git_diff_iterator;
/** @name Diff List Generator Functions /** @name Diff List Generator Functions
* *
* These are the functions you would use to create (or destroy) a * These are the functions you would use to create (or destroy) a
@ -321,6 +326,60 @@ GIT_EXTERN(int) git_diff_merge(
*/ */
/**@{*/ /**@{*/
/**
* Create a diff iterator object that can be used to traverse a diff.
*/
GIT_EXTERN(int) git_diff_iterator_new(
git_diff_iterator **iterator,
git_diff_list *diff);
GIT_EXTERN(void) git_diff_iterator_free(git_diff_iterator *iter);
/**
* Return the number of files in the diff.
*/
GIT_EXTERN(int) git_diff_iterator_num_files(git_diff_iterator *iterator);
GIT_EXTERN(int) git_diff_iterator_num_hunks_in_file(git_diff_iterator *iterator);
GIT_EXTERN(int) git_diff_iterator_num_lines_in_hunk(git_diff_iterator *iterator);
/**
* Return the delta information for the next file in the diff.
*
* This will return a pointer to the next git_diff_delta` to be processed or
* NULL if the iterator is at the end of the diff, then advance.
*/
GIT_EXTERN(int) git_diff_iterator_next_file(
git_diff_delta **delta,
git_diff_iterator *iterator);
/**
* Return the hunk information for the next hunk in the current file.
*
* It is recommended that you not call this if the file is a binary
* file, but it is allowed to do so.
*
* Warning! Call this function for the first time on a file is when the
* actual text diff will be computed (it cannot be computed incrementally)
* so the first call for a new file is expensive (at least in relative
* terms - in reality, it is still pretty darn fast).
*/
GIT_EXTERN(int) git_diff_iterator_next_hunk(
git_diff_range **range,
const char **header,
size_t *header_len,
git_diff_iterator *iterator);
/**
* Return the next line of the current hunk of diffs.
*/
GIT_EXTERN(int) git_diff_iterator_next_line(
char *line_origin, /**< GIT_DIFF_LINE_... value from above */
const char **content,
size_t *content_len,
git_diff_iterator *iterator);
/** /**
* Iterate over a diff list issuing callbacks. * Iterate over a diff list issuing callbacks.
* *

View File

@ -28,7 +28,7 @@ enum {
GIT_EUSER = -7, GIT_EUSER = -7,
GIT_PASSTHROUGH = -30, GIT_PASSTHROUGH = -30,
GIT_REVWALKOVER = -31, GIT_ITEROVER = -31,
}; };
typedef struct { typedef struct {

View File

@ -201,7 +201,7 @@ GIT_EXTERN(int) git_revwalk_hide_ref(git_revwalk *walk, const char *refname);
* @param oid Pointer where to store the oid of the next commit * @param oid Pointer where to store the oid of the next commit
* @param walk the walker to pop the commit from. * @param walk the walker to pop the commit from.
* @return 0 if the next commit was found; * @return 0 if the next commit was found;
* GIT_REVWALKOVER if there are no commits left to iterate * GIT_ITEROVER if there are no commits left to iterate
*/ */
GIT_EXTERN(int) git_revwalk_next(git_oid *oid, git_revwalk *walk); GIT_EXTERN(int) git_revwalk_next(git_oid *oid, git_revwalk *walk);

View File

@ -188,6 +188,7 @@ int git_attr_foreach(
error = callback(assign->name, assign->value, payload); error = callback(assign->name, assign->value, payload);
if (error) { if (error) {
giterr_clear();
error = GIT_EUSER; error = GIT_EUSER;
goto cleanup; goto cleanup;
} }

View File

@ -221,6 +221,7 @@ static int file_foreach(
/* abort iterator on non-zero return value */ /* abort iterator on non-zero return value */
if (fn(key, var->value, data)) { if (fn(key, var->value, data)) {
giterr_clear();
result = GIT_EUSER; result = GIT_EUSER;
goto cleanup; goto cleanup;
} }

View File

@ -316,6 +316,7 @@ static git_diff_list *git_diff_list_alloc(
if (diff == NULL) if (diff == NULL)
return NULL; return NULL;
GIT_REFCOUNT_INC(diff);
diff->repo = repo; diff->repo = repo;
if (git_vector_init(&diff->deltas, 0, diff_delta__cmp) < 0 || if (git_vector_init(&diff->deltas, 0, diff_delta__cmp) < 0 ||
@ -391,15 +392,12 @@ fail:
return NULL; return NULL;
} }
void git_diff_list_free(git_diff_list *diff) static void diff_list_free(git_diff_list *diff)
{ {
git_diff_delta *delta; git_diff_delta *delta;
git_attr_fnmatch *match; git_attr_fnmatch *match;
unsigned int i; unsigned int i;
if (!diff)
return;
git_vector_foreach(&diff->deltas, i, delta) { git_vector_foreach(&diff->deltas, i, delta) {
git__free(delta); git__free(delta);
diff->deltas.contents[i] = NULL; diff->deltas.contents[i] = NULL;
@ -416,6 +414,14 @@ void git_diff_list_free(git_diff_list *diff)
git__free(diff); git__free(diff);
} }
void git_diff_list_free(git_diff_list *diff)
{
if (!diff)
return;
GIT_REFCOUNT_DEC(diff, diff_list_free);
}
static int oid_for_workdir_item( static int oid_for_workdir_item(
git_repository *repo, git_repository *repo,
const git_index_entry *item, const git_index_entry *item,

View File

@ -26,6 +26,7 @@ enum {
}; };
struct git_diff_list { struct git_diff_list {
git_refcount rc;
git_repository *repo; git_repository *repo;
git_diff_options opts; git_diff_options opts;
git_vector pathspec; git_vector pathspec;

File diff suppressed because it is too large Load Diff

View File

@ -221,7 +221,7 @@ int git_fetch_negotiate(git_remote *remote)
} }
} }
if (error < 0 && error != GIT_REVWALKOVER) if (error < 0 && error != GIT_ITEROVER)
goto on_error; goto on_error;
/* Tell the other end that we're done negotiating */ /* Tell the other end that we're done negotiating */

View File

@ -75,6 +75,17 @@ extern void git_pool_swap(git_pool *a, git_pool *b);
*/ */
extern void *git_pool_malloc(git_pool *pool, uint32_t items); extern void *git_pool_malloc(git_pool *pool, uint32_t items);
/**
* Allocate space and zero it out.
*/
GIT_INLINE(void *) git_pool_mallocz(git_pool *pool, uint32_t items)
{
void *ptr = git_pool_malloc(pool, items);
if (ptr)
memset(ptr, 0, (size_t)items * (size_t)pool->item_size);
return ptr;
}
/** /**
* Allocate space and duplicate string data into it. * Allocate space and duplicate string data into it.
* *

View File

@ -1643,7 +1643,6 @@ int git_reference_normalize_name(
} }
} }
*buffer_out++ = *current++; *buffer_out++ = *current++;
buffer_size--; buffer_size--;
} }

View File

@ -493,7 +493,7 @@ static int walk_and_search(git_object **out, git_revwalk *walk, regex_t *regex)
git_object_free(obj); git_object_free(obj);
} }
if (error < 0 && error == GIT_REVWALKOVER) if (error < 0 && error == GIT_ITEROVER)
error = GIT_ENOTFOUND; error = GIT_ENOTFOUND;
return error; return error;

View File

@ -449,6 +449,7 @@ int git_merge_base(git_oid *out, git_repository *repo, git_oid *one, git_oid *tw
if (!result) { if (!result) {
git_revwalk_free(walk); git_revwalk_free(walk);
giterr_clear();
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
} }
@ -682,7 +683,8 @@ static int revwalk_next_timesort(commit_object **object_out, git_revwalk *walk)
} }
} }
return GIT_REVWALKOVER; giterr_clear();
return GIT_ITEROVER;
} }
static int revwalk_next_unsorted(commit_object **object_out, git_revwalk *walk) static int revwalk_next_unsorted(commit_object **object_out, git_revwalk *walk)
@ -700,7 +702,8 @@ static int revwalk_next_unsorted(commit_object **object_out, git_revwalk *walk)
} }
} }
return GIT_REVWALKOVER; giterr_clear();
return GIT_ITEROVER;
} }
static int revwalk_next_toposort(commit_object **object_out, git_revwalk *walk) static int revwalk_next_toposort(commit_object **object_out, git_revwalk *walk)
@ -710,8 +713,10 @@ static int revwalk_next_toposort(commit_object **object_out, git_revwalk *walk)
for (;;) { for (;;) {
next = commit_list_pop(&walk->iterator_topo); next = commit_list_pop(&walk->iterator_topo);
if (next == NULL) if (next == NULL) {
return GIT_REVWALKOVER; giterr_clear();
return GIT_ITEROVER;
}
if (next->in_degree > 0) { if (next->in_degree > 0) {
next->topo_delay = 1; next->topo_delay = 1;
@ -736,7 +741,7 @@ static int revwalk_next_toposort(commit_object **object_out, git_revwalk *walk)
static int revwalk_next_reverse(commit_object **object_out, git_revwalk *walk) static int revwalk_next_reverse(commit_object **object_out, git_revwalk *walk)
{ {
*object_out = commit_list_pop(&walk->iterator_reverse); *object_out = commit_list_pop(&walk->iterator_reverse);
return *object_out ? 0 : GIT_REVWALKOVER; return *object_out ? 0 : GIT_ITEROVER;
} }
@ -751,8 +756,10 @@ static int prepare_walk(git_revwalk *walk)
* If walk->one is NULL, there were no positive references, * If walk->one is NULL, there were no positive references,
* so we know that the walk is already over. * so we know that the walk is already over.
*/ */
if (walk->one == NULL) if (walk->one == NULL) {
return GIT_REVWALKOVER; giterr_clear();
return GIT_ITEROVER;
}
/* first figure out what the merge bases are */ /* first figure out what the merge bases are */
if (merge_bases_many(&bases, walk, walk->one, &walk->twos) < 0) if (merge_bases_many(&bases, walk, walk->one, &walk->twos) < 0)
@ -780,7 +787,7 @@ static int prepare_walk(git_revwalk *walk)
return -1; return -1;
} }
if (error != GIT_REVWALKOVER) if (error != GIT_ITEROVER)
return error; return error;
walk->get_next = &revwalk_next_toposort; walk->get_next = &revwalk_next_toposort;
@ -792,7 +799,7 @@ static int prepare_walk(git_revwalk *walk)
if (commit_list_insert(next, &walk->iterator_reverse) == NULL) if (commit_list_insert(next, &walk->iterator_reverse) == NULL)
return -1; return -1;
if (error != GIT_REVWALKOVER) if (error != GIT_ITEROVER)
return error; return error;
walk->get_next = &revwalk_next_reverse; walk->get_next = &revwalk_next_reverse;
@ -891,9 +898,10 @@ int git_revwalk_next(git_oid *oid, git_revwalk *walk)
error = walk->get_next(&next, walk); error = walk->get_next(&next, walk);
if (error == GIT_REVWALKOVER) { if (error == GIT_ITEROVER) {
git_revwalk_reset(walk); git_revwalk_reset(walk);
return GIT_REVWALKOVER; giterr_clear();
return GIT_ITEROVER;
} }
if (!error) if (!error)

View File

@ -151,6 +151,9 @@ cleanup:
git_diff_list_free(idx2head); git_diff_list_free(idx2head);
git_diff_list_free(wd2idx); git_diff_list_free(wd2idx);
if (err == GIT_EUSER)
giterr_clear();
return err; return err;
} }

View File

@ -163,6 +163,7 @@ int git_submodule_foreach(
} }
if (callback(sm, sm->name, payload)) { if (callback(sm, sm->name, payload)) {
giterr_clear();
error = GIT_EUSER; error = GIT_EUSER;
break; break;
} }

View File

@ -58,59 +58,59 @@ void test_diff_blob__can_compare_text_blobs(void)
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
a, b, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); a, b, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_mods == 1); cl_assert_equal_i(1, expected.file_mods);
cl_assert(expected.at_least_one_of_them_is_binary == false); cl_assert(expected.at_least_one_of_them_is_binary == false);
cl_assert(expected.hunks == 1); cl_assert_equal_i(1, expected.hunks);
cl_assert(expected.lines == 6); cl_assert_equal_i(6, expected.lines);
cl_assert(expected.line_ctxt == 1); cl_assert_equal_i(1, expected.line_ctxt);
cl_assert(expected.line_adds == 5); cl_assert_equal_i(5, expected.line_adds);
cl_assert(expected.line_dels == 0); cl_assert_equal_i(0, expected.line_dels);
/* diff on tests/resources/attr/root_test2 */ /* diff on tests/resources/attr/root_test2 */
memset(&expected, 0, sizeof(expected)); memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
b, c, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); b, c, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_mods == 1); cl_assert_equal_i(1, expected.file_mods);
cl_assert(expected.at_least_one_of_them_is_binary == false); cl_assert(expected.at_least_one_of_them_is_binary == false);
cl_assert(expected.hunks == 1); cl_assert_equal_i(1, expected.hunks);
cl_assert(expected.lines == 15); cl_assert_equal_i(15, expected.lines);
cl_assert(expected.line_ctxt == 3); cl_assert_equal_i(3, expected.line_ctxt);
cl_assert(expected.line_adds == 9); cl_assert_equal_i(9, expected.line_adds);
cl_assert(expected.line_dels == 3); cl_assert_equal_i(3, expected.line_dels);
/* diff on tests/resources/attr/root_test3 */ /* diff on tests/resources/attr/root_test3 */
memset(&expected, 0, sizeof(expected)); memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
a, c, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); a, c, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_mods == 1); cl_assert_equal_i(1, expected.file_mods);
cl_assert(expected.at_least_one_of_them_is_binary == false); cl_assert(expected.at_least_one_of_them_is_binary == false);
cl_assert(expected.hunks == 1); cl_assert_equal_i(1, expected.hunks);
cl_assert(expected.lines == 13); cl_assert_equal_i(13, expected.lines);
cl_assert(expected.line_ctxt == 0); cl_assert_equal_i(0, expected.line_ctxt);
cl_assert(expected.line_adds == 12); cl_assert_equal_i(12, expected.line_adds);
cl_assert(expected.line_dels == 1); cl_assert_equal_i(1, expected.line_dels);
memset(&expected, 0, sizeof(expected)); memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
c, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); c, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_mods == 1); cl_assert_equal_i(1, expected.file_mods);
cl_assert(expected.at_least_one_of_them_is_binary == false); cl_assert(expected.at_least_one_of_them_is_binary == false);
cl_assert(expected.hunks == 2); cl_assert_equal_i(2, expected.hunks);
cl_assert(expected.lines == 14); cl_assert_equal_i(14, expected.lines);
cl_assert(expected.line_ctxt == 4); cl_assert_equal_i(4, expected.line_ctxt);
cl_assert(expected.line_adds == 6); cl_assert_equal_i(6, expected.line_adds);
cl_assert(expected.line_dels == 4); cl_assert_equal_i(4, expected.line_dels);
git_blob_free(a); git_blob_free(a);
git_blob_free(b); git_blob_free(b);
@ -124,14 +124,14 @@ void test_diff_blob__can_compare_against_null_blobs(void)
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
d, e, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); d, e, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_dels == 1); cl_assert_equal_i(1, expected.file_dels);
cl_assert(expected.at_least_one_of_them_is_binary == false); cl_assert(expected.at_least_one_of_them_is_binary == false);
cl_assert(expected.hunks == 1); cl_assert_equal_i(1, expected.hunks);
cl_assert(expected.hunk_old_lines == 14); cl_assert_equal_i(14, expected.hunk_old_lines);
cl_assert(expected.lines == 14); cl_assert_equal_i(14, expected.lines);
cl_assert(expected.line_dels == 14); cl_assert_equal_i(14, expected.line_dels);
opts.flags |= GIT_DIFF_REVERSE; opts.flags |= GIT_DIFF_REVERSE;
memset(&expected, 0, sizeof(expected)); memset(&expected, 0, sizeof(expected));
@ -139,14 +139,14 @@ void test_diff_blob__can_compare_against_null_blobs(void)
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
d, e, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); d, e, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_adds == 1); cl_assert_equal_i(1, expected.file_adds);
cl_assert(expected.at_least_one_of_them_is_binary == false); cl_assert(expected.at_least_one_of_them_is_binary == false);
cl_assert(expected.hunks == 1); cl_assert_equal_i(1, expected.hunks);
cl_assert(expected.hunk_new_lines == 14); cl_assert_equal_i(14, expected.hunk_new_lines);
cl_assert(expected.lines == 14); cl_assert_equal_i(14, expected.lines);
cl_assert(expected.line_adds == 14); cl_assert_equal_i(14, expected.line_adds);
opts.flags ^= GIT_DIFF_REVERSE; opts.flags ^= GIT_DIFF_REVERSE;
memset(&expected, 0, sizeof(expected)); memset(&expected, 0, sizeof(expected));
@ -156,10 +156,10 @@ void test_diff_blob__can_compare_against_null_blobs(void)
cl_assert(expected.at_least_one_of_them_is_binary == true); cl_assert(expected.at_least_one_of_them_is_binary == true);
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_dels == 1); cl_assert_equal_i(1, expected.file_dels);
cl_assert(expected.hunks == 0); cl_assert_equal_i(0, expected.hunks);
cl_assert(expected.lines == 0); cl_assert_equal_i(0, expected.lines);
memset(&expected, 0, sizeof(expected)); memset(&expected, 0, sizeof(expected));
@ -168,18 +168,18 @@ void test_diff_blob__can_compare_against_null_blobs(void)
cl_assert(expected.at_least_one_of_them_is_binary == true); cl_assert(expected.at_least_one_of_them_is_binary == true);
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_adds == 1); cl_assert_equal_i(1, expected.file_adds);
cl_assert(expected.hunks == 0); cl_assert_equal_i(0, expected.hunks);
cl_assert(expected.lines == 0); cl_assert_equal_i(0, expected.lines);
} }
static void assert_identical_blobs_comparison(diff_expects expected) static void assert_identical_blobs_comparison(diff_expects expected)
{ {
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_unmodified == 1); cl_assert_equal_i(1, expected.file_unmodified);
cl_assert(expected.hunks == 0); cl_assert_equal_i(0, expected.hunks);
cl_assert(expected.lines == 0); cl_assert_equal_i(0, expected.lines);
} }
void test_diff_blob__can_compare_identical_blobs(void) void test_diff_blob__can_compare_identical_blobs(void)
@ -209,10 +209,10 @@ static void assert_binary_blobs_comparison(diff_expects expected)
{ {
cl_assert(expected.at_least_one_of_them_is_binary == true); cl_assert(expected.at_least_one_of_them_is_binary == true);
cl_assert(expected.files == 1); cl_assert_equal_i(1, expected.files);
cl_assert(expected.file_mods == 1); cl_assert_equal_i(1, expected.file_mods);
cl_assert(expected.hunks == 0); cl_assert_equal_i(0, expected.hunks);
cl_assert(expected.lines == 0); cl_assert_equal_i(0, expected.lines);
} }
void test_diff_blob__can_compare_two_binary_blobs(void) void test_diff_blob__can_compare_two_binary_blobs(void)
@ -292,7 +292,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.hunks == 2); cl_assert_equal_i(2, expected.hunks);
/* Test with inter-hunk-context explicitly set to 0 */ /* Test with inter-hunk-context explicitly set to 0 */
opts.interhunk_lines = 0; opts.interhunk_lines = 0;
@ -300,7 +300,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.hunks == 2); cl_assert_equal_i(2, expected.hunks);
/* Test with inter-hunk-context explicitly set to 1 */ /* Test with inter-hunk-context explicitly set to 1 */
opts.interhunk_lines = 1; opts.interhunk_lines = 1;
@ -308,7 +308,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
cl_git_pass(git_diff_blobs( cl_git_pass(git_diff_blobs(
old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn)); old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(expected.hunks == 1); cl_assert_equal_i(1, expected.hunks);
git_blob_free(old_d); git_blob_free(old_d);
} }

View File

@ -103,3 +103,74 @@ int diff_line_fn(
} }
return 0; return 0;
} }
int diff_foreach_via_iterator(
git_diff_list *diff,
void *data,
git_diff_file_fn file_cb,
git_diff_hunk_fn hunk_cb,
git_diff_data_fn line_cb)
{
int error, curr, total;
git_diff_iterator *iter;
git_diff_delta *delta;
if ((error = git_diff_iterator_new(&iter, diff)) < 0)
return error;
curr = 0;
total = git_diff_iterator_num_files(iter);
while (!(error = git_diff_iterator_next_file(&delta, iter))) {
git_diff_range *range;
const char *hdr;
size_t hdr_len;
/* call file_cb for this file */
if (file_cb != NULL && file_cb(data, delta, (float)curr / total) != 0)
goto abort;
if (!hunk_cb && !line_cb)
continue;
while (!(error = git_diff_iterator_next_hunk(
&range, &hdr, &hdr_len, iter))) {
char origin;
const char *line;
size_t line_len;
if (hunk_cb && hunk_cb(data, delta, range, hdr, hdr_len) != 0)
goto abort;
if (!line_cb)
continue;
while (!(error = git_diff_iterator_next_line(
&origin, &line, &line_len, iter))) {
if (line_cb(data, delta, range, origin, line, line_len) != 0)
goto abort;
}
if (error && error != GIT_ITEROVER)
goto done;
}
if (error && error != GIT_ITEROVER)
goto done;
}
done:
git_diff_iterator_free(iter);
if (error == GIT_ITEROVER)
error = 0;
return error;
abort:
git_diff_iterator_free(iter);
giterr_clear();
return GIT_EUSER;
}

View File

@ -45,3 +45,9 @@ extern int diff_line_fn(
const char *content, const char *content,
size_t content_len); size_t content_len);
extern int diff_foreach_via_iterator(
git_diff_list *diff,
void *data,
git_diff_file_fn file_cb,
git_diff_hunk_fn hunk_cb,
git_diff_data_fn line_cb);

116
tests-clar/diff/diffiter.c Normal file
View File

@ -0,0 +1,116 @@
#include "clar_libgit2.h"
#include "diff_helpers.h"
void test_diff_diffiter__initialize(void)
{
}
void test_diff_diffiter__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_diff_diffiter__create(void)
{
git_repository *repo = cl_git_sandbox_init("attr");
git_diff_list *diff;
git_diff_iterator *iter;
cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));
cl_git_pass(git_diff_iterator_new(&iter, diff));
git_diff_iterator_free(iter);
git_diff_list_free(diff);
}
void test_diff_diffiter__iterate_files(void)
{
git_repository *repo = cl_git_sandbox_init("attr");
git_diff_list *diff;
git_diff_iterator *iter;
git_diff_delta *delta;
int error, count = 0;
cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));
cl_git_pass(git_diff_iterator_new(&iter, diff));
while ((error = git_diff_iterator_next_file(&delta, iter)) != GIT_ITEROVER) {
cl_assert_equal_i(0, error);
cl_assert(delta != NULL);
count++;
}
cl_assert_equal_i(GIT_ITEROVER, error);
cl_assert(delta == NULL);
cl_assert_equal_i(6, count);
git_diff_iterator_free(iter);
git_diff_list_free(diff);
}
void test_diff_diffiter__iterate_files_2(void)
{
git_repository *repo = cl_git_sandbox_init("status");
git_diff_list *diff;
git_diff_iterator *iter;
git_diff_delta *delta;
int error, count = 0;
cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));
cl_git_pass(git_diff_iterator_new(&iter, diff));
while ((error = git_diff_iterator_next_file(&delta, iter)) != GIT_ITEROVER) {
cl_assert_equal_i(0, error);
cl_assert(delta != NULL);
count++;
}
cl_assert_equal_i(GIT_ITEROVER, error);
cl_assert(delta == NULL);
cl_assert_equal_i(8, count);
git_diff_iterator_free(iter);
git_diff_list_free(diff);
}
void test_diff_diffiter__iterate_files_and_hunks(void)
{
git_repository *repo = cl_git_sandbox_init("status");
git_diff_options opts = {0};
git_diff_list *diff = NULL;
git_diff_iterator *iter;
git_diff_delta *delta;
git_diff_range *range;
const char *header;
size_t header_len;
int error, file_count = 0, hunk_count = 0;
opts.context_lines = 3;
opts.interhunk_lines = 1;
opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));
cl_git_pass(git_diff_iterator_new(&iter, diff));
while ((error = git_diff_iterator_next_file(&delta, iter)) != GIT_ITEROVER) {
cl_assert_equal_i(0, error);
cl_assert(delta);
file_count++;
while ((error = git_diff_iterator_next_hunk(
&range, &header, &header_len, iter)) != GIT_ITEROVER) {
cl_assert_equal_i(0, error);
cl_assert(range);
hunk_count++;
}
}
cl_assert_equal_i(GIT_ITEROVER, error);
cl_assert(delta == NULL);
cl_assert_equal_i(13, file_count);
cl_assert_equal_i(8, hunk_count);
git_diff_iterator_free(iter);
git_diff_list_free(diff);
}

View File

@ -44,17 +44,17 @@ void test_diff_index__0(void)
* - git diff -U1 --cached 26a125ee1bf * - git diff -U1 --cached 26a125ee1bf
* - mv .git .gitted * - mv .git .gitted
*/ */
cl_assert(exp.files == 8); cl_assert_equal_i(8, exp.files);
cl_assert(exp.file_adds == 3); cl_assert_equal_i(3, exp.file_adds);
cl_assert(exp.file_dels == 2); cl_assert_equal_i(2, exp.file_dels);
cl_assert(exp.file_mods == 3); cl_assert_equal_i(3, exp.file_mods);
cl_assert(exp.hunks == 8); cl_assert_equal_i(8, exp.hunks);
cl_assert(exp.lines == 11); cl_assert_equal_i(11, exp.lines);
cl_assert(exp.line_ctxt == 3); cl_assert_equal_i(3, exp.line_ctxt);
cl_assert(exp.line_adds == 6); cl_assert_equal_i(6, exp.line_adds);
cl_assert(exp.line_dels == 2); cl_assert_equal_i(2, exp.line_dels);
git_diff_list_free(diff); git_diff_list_free(diff);
diff = NULL; diff = NULL;
@ -72,17 +72,17 @@ void test_diff_index__0(void)
* - git diff -U1 --cached 0017bd4ab1ec3 * - git diff -U1 --cached 0017bd4ab1ec3
* - mv .git .gitted * - mv .git .gitted
*/ */
cl_assert(exp.files == 12); cl_assert_equal_i(12, exp.files);
cl_assert(exp.file_adds == 7); cl_assert_equal_i(7, exp.file_adds);
cl_assert(exp.file_dels == 2); cl_assert_equal_i(2, exp.file_dels);
cl_assert(exp.file_mods == 3); cl_assert_equal_i(3, exp.file_mods);
cl_assert(exp.hunks == 12); cl_assert_equal_i(12, exp.hunks);
cl_assert(exp.lines == 16); cl_assert_equal_i(16, exp.lines);
cl_assert(exp.line_ctxt == 3); cl_assert_equal_i(3, exp.line_ctxt);
cl_assert(exp.line_adds == 11); cl_assert_equal_i(11, exp.line_adds);
cl_assert(exp.line_dels == 2); cl_assert_equal_i(2, exp.line_dels);
git_diff_list_free(diff); git_diff_list_free(diff);
diff = NULL; diff = NULL;
@ -132,7 +132,7 @@ void test_diff_index__1(void)
git_diff_foreach(diff, &exp, diff_stop_after_2_files, NULL, NULL) git_diff_foreach(diff, &exp, diff_stop_after_2_files, NULL, NULL)
); );
cl_assert(exp.files == 2); cl_assert_equal_i(2, exp.files);
git_diff_list_free(diff); git_diff_list_free(diff);
diff = NULL; diff = NULL;

View File

@ -39,17 +39,17 @@ void test_diff_tree__0(void)
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(exp.files == 5); cl_assert_equal_i(5, exp.files);
cl_assert(exp.file_adds == 2); cl_assert_equal_i(2, exp.file_adds);
cl_assert(exp.file_dels == 1); cl_assert_equal_i(1, exp.file_dels);
cl_assert(exp.file_mods == 2); cl_assert_equal_i(2, exp.file_mods);
cl_assert(exp.hunks == 5); cl_assert_equal_i(5, exp.hunks);
cl_assert(exp.lines == 7 + 24 + 1 + 6 + 6); cl_assert_equal_i(7 + 24 + 1 + 6 + 6, exp.lines);
cl_assert(exp.line_ctxt == 1); cl_assert_equal_i(1, exp.line_ctxt);
cl_assert(exp.line_adds == 24 + 1 + 5 + 5); cl_assert_equal_i(24 + 1 + 5 + 5, exp.line_adds);
cl_assert(exp.line_dels == 7 + 1); cl_assert_equal_i(7 + 1, exp.line_dels);
git_diff_list_free(diff); git_diff_list_free(diff);
diff = NULL; diff = NULL;
@ -61,17 +61,17 @@ void test_diff_tree__0(void)
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(exp.files == 2); cl_assert_equal_i(2, exp.files);
cl_assert(exp.file_adds == 0); cl_assert_equal_i(0, exp.file_adds);
cl_assert(exp.file_dels == 0); cl_assert_equal_i(0, exp.file_dels);
cl_assert(exp.file_mods == 2); cl_assert_equal_i(2, exp.file_mods);
cl_assert(exp.hunks == 2); cl_assert_equal_i(2, exp.hunks);
cl_assert(exp.lines == 8 + 15); cl_assert_equal_i(8 + 15, exp.lines);
cl_assert(exp.line_ctxt == 1); cl_assert_equal_i(1, exp.line_ctxt);
cl_assert(exp.line_adds == 1); cl_assert_equal_i(1, exp.line_adds);
cl_assert(exp.line_dels == 7 + 14); cl_assert_equal_i(7 + 14, exp.line_dels);
git_diff_list_free(diff); git_diff_list_free(diff);
@ -192,17 +192,17 @@ void test_diff_tree__bare(void)
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(exp.files == 3); cl_assert_equal_i(3, exp.files);
cl_assert(exp.file_adds == 2); cl_assert_equal_i(2, exp.file_adds);
cl_assert(exp.file_dels == 0); cl_assert_equal_i(0, exp.file_dels);
cl_assert(exp.file_mods == 1); cl_assert_equal_i(1, exp.file_mods);
cl_assert(exp.hunks == 3); cl_assert_equal_i(3, exp.hunks);
cl_assert(exp.lines == 4); cl_assert_equal_i(4, exp.lines);
cl_assert(exp.line_ctxt == 0); cl_assert_equal_i(0, exp.line_ctxt);
cl_assert(exp.line_adds == 3); cl_assert_equal_i(3, exp.line_adds);
cl_assert(exp.line_dels == 1); cl_assert_equal_i(1, exp.line_dels);
git_diff_list_free(diff); git_diff_list_free(diff);
git_tree_free(a); git_tree_free(a);
@ -242,17 +242,17 @@ void test_diff_tree__merge(void)
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff1, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff1, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert(exp.files == 6); cl_assert_equal_i(6, exp.files);
cl_assert(exp.file_adds == 2); cl_assert_equal_i(2, exp.file_adds);
cl_assert(exp.file_dels == 1); cl_assert_equal_i(1, exp.file_dels);
cl_assert(exp.file_mods == 3); cl_assert_equal_i(3, exp.file_mods);
cl_assert(exp.hunks == 6); cl_assert_equal_i(6, exp.hunks);
cl_assert(exp.lines == 59); cl_assert_equal_i(59, exp.lines);
cl_assert(exp.line_ctxt == 1); cl_assert_equal_i(1, exp.line_ctxt);
cl_assert(exp.line_adds == 36); cl_assert_equal_i(36, exp.line_adds);
cl_assert(exp.line_dels == 22); cl_assert_equal_i(22, exp.line_dels);
git_diff_list_free(diff1); git_diff_list_free(diff1);
} }

View File

@ -17,6 +17,7 @@ void test_diff_workdir__to_index(void)
git_diff_options opts = {0}; git_diff_options opts = {0};
git_diff_list *diff = NULL; git_diff_list *diff = NULL;
diff_expects exp; diff_expects exp;
int use_iterator;
g_repo = cl_git_sandbox_init("status"); g_repo = cl_git_sandbox_init("status");
@ -24,10 +25,15 @@ void test_diff_workdir__to_index(void)
opts.interhunk_lines = 1; opts.interhunk_lines = 1;
opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
@ -51,6 +57,7 @@ void test_diff_workdir__to_index(void)
cl_assert_equal_i(5, exp.line_ctxt); cl_assert_equal_i(5, exp.line_ctxt);
cl_assert_equal_i(4, exp.line_adds); cl_assert_equal_i(4, exp.line_adds);
cl_assert_equal_i(5, exp.line_dels); cl_assert_equal_i(5, exp.line_dels);
}
git_diff_list_free(diff); git_diff_list_free(diff);
} }
@ -65,6 +72,7 @@ void test_diff_workdir__to_tree(void)
git_diff_list *diff = NULL; git_diff_list *diff = NULL;
git_diff_list *diff2 = NULL; git_diff_list *diff2 = NULL;
diff_expects exp; diff_expects exp;
int use_iterator;
g_repo = cl_git_sandbox_init("status"); g_repo = cl_git_sandbox_init("status");
@ -75,8 +83,6 @@ void test_diff_workdir__to_tree(void)
opts.interhunk_lines = 1; opts.interhunk_lines = 1;
opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
memset(&exp, 0, sizeof(exp));
/* You can't really generate the equivalent of git_diff_workdir_to_tree() /* You can't really generate the equivalent of git_diff_workdir_to_tree()
* using C git. It really wants to interpose the index into the diff. * using C git. It really wants to interpose the index into the diff.
* *
@ -89,6 +95,13 @@ void test_diff_workdir__to_tree(void)
*/ */
cl_git_pass(git_diff_workdir_to_tree(g_repo, &opts, a, &diff)); cl_git_pass(git_diff_workdir_to_tree(g_repo, &opts, a, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
@ -98,6 +111,7 @@ void test_diff_workdir__to_tree(void)
cl_assert_equal_i(4, exp.file_mods); cl_assert_equal_i(4, exp.file_mods);
cl_assert_equal_i(1, exp.file_ignored); cl_assert_equal_i(1, exp.file_ignored);
cl_assert_equal_i(5, exp.file_untracked); cl_assert_equal_i(5, exp.file_untracked);
}
/* Since there is no git diff equivalent, let's just assume that the /* Since there is no git diff equivalent, let's just assume that the
* text diffs produced by git_diff_foreach are accurate here. We will * text diffs produced by git_diff_foreach are accurate here. We will
@ -117,6 +131,13 @@ void test_diff_workdir__to_tree(void)
cl_git_pass(git_diff_merge(diff, diff2)); cl_git_pass(git_diff_merge(diff, diff2));
git_diff_list_free(diff2); git_diff_list_free(diff2);
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
@ -133,6 +154,7 @@ void test_diff_workdir__to_tree(void)
cl_assert_equal_i(4, exp.line_ctxt); cl_assert_equal_i(4, exp.line_ctxt);
cl_assert_equal_i(8, exp.line_adds); cl_assert_equal_i(8, exp.line_adds);
cl_assert_equal_i(5, exp.line_dels); cl_assert_equal_i(5, exp.line_dels);
}
git_diff_list_free(diff); git_diff_list_free(diff);
diff = NULL; diff = NULL;
@ -146,6 +168,13 @@ void test_diff_workdir__to_tree(void)
cl_git_pass(git_diff_merge(diff, diff2)); cl_git_pass(git_diff_merge(diff, diff2));
git_diff_list_free(diff2); git_diff_list_free(diff2);
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
@ -162,6 +191,7 @@ void test_diff_workdir__to_tree(void)
cl_assert_equal_i(3, exp.line_ctxt); cl_assert_equal_i(3, exp.line_ctxt);
cl_assert_equal_i(12, exp.line_adds); cl_assert_equal_i(12, exp.line_adds);
cl_assert_equal_i(4, exp.line_dels); cl_assert_equal_i(4, exp.line_dels);
}
git_diff_list_free(diff); git_diff_list_free(diff);
@ -175,6 +205,7 @@ void test_diff_workdir__to_index_with_pathspec(void)
git_diff_list *diff = NULL; git_diff_list *diff = NULL;
diff_expects exp; diff_expects exp;
char *pathspec = NULL; char *pathspec = NULL;
int use_iterator;
g_repo = cl_git_sandbox_init("status"); g_repo = cl_git_sandbox_init("status");
@ -184,9 +215,15 @@ void test_diff_workdir__to_index_with_pathspec(void)
opts.pathspec.strings = &pathspec; opts.pathspec.strings = &pathspec;
opts.pathspec.count = 1; opts.pathspec.count = 1;
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff)); if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, NULL, NULL));
else
cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL)); cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));
cl_assert_equal_i(13, exp.files); cl_assert_equal_i(13, exp.files);
@ -195,13 +232,21 @@ void test_diff_workdir__to_index_with_pathspec(void)
cl_assert_equal_i(4, exp.file_mods); cl_assert_equal_i(4, exp.file_mods);
cl_assert_equal_i(1, exp.file_ignored); cl_assert_equal_i(1, exp.file_ignored);
cl_assert_equal_i(4, exp.file_untracked); cl_assert_equal_i(4, exp.file_untracked);
}
git_diff_list_free(diff); git_diff_list_free(diff);
memset(&exp, 0, sizeof(exp));
pathspec = "modified_file"; pathspec = "modified_file";
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, NULL, NULL));
else
cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL)); cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));
cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.files);
@ -210,13 +255,21 @@ void test_diff_workdir__to_index_with_pathspec(void)
cl_assert_equal_i(1, exp.file_mods); cl_assert_equal_i(1, exp.file_mods);
cl_assert_equal_i(0, exp.file_ignored); cl_assert_equal_i(0, exp.file_ignored);
cl_assert_equal_i(0, exp.file_untracked); cl_assert_equal_i(0, exp.file_untracked);
}
git_diff_list_free(diff); git_diff_list_free(diff);
memset(&exp, 0, sizeof(exp));
pathspec = "subdir"; pathspec = "subdir";
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, NULL, NULL));
else
cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL)); cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));
cl_assert_equal_i(3, exp.files); cl_assert_equal_i(3, exp.files);
@ -225,13 +278,21 @@ void test_diff_workdir__to_index_with_pathspec(void)
cl_assert_equal_i(1, exp.file_mods); cl_assert_equal_i(1, exp.file_mods);
cl_assert_equal_i(0, exp.file_ignored); cl_assert_equal_i(0, exp.file_ignored);
cl_assert_equal_i(1, exp.file_untracked); cl_assert_equal_i(1, exp.file_untracked);
}
git_diff_list_free(diff); git_diff_list_free(diff);
memset(&exp, 0, sizeof(exp));
pathspec = "*_deleted"; pathspec = "*_deleted";
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, NULL, NULL));
else
cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL)); cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));
cl_assert_equal_i(2, exp.files); cl_assert_equal_i(2, exp.files);
@ -240,6 +301,7 @@ void test_diff_workdir__to_index_with_pathspec(void)
cl_assert_equal_i(0, exp.file_mods); cl_assert_equal_i(0, exp.file_mods);
cl_assert_equal_i(0, exp.file_ignored); cl_assert_equal_i(0, exp.file_ignored);
cl_assert_equal_i(0, exp.file_untracked); cl_assert_equal_i(0, exp.file_untracked);
}
git_diff_list_free(diff); git_diff_list_free(diff);
} }
@ -249,6 +311,7 @@ void test_diff_workdir__filemode_changes(void)
git_config *cfg; git_config *cfg;
git_diff_list *diff = NULL; git_diff_list *diff = NULL;
diff_expects exp; diff_expects exp;
int use_iterator;
if (!cl_is_chmod_supported()) if (!cl_is_chmod_supported())
return; return;
@ -262,13 +325,20 @@ void test_diff_workdir__filemode_changes(void)
cl_git_pass(git_diff_workdir_to_index(g_repo, NULL, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, NULL, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.file_mods); cl_assert_equal_i(0, exp.file_mods);
cl_assert_equal_i(0, exp.hunks); cl_assert_equal_i(0, exp.hunks);
}
git_diff_list_free(diff); git_diff_list_free(diff);
@ -278,13 +348,20 @@ void test_diff_workdir__filemode_changes(void)
cl_git_pass(git_diff_workdir_to_index(g_repo, NULL, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, NULL, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(1, exp.file_mods); cl_assert_equal_i(1, exp.file_mods);
cl_assert_equal_i(0, exp.hunks); cl_assert_equal_i(0, exp.hunks);
}
git_diff_list_free(diff); git_diff_list_free(diff);
@ -347,6 +424,7 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void)
diff_expects exp; diff_expects exp;
char *pathspec = "staged_changes_modified_file"; char *pathspec = "staged_changes_modified_file";
git_tree *tree; git_tree *tree;
int use_iterator;
/* For this file, /* For this file,
* - head->index diff has 1 line of context, 1 line of diff * - head->index diff has 1 line of context, 1 line of diff
@ -366,9 +444,16 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void)
cl_git_pass(git_diff_index_to_tree(g_repo, &opts, tree, &diff_i2t)); cl_git_pass(git_diff_index_to_tree(g_repo, &opts, tree, &diff_i2t));
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff_w2i)); cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff_w2i));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_adds); cl_assert_equal_i(0, exp.file_adds);
cl_assert_equal_i(0, exp.file_dels); cl_assert_equal_i(0, exp.file_dels);
@ -378,10 +463,18 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void)
cl_assert_equal_i(1, exp.line_ctxt); cl_assert_equal_i(1, exp.line_ctxt);
cl_assert_equal_i(1, exp.line_adds); cl_assert_equal_i(1, exp.line_adds);
cl_assert_equal_i(0, exp.line_dels); cl_assert_equal_i(0, exp.line_dels);
}
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff_w2i, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff_w2i, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff_w2i, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_adds); cl_assert_equal_i(0, exp.file_adds);
cl_assert_equal_i(0, exp.file_dels); cl_assert_equal_i(0, exp.file_dels);
@ -391,12 +484,20 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void)
cl_assert_equal_i(2, exp.line_ctxt); cl_assert_equal_i(2, exp.line_ctxt);
cl_assert_equal_i(1, exp.line_adds); cl_assert_equal_i(1, exp.line_adds);
cl_assert_equal_i(0, exp.line_dels); cl_assert_equal_i(0, exp.line_dels);
}
cl_git_pass(git_diff_merge(diff_i2t, diff_w2i)); cl_git_pass(git_diff_merge(diff_i2t, diff_w2i));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_adds); cl_assert_equal_i(0, exp.file_adds);
cl_assert_equal_i(0, exp.file_dels); cl_assert_equal_i(0, exp.file_dels);
@ -406,6 +507,7 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void)
cl_assert_equal_i(1, exp.line_ctxt); cl_assert_equal_i(1, exp.line_ctxt);
cl_assert_equal_i(2, exp.line_adds); cl_assert_equal_i(2, exp.line_adds);
cl_assert_equal_i(0, exp.line_dels); cl_assert_equal_i(0, exp.line_dels);
}
git_diff_list_free(diff_i2t); git_diff_list_free(diff_i2t);
git_diff_list_free(diff_w2i); git_diff_list_free(diff_w2i);
@ -419,6 +521,7 @@ void test_diff_workdir__eof_newline_changes(void)
git_diff_list *diff = NULL; git_diff_list *diff = NULL;
diff_expects exp; diff_expects exp;
char *pathspec = "current_file"; char *pathspec = "current_file";
int use_iterator;
g_repo = cl_git_sandbox_init("status"); g_repo = cl_git_sandbox_init("status");
@ -427,9 +530,16 @@ void test_diff_workdir__eof_newline_changes(void)
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.file_adds); cl_assert_equal_i(0, exp.file_adds);
cl_assert_equal_i(0, exp.file_dels); cl_assert_equal_i(0, exp.file_dels);
@ -439,6 +549,7 @@ void test_diff_workdir__eof_newline_changes(void)
cl_assert_equal_i(0, exp.line_ctxt); cl_assert_equal_i(0, exp.line_ctxt);
cl_assert_equal_i(0, exp.line_adds); cl_assert_equal_i(0, exp.line_adds);
cl_assert_equal_i(0, exp.line_dels); cl_assert_equal_i(0, exp.line_dels);
}
git_diff_list_free(diff); git_diff_list_free(diff);
@ -446,9 +557,16 @@ void test_diff_workdir__eof_newline_changes(void)
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_adds); cl_assert_equal_i(0, exp.file_adds);
cl_assert_equal_i(0, exp.file_dels); cl_assert_equal_i(0, exp.file_dels);
@ -458,6 +576,7 @@ void test_diff_workdir__eof_newline_changes(void)
cl_assert_equal_i(1, exp.line_ctxt); cl_assert_equal_i(1, exp.line_ctxt);
cl_assert_equal_i(1, exp.line_adds); cl_assert_equal_i(1, exp.line_adds);
cl_assert_equal_i(0, exp.line_dels); cl_assert_equal_i(0, exp.line_dels);
}
git_diff_list_free(diff); git_diff_list_free(diff);
@ -465,9 +584,16 @@ void test_diff_workdir__eof_newline_changes(void)
cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff)); cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
else
cl_git_pass(git_diff_foreach( cl_git_pass(git_diff_foreach(
diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_adds); cl_assert_equal_i(0, exp.file_adds);
cl_assert_equal_i(0, exp.file_dels); cl_assert_equal_i(0, exp.file_dels);
@ -477,6 +603,7 @@ void test_diff_workdir__eof_newline_changes(void)
cl_assert_equal_i(0, exp.line_ctxt); cl_assert_equal_i(0, exp.line_ctxt);
cl_assert_equal_i(1, exp.line_adds); cl_assert_equal_i(1, exp.line_adds);
cl_assert_equal_i(2, exp.line_dels); cl_assert_equal_i(2, exp.line_dels);
}
git_diff_list_free(diff); git_diff_list_free(diff);
} }