range-diff: split lines manually

Currently range-diff uses the 'strbuf_getline()' function for doing
its line by line processing.  In a future patch we want to do parts of
that parsing using the 'parse_git_diff_header()' function.  That
function does its own line by line reading of the input, and doesn't
use strbufs.  This doesn't match with how we do the line-by-line
processing in range-diff currently.

Switch range-diff to do our own line by line parsing, so we can re-use
the 'parse_git_diff_header()' function later.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Thomas Gummerer 2019-07-11 17:08:46 +01:00 коммит произвёл Junio C Hamano
Родитель 1ca6922598
Коммит 44b67cb62b
1 изменённых файлов: 42 добавлений и 26 удалений

Просмотреть файл

@ -24,6 +24,17 @@ struct patch_util {
struct object_id oid; struct object_id oid;
}; };
static size_t find_end_of_line(char *buffer, unsigned long size)
{
char *eol = memchr(buffer, '\n', size);
if (!eol)
return size;
*eol = '\0';
return eol + 1 - buffer;
}
/* /*
* Reads the patches into a string list, with the `util` field being populated * Reads the patches into a string list, with the `util` field being populated
* as struct object_id (will need to be free()d). * as struct object_id (will need to be free()d).
@ -31,10 +42,12 @@ struct patch_util {
static int read_patches(const char *range, struct string_list *list) static int read_patches(const char *range, struct string_list *list)
{ {
struct child_process cp = CHILD_PROCESS_INIT; struct child_process cp = CHILD_PROCESS_INIT;
FILE *in; struct strbuf buf = STRBUF_INIT, contents = STRBUF_INIT;
struct strbuf buf = STRBUF_INIT, line = STRBUF_INIT;
struct patch_util *util = NULL; struct patch_util *util = NULL;
int in_header = 1; int in_header = 1;
char *line;
int offset, len;
size_t size;
argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges", argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
"--reverse", "--date-order", "--decorate=no", "--reverse", "--date-order", "--decorate=no",
@ -54,17 +67,20 @@ static int read_patches(const char *range, struct string_list *list)
if (start_command(&cp)) if (start_command(&cp))
return error_errno(_("could not start `log`")); return error_errno(_("could not start `log`"));
in = fdopen(cp.out, "r"); if (strbuf_read(&contents, cp.out, 0) < 0) {
if (!in) {
error_errno(_("could not read `log` output")); error_errno(_("could not read `log` output"));
finish_command(&cp); finish_command(&cp);
return -1; return -1;
} }
while (strbuf_getline(&line, in) != EOF) { line = contents.buf;
size = contents.len;
for (offset = 0; size > 0; offset += len, size -= len, line += len) {
const char *p; const char *p;
if (skip_prefix(line.buf, "commit ", &p)) { len = find_end_of_line(line, size);
line[len - 1] = '\0';
if (skip_prefix(line, "commit ", &p)) {
if (util) { if (util) {
string_list_append(list, buf.buf)->util = util; string_list_append(list, buf.buf)->util = util;
strbuf_reset(&buf); strbuf_reset(&buf);
@ -75,8 +91,7 @@ static int read_patches(const char *range, struct string_list *list)
free(util); free(util);
string_list_clear(list, 1); string_list_clear(list, 1);
strbuf_release(&buf); strbuf_release(&buf);
strbuf_release(&line); strbuf_release(&contents);
fclose(in);
finish_command(&cp); finish_command(&cp);
return -1; return -1;
} }
@ -85,26 +100,28 @@ static int read_patches(const char *range, struct string_list *list)
continue; continue;
} }
if (starts_with(line.buf, "diff --git")) { if (starts_with(line, "diff --git")) {
in_header = 0; in_header = 0;
strbuf_addch(&buf, '\n'); strbuf_addch(&buf, '\n');
if (!util->diff_offset) if (!util->diff_offset)
util->diff_offset = buf.len; util->diff_offset = buf.len;
strbuf_addch(&buf, ' '); strbuf_addch(&buf, ' ');
strbuf_addbuf(&buf, &line); strbuf_addstr(&buf, line);
} else if (in_header) { } else if (in_header) {
if (starts_with(line.buf, "Author: ")) { if (starts_with(line, "Author: ")) {
strbuf_addbuf(&buf, &line); strbuf_addstr(&buf, line);
strbuf_addstr(&buf, "\n\n"); strbuf_addstr(&buf, "\n\n");
} else if (starts_with(line.buf, " ")) { } else if (starts_with(line, " ")) {
strbuf_rtrim(&line); p = line + len - 2;
strbuf_addbuf(&buf, &line); while (isspace(*p) && p >= line)
p--;
strbuf_add(&buf, line, p - line + 1);
strbuf_addch(&buf, '\n'); strbuf_addch(&buf, '\n');
} }
continue; continue;
} else if (starts_with(line.buf, "@@ ")) } else if (starts_with(line, "@@ "))
strbuf_addstr(&buf, "@@"); strbuf_addstr(&buf, "@@");
else if (!line.buf[0] || starts_with(line.buf, "index ")) else if (!line[0] || starts_with(line, "index "))
/* /*
* A completely blank (not ' \n', which is context) * A completely blank (not ' \n', which is context)
* line is not valid in a diff. We skip it * line is not valid in a diff. We skip it
@ -117,25 +134,24 @@ static int read_patches(const char *range, struct string_list *list)
* we are not interested. * we are not interested.
*/ */
continue; continue;
else if (line.buf[0] == '>') { else if (line[0] == '>') {
strbuf_addch(&buf, '+'); strbuf_addch(&buf, '+');
strbuf_add(&buf, line.buf + 1, line.len - 1); strbuf_addstr(&buf, line + 1);
} else if (line.buf[0] == '<') { } else if (line[0] == '<') {
strbuf_addch(&buf, '-'); strbuf_addch(&buf, '-');
strbuf_add(&buf, line.buf + 1, line.len - 1); strbuf_addstr(&buf, line + 1);
} else if (line.buf[0] == '#') { } else if (line[0] == '#') {
strbuf_addch(&buf, ' '); strbuf_addch(&buf, ' ');
strbuf_add(&buf, line.buf + 1, line.len - 1); strbuf_addstr(&buf, line + 1);
} else { } else {
strbuf_addch(&buf, ' '); strbuf_addch(&buf, ' ');
strbuf_addbuf(&buf, &line); strbuf_addstr(&buf, line);
} }
strbuf_addch(&buf, '\n'); strbuf_addch(&buf, '\n');
util->diffsize++; util->diffsize++;
} }
fclose(in); strbuf_release(&contents);
strbuf_release(&line);
if (util) if (util)
string_list_append(list, buf.buf)->util = util; string_list_append(list, buf.buf)->util = util;