Merge branch 'jc/maint-1.6.0-blank-at-eof' (early part) into jc/maint-blank-at-eof
* 'jc/maint-1.6.0-blank-at-eof' (early part): diff.c: shuffling code around
This commit is contained in:
commit
bb35fefbc9
296
diff.c
296
diff.c
@ -174,6 +174,154 @@ static struct diff_tempfile {
|
||||
char tmp_path[PATH_MAX];
|
||||
} diff_temp[2];
|
||||
|
||||
typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
|
||||
|
||||
struct emit_callback {
|
||||
int color_diff;
|
||||
unsigned ws_rule;
|
||||
int blank_at_eof_in_preimage;
|
||||
int blank_at_eof_in_postimage;
|
||||
int lno_in_preimage;
|
||||
int lno_in_postimage;
|
||||
sane_truncate_fn truncate;
|
||||
const char **label_path;
|
||||
struct diff_words_data *diff_words;
|
||||
int *found_changesp;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
static int count_lines(const char *data, int size)
|
||||
{
|
||||
int count, ch, completely_empty = 1, nl_just_seen = 0;
|
||||
count = 0;
|
||||
while (0 < size--) {
|
||||
ch = *data++;
|
||||
if (ch == '\n') {
|
||||
count++;
|
||||
nl_just_seen = 1;
|
||||
completely_empty = 0;
|
||||
}
|
||||
else {
|
||||
nl_just_seen = 0;
|
||||
completely_empty = 0;
|
||||
}
|
||||
}
|
||||
if (completely_empty)
|
||||
return 0;
|
||||
if (!nl_just_seen)
|
||||
count++; /* no trailing newline */
|
||||
return count;
|
||||
}
|
||||
|
||||
static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
|
||||
{
|
||||
if (!DIFF_FILE_VALID(one)) {
|
||||
mf->ptr = (char *)""; /* does not matter */
|
||||
mf->size = 0;
|
||||
return 0;
|
||||
}
|
||||
else if (diff_populate_filespec(one, 0))
|
||||
return -1;
|
||||
|
||||
mf->ptr = one->data;
|
||||
mf->size = one->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)
|
||||
{
|
||||
char *ptr = mf->ptr;
|
||||
long size = mf->size;
|
||||
int cnt = 0;
|
||||
|
||||
if (!size)
|
||||
return cnt;
|
||||
ptr += size - 1; /* pointing at the very end */
|
||||
if (*ptr != '\n')
|
||||
; /* incomplete line */
|
||||
else
|
||||
ptr--; /* skip the last LF */
|
||||
while (mf->ptr < ptr) {
|
||||
char *prev_eol;
|
||||
for (prev_eol = ptr; mf->ptr <= prev_eol; prev_eol--)
|
||||
if (*prev_eol == '\n')
|
||||
break;
|
||||
if (!ws_blank_line(prev_eol + 1, ptr - prev_eol, ws_rule))
|
||||
break;
|
||||
cnt++;
|
||||
ptr = prev_eol - 1;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,
|
||||
struct emit_callback *ecbdata)
|
||||
{
|
||||
int l1, l2, at;
|
||||
unsigned ws_rule = ecbdata->ws_rule;
|
||||
l1 = count_trailing_blank(mf1, ws_rule);
|
||||
l2 = count_trailing_blank(mf2, ws_rule);
|
||||
if (l2 <= l1) {
|
||||
ecbdata->blank_at_eof_in_preimage = 0;
|
||||
ecbdata->blank_at_eof_in_postimage = 0;
|
||||
return;
|
||||
}
|
||||
at = count_lines(mf1->ptr, mf1->size);
|
||||
ecbdata->blank_at_eof_in_preimage = (at - l1) + 1;
|
||||
|
||||
at = count_lines(mf2->ptr, mf2->size);
|
||||
ecbdata->blank_at_eof_in_postimage = (at - l2) + 1;
|
||||
}
|
||||
|
||||
static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)
|
||||
{
|
||||
int has_trailing_newline, has_trailing_carriage_return;
|
||||
|
||||
has_trailing_newline = (len > 0 && line[len-1] == '\n');
|
||||
if (has_trailing_newline)
|
||||
len--;
|
||||
has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
|
||||
if (has_trailing_carriage_return)
|
||||
len--;
|
||||
|
||||
fputs(set, file);
|
||||
fwrite(line, len, 1, file);
|
||||
fputs(reset, file);
|
||||
if (has_trailing_carriage_return)
|
||||
fputc('\r', file);
|
||||
if (has_trailing_newline)
|
||||
fputc('\n', file);
|
||||
}
|
||||
|
||||
static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)
|
||||
{
|
||||
if (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&
|
||||
ecbdata->blank_at_eof_in_preimage &&
|
||||
ecbdata->blank_at_eof_in_postimage &&
|
||||
ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage &&
|
||||
ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage))
|
||||
return 0;
|
||||
return ws_blank_line(line + 1, len - 1, ecbdata->ws_rule);
|
||||
}
|
||||
|
||||
static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
|
||||
{
|
||||
const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
|
||||
const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
|
||||
|
||||
if (!*ws)
|
||||
emit_line(ecbdata->file, set, reset, line, len);
|
||||
else if (new_blank_line_at_eof(ecbdata, line, len))
|
||||
/* Blank line at EOF - paint '+' as well */
|
||||
emit_line(ecbdata->file, ws, reset, line, len);
|
||||
else {
|
||||
/* Emit just the prefix, then the rest. */
|
||||
emit_line(ecbdata->file, set, reset, line, 1);
|
||||
ws_check_emit(line + 1, len - 1, ecbdata->ws_rule,
|
||||
ecbdata->file, set, reset, ws);
|
||||
}
|
||||
}
|
||||
|
||||
static struct diff_tempfile *claim_diff_tempfile(void) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
|
||||
@ -201,29 +349,6 @@ static void remove_tempfile_on_signal(int signo)
|
||||
raise(signo);
|
||||
}
|
||||
|
||||
static int count_lines(const char *data, int size)
|
||||
{
|
||||
int count, ch, completely_empty = 1, nl_just_seen = 0;
|
||||
count = 0;
|
||||
while (0 < size--) {
|
||||
ch = *data++;
|
||||
if (ch == '\n') {
|
||||
count++;
|
||||
nl_just_seen = 1;
|
||||
completely_empty = 0;
|
||||
}
|
||||
else {
|
||||
nl_just_seen = 0;
|
||||
completely_empty = 0;
|
||||
}
|
||||
}
|
||||
if (completely_empty)
|
||||
return 0;
|
||||
if (!nl_just_seen)
|
||||
count++; /* no trailing newline */
|
||||
return count;
|
||||
}
|
||||
|
||||
static void print_line_count(FILE *file, int count)
|
||||
{
|
||||
switch (count) {
|
||||
@ -337,21 +462,6 @@ static void emit_rewrite_diff(const char *name_a,
|
||||
copy_file_with_prefix(o->file, '+', data_two, size_two, new, reset);
|
||||
}
|
||||
|
||||
static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
|
||||
{
|
||||
if (!DIFF_FILE_VALID(one)) {
|
||||
mf->ptr = (char *)""; /* does not matter */
|
||||
mf->size = 0;
|
||||
return 0;
|
||||
}
|
||||
else if (diff_populate_filespec(one, 0))
|
||||
return -1;
|
||||
|
||||
mf->ptr = one->data;
|
||||
mf->size = one->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct diff_words_buffer {
|
||||
mmfile_t text;
|
||||
long alloc;
|
||||
@ -529,22 +639,6 @@ static void diff_words_show(struct diff_words_data *diff_words)
|
||||
diff_words->minus.text.size = diff_words->plus.text.size = 0;
|
||||
}
|
||||
|
||||
typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
|
||||
|
||||
struct emit_callback {
|
||||
int color_diff;
|
||||
unsigned ws_rule;
|
||||
int blank_at_eof_in_preimage;
|
||||
int blank_at_eof_in_postimage;
|
||||
int lno_in_preimage;
|
||||
int lno_in_postimage;
|
||||
sane_truncate_fn truncate;
|
||||
const char **label_path;
|
||||
struct diff_words_data *diff_words;
|
||||
int *found_changesp;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
static void free_diff_words_data(struct emit_callback *ecbdata)
|
||||
{
|
||||
if (ecbdata->diff_words) {
|
||||
@ -570,55 +664,6 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix)
|
||||
return "";
|
||||
}
|
||||
|
||||
static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)
|
||||
{
|
||||
int has_trailing_newline, has_trailing_carriage_return;
|
||||
|
||||
has_trailing_newline = (len > 0 && line[len-1] == '\n');
|
||||
if (has_trailing_newline)
|
||||
len--;
|
||||
has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
|
||||
if (has_trailing_carriage_return)
|
||||
len--;
|
||||
|
||||
fputs(set, file);
|
||||
fwrite(line, len, 1, file);
|
||||
fputs(reset, file);
|
||||
if (has_trailing_carriage_return)
|
||||
fputc('\r', file);
|
||||
if (has_trailing_newline)
|
||||
fputc('\n', file);
|
||||
}
|
||||
|
||||
static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)
|
||||
{
|
||||
if (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&
|
||||
ecbdata->blank_at_eof_in_preimage &&
|
||||
ecbdata->blank_at_eof_in_postimage &&
|
||||
ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage &&
|
||||
ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage))
|
||||
return 0;
|
||||
return ws_blank_line(line + 1, len - 1, ecbdata->ws_rule);
|
||||
}
|
||||
|
||||
static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
|
||||
{
|
||||
const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
|
||||
const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
|
||||
|
||||
if (!*ws)
|
||||
emit_line(ecbdata->file, set, reset, line, len);
|
||||
else if (new_blank_line_at_eof(ecbdata, line, len))
|
||||
/* Blank line at EOF - paint '+' as well */
|
||||
emit_line(ecbdata->file, ws, reset, line, len);
|
||||
else {
|
||||
/* Emit just the prefix, then the rest. */
|
||||
emit_line(ecbdata->file, set, reset, line, 1);
|
||||
ws_check_emit(line + 1, len - 1, ecbdata->ws_rule,
|
||||
ecbdata->file, set, reset, ws);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
|
||||
{
|
||||
const char *cp;
|
||||
@ -1450,51 +1495,6 @@ static const char *get_textconv(struct diff_filespec *one)
|
||||
return one->driver->textconv;
|
||||
}
|
||||
|
||||
static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)
|
||||
{
|
||||
char *ptr = mf->ptr;
|
||||
long size = mf->size;
|
||||
int cnt = 0;
|
||||
|
||||
if (!size)
|
||||
return cnt;
|
||||
ptr += size - 1; /* pointing at the very end */
|
||||
if (*ptr != '\n')
|
||||
; /* incomplete line */
|
||||
else
|
||||
ptr--; /* skip the last LF */
|
||||
while (mf->ptr < ptr) {
|
||||
char *prev_eol;
|
||||
for (prev_eol = ptr; mf->ptr <= prev_eol; prev_eol--)
|
||||
if (*prev_eol == '\n')
|
||||
break;
|
||||
if (!ws_blank_line(prev_eol + 1, ptr - prev_eol, ws_rule))
|
||||
break;
|
||||
cnt++;
|
||||
ptr = prev_eol - 1;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,
|
||||
struct emit_callback *ecbdata)
|
||||
{
|
||||
int l1, l2, at;
|
||||
unsigned ws_rule = ecbdata->ws_rule;
|
||||
l1 = count_trailing_blank(mf1, ws_rule);
|
||||
l2 = count_trailing_blank(mf2, ws_rule);
|
||||
if (l2 <= l1) {
|
||||
ecbdata->blank_at_eof_in_preimage = 0;
|
||||
ecbdata->blank_at_eof_in_postimage = 0;
|
||||
return;
|
||||
}
|
||||
at = count_lines(mf1->ptr, mf1->size);
|
||||
ecbdata->blank_at_eof_in_preimage = (at - l1) + 1;
|
||||
|
||||
at = count_lines(mf2->ptr, mf2->size);
|
||||
ecbdata->blank_at_eof_in_postimage = (at - l2) + 1;
|
||||
}
|
||||
|
||||
static void builtin_diff(const char *name_a,
|
||||
const char *name_b,
|
||||
struct diff_filespec *one,
|
||||
|
Loading…
Reference in New Issue
Block a user