Documentation: fix links to tutorials and other new manual pages
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 6bcbe2082873c7f311931890d39afdbd5345838d..803fbba451dfe8226097dcb791c339ee2ccd6735 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -830,12 +830,12 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
        /* Sanity: give at least 5 columns to the graph,
         * but leave at least 10 columns for the name.
         */
-       if (width < name_width + 15) {
-               if (name_width <= 25)
-                       width = name_width + 15;
-               else
-                       name_width = width - 15;
-       }
+       if (width < 25)
+               width = 25;
+       if (name_width < 10)
+               name_width = 10;
+       else if (width < name_width + 15)
+               name_width = width - 15;
 
        /* Find the longest filename and max number of changes */
        reset = diff_get_color_opt(options, DIFF_RESET);
@@ -1140,8 +1140,38 @@ struct checkdiff_t {
        struct diff_options *o;
        unsigned ws_rule;
        unsigned status;
+       int trailing_blanks_start;
 };
 
+static int is_conflict_marker(const char *line, unsigned long len)
+{
+       char firstchar;
+       int cnt;
+
+       if (len < 8)
+               return 0;
+       firstchar = line[0];
+       switch (firstchar) {
+       case '=': case '>': case '<':
+               break;
+       default:
+               return 0;
+       }
+       for (cnt = 1; cnt < 7; cnt++)
+               if (line[cnt] != firstchar)
+                       return 0;
+       /* line[0] thru line[6] are same as firstchar */
+       if (firstchar == '=') {
+               /* divider between ours and theirs? */
+               if (len != 8 || line[7] != '\n')
+                       return 0;
+       } else if (len < 8 || !isspace(line[7])) {
+               /* not divider before ours nor after theirs */
+               return 0;
+       }
+       return 1;
+}
+
 static void checkdiff_consume(void *priv, char *line, unsigned long len)
 {
        struct checkdiff_t *data = priv;
@@ -1154,6 +1184,16 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len)
        if (line[0] == '+') {
                unsigned bad;
                data->lineno++;
+               if (!ws_blank_line(line + 1, len - 1, data->ws_rule))
+                       data->trailing_blanks_start = 0;
+               else if (!data->trailing_blanks_start)
+                       data->trailing_blanks_start = data->lineno;
+               if (is_conflict_marker(line + 1, len - 1)) {
+                       data->status |= 1;
+                       fprintf(data->o->file,
+                               "%s:%d: leftover conflict marker\n",
+                               data->filename, data->lineno);
+               }
                bad = ws_check(line + 1, len - 1, data->ws_rule);
                if (!bad)
                        return;
@@ -1165,14 +1205,16 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len)
                emit_line(data->o->file, set, reset, line, 1);
                ws_check_emit(line + 1, len - 1, data->ws_rule,
                              data->o->file, set, reset, ws);
-       } else if (line[0] == ' ')
+       } else if (line[0] == ' ') {
                data->lineno++;
-       else if (line[0] == '@') {
+               data->trailing_blanks_start = 0;
+       } else if (line[0] == '@') {
                char *plus = strchr(line, '+');
                if (plus)
                        data->lineno = strtol(plus, NULL, 10) - 1;
                else
                        die("invalid diff");
+               data->trailing_blanks_start = 0;
        }
 }
 
@@ -1584,6 +1626,12 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                ecb.outf = xdiff_outf;
                ecb.priv = &data;
                xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+
+               if (data.trailing_blanks_start) {
+                       fprintf(o->file, "%s:%d: ends with blank lines.\n",
+                               data.filename, data.trailing_blanks_start);
+                       data.status = 1; /* report errors */
+               }
        }
  free_and_return:
        diff_free_filespec_data(one);