diff options
author | Jason Haslam <jason@scitools.com> | 2015-07-16 10:17:16 -0600 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2015-11-02 16:33:58 -0500 |
commit | 3138ad936682addd191913c42946aae431b4eece (patch) | |
tree | abfb79a660933fb5ad68f3fdcd812fe9d0e61958 | |
parent | db1edf91e9ba9e82e6534c445008703766b5a6da (diff) | |
download | libgit2-3138ad936682addd191913c42946aae431b4eece.tar.gz |
Add diff progress callback.
-rw-r--r-- | CHANGELOG.md | 8 | ||||
-rw-r--r-- | include/git2/diff.h | 29 | ||||
-rw-r--r-- | src/diff.c | 15 | ||||
-rw-r--r-- | tests/diff/notify.c | 29 | ||||
-rw-r--r-- | tests/diff/tree.c | 2 |
5 files changed, 74 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ade3e3b1..0b2e43308 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ v0.23 + 1 the opportunity for concurrent operations and not committing any changes until the unlock. +* `git_diff_options` added a new callback `progress_cb` to report on the + progress of the diff as files are being compared. The documentation of + the existing callback `notify_cb` was updated to reflect that it only + gets called when new deltas are added to the diff. + ### API removals ### Breaking API changes @@ -36,6 +41,9 @@ v0.23 + 1 it existed in the index. This does not affect the higher-level `git_index_add_bypath` or `git_index_add_frombuffer` functions. +* The `notify_payload` field of `git_diff_options` was renamed to `payload` + to reflect that it's also the payload for the new progress callback. + v0.23 ------ diff --git a/include/git2/diff.h b/include/git2/diff.h index a0f6db350..cbffdb49a 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -351,6 +351,22 @@ typedef int (*git_diff_notify_cb)( void *payload); /** + * Diff progress callback. + * + * Called before each file comparison. + * + * @param diff_so_far The diff being generated. + * @param old_path The path to the old file or NULL. + * @param new_path The path to the new file or NULL. + * @return Non-zero to abort the diff. + */ +typedef int (*git_diff_progress_cb)( + const git_diff *diff_so_far, + const char *old_path, + const char *new_path, + void *payload); + +/** * Structure describing options about how the diff should be executed. * * Setting all values of the structure to zero will yield the default @@ -370,8 +386,10 @@ typedef int (*git_diff_notify_cb)( * - `max_size` is a file size (in bytes) above which a blob will be marked * as binary automatically; pass a negative value to disable. * - `notify_cb` is an optional callback function, notifying the consumer of - * which files are being examined as the diff is generated - * - `notify_payload` is the payload data to pass to the `notify_cb` function + * changes to the diff as new deltas are added. + * - `progress_cb` is an optional callback function, notifying the consumer of + * which files are being examined as the diff is generated. + * - `payload` is the payload to pass to the callback functions. * - `ignore_submodules` overrides the submodule ignore setting for all * submodules in the diff. */ @@ -383,8 +401,9 @@ typedef struct { git_submodule_ignore_t ignore_submodules; /**< submodule ignore rule */ git_strarray pathspec; /**< defaults to include all paths */ - git_diff_notify_cb notify_cb; - void *notify_payload; + git_diff_notify_cb notify_cb; + git_diff_progress_cb progress_cb; + void *payload; /* options controlling how to diff text is generated */ @@ -403,7 +422,7 @@ typedef struct { * `git_diff_options_init` programmatic initialization. */ #define GIT_DIFF_OPTIONS_INIT \ - {GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_UNSPECIFIED, {NULL,0}, NULL, NULL, 3} + {GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_UNSPECIFIED, {NULL,0}, NULL, NULL, NULL, 3} /** * Initializes a `git_diff_options` with default values. Equivalent to diff --git a/src/diff.c b/src/diff.c index b5e9b6cd5..c2362358a 100644 --- a/src/diff.c +++ b/src/diff.c @@ -56,7 +56,7 @@ static int diff_insert_delta( if (diff->opts.notify_cb) { error = diff->opts.notify_cb( - diff, delta, matched_pathspec, diff->opts.notify_payload); + diff, delta, matched_pathspec, diff->opts.payload); if (error) { git__free(delta); @@ -1260,7 +1260,18 @@ int git_diff__from_iterators( /* run iterators building diffs */ while (!error && (info.oitem || info.nitem)) { - int cmp = info.oitem ? + int cmp; + + /* report progress */ + if (opts && opts->progress_cb) { + if ((error = opts->progress_cb(diff, + info.oitem ? info.oitem->path : NULL, + info.nitem ? info.nitem->path : NULL, + opts->payload))) + break; + } + + cmp = info.oitem ? (info.nitem ? diff->entrycomp(info.oitem, info.nitem) : -1) : 1; /* create DELETED records for old items not matched in new */ diff --git a/tests/diff/notify.c b/tests/diff/notify.c index 6ef4af573..74abbc93b 100644 --- a/tests/diff/notify.c +++ b/tests/diff/notify.c @@ -55,7 +55,7 @@ static void test_notify( opts.pathspec.strings = searched_pathspecs; opts.pathspec.count = pathspecs_count; - opts.notify_payload = expected_matched_pathspecs; + opts.payload = expected_matched_pathspecs; memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); @@ -228,3 +228,30 @@ void test_diff_notify__notify_cb_can_be_used_as_filtering_function(void) git_diff_free(diff); } + +static int progress_abort_diff( + const git_diff *diff_so_far, + const char *old_path, + const char *new_path, + void *payload) +{ + GIT_UNUSED(old_path); + GIT_UNUSED(new_path); + GIT_UNUSED(payload); + + return -42; +} + +void test_diff_notify__progress_cb_can_abort_diff(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + + g_repo = cl_git_sandbox_init("status"); + + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + opts.progress_cb = progress_abort_diff; + + cl_git_fail_with( + git_diff_index_to_workdir(&diff, g_repo, NULL, &opts), -42); +} diff --git a/tests/diff/tree.c b/tests/diff/tree.c index 2bc9e6a55..e4b2a8bbe 100644 --- a/tests/diff/tree.c +++ b/tests/diff/tree.c @@ -90,7 +90,7 @@ void test_diff_tree__0(void) #define DIFF_OPTS(FLAGS, CTXT) \ {GIT_DIFF_OPTIONS_VERSION, (FLAGS), GIT_SUBMODULE_IGNORE_UNSPECIFIED, \ - {NULL,0}, NULL, NULL, (CTXT), 1} + {NULL,0}, NULL, NULL, NULL, (CTXT), 1} void test_diff_tree__options(void) { |