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];
|
char tmp_path[PATH_MAX];
|
||||||
} diff_temp[2];
|
} 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) {
|
static struct diff_tempfile *claim_diff_tempfile(void) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
|
for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
|
||||||
@ -201,29 +349,6 @@ static void remove_tempfile_on_signal(int signo)
|
|||||||
raise(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)
|
static void print_line_count(FILE *file, int count)
|
||||||
{
|
{
|
||||||
switch (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);
|
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 {
|
struct diff_words_buffer {
|
||||||
mmfile_t text;
|
mmfile_t text;
|
||||||
long alloc;
|
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;
|
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)
|
static void free_diff_words_data(struct emit_callback *ecbdata)
|
||||||
{
|
{
|
||||||
if (ecbdata->diff_words) {
|
if (ecbdata->diff_words) {
|
||||||
@ -570,55 +664,6 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix)
|
|||||||
return "";
|
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)
|
static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
|
||||||
{
|
{
|
||||||
const char *cp;
|
const char *cp;
|
||||||
@ -1450,51 +1495,6 @@ static const char *get_textconv(struct diff_filespec *one)
|
|||||||
return one->driver->textconv;
|
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,
|
static void builtin_diff(const char *name_a,
|
||||||
const char *name_b,
|
const char *name_b,
|
||||||
struct diff_filespec *one,
|
struct diff_filespec *one,
|
||||||
|
Loading…
Reference in New Issue
Block a user