summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/git2/diff.h37
-rw-r--r--src/diff_output.c35
-rw-r--r--tests-clar/diff/diff_helpers.c2
-rw-r--r--tests-clar/diff/diff_helpers.h1
-rw-r--r--tests-clar/diff/patch.c44
5 files changed, 74 insertions, 45 deletions
diff --git a/include/git2/diff.h b/include/git2/diff.h
index 0c9f620c1..d8dc91c80 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -154,19 +154,22 @@ typedef int (*git_diff_hunk_fn)(
* Line origin constants.
*
* These values describe where a line came from and will be passed to
- * the git_diff_line_fn when iterating over a diff. There are some
+ * the git_diff_data_fn when iterating over a diff. There are some
* special origin contants at the end that are used for the text
* output callbacks to demarcate lines that are actually part of
* the file or hunk headers.
*/
enum {
- /* these values will be sent to `git_diff_line_fn` along with the line */
+ /* these values will be sent to `git_diff_data_fn` along with the line */
GIT_DIFF_LINE_CONTEXT = ' ',
GIT_DIFF_LINE_ADDITION = '+',
GIT_DIFF_LINE_DELETION = '-',
GIT_DIFF_LINE_ADD_EOFNL = '\n', /**< LF was added at end of file */
GIT_DIFF_LINE_DEL_EOFNL = '\0', /**< LF was removed at end of file */
- /* these values will only be sent to a `git_diff_output_fn` */
+ /* these values will only be sent to a `git_diff_data_fn` when the content
+ * of a diff is being formatted (eg. through git_diff_print_patch() or
+ * git_diff_print_compact(), for instance).
+ */
GIT_DIFF_LINE_FILE_HDR = 'F',
GIT_DIFF_LINE_HUNK_HDR = 'H',
GIT_DIFF_LINE_BINARY = 'B'
@@ -174,25 +177,19 @@ enum {
/**
* When iterating over a diff, callback that will be made per text diff
- * line.
- */
-typedef int (*git_diff_line_fn)(
- void *cb_data,
- git_diff_delta *delta,
- char line_origin, /**< GIT_DIFF_LINE_... value from above */
- const char *content,
- size_t content_len);
-
-/**
+ * line. In this context, the provided range will be NULL.
+ *
* When printing a diff, callback that will be made to output each line
* of text. This uses some extra GIT_DIFF_LINE_... constants for output
* of lines of file and hunk headers.
*/
-typedef int (*git_diff_output_fn)(
+typedef int (*git_diff_data_fn)(
void *cb_data,
+ git_diff_delta *delta,
+ git_diff_range *range,
char line_origin, /**< GIT_DIFF_LINE_... value from above */
- const char *formatted_output);
-
+ const char *content,
+ size_t content_len);
/** @name Diff List Generator Functions
*
@@ -311,7 +308,7 @@ GIT_EXTERN(int) git_diff_foreach(
void *cb_data,
git_diff_file_fn file_cb,
git_diff_hunk_fn hunk_cb,
- git_diff_line_fn line_cb);
+ git_diff_data_fn line_cb);
/**
* Iterate over a diff generating text output like "git diff --name-status".
@@ -319,7 +316,7 @@ GIT_EXTERN(int) git_diff_foreach(
GIT_EXTERN(int) git_diff_print_compact(
git_diff_list *diff,
void *cb_data,
- git_diff_output_fn print_cb);
+ git_diff_data_fn print_cb);
/**
* Iterate over a diff generating text output like "git diff".
@@ -329,7 +326,7 @@ GIT_EXTERN(int) git_diff_print_compact(
GIT_EXTERN(int) git_diff_print_patch(
git_diff_list *diff,
void *cb_data,
- git_diff_output_fn print_cb);
+ git_diff_data_fn print_cb);
/**@}*/
@@ -348,7 +345,7 @@ GIT_EXTERN(int) git_diff_blobs(
git_diff_options *options,
void *cb_data,
git_diff_hunk_fn hunk_cb,
- git_diff_line_fn line_cb);
+ git_diff_data_fn line_cb);
GIT_END_DECL
diff --git a/src/diff_output.c b/src/diff_output.c
index 7c5b6f276..a5a11395f 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -18,9 +18,10 @@ typedef struct {
git_diff_list *diff;
void *cb_data;
git_diff_hunk_fn hunk_cb;
- git_diff_line_fn line_cb;
+ git_diff_data_fn line_cb;
unsigned int index;
git_diff_delta *delta;
+ git_diff_range range;
} diff_output_info;
static int read_next_int(const char **str, int *value)
@@ -62,6 +63,8 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
if (range.old_start < 0 || range.new_start < 0)
return -1;
+ memcpy(&info->range, &range, sizeof(git_diff_range));
+
return info->hunk_cb(
info->cb_data, info->delta, &range, bufs[0].ptr, bufs[0].size);
}
@@ -76,7 +79,7 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
GIT_DIFF_LINE_CONTEXT;
if (info->line_cb(
- info->cb_data, info->delta, origin, bufs[1].ptr, bufs[1].size) < 0)
+ info->cb_data, info->delta, &info->range, origin, bufs[1].ptr, bufs[1].size) < 0)
return -1;
/* deal with adding and removing newline at EOF */
@@ -87,7 +90,7 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
origin = GIT_DIFF_LINE_DEL_EOFNL;
return info->line_cb(
- info->cb_data, info->delta, origin, bufs[2].ptr, bufs[2].size);
+ info->cb_data, info->delta, &info->range, origin, bufs[2].ptr, bufs[2].size);
}
}
@@ -291,7 +294,7 @@ int git_diff_foreach(
void *data,
git_diff_file_fn file_cb,
git_diff_hunk_fn hunk_cb,
- git_diff_line_fn line_cb)
+ git_diff_data_fn line_cb)
{
int error = 0;
diff_output_info info;
@@ -433,7 +436,7 @@ cleanup:
typedef struct {
git_diff_list *diff;
- git_diff_output_fn print_cb;
+ git_diff_data_fn print_cb;
void *cb_data;
git_buf *buf;
} diff_print_info;
@@ -491,13 +494,13 @@ static int print_compact(void *data, git_diff_delta *delta, float progress)
if (git_buf_oom(pi->buf))
return -1;
- return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr);
+ return pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
}
int git_diff_print_compact(
git_diff_list *diff,
void *cb_data,
- git_diff_output_fn print_cb)
+ git_diff_data_fn print_cb)
{
int error;
git_buf buf = GIT_BUF_INIT;
@@ -586,7 +589,7 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
if (git_buf_oom(pi->buf))
return -1;
- result = pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr);
+ result = pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
if (result < 0)
return result;
@@ -600,7 +603,7 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
if (git_buf_oom(pi->buf))
return -1;
- return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_BINARY, pi->buf->ptr);
+ return pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_BINARY, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
}
static int print_patch_hunk(
@@ -612,27 +615,23 @@ static int print_patch_hunk(
{
diff_print_info *pi = data;
- GIT_UNUSED(d);
- GIT_UNUSED(r);
-
git_buf_clear(pi->buf);
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0)
return -1;
- return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_HUNK_HDR, pi->buf->ptr);
+ return pi->print_cb(pi->cb_data, d, r, GIT_DIFF_LINE_HUNK_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
}
static int print_patch_line(
void *data,
git_diff_delta *delta,
+ git_diff_range *range,
char line_origin, /* GIT_DIFF_LINE value from above */
const char *content,
size_t content_len)
{
diff_print_info *pi = data;
- GIT_UNUSED(delta);
-
git_buf_clear(pi->buf);
if (line_origin == GIT_DIFF_LINE_ADDITION ||
@@ -645,13 +644,13 @@ static int print_patch_line(
if (git_buf_oom(pi->buf))
return -1;
- return pi->print_cb(pi->cb_data, line_origin, pi->buf->ptr);
+ return pi->print_cb(pi->cb_data, delta, range, line_origin, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
}
int git_diff_print_patch(
git_diff_list *diff,
void *cb_data,
- git_diff_output_fn print_cb)
+ git_diff_data_fn print_cb)
{
int error;
git_buf buf = GIT_BUF_INIT;
@@ -678,7 +677,7 @@ int git_diff_blobs(
git_diff_options *options,
void *cb_data,
git_diff_hunk_fn hunk_cb,
- git_diff_line_fn line_cb)
+ git_diff_data_fn line_cb)
{
diff_output_info info;
git_diff_delta delta;
diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c
index c9a633cd0..85dd52601 100644
--- a/tests-clar/diff/diff_helpers.c
+++ b/tests-clar/diff/diff_helpers.c
@@ -60,12 +60,14 @@ int diff_hunk_fn(
int diff_line_fn(
void *cb_data,
git_diff_delta *delta,
+ git_diff_range *range,
char line_origin,
const char *content,
size_t content_len)
{
diff_expects *e = cb_data;
(void)delta;
+ (void)range;
(void)content;
(void)content_len;
e->lines++;
diff --git a/tests-clar/diff/diff_helpers.h b/tests-clar/diff/diff_helpers.h
index 010d156fa..ca8c40177 100644
--- a/tests-clar/diff/diff_helpers.h
+++ b/tests-clar/diff/diff_helpers.h
@@ -37,6 +37,7 @@ extern int diff_hunk_fn(
extern int diff_line_fn(
void *cb_data,
git_diff_delta *delta,
+ git_diff_range *range,
char line_origin,
const char *content,
size_t content_len);
diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c
index e2576277f..3da9ce82b 100644
--- a/tests-clar/diff/patch.c
+++ b/tests-clar/diff/patch.c
@@ -13,26 +13,56 @@ void test_diff_patch__cleanup(void)
cl_git_sandbox_cleanup();
}
-#define EXPECTED_OUTPUT "diff --git a/subdir.txt b/subdir.txt\n" \
+#define EXPECTED_HEADER "diff --git a/subdir.txt b/subdir.txt\n" \
"deleted file mode 100644\n" \
"index e8ee89e..0000000\n" \
"--- a/subdir.txt\n" \
"+++ /dev/null\n"
+#define EXPECTED_HUNK "@@ -1,2 +0,0 @@\n"
+
static int check_removal_cb(
void *cb_data,
+ git_diff_delta *delta,
+ git_diff_range *range,
char line_origin,
- const char *formatted_output)
+ const char *formatted_output,
+ size_t output_len)
{
GIT_UNUSED(cb_data);
- if (line_origin != 'F')
- return 0;
+ switch (line_origin) {
+ case GIT_DIFF_LINE_FILE_HDR:
+ cl_assert_equal_s(EXPECTED_HEADER, formatted_output);
+ cl_assert(range == NULL);
+ goto check_delta;
+
+ case GIT_DIFF_LINE_HUNK_HDR:
+ cl_assert_equal_s(EXPECTED_HUNK, formatted_output);
+ /* Fall through */
+
+ case GIT_DIFF_LINE_CONTEXT:
+ case GIT_DIFF_LINE_DELETION:
+ goto check_range;
+
+ default:
+ /* unexpected code path */
+ return -1;
+ }
+
+check_range:
+ cl_assert(range != NULL);
+ cl_assert_equal_i(1, range->old_start);
+ cl_assert_equal_i(2, range->old_lines);
+ cl_assert_equal_i(0, range->new_start);
+ cl_assert_equal_i(0, range->new_lines);
- if (strcmp(EXPECTED_OUTPUT, formatted_output) == 0)
- return 0;
+check_delta:
+ cl_assert_equal_s("subdir.txt", delta->old.path);
+ cl_assert_equal_s("subdir.txt", delta->new.path);
+ cl_assert_equal_i(GIT_DELTA_DELETED, delta->status);
- return -1;
+ return 0;
}
void test_diff_patch__can_properly_display_the_removal_of_a_file(void)