summaryrefslogtreecommitdiff
path: root/src/diff_output.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-02-21 12:40:33 -0800
committerRussell Belfer <rb@github.com>2013-02-21 12:40:33 -0800
commit960a04dd56d89e94b5092be19ba9704b2d292dba (patch)
treef85c54d36d40f46b3ed31fecfa284f197973c6c3 /src/diff_output.c
parent71a3d27ea686845811f04314d02798b4f1745046 (diff)
downloadlibgit2-960a04dd56d89e94b5092be19ba9704b2d292dba.tar.gz
Initial integration of similarity metric to diff
This is the initial integration of the similarity metric into the `git_diff_find_similar()` code path. The existing tests all pass, but the new functionality isn't currently well tested. The integration does go through the pluggable metric interface, so it should be possible to drop in an alternative to the internal metric that libgit2 implements. This comes along with a behavior change for an existing interface; namely, passing two NULLs to git_diff_blobs (or passing NULLs to git_diff_blob_to_buffer) will now call the file_cb parameter zero times instead of one time. I know it's strange that that change is paired with this other change, but it emerged from some initialization changes that I ended up making.
Diffstat (limited to 'src/diff_output.c')
-rw-r--r--src/diff_output.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/src/diff_output.c b/src/diff_output.c
index 5e9d5fe76..13434beb9 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -456,7 +456,7 @@ static void release_content(git_diff_file *file, git_map *map, git_blob *blob)
}
-static void diff_context_init(
+static int diff_context_init(
diff_context *ctxt,
git_diff_list *diff,
git_repository *repo,
@@ -468,6 +468,12 @@ static void diff_context_init(
{
memset(ctxt, 0, sizeof(diff_context));
+ if (!repo && diff)
+ repo = diff->repo;
+
+ if (!opts && diff)
+ opts = &diff->opts;
+
ctxt->repo = repo;
ctxt->diff = diff;
ctxt->opts = opts;
@@ -478,6 +484,8 @@ static void diff_context_init(
ctxt->error = 0;
setup_xdiff_options(ctxt->opts, &ctxt->xdiff_config, &ctxt->xdiff_params);
+
+ return 0;
}
static int diff_delta_file_callback(
@@ -922,6 +930,15 @@ static int diff_patch_line_cb(
return 0;
}
+static int diff_required(git_diff_list *diff, const char *action)
+{
+ if (!diff) {
+ giterr_set(GITERR_INVALID, "Must provide valid diff to %s", action);
+ return -1;
+ }
+
+ return 0;
+}
int git_diff_foreach(
git_diff_list *diff,
@@ -935,9 +952,12 @@ int git_diff_foreach(
size_t idx;
git_diff_patch patch;
- diff_context_init(
- &ctxt, diff, diff->repo, &diff->opts,
- file_cb, hunk_cb, data_cb, payload);
+ if (diff_required(diff, "git_diff_foreach") < 0)
+ return -1;
+
+ if (diff_context_init(
+ &ctxt, diff, NULL, NULL, file_cb, hunk_cb, data_cb, payload) < 0)
+ return -1;
diff_patch_init(&ctxt, &patch);
@@ -1306,8 +1326,10 @@ static int diff_single_init(
memset(data, 0, sizeof(*data));
- diff_context_init(
- &data->ctxt, NULL, repo, opts, file_cb, hunk_cb, data_cb, payload);
+ if (diff_context_init(
+ &data->ctxt, NULL, repo, opts,
+ file_cb, hunk_cb, data_cb, payload) < 0)
+ return -1;
diff_patch_init(&data->ctxt, &data->patch);
@@ -1374,6 +1396,9 @@ int git_diff_blobs(
new_blob ? git_object_owner((const git_object *)new_blob) :
old_blob ? git_object_owner((const git_object *)old_blob) : NULL;
+ if (!repo) /* Hmm, given two NULL blobs, silently do no callbacks? */
+ return 0;
+
if ((error = diff_single_init(
&d, repo, options, file_cb, hunk_cb, data_cb, payload)) < 0)
return error;
@@ -1405,6 +1430,9 @@ int git_diff_blob_to_buffer(
git_repository *repo =
old_blob ? git_object_owner((const git_object *)old_blob) : NULL;
+ if (!repo && !buf) /* Hmm, given NULLs, silently do no callbacks? */
+ return 0;
+
if ((error = diff_single_init(
&d, repo, options, file_cb, hunk_cb, data_cb, payload)) < 0)
return error;
@@ -1453,11 +1481,19 @@ int git_diff_get_patch(
if (patch_ptr)
*patch_ptr = NULL;
+ if (delta_ptr)
+ *delta_ptr = NULL;
+
+ if (diff_required(diff, "git_diff_get_patch") < 0)
+ return -1;
+
+ if (diff_context_init(
+ &ctxt, diff, NULL, NULL,
+ NULL, diff_patch_hunk_cb, diff_patch_line_cb, NULL) < 0)
+ return -1;
delta = git_vector_get(&diff->deltas, idx);
if (!delta) {
- if (delta_ptr)
- *delta_ptr = NULL;
giterr_set(GITERR_INVALID, "Index out of range for delta in diff");
return GIT_ENOTFOUND;
}
@@ -1470,10 +1506,6 @@ int git_diff_get_patch(
(diff->opts.flags & GIT_DIFF_SKIP_BINARY_CHECK) != 0))
return 0;
- diff_context_init(
- &ctxt, diff, diff->repo, &diff->opts,
- NULL, diff_patch_hunk_cb, diff_patch_line_cb, NULL);
-
if (git_diff_delta__should_skip(ctxt.opts, delta))
return 0;