mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-22 06:26:26 +00:00
patch: add support for partial patch application
Add hunk callback parameter to git_apply__patch to allow hunks to be skipped.
This commit is contained in:
committed by
Edward Thomson
parent
52e27b8404
commit
7263057269
@@ -150,6 +150,52 @@ void test_apply_fromdiff__prepend_nocontext(void)
|
||||
PATCH_ORIGINAL_TO_PREPEND_NOCONTEXT, &diff_opts));
|
||||
}
|
||||
|
||||
void test_apply_fromdiff__prepend_and_change(void)
|
||||
{
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_PREPEND_AND_CHANGE, "file.txt",
|
||||
PATCH_ORIGINAL_TO_PREPEND_AND_CHANGE, NULL));
|
||||
}
|
||||
|
||||
void test_apply_fromdiff__prepend_and_change_nocontext(void)
|
||||
{
|
||||
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
|
||||
diff_opts.context_lines = 0;
|
||||
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_PREPEND_AND_CHANGE, "file.txt",
|
||||
PATCH_ORIGINAL_TO_PREPEND_AND_CHANGE_NOCONTEXT, &diff_opts));
|
||||
}
|
||||
|
||||
void test_apply_fromdiff__delete_and_change(void)
|
||||
{
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_DELETE_AND_CHANGE, "file.txt",
|
||||
PATCH_ORIGINAL_TO_DELETE_AND_CHANGE, NULL));
|
||||
}
|
||||
|
||||
void test_apply_fromdiff__delete_and_change_nocontext(void)
|
||||
{
|
||||
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
|
||||
diff_opts.context_lines = 0;
|
||||
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_DELETE_AND_CHANGE, "file.txt",
|
||||
PATCH_ORIGINAL_TO_DELETE_AND_CHANGE_NOCONTEXT, &diff_opts));
|
||||
}
|
||||
|
||||
void test_apply_fromdiff__delete_firstline(void)
|
||||
{
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_DELETE_FIRSTLINE, "file.txt",
|
||||
PATCH_ORIGINAL_TO_DELETE_FIRSTLINE, NULL));
|
||||
}
|
||||
|
||||
void test_apply_fromdiff__append(void)
|
||||
{
|
||||
cl_git_pass(apply_buf(
|
||||
|
||||
161
tests/apply/partial.c
Normal file
161
tests/apply/partial.c
Normal file
@@ -0,0 +1,161 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/sys/repository.h"
|
||||
|
||||
#include "apply.h"
|
||||
#include "repository.h"
|
||||
#include "buf_text.h"
|
||||
|
||||
#include "../patch/patch_common.h"
|
||||
|
||||
static git_repository *repo = NULL;
|
||||
|
||||
void test_apply_partial__initialize(void)
|
||||
{
|
||||
repo = cl_git_sandbox_init("renames");
|
||||
}
|
||||
|
||||
void test_apply_partial__cleanup(void)
|
||||
{
|
||||
cl_git_sandbox_cleanup();
|
||||
}
|
||||
|
||||
static int skip_addition(
|
||||
const git_diff_hunk *hunk,
|
||||
void *payload)
|
||||
{
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
return (hunk->new_lines > hunk->old_lines) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int skip_deletion(
|
||||
const git_diff_hunk *hunk,
|
||||
void *payload)
|
||||
{
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
return (hunk->new_lines < hunk->old_lines) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int skip_change(
|
||||
const git_diff_hunk *hunk,
|
||||
void *payload)
|
||||
{
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
return (hunk->new_lines == hunk->old_lines) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int apply_buf(
|
||||
const char *old,
|
||||
const char *oldname,
|
||||
const char *new,
|
||||
const char *newname,
|
||||
const char *expected,
|
||||
const git_diff_options *diff_opts,
|
||||
git_apply_hunk_cb hunk_cb,
|
||||
void *payload)
|
||||
{
|
||||
git_patch *patch;
|
||||
git_buf result = GIT_BUF_INIT;
|
||||
git_buf patchbuf = GIT_BUF_INIT;
|
||||
git_apply_options opts = GIT_APPLY_OPTIONS_INIT;
|
||||
char *filename;
|
||||
unsigned int mode;
|
||||
int error;
|
||||
size_t oldsize = strlen(old);
|
||||
size_t newsize = strlen(new);
|
||||
|
||||
opts.hunk_cb = hunk_cb;
|
||||
opts.payload = payload;
|
||||
|
||||
cl_git_pass(git_patch_from_buffers(&patch, old, oldsize, oldname, new, newsize, newname, diff_opts));
|
||||
if ((error = git_apply__patch(&result, &filename, &mode, old, oldsize, patch, &opts)) == 0) {
|
||||
cl_assert_equal_s(expected, result.ptr);
|
||||
cl_assert_equal_s(newname, filename);
|
||||
cl_assert_equal_i(0100644, mode);
|
||||
}
|
||||
|
||||
git__free(filename);
|
||||
git_buf_free(&result);
|
||||
git_buf_free(&patchbuf);
|
||||
git_patch_free(patch);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void test_apply_partial__prepend_and_change_skip_addition(void)
|
||||
{
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_PREPEND_AND_CHANGE, "file.txt",
|
||||
FILE_ORIGINAL, NULL, skip_addition, NULL));
|
||||
}
|
||||
|
||||
void test_apply_partial__prepend_and_change_nocontext_skip_addition(void)
|
||||
{
|
||||
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
|
||||
diff_opts.context_lines = 0;
|
||||
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_PREPEND_AND_CHANGE, "file.txt",
|
||||
FILE_CHANGE_MIDDLE, &diff_opts, skip_addition, NULL));
|
||||
}
|
||||
|
||||
void test_apply_partial__prepend_and_change_skip_change(void)
|
||||
{
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_PREPEND_AND_CHANGE, "file.txt",
|
||||
FILE_PREPEND_AND_CHANGE, NULL, skip_change, NULL));
|
||||
}
|
||||
|
||||
void test_apply_partial__prepend_and_change_nocontext_skip_change(void)
|
||||
{
|
||||
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
|
||||
diff_opts.context_lines = 0;
|
||||
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_PREPEND_AND_CHANGE, "file.txt",
|
||||
FILE_PREPEND, &diff_opts, skip_change, NULL));
|
||||
}
|
||||
|
||||
void test_apply_partial__delete_and_change_skip_deletion(void)
|
||||
{
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_DELETE_AND_CHANGE, "file.txt",
|
||||
FILE_ORIGINAL, NULL, skip_deletion, NULL));
|
||||
}
|
||||
|
||||
void test_apply_partial__delete_and_change_nocontext_skip_deletion(void)
|
||||
{
|
||||
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
|
||||
diff_opts.context_lines = 0;
|
||||
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_DELETE_AND_CHANGE, "file.txt",
|
||||
FILE_CHANGE_MIDDLE, &diff_opts, skip_deletion, NULL));
|
||||
}
|
||||
|
||||
void test_apply_partial__delete_and_change_skip_change(void)
|
||||
{
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_DELETE_AND_CHANGE, "file.txt",
|
||||
FILE_DELETE_AND_CHANGE, NULL, skip_change, NULL));
|
||||
}
|
||||
|
||||
void test_apply_partial__delete_and_change_nocontext_skip_change(void)
|
||||
{
|
||||
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
|
||||
diff_opts.context_lines = 0;
|
||||
|
||||
cl_git_pass(apply_buf(
|
||||
FILE_ORIGINAL, "file.txt",
|
||||
FILE_DELETE_AND_CHANGE, "file.txt",
|
||||
FILE_DELETE_FIRSTLINE, &diff_opts, skip_change, NULL));
|
||||
}
|
||||
@@ -220,6 +220,112 @@
|
||||
"@@ -0,0 +1 @@\n" \
|
||||
"+insert at front\n"
|
||||
|
||||
/* An insertion at the beginning of the file and change in the middle */
|
||||
|
||||
#define FILE_PREPEND_AND_CHANGE \
|
||||
"insert at front\n" \
|
||||
"hey!\n" \
|
||||
"this is some context!\n" \
|
||||
"around some lines\n" \
|
||||
"that will change\n" \
|
||||
"yes it is!\n" \
|
||||
"(THIS line is changed!)\n" \
|
||||
"and this\n" \
|
||||
"is additional context\n" \
|
||||
"below it!\n"
|
||||
|
||||
#define PATCH_ORIGINAL_TO_PREPEND_AND_CHANGE \
|
||||
"diff --git a/file.txt b/file.txt\n" \
|
||||
"index 9432026..f73c8bb 100644\n" \
|
||||
"--- a/file.txt\n" \
|
||||
"+++ b/file.txt\n" \
|
||||
"@@ -1,9 +1,10 @@\n" \
|
||||
"+insert at front\n" \
|
||||
" hey!\n" \
|
||||
" this is some context!\n" \
|
||||
" around some lines\n" \
|
||||
" that will change\n" \
|
||||
" yes it is!\n" \
|
||||
"-(this line is changed)\n" \
|
||||
"+(THIS line is changed!)\n" \
|
||||
" and this\n" \
|
||||
" is additional context\n" \
|
||||
" below it!\n"
|
||||
|
||||
#define PATCH_ORIGINAL_TO_PREPEND_AND_CHANGE_NOCONTEXT \
|
||||
"diff --git a/file.txt b/file.txt\n" \
|
||||
"index 9432026..f73c8bb 100644\n" \
|
||||
"--- a/file.txt\n" \
|
||||
"+++ b/file.txt\n" \
|
||||
"@@ -0,0 +1 @@\n" \
|
||||
"+insert at front\n" \
|
||||
"@@ -6 +7 @@ yes it is!\n" \
|
||||
"-(this line is changed)\n" \
|
||||
"+(THIS line is changed!)\n"
|
||||
|
||||
/* A deletion at the beginning of the file and a change in the middle */
|
||||
|
||||
#define FILE_DELETE_AND_CHANGE \
|
||||
"this is some context!\n" \
|
||||
"around some lines\n" \
|
||||
"that will change\n" \
|
||||
"yes it is!\n" \
|
||||
"(THIS line is changed!)\n" \
|
||||
"and this\n" \
|
||||
"is additional context\n" \
|
||||
"below it!\n"
|
||||
|
||||
#define PATCH_ORIGINAL_TO_DELETE_AND_CHANGE \
|
||||
"diff --git a/file.txt b/file.txt\n" \
|
||||
"index 9432026..1e2dfa6 100644\n" \
|
||||
"--- a/file.txt\n" \
|
||||
"+++ b/file.txt\n" \
|
||||
"@@ -1,9 +1,8 @@\n" \
|
||||
"-hey!\n" \
|
||||
" this is some context!\n" \
|
||||
" around some lines\n" \
|
||||
" that will change\n" \
|
||||
" yes it is!\n" \
|
||||
"-(this line is changed)\n" \
|
||||
"+(THIS line is changed!)\n" \
|
||||
" and this\n" \
|
||||
" is additional context\n" \
|
||||
" below it!\n"
|
||||
|
||||
#define PATCH_ORIGINAL_TO_DELETE_AND_CHANGE_NOCONTEXT \
|
||||
"diff --git a/file.txt b/file.txt\n" \
|
||||
"index 9432026..1e2dfa6 100644\n" \
|
||||
"--- a/file.txt\n" \
|
||||
"+++ b/file.txt\n" \
|
||||
"@@ -1 +0,0 @@\n" \
|
||||
"-hey!\n" \
|
||||
"@@ -6 +5 @@ yes it is!\n" \
|
||||
"-(this line is changed)\n" \
|
||||
"+(THIS line is changed!)\n"
|
||||
|
||||
/* A deletion at the beginning of the file */
|
||||
|
||||
#define FILE_DELETE_FIRSTLINE \
|
||||
"this is some context!\n" \
|
||||
"around some lines\n" \
|
||||
"that will change\n" \
|
||||
"yes it is!\n" \
|
||||
"(this line is changed)\n" \
|
||||
"and this\n" \
|
||||
"is additional context\n" \
|
||||
"below it!\n"
|
||||
|
||||
#define PATCH_ORIGINAL_TO_DELETE_FIRSTLINE \
|
||||
"diff --git a/file.txt b/file.txt\n" \
|
||||
"index 9432026..f31fa13 100644\n" \
|
||||
"--- a/file.txt\n" \
|
||||
"+++ b/file.txt\n" \
|
||||
"@@ -1,4 +1,3 @@\n" \
|
||||
"-hey!\n" \
|
||||
" this is some context!\n" \
|
||||
" around some lines\n" \
|
||||
" that will change\n"
|
||||
|
||||
/* An insertion at the end of the file (and the resultant patch) */
|
||||
|
||||
#define FILE_APPEND \
|
||||
|
||||
Reference in New Issue
Block a user