mirror of
https://git.proxmox.com/git/libgit2
synced 2025-12-28 20:32:21 +00:00
Introduce git_diff_blob_to_buffer
This commit is contained in:
parent
7dfc5c3c6c
commit
f6234cd994
@ -824,6 +824,30 @@ GIT_EXTERN(int) git_diff_blobs(
|
||||
git_diff_data_cb line_cb,
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* Directly run a text diff between a blob and a buffer.
|
||||
*
|
||||
* Compared to a file, a blob and a buffer lack some contextual information. As such,
|
||||
* the `git_diff_file` parameters of the callbacks will be filled
|
||||
* accordingly to the following: `mode` will be set to 0, `path` will be set
|
||||
* to NULL. When dealing with a NULL blob, `oid` will be set to 0.
|
||||
*
|
||||
* When at least the blob or the buffer are binary, the
|
||||
* `git_diff_delta` binary attribute will be set to 1 and no call to the
|
||||
* hunk_cb nor line_cb will be made.
|
||||
*
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_blob_to_buffer(
|
||||
git_blob *old_blob,
|
||||
char *buffer,
|
||||
size_t buffer_len,
|
||||
const git_diff_options *options,
|
||||
git_diff_file_cb file_cb,
|
||||
git_diff_hunk_cb hunk_cb,
|
||||
git_diff_data_cb data_cb,
|
||||
void *payload);
|
||||
|
||||
GIT_END_DECL
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -1231,7 +1231,6 @@ int git_diff_print_patch(
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static void set_data_from_blob(
|
||||
git_blob *blob, git_map *map, git_diff_file *file)
|
||||
{
|
||||
@ -1328,6 +1327,91 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
static void set_data_from_buffer(
|
||||
char *buffer, size_t buffer_len, git_map *map, git_diff_file *file)
|
||||
{
|
||||
file->size = buffer_len;
|
||||
file->mode = 0644;
|
||||
|
||||
map->len = (size_t)file->size;
|
||||
map->data = (char *)buffer;
|
||||
}
|
||||
|
||||
int git_diff_blob_to_buffer(
|
||||
git_blob *old_blob,
|
||||
char *buffer,
|
||||
size_t buffer_len,
|
||||
const git_diff_options *options,
|
||||
git_diff_file_cb file_cb,
|
||||
git_diff_hunk_cb hunk_cb,
|
||||
git_diff_data_cb data_cb,
|
||||
void *payload)
|
||||
{
|
||||
int error;
|
||||
git_repository *repo;
|
||||
diff_context ctxt;
|
||||
git_diff_delta delta;
|
||||
git_diff_patch patch;
|
||||
|
||||
GITERR_CHECK_VERSION(options, GIT_DIFF_OPTIONS_VERSION, "git_diff_options");
|
||||
|
||||
if (old_blob)
|
||||
repo = git_object_owner((git_object *)old_blob);
|
||||
else
|
||||
repo = NULL;
|
||||
|
||||
diff_context_init(
|
||||
&ctxt, NULL, repo, options,
|
||||
file_cb, hunk_cb, data_cb, payload);
|
||||
|
||||
diff_patch_init(&ctxt, &patch);
|
||||
|
||||
/* create a fake delta record and simulate diff_patch_load */
|
||||
|
||||
memset(&delta, 0, sizeof(delta));
|
||||
delta.binary = -1;
|
||||
|
||||
if (options && (options->flags & GIT_DIFF_REVERSE)) {
|
||||
set_data_from_blob(old_blob, &patch.new_data, &delta.new_file);
|
||||
set_data_from_buffer(buffer, buffer_len, &patch.old_data, &delta.old_file);
|
||||
} else {
|
||||
set_data_from_blob(old_blob, &patch.old_data, &delta.old_file);
|
||||
set_data_from_buffer(buffer, buffer_len, &patch.new_data, &delta.new_file);
|
||||
}
|
||||
|
||||
delta.status = buffer ?
|
||||
(old_blob ? GIT_DELTA_MODIFIED : GIT_DELTA_ADDED) :
|
||||
(old_blob ? GIT_DELTA_DELETED : GIT_DELTA_UNTRACKED);
|
||||
|
||||
if (git_oid_cmp(&delta.new_file.oid, &delta.old_file.oid) == 0)
|
||||
delta.status = GIT_DELTA_UNMODIFIED;
|
||||
|
||||
patch.delta = δ
|
||||
|
||||
if ((error = diff_delta_is_binary_by_content(
|
||||
&ctxt, &delta, &delta.old_file, &patch.old_data)) < 0 ||
|
||||
(error = diff_delta_is_binary_by_content(
|
||||
&ctxt, &delta, &delta.new_file, &patch.new_data)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
patch.flags |= GIT_DIFF_PATCH_LOADED;
|
||||
if (delta.binary != 1 && delta.status != GIT_DELTA_UNMODIFIED)
|
||||
patch.flags |= GIT_DIFF_PATCH_DIFFABLE;
|
||||
|
||||
/* do diffs */
|
||||
|
||||
if (!(error = diff_delta_file_callback(&ctxt, patch.delta, 1)))
|
||||
error = diff_patch_generate(&ctxt, &patch);
|
||||
|
||||
cleanup:
|
||||
diff_patch_unload(&patch);
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
giterr_clear();
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
size_t git_diff_num_deltas(git_diff_list *diff)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user