Commit 3b5f7954 by Russell Belfer

Create git_diff_line and extend git_diff_hunk

Instead of having functions with so very many parameters to pass
hunk and line data, this takes the existing git_diff_hunk struct
and extends it with more hunk data, plus adds a git_diff_line.
Those structs are used to pass back hunk and line data instead of
the old APIs that took tons of parameters.

Some work that was previously only being done for git_diff_patch
creation (scanning the diff content for exact line counts) is now
done for all callbacks, but the performance difference should not
be noticable.
parent 74a627f0
......@@ -45,25 +45,23 @@ char *colors[] = {
static int printer(
const git_diff_delta *delta,
const git_diff_hunk *range,
char usage,
const char *line,
size_t line_len,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *data)
{
int *last_color = data, color = 0;
(void)delta; (void)range; (void)line_len;
(void)delta; (void)hunk;
if (*last_color >= 0) {
switch (usage) {
case GIT_DIFF_LINE_ADDITION: color = 3; break;
case GIT_DIFF_LINE_DELETION: color = 2; break;
switch (line->origin) {
case GIT_DIFF_LINE_ADDITION: color = 3; break;
case GIT_DIFF_LINE_DELETION: color = 2; break;
case GIT_DIFF_LINE_ADD_EOFNL: color = 3; break;
case GIT_DIFF_LINE_DEL_EOFNL: color = 2; break;
case GIT_DIFF_LINE_FILE_HDR: color = 1; break;
case GIT_DIFF_LINE_HUNK_HDR: color = 4; break;
default: color = 0;
case GIT_DIFF_LINE_FILE_HDR: color = 1; break;
case GIT_DIFF_LINE_HUNK_HDR: color = 4; break;
default: break;
}
if (color != *last_color) {
if (*last_color == 1 || color == 1)
......@@ -73,7 +71,13 @@ static int printer(
}
}
fputs(line, stdout);
if (line->origin == GIT_DIFF_LINE_CONTEXT ||
line->origin == GIT_DIFF_LINE_ADDITION ||
line->origin == GIT_DIFF_LINE_DELETION)
fputc(line->origin, stdout);
fwrite(line->content, 1, line->content_len, stdout);
return 0;
}
......
......@@ -184,14 +184,18 @@ static void print_commit(git_commit *commit)
static int print_diff(
const git_diff_delta *delta,
const git_diff_hunk *range,
char usage,
const char *line,
size_t line_len,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *data)
{
(void)delta; (void)range; (void)usage; (void)line_len; (void)data;
fputs(line, stdout);
(void)delta; (void)hunk; (void)data;
if (line->origin == GIT_DIFF_LINE_CONTEXT ||
line->origin == GIT_DIFF_LINE_ADDITION ||
line->origin == GIT_DIFF_LINE_DELETION)
fputc(line->origin, stdout);
fwrite(line->content, 1, line->content_len, stdout);
return 0;
}
......
......@@ -385,10 +385,12 @@ typedef int (*git_diff_file_cb)(
*/
typedef struct git_diff_hunk git_diff_hunk;
struct git_diff_hunk {
int old_start; /** Starting line number in old_file */
int old_lines; /** Number of lines in old_file */
int new_start; /** Starting line number in new_file */
int new_lines; /** Number of lines in new_file */
int old_start; /** Starting line number in old_file */
int old_lines; /** Number of lines in old_file */
int new_start; /** Starting line number in new_file */
int new_lines; /** Number of lines in new_file */
size_t header_len; /** Number of bytes in header text */
char header[128]; /** Header text, NUL-byte terminated */
};
/**
......@@ -397,8 +399,6 @@ struct git_diff_hunk {
typedef int (*git_diff_hunk_cb)(
const git_diff_delta *delta,
const git_diff_hunk *hunk,
const char *header,
size_t header_len,
void *payload);
/**
......@@ -429,6 +429,19 @@ typedef enum {
} git_diff_line_t;
/**
* Structure describing a line (or data span) of a diff.
*/
typedef struct git_diff_line git_diff_line;
struct git_diff_line {
char origin; /** A git_diff_line_t value */
int old_lineno; /** Line number in old file or -1 for added line */
int new_lineno; /** Line number in new file or -1 for deleted line */
int num_lines; /** Number of newline characters in content */
size_t content_len; /** Number of bytes of data */
const char *content; /** Pointer to diff text, not NUL-byte terminated */
};
/**
* When iterating over a diff, callback that will be made per text diff
* line. In this context, the provided range will be NULL.
*
......@@ -438,10 +451,8 @@ typedef enum {
*/
typedef int (*git_diff_line_cb)(
const git_diff_delta *delta, /** delta that contains this data */
const git_diff_hunk *hunk, /** range of lines containing this data */
char line_origin, /** git_diff_t value from above */
const char *content, /** diff data - not NUL terminated */
size_t content_len, /** number of bytes of diff data */
const git_diff_hunk *hunk, /** hunk containing this data */
const git_diff_line *line, /** line data */
void *payload); /** user reference data */
/**
......
......@@ -150,9 +150,6 @@ GIT_EXTERN(int) git_patch_line_stats(
* as NULL if you don't care about that particular piece of information.
*
* @param out Output pointer to git_diff_hunk of hunk
* @param header Output pointer to header string for hunk. Unlike the
* content pointer for each line, this will be NUL-terminated
* @param header_len Output value of characters in header string
* @param lines_in_hunk Output count of total lines in this hunk
* @param patch Input pointer to patch object
* @param hunk_idx Input index of hunk to get information about
......@@ -160,8 +157,6 @@ GIT_EXTERN(int) git_patch_line_stats(
*/
GIT_EXTERN(int) git_patch_get_hunk(
const git_diff_hunk **out,
const char **header,
size_t *header_len,
size_t *lines_in_hunk,
git_patch *patch,
size_t hunk_idx);
......@@ -185,22 +180,14 @@ GIT_EXTERN(int) git_patch_num_lines_in_hunk(
* index larger than the number of hunks or a line index larger than
* the number of lines in the hunk, this will return -1.
*
* @param line_origin A GIT_DIFF_LINE constant from above
* @param content Pointer to content of diff line, not NUL-terminated
* @param content_len Number of characters in content
* @param old_lineno Line number in old file or -1 if line is added
* @param new_lineno Line number in new file or -1 if line is deleted
* @param out The git_diff_line data for this line
* @param patch The patch to look in
* @param hunk_idx The index of the hunk
* @param line_of_hunk The index of the line in the hunk
* @return 0 on success, <0 on failure
*/
GIT_EXTERN(int) git_patch_get_line_in_hunk(
char *line_origin,
const char **content,
size_t *content_len,
int *old_lineno,
int *new_lineno,
const git_diff_line **out,
git_patch *patch,
size_t hunk_idx,
size_t line_of_hunk);
......
......@@ -12,23 +12,10 @@
#include "diff_xdiff.h"
#include "fileops.h"
/* cached information about a single span in a diff */
typedef struct diff_patch_line diff_patch_line;
struct diff_patch_line {
const char *ptr;
size_t len;
size_t lines;
size_t oldno;
size_t newno;
char origin;
};
/* cached information about a hunk in a diff */
typedef struct diff_patch_hunk diff_patch_hunk;
struct diff_patch_hunk {
git_diff_hunk hunk;
char header[128];
size_t header_len;
size_t line_start;
size_t line_count;
};
......@@ -42,8 +29,7 @@ struct git_patch {
git_diff_file_content nfile;
uint32_t flags;
git_array_t(diff_patch_hunk) hunks;
git_array_t(diff_patch_line) lines;
size_t oldno, newno;
git_array_t(git_diff_line) lines;
size_t content_size, context_size, header_size;
git_pool flattened;
};
......@@ -57,7 +43,8 @@ enum {
GIT_DIFF_PATCH_FLATTENED = (1 << 5),
};
static void diff_output_init(git_diff_output*, const git_diff_options*,
static void diff_output_init(
git_diff_output*, const git_diff_options*,
git_diff_file_cb, git_diff_hunk_cb, git_diff_line_cb, void*);
static void diff_output_to_patch(git_diff_output *, git_patch *);
......@@ -81,7 +68,7 @@ static void diff_patch_init_common(git_patch *patch)
diff_patch_update_binary(patch);
if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0)
patch->flags |= GIT_DIFF_PATCH_LOADED; /* set LOADED but not DIFFABLE */
patch->flags |= GIT_DIFF_PATCH_LOADED; /* LOADED but not DIFFABLE */
patch->flags |= GIT_DIFF_PATCH_INITIALIZED;
......@@ -687,7 +674,7 @@ int git_patch_line_stats(
memset(totals, 0, sizeof(totals));
for (idx = 0; idx < git_array_size(patch->lines); ++idx) {
diff_patch_line *line = git_array_get(patch->lines, idx);
git_diff_line *line = git_array_get(patch->lines, idx);
if (!line)
continue;
......@@ -721,8 +708,6 @@ static int diff_error_outofrange(const char *thing)
int git_patch_get_hunk(
const git_diff_hunk **out,
const char **header,
size_t *header_len,
size_t *lines_in_hunk,
git_patch *patch,
size_t hunk_idx)
......@@ -734,15 +719,11 @@ int git_patch_get_hunk(
if (!hunk) {
if (out) *out = NULL;
if (header) *header = NULL;
if (header_len) *header_len = 0;
if (lines_in_hunk) *lines_in_hunk = 0;
return diff_error_outofrange("hunk");
}
if (out) *out = &hunk->hunk;
if (header) *header = hunk->header;
if (header_len) *header_len = hunk->header_len;
if (lines_in_hunk) *lines_in_hunk = hunk->line_count;
return 0;
}
......@@ -758,49 +739,30 @@ int git_patch_num_lines_in_hunk(git_patch *patch, size_t hunk_idx)
}
int git_patch_get_line_in_hunk(
char *line_origin,
const char **content,
size_t *content_len,
int *old_lineno,
int *new_lineno,
const git_diff_line **out,
git_patch *patch,
size_t hunk_idx,
size_t line_of_hunk)
{
diff_patch_hunk *hunk;
diff_patch_line *line;
const char *thing;
git_diff_line *line;
assert(patch);
if (!(hunk = git_array_get(patch->hunks, hunk_idx))) {
thing = "hunk";
goto notfound;
if (out) *out = NULL;
return diff_error_outofrange("hunk");
}
if (line_of_hunk >= hunk->line_count ||
!(line = git_array_get(
patch->lines, hunk->line_start + line_of_hunk))) {
thing = "line";
goto notfound;
if (out) *out = NULL;
return diff_error_outofrange("line");
}
if (line_origin) *line_origin = line->origin;
if (content) *content = line->ptr;
if (content_len) *content_len = line->len;
if (old_lineno) *old_lineno = (int)line->oldno;
if (new_lineno) *new_lineno = (int)line->newno;
if (out) *out = line;
return 0;
notfound:
if (line_origin) *line_origin = GIT_DIFF_LINE_CONTEXT;
if (content) *content = NULL;
if (content_len) *content_len = 0;
if (old_lineno) *old_lineno = -1;
if (new_lineno) *new_lineno = -1;
return diff_error_outofrange(thing);
}
size_t git_patch_size(
......@@ -880,18 +842,16 @@ int git_patch__invoke_callbacks(
for (i = 0; !error && i < git_array_size(patch->hunks); ++i) {
diff_patch_hunk *h = git_array_get(patch->hunks, i);
error = hunk_cb(
patch->delta, &h->hunk, h->header, h->header_len, payload);
error = hunk_cb(patch->delta, &h->hunk, payload);
if (!line_cb)
continue;
for (j = 0; !error && j < h->line_count; ++j) {
diff_patch_line *l =
git_diff_line *l =
git_array_get(patch->lines, h->line_start + j);
error = line_cb(
patch->delta, &h->hunk, l->origin, l->ptr, l->len, payload);
error = line_cb(patch->delta, &h->hunk, l, payload);
}
}
......@@ -911,8 +871,6 @@ static int diff_patch_file_cb(
static int diff_patch_hunk_cb(
const git_diff_delta *delta,
const git_diff_hunk *hunk_,
const char *header,
size_t header_len,
void *payload)
{
git_patch *patch = payload;
......@@ -925,34 +883,23 @@ static int diff_patch_hunk_cb(
memcpy(&hunk->hunk, hunk_, sizeof(hunk->hunk));
assert(header_len + 1 < sizeof(hunk->header));
memcpy(&hunk->header, header, header_len);
hunk->header[header_len] = '\0';
hunk->header_len = header_len;
patch->header_size += header_len;
patch->header_size += hunk_->header_len;
hunk->line_start = git_array_size(patch->lines);
hunk->line_count = 0;
patch->oldno = hunk_->old_start;
patch->newno = hunk_->new_start;
return 0;
}
static int diff_patch_line_cb(
const git_diff_delta *delta,
const git_diff_hunk *hunk_,
char line_origin,
const char *content,
size_t content_len,
const git_diff_line *line_,
void *payload)
{
git_patch *patch = payload;
diff_patch_hunk *hunk;
diff_patch_line *line;
const char *content_end = content + content_len;
git_diff_line *line;
GIT_UNUSED(delta);
GIT_UNUSED(hunk_);
......@@ -963,48 +910,20 @@ static int diff_patch_line_cb(
line = git_array_alloc(patch->lines);
GITERR_CHECK_ALLOC(line);
line->ptr = content;
line->len = content_len;
line->origin = line_origin;
memcpy(line, line_, sizeof(*line));
/* do some bookkeeping so we can provide old/new line numbers */
line->lines = 0;
while (content < content_end)
if (*content++ == '\n')
++line->lines;
patch->content_size += line->content_len;
patch->content_size += content_len;
switch (line_origin) {
case GIT_DIFF_LINE_ADDITION:
patch->content_size += 1;
case GIT_DIFF_LINE_DEL_EOFNL:
line->oldno = -1;
line->newno = patch->newno;
patch->newno += line->lines;
break;
case GIT_DIFF_LINE_DELETION:
if (line->origin == GIT_DIFF_LINE_ADDITION ||
line->origin == GIT_DIFF_LINE_DELETION)
patch->content_size += 1;
case GIT_DIFF_LINE_ADD_EOFNL:
line->oldno = patch->oldno;
line->newno = -1;
patch->oldno += line->lines;
break;
case GIT_DIFF_LINE_CONTEXT:
else if (line->origin == GIT_DIFF_LINE_CONTEXT) {
patch->content_size += 1;
patch->context_size += 1;
case GIT_DIFF_LINE_CONTEXT_EOFNL:
patch->context_size += content_len;
line->oldno = patch->oldno;
line->newno = patch->newno;
patch->oldno += line->lines;
patch->newno += line->lines;
break;
default:
assert(false);
break;
}
patch->context_size += line->content_len + 1;
} else if (line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL)
patch->context_size += line->content_len;
hunk->line_count++;
......
......@@ -17,6 +17,7 @@ typedef struct {
git_buf *buf;
uint32_t flags;
int oid_strlen;
git_diff_line line;
} diff_print_info;
static int diff_print_info_init(
......@@ -51,6 +52,11 @@ static int diff_print_info_init(
else if (pi->oid_strlen > GIT_OID_HEXSZ + 1)
pi->oid_strlen = GIT_OID_HEXSZ + 1;
memset(&pi->line, 0, sizeof(pi->line));
pi->line.old_lineno = -1;
pi->line.new_lineno = -1;
pi->line.num_lines = 1;
return 0;
}
......@@ -107,8 +113,11 @@ static int diff_print_one_name_only(
git_buf_putc(out, '\n'))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(out), git_buf_len(out), pi->payload))
pi->line.origin = GIT_DIFF_LINE_FILE_HDR;
pi->line.content = git_buf_cstr(out);
pi->line.content_len = git_buf_len(out);
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
return callback_error();
return 0;
......@@ -149,8 +158,11 @@ static int diff_print_one_name_status(
if (git_buf_oom(out))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(out), git_buf_len(out), pi->payload))
pi->line.origin = GIT_DIFF_LINE_FILE_HDR;
pi->line.content = git_buf_cstr(out);
pi->line.content_len = git_buf_len(out);
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
return callback_error();
return 0;
......@@ -192,8 +204,11 @@ static int diff_print_one_raw(
if (git_buf_oom(out))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(out), git_buf_len(out), pi->payload))
pi->line.origin = GIT_DIFF_LINE_FILE_HDR;
pi->line.content = git_buf_cstr(out);
pi->line.content_len = git_buf_len(out);
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
return callback_error();
return 0;
......@@ -302,8 +317,11 @@ static int diff_print_patch_file(
pi->buf, delta, oldpfx, newpfx, pi->oid_strlen) < 0)
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
pi->line.origin = GIT_DIFF_LINE_FILE_HDR;
pi->line.content = git_buf_cstr(pi->buf);
pi->line.content_len = git_buf_len(pi->buf);
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
return callback_error();
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0)
......@@ -316,8 +334,12 @@ static int diff_print_patch_file(
"Binary files %s%s and %s%s differ\n") < 0)
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_BINARY,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
pi->line.origin = GIT_DIFF_LINE_BINARY;
pi->line.content = git_buf_cstr(pi->buf);
pi->line.content_len = git_buf_len(pi->buf);
pi->line.num_lines = 1;
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
return callback_error();
return 0;
......@@ -325,9 +347,7 @@ static int diff_print_patch_file(
static int diff_print_patch_hunk(
const git_diff_delta *d,
const git_diff_hunk *r,
const char *header,
size_t header_len,
const git_diff_hunk *h,
void *data)
{
diff_print_info *pi = data;
......@@ -335,12 +355,11 @@ static int diff_print_patch_hunk(
if (S_ISDIR(d->new_file.mode))
return 0;
git_buf_clear(pi->buf);
if (git_buf_put(pi->buf, header, header_len) < 0)
return -1;
pi->line.origin = GIT_DIFF_LINE_HUNK_HDR;
pi->line.content = h->header;
pi->line.content_len = h->header_len;
if (pi->print_cb(d, r, GIT_DIFF_LINE_HUNK_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
if (pi->print_cb(d, h, &pi->line, pi->payload))
return callback_error();
return 0;
......@@ -348,10 +367,8 @@ static int diff_print_patch_hunk(
static int diff_print_patch_line(
const git_diff_delta *delta,
const git_diff_hunk *range,
char line_origin, /* GIT_DIFF_LINE value from above */
const char *content,
size_t content_len,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *data)
{
diff_print_info *pi = data;
......@@ -359,21 +376,7 @@ static int diff_print_patch_line(
if (S_ISDIR(delta->new_file.mode))
return 0;
git_buf_clear(pi->buf);
git_buf_grow(pi->buf, content_len + 2);
if (line_origin == GIT_DIFF_LINE_ADDITION ||
line_origin == GIT_DIFF_LINE_DELETION ||
line_origin == GIT_DIFF_LINE_CONTEXT)
git_buf_putc(pi->buf, line_origin);
git_buf_put(pi->buf, content, content_len);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, range, line_origin,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
if (pi->print_cb(delta, hunk, line, pi->payload))
return callback_error();
return 0;
......@@ -452,15 +455,19 @@ int git_patch_print(
static int diff_print_to_buffer_cb(
const git_diff_delta *delta,
const git_diff_hunk *range,
char line_origin,
const char *content,
size_t content_len,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *payload)
{
git_buf *output = payload;
GIT_UNUSED(delta); GIT_UNUSED(range); GIT_UNUSED(line_origin);
return git_buf_put(output, content, content_len);
GIT_UNUSED(delta); GIT_UNUSED(hunk);
if (line->origin == GIT_DIFF_LINE_ADDITION ||
line->origin == GIT_DIFF_LINE_DELETION ||
line->origin == GIT_DIFF_LINE_CONTEXT)
git_buf_putc(output, line->origin);
return git_buf_put(output, line->content, line->content_len);
}
/* print a git_patch to a string buffer */
......
......@@ -53,36 +53,94 @@ typedef struct {
git_xdiff_output *xo;
git_patch *patch;
git_diff_hunk hunk;
size_t old_lineno, new_lineno;
} git_xdiff_info;
static int diff_update_lines(
git_xdiff_info *info,
git_diff_line *line,
const char *content,
size_t content_len)
{
const char *scan = content, *scan_end = content + content_len;
for (line->num_lines = 0; scan < scan_end; ++scan)
if (*scan == '\n')
++line->num_lines;
line->content = content;
line->content_len = content_len;
/* expect " "/"-"/"+", then data */
switch (line->origin) {
case GIT_DIFF_LINE_ADDITION:
case GIT_DIFF_LINE_DEL_EOFNL:
line->old_lineno = -1;
line->new_lineno = info->new_lineno;
info->new_lineno += line->num_lines;
break;
case GIT_DIFF_LINE_DELETION:
case GIT_DIFF_LINE_ADD_EOFNL:
line->old_lineno = info->old_lineno;
line->new_lineno = -1;
info->old_lineno += line->num_lines;
break;
case GIT_DIFF_LINE_CONTEXT:
case GIT_DIFF_LINE_CONTEXT_EOFNL:
line->old_lineno = info->old_lineno;
line->new_lineno = info->new_lineno;
info->old_lineno += line->num_lines;
info->new_lineno += line->num_lines;
break;
default:
giterr_set(GITERR_INVALID, "Unknown diff line origin %02x",
(unsigned int)line->origin);
return -1;
}
return 0;
}
static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len)
{
git_xdiff_info *info = priv;
git_patch *patch = info->patch;
const git_diff_delta *delta = git_patch_get_delta(patch);
git_diff_output *output = &info->xo->output;
git_diff_line line;
if (len == 1) {
output->error = git_xdiff_parse_hunk(&info->hunk, bufs[0].ptr);
if (output->error < 0)
return output->error;
info->hunk.header_len = bufs[0].size;
if (info->hunk.header_len >= sizeof(info->hunk.header))
info->hunk.header_len = sizeof(info->hunk.header) - 1;
memcpy(info->hunk.header, bufs[0].ptr, info->hunk.header_len);
info->hunk.header[info->hunk.header_len] = '\0';
if (output->hunk_cb != NULL &&
output->hunk_cb(delta, &info->hunk,
bufs[0].ptr, bufs[0].size, output->payload))
output->hunk_cb(delta, &info->hunk, output->payload))
output->error = GIT_EUSER;
info->old_lineno = info->hunk.old_start;
info->new_lineno = info->hunk.new_start;
}
if (len == 2 || len == 3) {
/* expect " "/"-"/"+", then data */
char origin =
line.origin =
(*bufs[0].ptr == '+') ? GIT_DIFF_LINE_ADDITION :
(*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION :
GIT_DIFF_LINE_CONTEXT;
if (output->data_cb != NULL &&
output->data_cb(delta, &info->hunk,
origin, bufs[1].ptr, bufs[1].size, output->payload))
output->error = diff_update_lines(
info, &line, bufs[1].ptr, bufs[1].size);
if (!output->error &&
output->data_cb != NULL &&
output->data_cb(delta, &info->hunk, &line, output->payload))
output->error = GIT_EUSER;
}
......@@ -92,14 +150,17 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len)
* If we have a '-' and a third buf, then we have removed a line
* with out a newline but added a blank line, so ADD_EOFNL.
*/
char origin =
line.origin =
(*bufs[0].ptr == '+') ? GIT_DIFF_LINE_DEL_EOFNL :
(*bufs[0].ptr == '-') ? GIT_DIFF_LINE_ADD_EOFNL :
GIT_DIFF_LINE_CONTEXT_EOFNL;
if (output->data_cb != NULL &&
output->data_cb(delta, &info->hunk,
origin, bufs[2].ptr, bufs[2].size, output->payload))
output->error = diff_update_lines(
info, &line, bufs[2].ptr, bufs[2].size);
if (!output->error &&
output->data_cb != NULL &&
output->data_cb(delta, &info->hunk, &line, output->payload))
output->error = GIT_EUSER;
}
......
......@@ -319,8 +319,8 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void)
git_blob *e = NULL;
git_patch *p;
const git_diff_delta *delta;
int line;
char origin;
const git_diff_line *line;
int l, max_l;
cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts));
......@@ -337,10 +337,10 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void)
cl_assert_equal_i(1, (int)git_patch_num_hunks(p));
cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0));
for (line = 0; line < git_patch_num_lines_in_hunk(p, 0); ++line) {
cl_git_pass(git_patch_get_line_in_hunk(
&origin, NULL, NULL, NULL, NULL, p, 0, line));
cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin);
max_l = git_patch_num_lines_in_hunk(p, 0);
for (l = 0; l < max_l; ++l) {
cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l));
cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin);
}
git_patch_free(p);
......@@ -362,10 +362,10 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void)
cl_assert_equal_i(1, (int)git_patch_num_hunks(p));
cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0));
for (line = 0; line < git_patch_num_lines_in_hunk(p, 0); ++line) {
cl_git_pass(git_patch_get_line_in_hunk(
&origin, NULL, NULL, NULL, NULL, p, 0, line));
cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin);
max_l = git_patch_num_lines_in_hunk(p, 0);
for (l = 0; l < max_l; ++l) {
cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l));
cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin);
}
git_patch_free(p);
......
......@@ -95,41 +95,37 @@ int diff_print_file_cb(
int diff_hunk_cb(
const git_diff_delta *delta,
const git_diff_hunk *range,
const char *header,
size_t header_len,
const git_diff_hunk *hunk,
void *payload)
{
diff_expects *e = payload;
const char *scan = hunk->header, *scan_end = scan + hunk->header_len;
GIT_UNUSED(delta);
/* confirm no NUL bytes in header text */
while (header_len--) cl_assert('\0' != *header++);
while (scan < scan_end)
cl_assert('\0' != *scan++);
e->hunks++;
e->hunk_old_lines += range->old_lines;
e->hunk_new_lines += range->new_lines;
e->hunk_old_lines += hunk->old_lines;
e->hunk_new_lines += hunk->new_lines;
return 0;
}
int diff_line_cb(
const git_diff_delta *delta,
const git_diff_hunk *range,
char line_origin,
const char *content,
size_t content_len,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *payload)
{
diff_expects *e = payload;
GIT_UNUSED(delta);
GIT_UNUSED(range);
GIT_UNUSED(content);
GIT_UNUSED(content_len);
GIT_UNUSED(hunk);
e->lines++;
switch (line_origin) {
switch (line->origin) {
case GIT_DIFF_LINE_CONTEXT:
case GIT_DIFF_LINE_CONTEXT_EOFNL: /* techically not a line */
e->line_ctxt++;
......@@ -186,30 +182,23 @@ int diff_foreach_via_iterator(
num_h = git_patch_num_hunks(patch);
for (h = 0; h < num_h; h++) {
const git_diff_hunk *range;
const char *hdr;
size_t hdr_len, l, num_l;
const git_diff_hunk *hunk;
size_t l, num_l;
cl_git_pass(git_patch_get_hunk(
&range, &hdr, &hdr_len, &num_l, patch, h));
cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h));
if (hunk_cb && hunk_cb(delta, range, hdr, hdr_len, data) != 0) {
if (hunk_cb && hunk_cb(delta, hunk, data) != 0) {
git_patch_free(patch);
goto abort;
}
for (l = 0; l < num_l; ++l) {
char origin;
const char *line;
size_t line_len;
int old_lineno, new_lineno;
const git_diff_line *line;
cl_git_pass(git_patch_get_line_in_hunk(
&origin, &line, &line_len, &old_lineno, &new_lineno,
patch, h, l));
cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l));
if (line_cb &&
line_cb(delta, range, origin, line, line_len, data) != 0) {
line_cb(delta, hunk, line, data) != 0) {
git_patch_free(patch);
goto abort;
}
......@@ -228,18 +217,15 @@ abort:
static int diff_print_cb(
const git_diff_delta *delta,
const git_diff_hunk *range,
char line_origin, /**< GIT_DIFF_LINE_... value from above */
const char *content,
size_t content_len,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *payload)
{
GIT_UNUSED(payload);
GIT_UNUSED(delta);
GIT_UNUSED(range);
GIT_UNUSED(line_origin);
GIT_UNUSED(content_len);
fputs(content, (FILE *)payload);
GIT_UNUSED(hunk);
fprintf((FILE *)payload, "%c%.*s",
line->origin, (int)line->content_len, line->content);
return 0;
}
......
......@@ -44,17 +44,13 @@ extern int diff_print_file_cb(
extern int diff_hunk_cb(
const git_diff_delta *delta,
const git_diff_hunk *range,
const char *header,
size_t header_len,
const git_diff_hunk *hunk,
void *cb_data);
extern int diff_line_cb(
const git_diff_delta *delta,
const git_diff_hunk *range,
char line_origin,
const char *content,
size_t content_len,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *cb_data);
extern int diff_foreach_via_iterator(
......
......@@ -101,15 +101,10 @@ void test_diff_diffiter__iterate_files_and_hunks(void)
num_h = git_patch_num_hunks(patch);
for (h = 0; h < num_h; h++) {
const git_diff_hunk *range;
const char *header;
size_t header_len, num_l;
cl_git_pass(git_patch_get_hunk(
&range, &header, &header_len, &num_l, patch, h));
const git_diff_hunk *hunk;
cl_assert(range);
cl_assert(header);
cl_git_pass(git_patch_get_hunk(&hunk, NULL, patch, h));
cl_assert(hunk);
hunk_count++;
}
......@@ -229,22 +224,17 @@ void test_diff_diffiter__iterate_all(void)
num_h = git_patch_num_hunks(patch);
for (h = 0; h < num_h; h++) {
const git_diff_hunk *range;
const char *header;
size_t header_len, l, num_l;
size_t l, num_l;
cl_git_pass(git_patch_get_hunk(
&range, &header, &header_len, &num_l, patch, h));
cl_assert(range && header);
cl_git_pass(git_patch_get_hunk(&range, &num_l, patch, h));
cl_assert(range);
exp.hunks++;
for (l = 0; l < num_l; ++l) {
char origin;
const char *content;
size_t content_len;
const git_diff_line *line;
cl_git_pass(git_patch_get_line_in_hunk(
&origin, &content, &content_len, NULL, NULL, patch, h, l));
cl_assert(content);
cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l));
cl_assert(line && line->content);
exp.lines++;
}
}
......
......@@ -257,11 +257,10 @@ void test_diff_tree__larger_hunks(void)
{
const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69";
const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10";
size_t d, num_d, h, num_h, l, num_l, header_len, line_len;
size_t d, num_d, h, num_h, l, num_l;
git_patch *patch;
const git_diff_hunk *range;
const char *header, *line;
char origin;
const git_diff_hunk *hunk;
const git_diff_line *line;
g_repo = cl_git_sandbox_init("diff");
......@@ -280,21 +279,17 @@ void test_diff_tree__larger_hunks(void)
num_h = git_patch_num_hunks(patch);
for (h = 0; h < num_h; h++) {
cl_git_pass(git_patch_get_hunk(
&range, &header, &header_len, &num_l, patch, h));
cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h));
for (l = 0; l < num_l; ++l) {
cl_git_pass(git_patch_get_line_in_hunk(
&origin, &line, &line_len, NULL, NULL, patch, h, l));
cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l));
cl_assert(line);
}
cl_git_fail(git_patch_get_line_in_hunk(
&origin, &line, &line_len, NULL, NULL, patch, h, num_l));
cl_git_fail(git_patch_get_line_in_hunk(&line, patch, h, num_l));
}
cl_git_fail(git_patch_get_hunk(
&range, &header, &header_len, &num_l, patch, num_h));
cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h));
git_patch_free(patch);
}
......
......@@ -673,7 +673,7 @@ void test_diff_workdir__larger_hunks(void)
const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10";
git_tree *a, *b;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
size_t i, d, num_d, h, num_h, l, num_l, header_len, line_len;
size_t i, d, num_d, h, num_h, l, num_l;
g_repo = cl_git_sandbox_init("diff");
......@@ -686,9 +686,8 @@ void test_diff_workdir__larger_hunks(void)
for (i = 0; i <= 2; ++i) {
git_diff *diff = NULL;
git_patch *patch;
const git_diff_hunk *range;
const char *header, *line;
char origin;
const git_diff_hunk *hunk;
const git_diff_line *line;
/* okay, this is a bit silly, but oh well */
switch (i) {
......@@ -712,23 +711,21 @@ void test_diff_workdir__larger_hunks(void)
num_h = git_patch_num_hunks(patch);
for (h = 0; h < num_h; h++) {
cl_git_pass(git_patch_get_hunk(
&range, &header, &header_len, &num_l, patch, h));
cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h));
for (l = 0; l < num_l; ++l) {
cl_git_pass(git_patch_get_line_in_hunk(
&origin, &line, &line_len, NULL, NULL, patch, h, l));
cl_git_pass(
git_patch_get_line_in_hunk(&line, patch, h, l));
cl_assert(line);
}
/* confirm fail after the last item */
cl_git_fail(git_patch_get_line_in_hunk(
&origin, &line, &line_len, NULL, NULL, patch, h, num_l));
cl_git_fail(
git_patch_get_line_in_hunk(&line, patch, h, num_l));
}
/* confirm fail after the last item */
cl_git_fail(git_patch_get_hunk(
&range, &header, &header_len, &num_l, patch, num_h));
cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h));
git_patch_free(patch);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment