Blame src/patch.c

Packit Service 20376f
#include "git2/patch.h"
Packit Service 20376f
#include "diff.h"
Packit Service 20376f
#include "patch.h"
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
int git_patch__invoke_callbacks(
Packit Service 20376f
	git_patch *patch,
Packit Service 20376f
	git_diff_file_cb file_cb,
Packit Service 20376f
	git_diff_binary_cb binary_cb,
Packit Service 20376f
	git_diff_hunk_cb hunk_cb,
Packit Service 20376f
	git_diff_line_cb line_cb,
Packit Service 20376f
	void *payload)
Packit Service 20376f
{
Packit Service 20376f
	int error = 0;
Packit Service 20376f
	uint32_t i, j;
Packit Service 20376f
Packit Service 20376f
	if (file_cb)
Packit Service 20376f
		error = file_cb(patch->delta, 0, payload);
Packit Service 20376f
Packit Service 20376f
	if (error)
Packit Service 20376f
		return error;
Packit Service 20376f
Packit Service 20376f
	if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0) {
Packit Service 20376f
		if (binary_cb)
Packit Service 20376f
			error = binary_cb(patch->delta, &patch->binary, payload);
Packit Service 20376f
Packit Service 20376f
		return error;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (!hunk_cb && !line_cb)
Packit Service 20376f
		return error;
Packit Service 20376f
Packit Service 20376f
	for (i = 0; !error && i < git_array_size(patch->hunks); ++i) {
Packit Service 20376f
		git_patch_hunk *h = git_array_get(patch->hunks, i);
Packit Service 20376f
Packit Service 20376f
		if (hunk_cb)
Packit Service 20376f
			error = hunk_cb(patch->delta, &h->hunk, payload);
Packit Service 20376f
Packit Service 20376f
		if (!line_cb)
Packit Service 20376f
			continue;
Packit Service 20376f
Packit Service 20376f
		for (j = 0; !error && j < h->line_count; ++j) {
Packit Service 20376f
			git_diff_line *l =
Packit Service 20376f
				git_array_get(patch->lines, h->line_start + j);
Packit Service 20376f
Packit Service 20376f
			error = line_cb(patch->delta, &h->hunk, l, payload);
Packit Service 20376f
		}
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	return error;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
size_t git_patch_size(
Packit Service 20376f
	git_patch *patch,
Packit Service 20376f
	int include_context,
Packit Service 20376f
	int include_hunk_headers,
Packit Service 20376f
	int include_file_headers)
Packit Service 20376f
{
Packit Service 20376f
	size_t out;
Packit Service 20376f
Packit Service 20376f
	assert(patch);
Packit Service 20376f
Packit Service 20376f
	out = patch->content_size;
Packit Service 20376f
Packit Service 20376f
	if (!include_context)
Packit Service 20376f
		out -= patch->context_size;
Packit Service 20376f
Packit Service 20376f
	if (include_hunk_headers)
Packit Service 20376f
		out += patch->header_size;
Packit Service 20376f
Packit Service 20376f
	if (include_file_headers) {
Packit Service 20376f
		git_buf file_header = GIT_BUF_INIT;
Packit Service 20376f
Packit Service 20376f
		if (git_diff_delta__format_file_header(
Packit Service 20376f
			&file_header, patch->delta, NULL, NULL, 0) < 0)
Packit Service 20376f
			giterr_clear();
Packit Service 20376f
		else
Packit Service 20376f
			out += git_buf_len(&file_header);
Packit Service 20376f
Packit Service 20376f
		git_buf_free(&file_header);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	return out;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
int git_patch_line_stats(
Packit Service 20376f
	size_t *total_ctxt,
Packit Service 20376f
	size_t *total_adds,
Packit Service 20376f
	size_t *total_dels,
Packit Service 20376f
	const git_patch *patch)
Packit Service 20376f
{
Packit Service 20376f
	size_t totals[3], idx;
Packit Service 20376f
Packit Service 20376f
	memset(totals, 0, sizeof(totals));
Packit Service 20376f
Packit Service 20376f
	for (idx = 0; idx < git_array_size(patch->lines); ++idx) {
Packit Service 20376f
		git_diff_line *line = git_array_get(patch->lines, idx);
Packit Service 20376f
		if (!line)
Packit Service 20376f
			continue;
Packit Service 20376f
Packit Service 20376f
		switch (line->origin) {
Packit Service 20376f
		case GIT_DIFF_LINE_CONTEXT:  totals[0]++; break;
Packit Service 20376f
		case GIT_DIFF_LINE_ADDITION: totals[1]++; break;
Packit Service 20376f
		case GIT_DIFF_LINE_DELETION: totals[2]++; break;
Packit Service 20376f
		default:
Packit Service 20376f
			/* diff --stat and --numstat don't count EOFNL marks because
Packit Service 20376f
			* they will always be paired with a ADDITION or DELETION line.
Packit Service 20376f
			*/
Packit Service 20376f
			break;
Packit Service 20376f
		}
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (total_ctxt)
Packit Service 20376f
		*total_ctxt = totals[0];
Packit Service 20376f
	if (total_adds)
Packit Service 20376f
		*total_adds = totals[1];
Packit Service 20376f
	if (total_dels)
Packit Service 20376f
		*total_dels = totals[2];
Packit Service 20376f
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
const git_diff_delta *git_patch_get_delta(const git_patch *patch)
Packit Service 20376f
{
Packit Service 20376f
	assert(patch);
Packit Service 20376f
	return patch->delta;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
size_t git_patch_num_hunks(const git_patch *patch)
Packit Service 20376f
{
Packit Service 20376f
	assert(patch);
Packit Service 20376f
	return git_array_size(patch->hunks);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static int patch_error_outofrange(const char *thing)
Packit Service 20376f
{
Packit Service 20376f
	giterr_set(GITERR_INVALID, "patch %s index out of range", thing);
Packit Service 20376f
	return GIT_ENOTFOUND;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
int git_patch_get_hunk(
Packit Service 20376f
	const git_diff_hunk **out,
Packit Service 20376f
	size_t *lines_in_hunk,
Packit Service 20376f
	git_patch *patch,
Packit Service 20376f
	size_t hunk_idx)
Packit Service 20376f
{
Packit Service 20376f
	git_patch_hunk *hunk;
Packit Service 20376f
	assert(patch);
Packit Service 20376f
Packit Service 20376f
	hunk = git_array_get(patch->hunks, hunk_idx);
Packit Service 20376f
Packit Service 20376f
	if (!hunk) {
Packit Service 20376f
		if (out) *out = NULL;
Packit Service 20376f
		if (lines_in_hunk) *lines_in_hunk = 0;
Packit Service 20376f
		return patch_error_outofrange("hunk");
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (out) *out = &hunk->hunk;
Packit Service 20376f
	if (lines_in_hunk) *lines_in_hunk = hunk->line_count;
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
int git_patch_num_lines_in_hunk(const git_patch *patch, size_t hunk_idx)
Packit Service 20376f
{
Packit Service 20376f
	git_patch_hunk *hunk;
Packit Service 20376f
	assert(patch);
Packit Service 20376f
Packit Service 20376f
	if (!(hunk = git_array_get(patch->hunks, hunk_idx)))
Packit Service 20376f
		return patch_error_outofrange("hunk");
Packit Service 20376f
	return (int)hunk->line_count;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
int git_patch_get_line_in_hunk(
Packit Service 20376f
	const git_diff_line **out,
Packit Service 20376f
	git_patch *patch,
Packit Service 20376f
	size_t hunk_idx,
Packit Service 20376f
	size_t line_of_hunk)
Packit Service 20376f
{
Packit Service 20376f
	git_patch_hunk *hunk;
Packit Service 20376f
	git_diff_line *line;
Packit Service 20376f
Packit Service 20376f
	assert(patch);
Packit Service 20376f
Packit Service 20376f
	if (!(hunk = git_array_get(patch->hunks, hunk_idx))) {
Packit Service 20376f
		if (out) *out = NULL;
Packit Service 20376f
		return patch_error_outofrange("hunk");
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (line_of_hunk >= hunk->line_count ||
Packit Service 20376f
		!(line = git_array_get(
Packit Service 20376f
			patch->lines, hunk->line_start + line_of_hunk))) {
Packit Service 20376f
		if (out) *out = NULL;
Packit Service 20376f
		return patch_error_outofrange("line");
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (out) *out = line;
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
int git_patch_from_diff(git_patch **out, git_diff *diff, size_t idx)
Packit Service 20376f
{
Packit Service 20376f
	assert(out && diff && diff->patch_fn);
Packit Service 20376f
	return diff->patch_fn(out, diff, idx);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static void git_patch__free(git_patch *patch)
Packit Service 20376f
{
Packit Service 20376f
	if (patch->free_fn)
Packit Service 20376f
		patch->free_fn(patch);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void git_patch_free(git_patch *patch)
Packit Service 20376f
{
Packit Service 20376f
	if (patch)
Packit Service 20376f
		GIT_REFCOUNT_DEC(patch, git_patch__free);
Packit Service 20376f
}