diff options
author | Russell Belfer <rb@github.com> | 2012-08-30 14:24:16 -0700 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2012-09-05 15:17:24 -0700 |
commit | f335ecd6e126aa9dea28786522c0e6ce71596e91 (patch) | |
tree | 3393df3457e423ddc1aaad4d89fb29184246f3a8 /tests-clar/diff/diff_helpers.c | |
parent | 4d3834038bd0aaef63d62c54900f6ddafec09515 (diff) | |
download | libgit2-f335ecd6e126aa9dea28786522c0e6ce71596e91.tar.gz |
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.
Diffstat (limited to 'tests-clar/diff/diff_helpers.c')
-rw-r--r-- | tests-clar/diff/diff_helpers.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c index 7b391262..59e01802 100644 --- a/tests-clar/diff/diff_helpers.c +++ b/tests-clar/diff/diff_helpers.c @@ -103,3 +103,74 @@ int diff_line_fn( } 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; +} |