Merge branch 'es/format-patch-interdiff'
authorJunio C Hamano <gitster@pobox.com>
Mon, 17 Sep 2018 20:53:55 +0000 (13:53 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 17 Sep 2018 20:53:55 +0000 (13:53 -0700)
"git format-patch" learned a new "--interdiff" option to explain
the difference between this version and the previous atttempt in
the cover letter (or after the tree-dashes as a comment).

* es/format-patch-interdiff:
format-patch: allow --interdiff to apply to a lone-patch
log-tree: show_log: make commentary block delimiting reusable
interdiff: teach show_interdiff() to indent interdiff
format-patch: teach --interdiff to respect -v/--reroll-count
format-patch: add --interdiff option to embed diff in cover letter
format-patch: allow additional generated content in make_cover_letter()

1  2 
Makefile
builtin/log.c
log-tree.c
revision.h
diff --combined Makefile
index 7cf682001364a55a1bf68cd834fc5d0e1ad1658d,b2685190e1d9a6c0ad39bf3f5a6bd9a4e84f7273..b567ccca45883c15bc9b8dbd60abe6a88186620f
+++ b/Makefile
@@@ -484,11 -484,6 +484,11 @@@ all:
  #        The DEVELOPER mode enables -Wextra with a few exceptions. By
  #        setting this flag the exceptions are removed, and all of
  #        -Wextra is used.
 +#
 +#    pedantic:
 +#
 +#        Enable -pedantic compilation. This also disables
 +#        USE_PARENS_AROUND_GETTEXT_N to produce only relevant warnings.
  
  GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@@ -569,7 -564,7 +569,7 @@@ SPATCH = spatc
  export TCL_PATH TCLTK_PATH
  
  SPARSE_FLAGS =
 -SPATCH_FLAGS = --all-includes
 +SPATCH_FLAGS = --all-includes --patch .
  
  
  
@@@ -714,7 -709,6 +714,7 @@@ TEST_BUILTINS_OBJS += test-example-deco
  TEST_BUILTINS_OBJS += test-genrandom.o
  TEST_BUILTINS_OBJS += test-hashmap.o
  TEST_BUILTINS_OBJS += test-index-version.o
 +TEST_BUILTINS_OBJS += test-json-writer.o
  TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o
  TEST_BUILTINS_OBJS += test-match-trees.o
  TEST_BUILTINS_OBJS += test-mergesort.o
@@@ -722,12 -716,9 +722,12 @@@ TEST_BUILTINS_OBJS += test-mktemp.
  TEST_BUILTINS_OBJS += test-online-cpus.o
  TEST_BUILTINS_OBJS += test-path-utils.o
  TEST_BUILTINS_OBJS += test-prio-queue.o
 +TEST_BUILTINS_OBJS += test-reach.o
  TEST_BUILTINS_OBJS += test-read-cache.o
 +TEST_BUILTINS_OBJS += test-read-midx.o
  TEST_BUILTINS_OBJS += test-ref-store.o
  TEST_BUILTINS_OBJS += test-regex.o
 +TEST_BUILTINS_OBJS += test-repository.o
  TEST_BUILTINS_OBJS += test-revision-walking.o
  TEST_BUILTINS_OBJS += test-run-command.o
  TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
@@@ -837,7 -828,6 +837,7 @@@ LIB_OBJS += column.
  LIB_OBJS += combine-diff.o
  LIB_OBJS += commit.o
  LIB_OBJS += commit-graph.o
 +LIB_OBJS += commit-reach.o
  LIB_OBJS += compat/obstack.o
  LIB_OBJS += compat/terminal.o
  LIB_OBJS += config.o
@@@ -850,7 -840,6 +850,7 @@@ LIB_OBJS += csum-file.
  LIB_OBJS += ctype.o
  LIB_OBJS += date.o
  LIB_OBJS += decorate.o
 +LIB_OBJS += delta-islands.o
  LIB_OBJS += diffcore-break.o
  LIB_OBJS += diffcore-delta.o
  LIB_OBJS += diffcore-order.o
@@@ -870,7 -859,6 +870,7 @@@ LIB_OBJS += ewah/ewah_bitmap.
  LIB_OBJS += ewah/ewah_io.o
  LIB_OBJS += ewah/ewah_rlw.o
  LIB_OBJS += exec-cmd.o
 +LIB_OBJS += fetch-negotiator.o
  LIB_OBJS += fetch-object.o
  LIB_OBJS += fetch-pack.o
  LIB_OBJS += fsck.o
@@@ -880,11 -868,10 +880,12 @@@ LIB_OBJS += gpg-interface.
  LIB_OBJS += graph.o
  LIB_OBJS += grep.o
  LIB_OBJS += hashmap.o
 +LIB_OBJS += linear-assignment.o
  LIB_OBJS += help.o
  LIB_OBJS += hex.o
  LIB_OBJS += ident.o
+ LIB_OBJS += interdiff.o
 +LIB_OBJS += json-writer.o
  LIB_OBJS += kwset.o
  LIB_OBJS += levenshtein.o
  LIB_OBJS += line-log.o
@@@ -904,10 -891,7 +905,10 @@@ LIB_OBJS += merge.
  LIB_OBJS += merge-blobs.o
  LIB_OBJS += merge-recursive.o
  LIB_OBJS += mergesort.o
 +LIB_OBJS += midx.o
  LIB_OBJS += name-hash.o
 +LIB_OBJS += negotiator/default.o
 +LIB_OBJS += negotiator/skipping.o
  LIB_OBJS += notes.o
  LIB_OBJS += notes-cache.o
  LIB_OBJS += notes-merge.o
@@@ -937,7 -921,6 +938,7 @@@ LIB_OBJS += progress.
  LIB_OBJS += prompt.o
  LIB_OBJS += protocol.o
  LIB_OBJS += quote.o
 +LIB_OBJS += range-diff.o
  LIB_OBJS += reachable.o
  LIB_OBJS += read-cache.o
  LIB_OBJS += reflog-walk.o
@@@ -1065,7 -1048,6 +1066,7 @@@ BUILTIN_OBJS += builtin/merge-recursive
  BUILTIN_OBJS += builtin/merge-tree.o
  BUILTIN_OBJS += builtin/mktag.o
  BUILTIN_OBJS += builtin/mktree.o
 +BUILTIN_OBJS += builtin/multi-pack-index.o
  BUILTIN_OBJS += builtin/mv.o
  BUILTIN_OBJS += builtin/name-rev.o
  BUILTIN_OBJS += builtin/notes.o
@@@ -1077,7 -1059,6 +1078,7 @@@ BUILTIN_OBJS += builtin/prune-packed.
  BUILTIN_OBJS += builtin/prune.o
  BUILTIN_OBJS += builtin/pull.o
  BUILTIN_OBJS += builtin/push.o
 +BUILTIN_OBJS += builtin/range-diff.o
  BUILTIN_OBJS += builtin/read-tree.o
  BUILTIN_OBJS += builtin/rebase--helper.o
  BUILTIN_OBJS += builtin/receive-pack.o
@@@ -2053,7 -2034,7 +2054,7 @@@ $(BUILT_INS): git$
  
  command-list.h: generate-cmdlist.sh command-list.txt
  
 -command-list.h: $(wildcard Documentation/git*.txt)
 +command-list.h: $(wildcard Documentation/git*.txt) Documentation/*config.txt
        $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
  
  SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
@@@ -2689,16 -2670,10 +2690,16 @@@ check: command-list.
        fi
  
  C_SOURCES = $(patsubst %.o,%.c,$(C_OBJ))
 -%.cocci.patch: %.cocci $(C_SOURCES)
 +ifdef DC_SHA1_SUBMODULE
 +COCCI_SOURCES = $(filter-out sha1collisiondetection/%,$(C_SOURCES))
 +else
 +COCCI_SOURCES = $(filter-out sha1dc/%,$(C_SOURCES))
 +endif
 +
 +%.cocci.patch: %.cocci $(COCCI_SOURCES)
        @echo '    ' SPATCH $<; \
        ret=0; \
 -      for f in $(C_SOURCES); do \
 +      for f in $(COCCI_SOURCES); do \
                $(SPATCH) --sp-file $< $$f $(SPATCH_FLAGS) || \
                        { ret=$$?; break; }; \
        done >$@+ 2>$@.log; \
        then \
                echo '    ' SPATCH result: $@; \
        fi
 -coccicheck: $(patsubst %.cocci,%.cocci.patch,$(wildcard contrib/coccinelle/*.cocci))
 +coccicheck: $(addsuffix .patch,$(wildcard contrib/coccinelle/*.cocci))
 +
 +.PHONY: coccicheck
  
  ### Installation rules
  
@@@ -2926,10 -2899,7 +2927,10 @@@ profile-clean
        $(RM) $(addsuffix *.gcda,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
        $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
  
 -clean: profile-clean coverage-clean
 +cocciclean:
 +      $(RM) contrib/coccinelle/*.cocci.patch*
 +
 +clean: profile-clean coverage-clean cocciclean
        $(RM) *.res
        $(RM) $(OBJECTS)
        $(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
        $(RM) -r $(GIT_TARNAME) .doc-tmp-dir
        $(RM) $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
        $(RM) $(htmldocs).tar.gz $(manpages).tar.gz
 -      $(RM) contrib/coccinelle/*.cocci.patch*
        $(MAKE) -C Documentation/ clean
  ifndef NO_PERL
        $(MAKE) -C gitweb clean
@@@ -2956,7 -2927,7 +2957,7 @@@ endi
        $(RM) GIT-USER-AGENT GIT-PREFIX
        $(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PERL-HEADER GIT-PYTHON-VARS
  
 -.PHONY: all install profile-clean clean strip
 +.PHONY: all install profile-clean cocciclean clean strip
  .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
  .PHONY: FORCE cscope
  
diff --combined builtin/log.c
index 517c5e67890d421fd1f15fb454221eb1fa0634f4,e990027c282564e4e60f829a83b546db3604d5e5..df4201131284317948de938242c22d9862c0ffbb
@@@ -30,8 -30,7 +30,9 @@@
  #include "gpg-interface.h"
  #include "progress.h"
  #include "commit-slab.h"
 +#include "repository.h"
 +#include "commit-reach.h"
+ #include "interdiff.h"
  
  #define MAIL_DEFAULT_WRAP 72
  
@@@ -621,7 -620,7 +622,7 @@@ int cmd_show(int argc, const char **arg
                        rev.shown_one = 1;
                        if (ret)
                                break;
 -                      o = parse_object(&t->tagged->oid);
 +                      o = parse_object(the_repository, &t->tagged->oid);
                        if (!o)
                                ret = error(_("Could not read object %s"),
                                            oid_to_hex(&t->tagged->oid));
@@@ -908,8 -907,8 +909,8 @@@ static void get_patch_ids(struct rev_in
        o2 = rev->pending.objects[1].item;
        flags1 = o1->flags;
        flags2 = o2->flags;
 -      c1 = lookup_commit_reference(&o1->oid);
 -      c2 = lookup_commit_reference(&o2->oid);
 +      c1 = lookup_commit_reference(the_repository, &o1->oid);
 +      c2 = lookup_commit_reference(the_repository, &o2->oid);
  
        if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
                die(_("Not a range."));
@@@ -999,6 -998,26 +1000,26 @@@ static char *find_branch_name(struct re
        return branch;
  }
  
+ static void show_diffstat(struct rev_info *rev,
+                         struct commit *origin, struct commit *head)
+ {
+       struct diff_options opts;
+       memcpy(&opts, &rev->diffopt, sizeof(opts));
+       opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
+       opts.stat_width = MAIL_DEFAULT_WRAP;
+       diff_setup_done(&opts);
+       diff_tree_oid(get_commit_tree_oid(origin),
+                     get_commit_tree_oid(head),
+                     "", &opts);
+       diffcore_std(&opts);
+       diff_flush(&opts);
+       fprintf(rev->diffopt.file, "\n");
+ }
  static void make_cover_letter(struct rev_info *rev, int use_stdout,
                              struct commit *origin,
                              int nr, struct commit **list,
        struct strbuf sb = STRBUF_INIT;
        int i;
        const char *encoding = "UTF-8";
-       struct diff_options opts;
        int need_8bit_cte = 0;
        struct pretty_print_context pp = {0};
        struct commit *head = list[0];
  
        shortlog_output(&log);
  
-       /*
-        * We can only do diffstat with a unique reference point
-        */
-       if (!origin)
-               return;
+       /* We can only do diffstat with a unique reference point */
+       if (origin)
+               show_diffstat(rev, origin, head);
  
-       memcpy(&opts, &rev->diffopt, sizeof(opts));
-       opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
-       opts.stat_width = MAIL_DEFAULT_WRAP;
-       diff_setup_done(&opts);
-       diff_tree_oid(get_commit_tree_oid(origin),
-                     get_commit_tree_oid(head),
-                     "", &opts);
-       diffcore_std(&opts);
-       diff_flush(&opts);
-       fprintf(rev->diffopt.file, "\n");
+       if (rev->idiff_oid1) {
+               fprintf_ln(rev->diffopt.file, "%s", rev->idiff_title);
+               show_interdiff(rev, 0);
+       }
  }
  
  static const char *clean_message_id(const char *msg_id)
