Merge branch 'ec/diff-noprefix-config'
authorJunio C Hamano <gitster@pobox.com>
Fri, 18 Jun 2010 18:16:55 +0000 (11:16 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 18 Jun 2010 18:16:55 +0000 (11:16 -0700)
* ec/diff-noprefix-config:
diff: add configuration option for disabling diff prefixes.

1  2 
Documentation/config.txt
diff.c
diff --combined Documentation/config.txt
index 95cf73cd47961f76bc40fda08ccc79494a8da748,93ab49772c1a537de8b32fa1f63530f20f092d3f..7afd0a333f5e67fcfcc5c5277c3a871f6825ea83
@@@ -520,12 -520,18 +520,12 @@@ check that makes sure that existing obj
  
  core.notesRef::
        When showing commit messages, also show notes which are stored in
 -      the given ref.  This ref is expected to contain files named
 -      after the full SHA-1 of the commit they annotate.  The ref
 -      must be fully qualified.
 +      the given ref.  The ref must be fully qualified.  If the given
 +      ref does not exist, it is not an error but means that no
 +      notes should be printed.
  +
 -If such a file exists in the given ref, the referenced blob is read, and
 -appended to the commit message, separated by a "Notes (<refname>):"
 -line (shortened to "Notes:" in the case of "refs/notes/commits").  If the
 -given ref itself does not exist, it is not an error, but means that no
 -notes should be printed.
 -+
 -This setting defaults to "refs/notes/commits", and can be overridden by
 -the `GIT_NOTES_REF` environment variable.
 +This setting defaults to "refs/notes/commits", and it can be overridden by
 +the 'GIT_NOTES_REF' environment variable.  See linkgit:git-notes[1].
  
  core.sparseCheckout::
        Enable "sparse checkout" feature. See section "Sparse checkout" in
@@@ -792,6 -798,8 +792,8 @@@ diff.mnemonicprefix:
        standard "a/" and "b/" depending on what is being compared.  When
        this configuration is in effect, reverse diff output also swaps
        the order of the prefixes:
+ diff.noprefix::
+       If set, 'git diff' does not show any source or destination prefix.
  `git diff`;;
        compares the (i)ndex and the (w)ork tree;
  `git diff HEAD`;;
@@@ -940,19 -948,13 +942,19 @@@ gc.pruneexpire:
        unreachable objects immediately.
  
  gc.reflogexpire::
 +gc.<pattern>.reflogexpire::
        'git reflog expire' removes reflog entries older than
 -      this time; defaults to 90 days.
 +      this time; defaults to 90 days.  With "<pattern>" (e.g.
 +      "refs/stash") in the middle the setting applies only to
 +      the refs that match the <pattern>.
  
  gc.reflogexpireunreachable::
 +gc.<ref>.reflogexpireunreachable::
        'git reflog expire' removes reflog entries older than
        this time and are not reachable from the current tip;
 -      defaults to 30 days.
 +      defaults to 30 days.  With "<pattern>" (e.g. "refs/stash")
 +      in the middle, the setting applies only to the refs that
 +      match the <pattern>.
  
  gc.rerereresolved::
        Records of conflicted merge you resolved earlier are
@@@ -1475,16 -1477,6 +1477,16 @@@ pager.<cmd>:
        it takes precedence over this option.  To disable pagination for
        all commands, set `core.pager` or `GIT_PAGER` to `cat`.
  
 +pretty.<name>::
 +      Alias for a --pretty= format string, as specified in
 +      linkgit:git-log[1]. Any aliases defined here can be used just
 +      as the built-in pretty formats could. For example,
 +      running `git config pretty.changelog "format:{asterisk} %H %s"`
 +      would cause the invocation `git log --pretty=changelog`
 +      to be equivalent to running `git log "--pretty=format:{asterisk} %H %s"`.
 +      Note that an alias with the same name as a built-in format
 +      will be silently ignored.
 +
  pull.octopus::
        The default merge strategy to use when pulling multiple branches
        at once.
@@@ -1535,7 -1527,7 +1537,7 @@@ receive.denyDeletes:
        the ref. Use this to prevent such a ref deletion via a push.
  
  receive.denyCurrentBranch::
 -      If set to true or "refuse", receive-pack will deny a ref update
 +      If set to true or "refuse", git-receive-pack will deny a ref update
        to the currently checked out branch of a non-bare repository.
        Such a push is potentially dangerous because it brings the HEAD
        out of sync with the index and working tree. If set to "warn",
@@@ -1597,9 -1589,7 +1599,9 @@@ remote.<name>.uploadpack:
  
  remote.<name>.tagopt::
        Setting this value to \--no-tags disables automatic tag following when
 -      fetching from remote <name>
 +      fetching from remote <name>. Setting it to \--tags will fetch every
 +      tag from remote <name>, even if they are not reachable from remote
 +      branch heads.
  
  remote.<name>.vcs::
        Setting this to a value <vcs> will cause git to interact with
@@@ -1703,13 -1693,6 +1705,13 @@@ If this variable is not specified, it d
  This variable can be overridden with the -u|--untracked-files option
  of linkgit:git-status[1] and linkgit:git-commit[1].
  
 +status.submodulesummary::
 +      Defaults to false.
 +      If this is set to a non zero number or true (identical to -1 or an
 +      unlimited number), the submodule summary will be enabled and a
 +      summary of commits for modified submodules will be shown (see
 +      --summary-limit option of linkgit:git-submodule[1]).
 +
  tar.umask::
        This variable can be used to restrict the permission bits of
        tar archive entries.  The default is 0002, which turns off the
diff --combined diff.c
index 4e077445c6e93332bbfe73fd90360b2370a722be,6d9928cb968417d5d0e83f07acf22ed2705db567..c82b605a942b8611c3eaf0e41a173185fdb40779
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -30,6 -30,7 +30,7 @@@ static const char *diff_word_regex_cfg
  static const char *external_diff_cmd_cfg;
  int diff_auto_refresh_index = 1;
  static int diff_mnemonic_prefix;
+ static int diff_no_prefix;
  
  static char diff_colors[][COLOR_MAXLEN] = {
        GIT_COLOR_RESET,
@@@ -101,6 -102,10 +102,10 @@@ int git_diff_ui_config(const char *var
                diff_mnemonic_prefix = git_config_bool(var, value);
                return 0;
        }
+       if (!strcmp(var, "diff.noprefix")) {
+               diff_no_prefix = git_config_bool(var, value);
+               return 0;
+       }
        if (!strcmp(var, "diff.external"))
                return git_config_string(&external_diff_cmd_cfg, var, value);
        if (!strcmp(var, "diff.wordregex"))
@@@ -560,68 -565,16 +565,68 @@@ static void diff_words_append(char *lin
        buffer->text.ptr[buffer->text.size] = '\0';
  }
  
 +struct diff_words_style_elem
 +{
 +      const char *prefix;
 +      const char *suffix;
 +      const char *color; /* NULL; filled in by the setup code if
 +                          * color is enabled */
 +};
 +
 +struct diff_words_style
 +{
 +      enum diff_words_type type;
 +      struct diff_words_style_elem new, old, ctx;
 +      const char *newline;
 +};
 +
 +struct diff_words_style diff_words_styles[] = {
 +      { DIFF_WORDS_PORCELAIN, {"+", "\n"}, {"-", "\n"}, {" ", "\n"}, "~\n" },
 +      { DIFF_WORDS_PLAIN, {"{+", "+}"}, {"[-", "-]"}, {"", ""}, "\n" },
 +      { DIFF_WORDS_COLOR, {"", ""}, {"", ""}, {"", ""}, "\n" }
 +};
 +
  struct diff_words_data {
        struct diff_words_buffer minus, plus;
        const char *current_plus;
        FILE *file;
        regex_t *word_regex;
 +      enum diff_words_type type;
 +      struct diff_words_style *style;
  };
  
 +static int fn_out_diff_words_write_helper(FILE *fp,
 +                                        struct diff_words_style_elem *st_el,
 +                                        const char *newline,
 +                                        size_t count, const char *buf)
 +{
 +      while (count) {
 +              char *p = memchr(buf, '\n', count);
 +              if (p != buf) {
 +                      if (st_el->color && fputs(st_el->color, fp) < 0)
 +                              return -1;
 +                      if (fputs(st_el->prefix, fp) < 0 ||
 +                          fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
 +                          fputs(st_el->suffix, fp) < 0)
 +                              return -1;
 +                      if (st_el->color && *st_el->color
 +                          && fputs(GIT_COLOR_RESET, fp) < 0)
 +                              return -1;
 +              }
 +              if (!p)
 +                      return 0;
 +              if (fputs(newline, fp) < 0)
 +                      return -1;
 +              count -= p + 1 - buf;
 +              buf = p + 1;
 +      }
 +      return 0;
 +}
 +
  static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
  {
        struct diff_words_data *diff_words = priv;
 +      struct diff_words_style *style = diff_words->style;
        int minus_first, minus_len, plus_first, plus_len;
        const char *minus_begin, *minus_end, *plus_begin, *plus_end;
  
                plus_begin = plus_end = diff_words->plus.orig[plus_first].end;
  
        if (diff_words->current_plus != plus_begin)
 -              fwrite(diff_words->current_plus,
 -                              plus_begin - diff_words->current_plus, 1,
 -                              diff_words->file);
 +              fn_out_diff_words_write_helper(diff_words->file,
 +                              &style->ctx, style->newline,
 +                              plus_begin - diff_words->current_plus,
 +                              diff_words->current_plus);
        if (minus_begin != minus_end)
 -              color_fwrite_lines(diff_words->file,
 -                              diff_get_color(1, DIFF_FILE_OLD),
 +              fn_out_diff_words_write_helper(diff_words->file,
 +                              &style->old, style->newline,
                                minus_end - minus_begin, minus_begin);
        if (plus_begin != plus_end)
 -              color_fwrite_lines(diff_words->file,
 -                              diff_get_color(1, DIFF_FILE_NEW),
 +              fn_out_diff_words_write_helper(diff_words->file,
 +                              &style->new, style->newline,
                                plus_end - plus_begin, plus_begin);
  
        diff_words->current_plus = plus_end;
@@@ -737,12 -689,11 +742,12 @@@ static void diff_words_show(struct diff
        xpparam_t xpp;
        xdemitconf_t xecfg;
        mmfile_t minus, plus;
 +      struct diff_words_style *style = diff_words->style;
  
        /* special case: only removal */
        if (!diff_words->plus.text.size) {
 -              color_fwrite_lines(diff_words->file,
 -                      diff_get_color(1, DIFF_FILE_OLD),
 +              fn_out_diff_words_write_helper(diff_words->file,
 +                      &style->old, style->newline,
                        diff_words->minus.text.size, diff_words->minus.text.ptr);
                diff_words->minus.text.size = 0;
                return;
        memset(&xecfg, 0, sizeof(xecfg));
        diff_words_fill(&diff_words->minus, &minus, diff_words->word_regex);
        diff_words_fill(&diff_words->plus, &plus, diff_words->word_regex);
 -      xpp.flags = XDF_NEED_MINIMAL;
 +      xpp.flags = 0;
        /* as only the hunk header will be parsed, we need a 0-context */
        xecfg.ctxlen = 0;
        xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
        free(plus.ptr);
        if (diff_words->current_plus != diff_words->plus.text.ptr +
                        diff_words->plus.text.size)
 -              fwrite(diff_words->current_plus,
 +              fn_out_diff_words_write_helper(diff_words->file,
 +                      &style->ctx, style->newline,
                        diff_words->plus.text.ptr + diff_words->plus.text.size
 -                      - diff_words->current_plus, 1,
 -                      diff_words->file);
 +                      - diff_words->current_plus, diff_words->current_plus);
        diff_words->minus.text.size = diff_words->plus.text.size = 0;
  }
  
@@@ -878,9 -829,6 +883,9 @@@ static void fn_out_consume(void *priv, 
  
        if (len < 1) {
                emit_line(ecbdata->file, reset, reset, line, len);
 +              if (ecbdata->diff_words
 +                  && ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN)
 +                      fputs("~\n", ecbdata->file);
                return;
        }
  
                        return;
                }
                diff_words_flush(ecbdata);
 -              line++;
 -              len--;
 -              emit_line(ecbdata->file, plain, reset, line, len);
 +              if (ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN) {
 +                      emit_line(ecbdata->file, plain, reset, line, len);
 +                      fputs("~\n", ecbdata->file);
 +              } else {
 +                      /* don't print the prefix character */
 +                      emit_line(ecbdata->file, plain, reset, line+1, len-1);
 +              }
                return;
        }
  
@@@ -1706,21 -1650,21 +1711,21 @@@ static void builtin_diff(const char *na
        if (lbl[0][0] == '/') {
                /* /dev/null */
                strbuf_addf(&header, "%snew file mode %06o%s\n", set, two->mode, reset);
 -              if (xfrm_msg && xfrm_msg[0])
 -                      strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
 +              if (xfrm_msg)
 +                      strbuf_addstr(&header, xfrm_msg);
        }
        else if (lbl[1][0] == '/') {
                strbuf_addf(&header, "%sdeleted file mode %06o%s\n", set, one->mode, reset);
 -              if (xfrm_msg && xfrm_msg[0])
 -                      strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
 +              if (xfrm_msg)
 +                      strbuf_addstr(&header, xfrm_msg);
        }
        else {
                if (one->mode != two->mode) {
                        strbuf_addf(&header, "%sold mode %06o%s\n", set, one->mode, reset);
                        strbuf_addf(&header, "%snew mode %06o%s\n", set, two->mode, reset);
                }
 -              if (xfrm_msg && xfrm_msg[0])
 -                      strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
 +              if (xfrm_msg)
 +                      strbuf_addstr(&header, xfrm_msg);
  
                /*
                 * we do not run diff between different kind
                        check_blank_at_eof(&mf1, &mf2, &ecbdata);
                ecbdata.file = o->file;
                ecbdata.header = header.len ? &header : NULL;
 -              xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
 +              xpp.flags = o->xdl_opts;
                xecfg.ctxlen = o->context;
                xecfg.interhunkctxlen = o->interhunkcontext;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
                        xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
                else if (!prefixcmp(diffopts, "-u"))
                        xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
 -              if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) {
 +              if (o->word_diff) {
 +                      int i;
 +
                        ecbdata.diff_words =
                                xcalloc(1, sizeof(struct diff_words_data));
                        ecbdata.diff_words->file = o->file;
 +                      ecbdata.diff_words->type = o->word_diff;
                        if (!o->word_regex)
                                o->word_regex = userdiff_word_regex(one);
                        if (!o->word_regex)
                                        die ("Invalid regular expression: %s",
                                                        o->word_regex);
                        }
 +                      for (i = 0; i < ARRAY_SIZE(diff_words_styles); i++) {
 +                              if (o->word_diff == diff_words_styles[i].type) {
 +                                      ecbdata.diff_words->style =
 +                                              &diff_words_styles[i];
 +                                      break;
 +                              }
 +                      }
 +                      if (DIFF_OPT_TST(o, COLOR_DIFF)) {
 +                              struct diff_words_style *st = ecbdata.diff_words->style;
 +                              st->old.color = diff_get_color_opt(o, DIFF_FILE_OLD);
 +                              st->new.color = diff_get_color_opt(o, DIFF_FILE_NEW);
 +                              st->ctx.color = diff_get_color_opt(o, DIFF_PLAIN);
 +                      }
                }
                xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
                              &xpp, &xecfg);
 -              if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS))
 +              if (o->word_diff)
                        free_diff_words_data(&ecbdata);
                if (textconv_one)
                        free(mf1.ptr);
@@@ -1894,7 -1822,7 +1899,7 @@@ static void builtin_diffstat(const cha
  
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
 -              xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
 +              xpp.flags = o->xdl_opts;
                xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
                              &xpp, &xecfg);
        }
@@@ -1942,7 -1870,7 +1947,7 @@@ static void builtin_checkdiff(const cha
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                xecfg.ctxlen = 1; /* at least one context line */
 -              xpp.flags = XDF_NEED_MINIMAL;
 +              xpp.flags = 0;
                xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
                              &xpp, &xecfg);
  
@@@ -2379,36 -2307,30 +2384,36 @@@ static void fill_metainfo(struct strbu
                          struct diff_filespec *one,
                          struct diff_filespec *two,
                          struct diff_options *o,
 -                        struct diff_filepair *p)
 +                        struct diff_filepair *p,
 +                        int use_color)
  {
 +      const char *set = diff_get_color(use_color, DIFF_METAINFO);
 +      const char *reset = diff_get_color(use_color, DIFF_RESET);
 +
        strbuf_init(msg, PATH_MAX * 2 + 300);
        switch (p->status) {
        case DIFF_STATUS_COPIED:
 -              strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
 -              strbuf_addstr(msg, "\ncopy from ");
 +              strbuf_addf(msg, "%ssimilarity index %d%%",
 +                          set, similarity_index(p));
 +              strbuf_addf(msg, "%s\n%scopy from ", reset, set);
                quote_c_style(name, msg, NULL, 0);
 -              strbuf_addstr(msg, "\ncopy to ");
 +              strbuf_addf(msg, "%s\n%scopy to ", reset, set);
                quote_c_style(other, msg, NULL, 0);
 -              strbuf_addch(msg, '\n');
 +              strbuf_addf(msg, "%s\n", reset);
                break;
        case DIFF_STATUS_RENAMED:
 -              strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
 -              strbuf_addstr(msg, "\nrename from ");
 +              strbuf_addf(msg, "%ssimilarity index %d%%",
 +                          set, similarity_index(p));
 +              strbuf_addf(msg, "%s\n%srename from ", reset, set);
                quote_c_style(name, msg, NULL, 0);
 -              strbuf_addstr(msg, "\nrename to ");
 +              strbuf_addf(msg, "%s\n%srename to ", reset, set);
                quote_c_style(other, msg, NULL, 0);
 -              strbuf_addch(msg, '\n');
 +              strbuf_addf(msg, "%s\n", reset);
                break;
        case DIFF_STATUS_MODIFIED:
                if (p->score) {
 -                      strbuf_addf(msg, "dissimilarity index %d%%\n",
 -                                  similarity_index(p));
 +                      strbuf_addf(msg, "%sdissimilarity index %d%%%s\n",
 +                                  set, similarity_index(p), reset);
                        break;
                }
                /* fallthru */
                            (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
                                abbrev = 40;
                }
 -              strbuf_addf(msg, "index %.*s..%.*s",
 +              strbuf_addf(msg, "%sindex %.*s..%.*s", set,
                            abbrev, sha1_to_hex(one->sha1),
                            abbrev, sha1_to_hex(two->sha1));
                if (one->mode == two->mode)
                        strbuf_addf(msg, " %06o", one->mode);
 -              strbuf_addch(msg, '\n');
 +              strbuf_addf(msg, "%s\n", reset);
        }
 -      if (msg->len)
 -              strbuf_setlen(msg, msg->len - 1);
  }
  
  static void run_diff_cmd(const char *pgm,
        const char *xfrm_msg = NULL;
        int complete_rewrite = (p->status == DIFF_STATUS_MODIFIED) && p->score;
  
 -      if (msg) {
 -              fill_metainfo(msg, name, other, one, two, o, p);
 -              xfrm_msg = msg->len ? msg->buf : NULL;
 -      }
 -
        if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
                pgm = NULL;
        else {
                        pgm = drv->external;
        }
  
 +      if (msg) {
 +              /*
 +               * don't use colors when the header is intended for an
 +               * external diff driver
 +               */
 +              fill_metainfo(msg, name, other, one, two, o, p,
 +                            DIFF_OPT_TST(o, COLOR_DIFF) && !pgm);
 +              xfrm_msg = msg->len ? msg->buf : NULL;
 +      }
 +
        if (pgm) {
                run_external_diff(pgm, name, other, one, two, xfrm_msg,
                                  complete_rewrite);
@@@ -2609,7 -2528,6 +2614,7 @@@ static void run_checkdiff(struct diff_f
  void diff_setup(struct diff_options *options)
  {
        memset(options, 0, sizeof(*options));
 +      memset(&diff_queued_diff, 0, sizeof(diff_queued_diff));
  
        options->file = stdout;
  
                DIFF_OPT_SET(options, COLOR_DIFF);
        options->detect_rename = diff_detect_rename_default;
  
-       if (!diff_mnemonic_prefix) {
+       if (diff_no_prefix) {
+               options->a_prefix = options->b_prefix = "";
+       } else if (!diff_mnemonic_prefix) {
                options->a_prefix = "a/";
                options->b_prefix = "b/";
        }
@@@ -2788,7 -2708,7 +2795,7 @@@ int diff_opt_parse(struct diff_options 
        const char *arg = av[0];
  
        /* Output format options */
 -      if (!strcmp(arg, "-p") || !strcmp(arg, "-u"))
 +      if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch"))
                options->output_format |= DIFF_FORMAT_PATCH;
        else if (opt_arg(arg, 'U', "unified", &options->context))
                options->output_format |= DIFF_FORMAT_PATCH;
                DIFF_OPT_CLR(options, COLOR_DIFF);
        else if (!strcmp(arg, "--color-words")) {
                DIFF_OPT_SET(options, COLOR_DIFF);
 -              DIFF_OPT_SET(options, COLOR_DIFF_WORDS);
 +              options->word_diff = DIFF_WORDS_COLOR;
        }
        else if (!prefixcmp(arg, "--color-words=")) {
                DIFF_OPT_SET(options, COLOR_DIFF);
 -              DIFF_OPT_SET(options, COLOR_DIFF_WORDS);
 +              options->word_diff = DIFF_WORDS_COLOR;
                options->word_regex = arg + 14;
        }
 +      else if (!strcmp(arg, "--word-diff")) {
 +              if (options->word_diff == DIFF_WORDS_NONE)
 +                      options->word_diff = DIFF_WORDS_PLAIN;
 +      }
 +      else if (!prefixcmp(arg, "--word-diff=")) {
 +              const char *type = arg + 12;
 +              if (!strcmp(type, "plain"))
 +                      options->word_diff = DIFF_WORDS_PLAIN;
 +              else if (!strcmp(type, "color")) {
 +                      DIFF_OPT_SET(options, COLOR_DIFF);
 +                      options->word_diff = DIFF_WORDS_COLOR;
 +              }
 +              else if (!strcmp(type, "porcelain"))
 +                      options->word_diff = DIFF_WORDS_PORCELAIN;
 +              else if (!strcmp(type, "none"))
 +                      options->word_diff = DIFF_WORDS_NONE;
 +              else
 +                      die("bad --word-diff argument: %s", type);
 +      }
 +      else if (!prefixcmp(arg, "--word-diff-regex=")) {
 +              if (options->word_diff == DIFF_WORDS_NONE)
 +                      options->word_diff = DIFF_WORDS_PLAIN;
 +              options->word_regex = arg + 18;
 +      }
        else if (!strcmp(arg, "--exit-code"))
                DIFF_OPT_SET(options, EXIT_WITH_STATUS);
        else if (!strcmp(arg, "--quiet"))
@@@ -3530,7 -3426,7 +3537,7 @@@ static int diff_get_patch_id(struct dif
                                        len2, p->two->path);
                git_SHA1_Update(&ctx, buffer, len1);
  
 -              xpp.flags = XDF_NEED_MINIMAL;
 +              xpp.flags = 0;
                xecfg.ctxlen = 3;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
                xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
@@@ -3551,7 -3447,8 +3558,7 @@@ int diff_flush_patch_id(struct diff_opt
                diff_free_filepair(q->queue[i]);
  
        free(q->queue);
 -      q->queue = NULL;
 -      q->nr = q->alloc = 0;
 +      DIFF_QUEUE_CLEAR(q);
  
        return result;
  }
@@@ -3679,7 -3576,8 +3686,7 @@@ void diff_flush(struct diff_options *op
                diff_free_filepair(q->queue[i]);
  free_queue:
        free(q->queue);
 -      q->queue = NULL;
 -      q->nr = q->alloc = 0;
 +      DIFF_QUEUE_CLEAR(q);
        if (options->close_file)
                fclose(options->file);
  
@@@ -3701,7 -3599,8 +3708,7 @@@ static void diffcore_apply_filter(cons
        int i;
        struct diff_queue_struct *q = &diff_queued_diff;
        struct diff_queue_struct outq;
 -      outq.queue = NULL;
 -      outq.nr = outq.alloc = 0;
 +      DIFF_QUEUE_CLEAR(&outq);
  
        if (!filter)
                return;
@@@ -3769,7 -3668,8 +3776,7 @@@ static void diffcore_skip_stat_unmatch(
        int i;
        struct diff_queue_struct *q = &diff_queued_diff;
        struct diff_queue_struct outq;
 -      outq.queue = NULL;
 -      outq.nr = outq.alloc = 0;
 +      DIFF_QUEUE_CLEAR(&outq);
  
        for (i = 0; i < q->nr; i++) {
                struct diff_filepair *p = q->queue[i];
@@@ -3830,12 -3730,6 +3837,12 @@@ void diffcore_fix_diff_index(struct dif
  
  void diffcore_std(struct diff_options *options)
  {
 +      /* We never run this function more than one time, because the
 +       * rename/copy detection logic can only run once.
 +       */
 +      if (diff_queued_diff.run)
 +              return;
 +
        if (options->skip_stat_unmatch)
                diffcore_skip_stat_unmatch(options);
        if (options->break_opt != -1)
                DIFF_OPT_SET(options, HAS_CHANGES);
        else
                DIFF_OPT_CLR(options, HAS_CHANGES);
 +
 +      diff_queued_diff.run = 1;
  }
  
  int diff_result_code(struct diff_options *opt, int status)