#include "color.h"
#include "attr.h"
#include "run-command.h"
+#include "utf8.h"
#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
}
}
+typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
+
struct emit_callback {
struct xdiff_emit_state xm;
int nparents, color_diff;
unsigned ws_rule;
+ sane_truncate_fn truncate;
const char **label_path;
struct diff_words_data *diff_words;
int *found_changesp;
}
}
+static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
+{
+ const char *cp;
+ unsigned long allot;
+ size_t l = len;
+
+ if (ecb->truncate)
+ return ecb->truncate(line, len);
+ cp = line;
+ allot = l;
+ while (0 < l) {
+ (void) utf8_width(&cp, &l);
+ if (!cp)
+ break; /* truncated in the middle? */
+ }
+ return allot - l;
+}
+
static void fn_out_consume(void *priv, char *line, unsigned long len)
{
int i;
;
if (2 <= i && i < len && line[i] == ' ') {
ecbdata->nparents = i - 1;
+ len = sane_truncate_line(ecbdata, line, len);
emit_line(diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO),
reset, line, len);
+ if (line[len-1] != '\n')
+ putchar('\n');
return;
}
--- /dev/null
+#!/bin/sh
+
+test_description='diff hunk header truncation'
+
+. ./test-lib.sh
+
+N='日本語'
+N1='日'
+N2='日本'
+NS="$N$N$N$N$N$N$N$N$N$N$N$N$N"
+
+test_expect_success setup '
+
+ (
+ echo "A $NS"
+ for c in B C D E F G H I J K
+ do
+ echo " $c"
+ done
+ echo "L $NS"
+ for c in M N O P Q R S T U V
+ do
+ echo " $c"
+ done
+ ) >file &&
+ git add file &&
+
+ sed -e "/^ [EP]/s/$/ modified/" <file >file+ &&
+ mv file+ file
+
+'
+
+test_expect_success 'hunk header truncation with an overly long line' '
+
+ git diff | sed -n -e "s/^.*@@//p" >actual &&
+ (
+ echo " A $N$N$N$N$N$N$N$N$N2"
+ echo " L $N$N$N$N$N$N$N$N$N1"
+ ) >expected &&
+ diff -u actual expected
+
+'
+
+test_done