@@@ -1420,6 -1427,16 +1429,16 @@@ static void print_bases(struct base_tre
        oidclr(&bases->base_commit);
  }
  
+ static const char *diff_title(struct strbuf *sb, int reroll_count,
+                      const char *generic, const char *rerolled)
+ {
+       if (reroll_count <= 0)
+               strbuf_addstr(sb, generic);
+       else /* RFC may be v0, so allow -v1 to diff against v0 */
+               strbuf_addf(sb, rerolled, reroll_count - 1);
+       return sb->buf;
+ }
  int cmd_format_patch(int argc, const char **argv, const char *prefix)
  {
        struct commit *commit;
        struct base_tree_info bases;
        int show_progress = 0;
        struct progress *progress = NULL;
+       struct oid_array idiff_prev = OID_ARRAY_INIT;
+       struct strbuf idiff_title = STRBUF_INIT;
  
        const struct option builtin_format_patch_options[] = {
                { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
                OPT__QUIET(&quiet, N_("don't print the patch filenames")),
                OPT_BOOL(0, "progress", &show_progress,
                         N_("show progress while generating patches")),
+               OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"),
+                            N_("show changes against <rev> in cover letter or single patch"),
+                            parse_opt_object_name),
                OPT_END()
        };
  
                numbered = 0;
  
        if (numbered && keep_subject)
 -              die (_("-n and -k are mutually exclusive."));
 +              die(_("-n and -k are mutually exclusive"));
        if (keep_subject && subject_prefix)
 -              die (_("--subject-prefix/--rfc and -k are mutually exclusive."));
 +              die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
        rev.preserve_subject = keep_subject;
  
        argc = setup_revisions(argc, argv, &rev, &s_r_opt);
        if (argc > 1)
 -              die (_("unrecognized argument: %s"), argv[1]);
 +              die(_("unrecognized argument: %s"), argv[1]);
  
        if (rev.diffopt.output_format & DIFF_FORMAT_NAME)
                die(_("--name-only does not make sense"));
                if (rev.pending.nr == 2) {
                        struct object_array_entry *o = rev.pending.objects;
                        if (oidcmp(&o[0].item->oid, &o[1].item->oid) == 0)
-                               return 0;
+                               goto done;
                }
                get_patch_ids(&rev, &ids);
        }
        }
        if (nr == 0)
                /* nothing to do */
