mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-11-04 07:09:14 +00:00 
			
		
		
		
	Merge pull request #3908 from libgit2/ethomson/patch_from_diff
Teach `git_patch_from_diff` about parsed diffs
This commit is contained in:
		
						commit
						5671e81fdd
					
				@ -8,6 +8,7 @@
 | 
			
		||||
#define INCLUDE_diff_h__
 | 
			
		||||
 | 
			
		||||
#include "git2/diff.h"
 | 
			
		||||
#include "git2/patch.h"
 | 
			
		||||
#include "git2/sys/diff.h"
 | 
			
		||||
#include "git2/oid.h"
 | 
			
		||||
 | 
			
		||||
@ -44,6 +45,7 @@ struct git_diff {
 | 
			
		||||
	int (*pfxcomp)(const char *str, const char *pfx);
 | 
			
		||||
	int (*entrycomp)(const void *a, const void *b);
 | 
			
		||||
 | 
			
		||||
	int (*patch_fn)(git_patch **out, git_diff *diff, size_t idx);
 | 
			
		||||
	void (*free_fn)(git_diff *diff);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "diff.h"
 | 
			
		||||
#include "diff_generate.h"
 | 
			
		||||
#include "patch_generate.h"
 | 
			
		||||
#include "fileops.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "attr_file.h"
 | 
			
		||||
@ -414,6 +415,7 @@ static git_diff_generated *diff_generated_alloc(
 | 
			
		||||
	diff->base.repo = repo;
 | 
			
		||||
	diff->base.old_src = old_iter->type;
 | 
			
		||||
	diff->base.new_src = new_iter->type;
 | 
			
		||||
	diff->base.patch_fn = git_patch_generated_from_diff;
 | 
			
		||||
	diff->base.free_fn = diff_generated_free;
 | 
			
		||||
	memcpy(&diff->base.opts, &dflt, sizeof(git_diff_options));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,15 +6,10 @@
 | 
			
		||||
 */
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "diff.h"
 | 
			
		||||
#include "diff_parse.h"
 | 
			
		||||
#include "patch.h"
 | 
			
		||||
#include "patch_parse.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	struct git_diff base;
 | 
			
		||||
 | 
			
		||||
	git_vector patches;
 | 
			
		||||
} git_diff_parsed;
 | 
			
		||||
 | 
			
		||||
static void diff_parsed_free(git_diff *d)
 | 
			
		||||
{
 | 
			
		||||
	git_diff_parsed *diff = (git_diff_parsed *)d;
 | 
			
		||||
@ -47,6 +42,7 @@ static git_diff_parsed *diff_parsed_alloc(void)
 | 
			
		||||
	diff->base.strncomp = git__strncmp;
 | 
			
		||||
	diff->base.pfxcomp = git__prefixcmp;
 | 
			
		||||
	diff->base.entrycomp = git_diff__entry_cmp;
 | 
			
		||||
	diff->base.patch_fn = git_patch_parsed_from_diff;
 | 
			
		||||
	diff->base.free_fn = diff_parsed_free;
 | 
			
		||||
 | 
			
		||||
	git_pool_init(&diff->base.pool, 1);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								src/diff_parse.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/diff_parse.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) the libgit2 contributors. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 | 
			
		||||
 * a Linking Exception. For full terms see the included COPYING file.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDE_diff_parse_h__
 | 
			
		||||
#define INCLUDE_diff_parse_h__
 | 
			
		||||
 | 
			
		||||
#include "diff.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	struct git_diff base;
 | 
			
		||||
 | 
			
		||||
	git_vector patches;
 | 
			
		||||
} git_diff_parsed;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -194,6 +194,12 @@ int git_patch_get_line_in_hunk(
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int git_patch_from_diff(git_patch **out, git_diff *diff, size_t idx)
 | 
			
		||||
{
 | 
			
		||||
	assert(out && diff && diff->patch_fn);
 | 
			
		||||
	return diff->patch_fn(out, diff, idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void git_patch__free(git_patch *patch)
 | 
			
		||||
{
 | 
			
		||||
	if (patch->free_fn)
 | 
			
		||||
 | 
			
		||||
@ -746,7 +746,7 @@ int git_patch_from_buffers(
 | 
			
		||||
	return patch_from_sources(out, &osrc, &nsrc, opts);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int git_patch_from_diff(
 | 
			
		||||
int git_patch_generated_from_diff(
 | 
			
		||||
	git_patch **patch_ptr, git_diff *diff, size_t idx)
 | 
			
		||||
{
 | 
			
		||||
	int error = 0;
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,8 @@ extern void git_patch_generated_old_data(
 | 
			
		||||
	char **, size_t *, git_patch_generated *);
 | 
			
		||||
extern void git_patch_generated_new_data(
 | 
			
		||||
	char **, size_t *, git_patch_generated *);
 | 
			
		||||
extern int git_patch_generated_from_diff(
 | 
			
		||||
	git_patch **, git_diff *, size_t);
 | 
			
		||||
 | 
			
		||||
typedef struct git_patch_generated_output git_patch_generated_output;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@
 | 
			
		||||
#include "git2/patch.h"
 | 
			
		||||
#include "patch.h"
 | 
			
		||||
#include "patch_parse.h"
 | 
			
		||||
#include "diff_parse.h"
 | 
			
		||||
#include "path.h"
 | 
			
		||||
 | 
			
		||||
#define parse_err(...) \
 | 
			
		||||
@ -1025,6 +1026,20 @@ void git_patch_parse_ctx_free(git_patch_parse_ctx *ctx)
 | 
			
		||||
	GIT_REFCOUNT_DEC(ctx, patch_parse_ctx_free);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int git_patch_parsed_from_diff(git_patch **out, git_diff *d, size_t idx)
 | 
			
		||||
{
 | 
			
		||||
	git_diff_parsed *diff = (git_diff_parsed *)d;
 | 
			
		||||
	git_patch *p;
 | 
			
		||||
 | 
			
		||||
	if ((p = git_vector_get(&diff->patches, idx)) == NULL)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	GIT_REFCOUNT_INC(p);
 | 
			
		||||
	*out = p;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void patch_parsed__free(git_patch *p)
 | 
			
		||||
{
 | 
			
		||||
	git_patch_parsed *patch = (git_patch_parsed *)p;
 | 
			
		||||
 | 
			
		||||
@ -51,4 +51,6 @@ extern int git_patch_parse(
 | 
			
		||||
	git_patch **out,
 | 
			
		||||
	git_patch_parse_ctx *ctx);
 | 
			
		||||
 | 
			
		||||
extern int git_patch_parsed_from_diff(git_patch **, git_diff *, size_t);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
#include "patch.h"
 | 
			
		||||
#include "patch_parse.h"
 | 
			
		||||
#include "diff_helpers.h"
 | 
			
		||||
#include "../src/diff.h"
 | 
			
		||||
 | 
			
		||||
#include "../patch/patch_common.h"
 | 
			
		||||
 | 
			
		||||
@ -151,3 +152,47 @@ void test_diff_parse__can_parse_generated_diff(void)
 | 
			
		||||
		GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED | GIT_DIFF_FIND_EXACT_MATCH_ONLY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_diff_parse__get_patch_from_diff(void)
 | 
			
		||||
{
 | 
			
		||||
	git_repository *repo;
 | 
			
		||||
	git_diff *computed, *parsed;
 | 
			
		||||
	git_tree *a, *b;
 | 
			
		||||
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
 | 
			
		||||
	git_buf computed_buf = GIT_BUF_INIT;
 | 
			
		||||
	git_patch *patch_computed, *patch_parsed;
 | 
			
		||||
 | 
			
		||||
	repo = cl_git_sandbox_init("diff");
 | 
			
		||||
 | 
			
		||||
	opts.flags = GIT_DIFF_SHOW_BINARY;
 | 
			
		||||
 | 
			
		||||
	cl_assert((a = resolve_commit_oid_to_tree(repo,
 | 
			
		||||
		"d70d245ed97ed2aa596dd1af6536e4bfdb047b69")) != NULL);
 | 
			
		||||
	cl_assert((b = resolve_commit_oid_to_tree(repo,
 | 
			
		||||
		"7a9e0b02e63179929fed24f0a3e0f19168114d10")) != NULL);
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_diff_tree_to_tree(&computed, repo, a, b, &opts));
 | 
			
		||||
	cl_git_pass(git_diff_to_buf(&computed_buf,
 | 
			
		||||
		computed, GIT_DIFF_FORMAT_PATCH));
 | 
			
		||||
	cl_git_pass(git_patch_from_diff(&patch_computed, computed, 0));
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_diff_from_buffer(&parsed,
 | 
			
		||||
		computed_buf.ptr, computed_buf.size));
 | 
			
		||||
	cl_git_pass(git_patch_from_diff(&patch_parsed, parsed, 0));
 | 
			
		||||
 | 
			
		||||
	cl_assert_equal_i(
 | 
			
		||||
		git_patch_num_hunks(patch_computed),
 | 
			
		||||
		git_patch_num_hunks(patch_parsed));
 | 
			
		||||
 | 
			
		||||
	git_patch_free(patch_computed);
 | 
			
		||||
	git_patch_free(patch_parsed);
 | 
			
		||||
 | 
			
		||||
	git_tree_free(a);
 | 
			
		||||
	git_tree_free(b);
 | 
			
		||||
 | 
			
		||||
	git_diff_free(computed);
 | 
			
		||||
	git_diff_free(parsed);
 | 
			
		||||
 | 
			
		||||
	git_buf_free(&computed_buf);
 | 
			
		||||
 | 
			
		||||
	cl_git_sandbox_cleanup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user