Merge branch 'jk/diff-algo-finishing-touches' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 24 Apr 2013 23:17:13 +0000 (16:17 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 24 Apr 2013 23:19:42 +0000 (16:19 -0700)
"git diff --diff-algorithm=algo" was understood by the command line
parser, but "git diff --diff-algorithm algo" was not.

* jk/diff-algo-finishing-touches:
diff: allow unstuck arguments with --diff-algorithm
git-merge(1): document diff-algorithm option to merge-recursive

1  2 
diff.c
diff --combined diff.c
index 0eb26535f52adf516961672628f2810e55a31a9d,08e39144c2fe214b3e556a9759720da1c7caa99c..649ec86b87c4eb201f9e587a0173e381e9b5b8b5
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -425,7 -425,12 +425,7 @@@ static void emit_line_0(struct diff_opt
        int nofirst;
        FILE *file = o->file;
  
 -      if (o->output_prefix) {
 -              struct strbuf *msg = NULL;
 -              msg = o->output_prefix(o, o->output_prefix_data);
 -              assert(msg);
 -              fwrite(msg->buf, msg->len, 1, file);
 -      }
 +      fputs(diff_line_prefix(o), file);
  
        if (len == 0) {
                has_trailing_newline = (first == '\n');
@@@ -643,7 -648,13 +643,7 @@@ static void emit_rewrite_diff(const cha
        char *data_one, *data_two;
        size_t size_one, size_two;
        struct emit_callback ecbdata;
 -      char *line_prefix = "";
 -      struct strbuf *msgbuf;
 -
 -      if (o && o->output_prefix) {
 -              msgbuf = o->output_prefix(o, o->output_prefix_data);
 -              line_prefix = msgbuf->buf;
 -      }
 +      const char *line_prefix = diff_line_prefix(o);
  
        if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) {
                a_prefix = o->b_prefix;
@@@ -839,14 -850,18 +839,14 @@@ static void fn_out_diff_words_aux(void 
        int minus_first, minus_len, plus_first, plus_len;
        const char *minus_begin, *minus_end, *plus_begin, *plus_end;
        struct diff_options *opt = diff_words->opt;
 -      struct strbuf *msgbuf;
 -      char *line_prefix = "";
 +      const char *line_prefix;
  
        if (line[0] != '@' || parse_hunk_header(line, len,
                        &minus_first, &minus_len, &plus_first, &plus_len))
                return;
  
        assert(opt);
 -      if (opt->output_prefix) {
 -              msgbuf = opt->output_prefix(opt, opt->output_prefix_data);
 -              line_prefix = msgbuf->buf;
 -      }
 +      line_prefix = diff_line_prefix(opt);
  
        /* POSIX requires that first be decremented by one if len == 0... */
        if (minus_len) {
@@@ -970,10 -985,14 +970,10 @@@ static void diff_words_show(struct diff
        struct diff_words_style *style = diff_words->style;
  
        struct diff_options *opt = diff_words->opt;
 -      struct strbuf *msgbuf;
 -      char *line_prefix = "";
 +      const char *line_prefix;
  
        assert(opt);
 -      if (opt->output_prefix) {
 -              msgbuf = opt->output_prefix(opt, opt->output_prefix_data);
 -              line_prefix = msgbuf->buf;
 -      }
 +      line_prefix = diff_line_prefix(opt);
  
        /* special case: only removal */
        if (!diff_words->plus.text.size) {
@@@ -1109,16 -1128,6 +1109,16 @@@ const char *diff_get_color(int diff_use
        return "";
  }
  
 +const char *diff_line_prefix(struct diff_options *opt)
 +{
 +      struct strbuf *msgbuf;
 +      if (!opt->output_prefix)
 +              return "";
 +
 +      msgbuf = opt->output_prefix(opt, opt->output_prefix_data);
 +      return msgbuf->buf;
 +}
 +
  static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
  {
        const char *cp;
@@@ -1159,7 -1168,13 +1159,7 @@@ static void fn_out_consume(void *priv, 
        const char *plain = diff_get_color(ecbdata->color_diff, DIFF_PLAIN);
        const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
        struct diff_options *o = ecbdata->opt;
 -      char *line_prefix = "";
 -      struct strbuf *msgbuf;
 -
 -      if (o && o->output_prefix) {
 -              msgbuf = o->output_prefix(o, o->output_prefix_data);
 -              line_prefix = msgbuf->buf;
 -      }
 +      const char *line_prefix = diff_line_prefix(o);
  
        if (ecbdata->header) {
                fprintf(ecbdata->opt->file, "%s", ecbdata->header->buf);
@@@ -1264,7 -1279,6 +1264,7 @@@ static char *pprint_rename(const char *
        const char *new = b;
        struct strbuf name = STRBUF_INIT;
        int pfx_length, sfx_length;
 +      int pfx_adjust_for_slash;
        int len_a = strlen(a);
        int len_b = strlen(b);
        int a_midlen, b_midlen;
        old = a + len_a;
        new = b + len_b;
        sfx_length = 0;
 -      while (a <= old && b <= new && *old == *new) {
 +      /*
 +       * If there is a common prefix, it must end in a slash.  In
 +       * that case we let this loop run 1 into the prefix to see the
 +       * same slash.
 +       *
 +       * If there is no common prefix, we cannot do this as it would
 +       * underrun the input strings.
 +       */
 +      pfx_adjust_for_slash = (pfx_length ? 1 : 0);
 +      while (a + pfx_length - pfx_adjust_for_slash <= old &&
 +             b + pfx_length - pfx_adjust_for_slash <= new &&
 +             *old == *new) {
                if (*old == '/')
                        sfx_length = len_a - (old - a);
                old--;
@@@ -1495,11 -1498,16 +1495,11 @@@ static void show_stats(struct diffstat_
        const char *reset, *add_c, *del_c;
        const char *line_prefix = "";
        int extra_shown = 0;
 -      struct strbuf *msg = NULL;
  
        if (data->nr == 0)
                return;
  
 -      if (options->output_prefix) {
 -              msg = options->output_prefix(options, options->output_prefix_data);
 -              line_prefix = msg->buf;
 -      }
 -
 +      line_prefix = diff_line_prefix(options);
        count = options->stat_count ? options->stat_count : data->nr;
  
        reset = diff_get_color_opt(options, DIFF_RESET);
         * Binary files are displayed with "Bin XXX -> YYY bytes"
         * instead of the change count and graph. This part is treated
         * similarly to the graph part, except that it is not
 -       * "scaled". If total width is too small to accomodate the
 +       * "scaled". If total width is too small to accommodate the
         * guaranteed minimum width of the filename part and the
         * separators and this message, this message will "overflow"
         * making the line longer than the maximum width.
@@@ -1751,7 -1759,12 +1751,7 @@@ static void show_shortstats(struct diff
                        dels += deleted;
                }
        }
 -      if (options->output_prefix) {
 -              struct strbuf *msg = NULL;
 -              msg = options->output_prefix(options,
 -                              options->output_prefix_data);
 -              fprintf(options->file, "%s", msg->buf);
 -      }
 +      fprintf(options->file, "%s", diff_line_prefix(options));
        print_stat_summary(options->file, total_files, adds, dels);
  }
  
@@@ -1765,7 -1778,12 +1765,7 @@@ static void show_numstat(struct diffsta
        for (i = 0; i < data->nr; i++) {
                struct diffstat_file *file = data->files[i];
  
 -              if (options->output_prefix) {
 -                      struct strbuf *msg = NULL;
 -                      msg = options->output_prefix(options,
 -                                      options->output_prefix_data);
 -                      fprintf(options->file, "%s", msg->buf);
 -              }
 +              fprintf(options->file, "%s", diff_line_prefix(options));
  
                if (file->is_binary)
                        fprintf(options->file, "-\t-\t");
@@@ -1807,7 -1825,13 +1807,7 @@@ static long gather_dirstat(struct diff_
  {
        unsigned long this_dir = 0;
        unsigned int sources = 0;
 -      const char *line_prefix = "";
 -      struct strbuf *msg = NULL;
 -
 -      if (opt->output_prefix) {
 -              msg = opt->output_prefix(opt, opt->output_prefix_data);
 -              line_prefix = msg->buf;
 -      }
 +      const char *line_prefix = diff_line_prefix(opt);
  
        while (dir->nr) {
                struct dirstat_file *f = dir->files;
@@@ -2057,10 -2081,15 +2057,10 @@@ static void checkdiff_consume(void *pri
        const char *reset = diff_get_color(data->o->use_color, DIFF_RESET);
        const char *set = diff_get_color(data->o->use_color, DIFF_FILE_NEW);
        char *err;
 -      char *line_prefix = "";
 -      struct strbuf *msgbuf;
 +      const char *line_prefix;
  
        assert(data->o);
 -      if (data->o->output_prefix) {
 -              msgbuf = data->o->output_prefix(data->o,
 -                      data->o->output_prefix_data);
 -              line_prefix = msgbuf->buf;
 -      }
 +      line_prefix = diff_line_prefix(data->o);
  
        if (line[0] == '+') {
                unsigned bad;
@@@ -2117,8 -2146,7 +2117,8 @@@ static unsigned char *deflate_it(char *
        return deflated;
  }
  
 -static void emit_binary_diff_body(FILE *file, mmfile_t *one, mmfile_t *two, char *prefix)
 +static void emit_binary_diff_body(FILE *file, mmfile_t *one, mmfile_t *two,
 +                                const char *prefix)
  {
        void *cp;
        void *delta;
        free(data);
  }
  
 -static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two, char *prefix)
 +static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two,
 +                           const char *prefix)
  {
        fprintf(file, "%sGIT binary patch\n", prefix);
        emit_binary_diff_body(file, one, two, prefix);
@@@ -2247,7 -2274,13 +2247,7 @@@ static void builtin_diff(const char *na
        struct userdiff_driver *textconv_one = NULL;
        struct userdiff_driver *textconv_two = NULL;
        struct strbuf header = STRBUF_INIT;
 -      struct strbuf *msgbuf;
 -      char *line_prefix = "";
 -
 -      if (o->output_prefix) {
 -              msgbuf = o->output_prefix(o, o->output_prefix_data);
 -              line_prefix = msgbuf->buf;
 -      }
 +      const char *line_prefix = diff_line_prefix(o);
  
        if (DIFF_OPT_TST(o, SUBMODULE_LOG) &&
                        (!one->mode || S_ISGITLINK(one->mode)) &&
@@@ -2946,9 -2979,14 +2946,9 @@@ static void fill_metainfo(struct strbu
  {
        const char *set = diff_get_color(use_color, DIFF_METAINFO);
        const char *reset = diff_get_color(use_color, DIFF_RESET);
 -      struct strbuf *msgbuf;
 -      char *line_prefix = "";
 +      const char *line_prefix = diff_line_prefix(o);
  
        *must_show_header = 1;
 -      if (o->output_prefix) {
 -              msgbuf = o->output_prefix(o, o->output_prefix_data);
 -              line_prefix = msgbuf->buf;
 -      }
        strbuf_init(msg, PATH_MAX * 2 + 300);
        switch (p->status) {
        case DIFF_STATUS_COPIED:
@@@ -3596,8 -3634,8 +3596,8 @@@ int diff_opt_parse(struct diff_options 
                options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
        else if (!strcmp(arg, "--histogram"))
                options->xdl_opts = DIFF_WITH_ALG(options, HISTOGRAM_DIFF);
-       else if (!prefixcmp(arg, "--diff-algorithm=")) {
-               long value = parse_algorithm_value(arg+17);
+       else if ((argcount = parse_long_opt("diff-algorithm", av, &optarg))) {
+               long value = parse_algorithm_value(optarg);
                if (value < 0)
                        return error("option diff-algorithm accepts \"myers\", "
                                     "\"minimal\", \"patience\" and \"histogram\"");
                DIFF_XDL_CLR(options, NEED_MINIMAL);
                options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
                options->xdl_opts |= value;
+               return argcount;
        }
  
        /* flags options */
                DIFF_OPT_SET(options, FIND_COPIES_HARDER);
        else if (!strcmp(arg, "--follow"))
                DIFF_OPT_SET(options, FOLLOW_RENAMES);
 +      else if (!strcmp(arg, "--no-follow"))
 +              DIFF_OPT_CLR(options, FOLLOW_RENAMES);
        else if (!strcmp(arg, "--color"))
                options->use_color = 1;
        else if (!prefixcmp(arg, "--color=")) {
@@@ -3896,8 -3933,12 +3897,8 @@@ static void diff_flush_raw(struct diff_
  {
        int line_termination = opt->line_termination;
        int inter_name_termination = line_termination ? '\t' : '\0';
 -      if (opt->output_prefix) {
 -              struct strbuf *msg = NULL;
 -              msg = opt->output_prefix(opt, opt->output_prefix_data);
 -              fprintf(opt->file, "%s", msg->buf);
 -      }
  
 +      fprintf(opt->file, "%s", diff_line_prefix(opt));
        if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) {
                fprintf(opt->file, ":%06o %06o %s ", p->one->mode, p->two->mode,
                        diff_unique_abbrev(p->one->sha1, opt->abbrev));
@@@ -4167,7 -4208,12 +4168,7 @@@ static void show_rename_copy(FILE *file
  static void diff_summary(struct diff_options *opt, struct diff_filepair *p)
  {
        FILE *file = opt->file;
 -      char *line_prefix = "";
 -
 -      if (opt->output_prefix) {
 -              struct strbuf *buf = opt->output_prefix(opt, opt->output_prefix_data);
 -              line_prefix = buf->buf;
 -      }
 +      const char *line_prefix = diff_line_prefix(opt);
  
        switch(p->status) {
        case DIFF_STATUS_DELETED:
@@@ -4468,9 -4514,13 +4469,9 @@@ void diff_flush(struct diff_options *op
  
        if (output_format & DIFF_FORMAT_PATCH) {
                if (separator) {
 -                      if (options->output_prefix) {
 -                              struct strbuf *msg = NULL;
 -                              msg = options->output_prefix(options,
 -                                      options->output_prefix_data);
 -                              fwrite(msg->buf, msg->len, 1, stdout);
 -                      }
 -                      putc(options->line_termination, options->file);
 +                      fprintf(options->file, "%s%c",
 +                              diff_line_prefix(options),
 +                              options->line_termination);
                        if (options->stat_sep) {
                                /* attach patch instead of inline */
                                fputs(options->stat_sep, options->file);
@@@ -4674,7 -4724,7 +4675,7 @@@ int diff_result_code(struct diff_option
  {
        int result = 0;
  
 -      diff_warn_rename_limit("diff.renamelimit",
 +      diff_warn_rename_limit("diff.renameLimit",
                               opt->needed_rename_limit,
                               opt->degraded_cc_to_c);
        if (!DIFF_OPT_TST(opt, EXIT_WITH_STATUS) &&