-               return 0;
+               goto done;
        total = nr;
        if (cover_letter == -1) {
                if (config_cover_letter == COVER_AUTO)
        if (numbered)
                rev.total = total + start_number - 1;
  
+       if (idiff_prev.nr) {
+               if (!cover_letter && total != 1)
+                       die(_("--interdiff requires --cover-letter or single patch"));
+               rev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1];
+               rev.idiff_oid2 = get_commit_tree_oid(list[0]);
+               rev.idiff_title = diff_title(&idiff_title, reroll_count,
+                                            _("Interdiff:"),
+                                            _("Interdiff against v%d:"));
+       }
        if (!signature) {
                ; /* --no-signature inhibits all signatures */
        } else if (signature && signature != git_version_string) {
                print_signature(rev.diffopt.file);
                total++;
                start_number--;
+               /* interdiff in cover-letter; omit from patches */
+               rev.idiff_oid1 = NULL;
        }
        rev.add_signoff = do_signoff;
  
        string_list_clear(&extra_hdr, 0);
        if (ignore_if_in_upstream)
                free_patch_ids(&ids);
+ done:
+       oid_array_clear(&idiff_prev);
+       strbuf_release(&idiff_title);
        return 0;
  }
  
@@@ -1866,8 -1904,7 +1906,8 @@@ static int add_pending_commit(const cha
  {
        struct object_id oid;
        if (get_oid(arg, &oid) == 0) {
 -              struct commit *commit = lookup_commit_reference(&oid);
 +              struct commit *commit = lookup_commit_reference(the_repository,
 +                                                              &oid);
                if (commit) {
                        commit->object.flags |= flags;
                        add_pending_object(revs, &commit->object, arg);
diff --combined log-tree.c
index 7443e5fcc74b7964c478327c6557d53eb4f6b425,56513fa83ddfaf72a5731ef62600bd32d09977cb..f482f47b83dc3e2a999e00c93ac089fc6de5a6b9
@@@ -2,7 -2,6 +2,7 @@@
  #include "config.h"
  #include "diff.h"
  #include "object-store.h"
 +#include "repository.h"
  #include "commit.h"
  #include "tag.h"
  #include "graph.h"
@@@ -15,6 -14,7 +15,7 @@@
  #include "sequencer.h"
  #include "line-log.h"
  #include "help.h"
+ #include "interdiff.h"
  
  static struct decoration name_decoration = { "object names" };
  static int decoration_loaded;
@@@ -92,20 -92,20 +93,20 @@@ static int add_ref_decoration(const cha
  
        if (starts_with(refname, git_replace_ref_base)) {
                struct object_id original_oid;
 -              if (!check_replace_refs)
 +              if (!read_replace_refs)
                        return 0;
                if (get_oid_hex(refname + strlen(git_replace_ref_base),
                                &original_oid)) {
                        warning("invalid replace ref %s", refname);
                        return 0;
                }
 -              obj = parse_object(&original_oid);
 +              obj = parse_object(the_repository, &original_oid);
                if (obj)
                        add_name_decoration(DECORATION_GRAFTED, "replaced", obj);
                return 0;
        }
  
 -      obj = parse_object(oid);
 +      obj = parse_object(the_repository, oid);
        if (!obj)
                return 0;
  
                if (!obj)
                        break;
                if (!obj->parsed)
 -                      parse_object(&obj->oid);
 +                      parse_object(the_repository, &obj->oid);
                add_name_decoration(DECORATION_REF_TAG, refname, obj);
        }
        return 0;
  
  static int add_graft_decoration(const struct commit_graft *graft, void *cb_data)
  {
 -      struct commit *commit = lookup_commit(&graft->oid);
 +      struct commit *commit = lookup_commit(the_repository, &graft->oid);
        if (!commit)
                return 0;
        add_name_decoration(DECORATION_GRAFTED, "grafted", &commit->object);
@@@ -498,12 -498,12 +499,12 @@@ static int show_one_mergetag(struct com
        size_t payload_size, gpg_message_offset;
  
        hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &oid);
 -      tag = lookup_tag(&oid);
 +      tag = lookup_tag(the_repository, &oid);
        if (!tag)
                return -1; /* error message already given */
  
        strbuf_init(&verify_message, 256);
 -      if (parse_tag_buffer(tag, extra->value, extra->len))
 +      if (parse_tag_buffer(the_repository, tag, extra->value, extra->len))
                strbuf_addstr(&verify_message, "malformed mergetag\n");
        else if (is_common_merge(commit) &&
                 !oidcmp(&tag->tagged->oid,
@@@ -542,12 -542,22 +543,22 @@@ static int show_mergetag(struct rev_inf
        return for_each_mergetag(show_one_mergetag, commit, opt);
  }
  
+ static void next_commentary_block(struct rev_info *opt, struct strbuf *sb)
+ {
+       const char *x = opt->shown_dashes ? "\n" : "---\n";
+       if (sb)
+               strbuf_addstr(sb, x);
+       else
+               fputs(x, opt->diffopt.file);
+       opt->shown_dashes = 1;
+ }
  void show_log(struct rev_info *opt)
  {
        struct strbuf msgbuf = STRBUF_INIT;
        struct log_info *log = opt->loginfo;
        struct commit *commit = log->commit, *parent = log->parent;
 -      int abbrev_commit = opt->abbrev_commit ? opt->abbrev : GIT_SHA1_HEXSZ;
 +      int abbrev_commit = opt->abbrev_commit ? opt->abbrev : the_hash_algo->hexsz;
        const char *extra_headers = opt->extra_headers;
        struct pretty_print_context ctx = {0};
  
  
        if ((ctx.fmt != CMIT_FMT_USERFORMAT) &&
            ctx.notes_message && *ctx.notes_message) {
-               if (cmit_fmt_is_mail(ctx.fmt)) {
-                       strbuf_addstr(&msgbuf, "---\n");
-                       opt->shown_dashes = 1;
-               }
+               if (cmit_fmt_is_mail(ctx.fmt))
+                       next_commentary_block(opt, &msgbuf);
                strbuf_addstr(&msgbuf, ctx.notes_message);
        }
  
  
        strbuf_release(&msgbuf);
        free(ctx.notes_message);
+       if (cmit_fmt_is_mail(ctx.fmt) && opt->idiff_oid1) {
+               struct diff_queue_struct dq;
+               memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
+               DIFF_QUEUE_CLEAR(&diff_queued_diff);
+               next_commentary_block(opt, NULL);
+               fprintf_ln(opt->diffopt.file, "%s", opt->idiff_title);
+               show_interdiff(opt, 2);
+               memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff));
+       }
  }
  
  int log_tree_diff_flush(struct rev_info *opt)
  
                        /*
                         * We may have shown three-dashes line early
-                        * between notes and the log message, in which
-                        * case we only want a blank line after the
-                        * notes without (an extra) three-dashes line.
+                        * between generated commentary (notes, etc.)
+                        * and the log message, in which case we only
+                        * want a blank line after the commentary
+                        * without (an extra) three-dashes line.
                         * Otherwise, we show the three-dashes line if
                         * we are showing the patch with diffstat, but
                         * in that case, there is no extra blank line
diff --combined revision.h
index 12259579271d9c51652f671b29598f09de967f0a,ffeadc261a99ba008220d2d7bbe730727bb56b06..91bc180e37dc7d7810c0ab3e883e26cbe851385a
@@@ -1,7 -1,6 +1,7 @@@
  #ifndef REVISION_H
  #define REVISION_H
  
 +#include "commit.h"
  #include "parse-options.h"
  #include "grep.h"
  #include "notes.h"
@@@ -21,9 -20,8 +21,9 @@@
  #define SYMMETRIC_LEFT        (1u<<8)
  #define PATCHSAME     (1u<<9)
  #define BOTTOM                (1u<<10)
 +#define USER_GIVEN    (1u<<25) /* given directly by the user */
  #define TRACK_LINEAR  (1u<<26)
 -#define ALL_REV_FLAGS (((1u<<11)-1) | TRACK_LINEAR)
 +#define ALL_REV_FLAGS (((1u<<11)-1) | USER_GIVEN | TRACK_LINEAR)
  
  #define DECORATE_SHORT_REFS   1
  #define DECORATE_FULL_REFS    2
@@@ -82,11 -80,6 +82,11 @@@ struct rev_info 
         */
        int rev_input_given;
  
 +      /*
 +       * Whether we read from stdin due to the --stdin option.
 +       */
 +      int read_from_stdin;
 +
        /* topo-sort */
        enum rev_sort_order sort_order;
  
        /* notes-specific options: which refs to show */
        struct display_notes_opt notes_opt;
  
+       /* interdiff */
+       const struct object_id *idiff_oid1;
+       const struct object_id *idiff_oid2;
+       const char *idiff_title;
        /* commit counts */
        int count_left;
        int count_right;
        struct revision_sources *sources;
  };
  
 -extern int ref_excluded(struct string_list *, const char *path);
 +int ref_excluded(struct string_list *, const char *path);
  void clear_ref_exclusion(struct string_list **);
  void add_ref_exclusion(struct string_list **, const char *exclude);
  
@@@ -258,39 -256,39 +263,39 @@@ struct setup_revision_opt 
        unsigned revarg_opt;
  };
  
 -extern void init_revisions(struct rev_info *revs, const char *prefix);
 -extern int setup_revisions(int argc, const char **argv, struct rev_info *revs,
 -                         struct setup_revision_opt *);
 -extern void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
 -                             const struct option *options,
 -                             const char * const usagestr[]);
 +void init_revisions(struct rev_info *revs, const char *prefix);
 +int setup_revisions(int argc, const char **argv, struct rev_info *revs,
 +                  struct setup_revision_opt *);
 +void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
 +                      const struct option *options,
 +                      const char * const usagestr[]);
  #define REVARG_CANNOT_BE_FILENAME 01
  #define REVARG_COMMITTISH 02
 -extern int handle_revision_arg(const char *arg, struct rev_info *revs,
 -                             int flags, unsigned revarg_opt);
 +int handle_revision_arg(const char *arg, struct rev_info *revs,
 +                      int flags, unsigned revarg_opt);
  
 -extern void reset_revision_walk(void);
 -extern int prepare_revision_walk(struct rev_info *revs);
 -extern struct commit *get_revision(struct rev_info *revs);
 -extern char *get_revision_mark(const struct rev_info *revs,
 -                             const struct commit *commit);
 -extern void put_revision_mark(const struct rev_info *revs,
 -                            const struct commit *commit);
 +void reset_revision_walk(void);
 +int prepare_revision_walk(struct rev_info *revs);
 +struct commit *get_revision(struct rev_info *revs);
 +char *get_revision_mark(const struct rev_info *revs,
 +                      const struct commit *commit);
 +void put_revision_mark(const struct rev_info *revs,
 +                     const struct commit *commit);
  
 -extern void mark_parents_uninteresting(struct commit *commit);
 -extern void mark_tree_uninteresting(struct tree *tree);
 +void mark_parents_uninteresting(struct commit *commit);
 +void mark_tree_uninteresting(struct tree *tree);
  
 -extern void show_object_with_name(FILE *, struct object *, const char *);
 +void show_object_with_name(FILE *, struct object *, const char *);
  
 -extern void add_pending_object(struct rev_info *revs,
 -                             struct object *obj, const char *name);
 -extern void add_pending_oid(struct rev_info *revs,
 -                          const char *name, const struct object_id *oid,
 -                          unsigned int flags);
 +void add_pending_object(struct rev_info *revs,
 +                      struct object *obj, const char *name);
 +void add_pending_oid(struct rev_info *revs,
 +                   const char *name, const struct object_id *oid,
 +                   unsigned int flags);
  
 -extern void add_head_to_pending(struct rev_info *);
 -extern void add_reflogs_to_pending(struct rev_info *, unsigned int flags);
 -extern void add_index_objects_to_pending(struct rev_info *, unsigned int flags);
 +void add_head_to_pending(struct rev_info *);
 +void add_reflogs_to_pending(struct rev_info *, unsigned int flags);
 +void add_index_objects_to_pending(struct rev_info *, unsigned int flags);
  
  enum commit_action {
        commit_ignore,
        commit_error
  };
  
 -extern enum commit_action get_commit_action(struct rev_info *revs,
 -                                          struct commit *commit);
 -extern enum commit_action simplify_commit(struct rev_info *revs,
 -                                        struct commit *commit);
 +enum commit_action get_commit_action(struct rev_info *revs,
 +                                   struct commit *commit);
 +enum commit_action simplify_commit(struct rev_info *revs,
 +                                 struct commit *commit);
  
  enum rewrite_result {
        rewrite_one_ok,
  
  typedef enum rewrite_result (*rewrite_parent_fn_t)(struct rev_info *revs, struct commit **pp);
  
 -extern int rewrite_parents(struct rev_info *revs, struct commit *commit,
 -      rewrite_parent_fn_t rewrite_parent);
 +int rewrite_parents(struct rev_info *revs,
 +                  struct commit *commit,
 +                  rewrite_parent_fn_t rewrite_parent);
  
  /*
   * The log machinery saves the original parent list so that
   * get_saved_parents() will transparently return commit->parents if
   * history simplification is off.
   */
 -extern struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit);
 +struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit);
  
  #endif