Merge branch 'nd/diff-with-path-params'
authorJunio C Hamano <gitster@pobox.com>
Wed, 3 Feb 2016 22:16:04 +0000 (14:16 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Feb 2016 22:16:04 +0000 (14:16 -0800)
A few options of "git diff" did not work well when the command was
run from a subdirectory.

* nd/diff-with-path-params:
diff: make -O and --output work in subdirectory
diff-no-index: do not take a redundant prefix argument

1  2 
builtin/am.c
builtin/diff.c
diff-no-index.c
diff.c
diff.h
revision.c
diff --combined builtin/am.c
index b55f903f058047bc59773dd691892c621351f9ba,919bd91b0ffc87c9b6857fa8ad761d39d70c9e56..259dc1cd117ec18d37d4199873c11bbf70ad6dfb
@@@ -27,7 -27,6 +27,7 @@@
  #include "notes-utils.h"
  #include "rerere.h"
  #include "prompt.h"
 +#include "mailinfo.h"
  
  /**
   * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@@ -45,6 -44,21 +45,6 @@@ static int is_empty_file(const char *fi
        return !st.st_size;
  }
  
 -/**
 - * Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators.
 - */
 -static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
 -{
 -      if (strbuf_getwholeline(sb, fp, '\n'))
 -              return EOF;
 -      if (sb->buf[sb->len - 1] == '\n') {
 -              strbuf_setlen(sb, sb->len - 1);
 -              if (sb->len > 0 && sb->buf[sb->len - 1] == '\r')
 -                      strbuf_setlen(sb, sb->len - 1);
 -      }
 -      return 0;
 -}
 -
  /**
   * Returns the length of the first line of msg.
   */
@@@ -269,7 -283,7 +269,7 @@@ static char *read_shell_var(FILE *fp, c
        struct strbuf sb = STRBUF_INIT;
        const char *str;
  
 -      if (strbuf_getline(&sb, fp, '\n'))
 +      if (strbuf_getline_lf(&sb, fp))
                goto fail;
  
        if (!skip_prefix(sb.buf, key, &str))
@@@ -558,7 -572,7 +558,7 @@@ static int copy_notes_for_rebase(const 
  
        fp = xfopen(am_path(state, "rewritten"), "r");
  
 -      while (!strbuf_getline(&sb, fp, '\n')) {
 +      while (!strbuf_getline_lf(&sb, fp)) {
                unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ];
  
                if (sb.len != GIT_SHA1_HEXSZ * 2 + 1) {
@@@ -613,7 -627,7 +613,7 @@@ static int is_mail(FILE *fp
        if (regcomp(&regex, header_regex, REG_NOSUB | REG_EXTENDED))
                die("invalid pattern: %s", header_regex);
  
 -      while (!strbuf_getline_crlf(&sb, fp)) {
 +      while (!strbuf_getline(&sb, fp)) {
                if (!sb.len)
                        break; /* End of header */
  
@@@ -660,7 -674,7 +660,7 @@@ static int detect_patch_format(const ch
  
        fp = xfopen(*paths, "r");
  
 -      while (!strbuf_getline_crlf(&l1, fp)) {
 +      while (!strbuf_getline(&l1, fp)) {
                if (l1.len)
                        break;
        }
        }
  
        strbuf_reset(&l2);
 -      strbuf_getline_crlf(&l2, fp);
 +      strbuf_getline(&l2, fp);
        strbuf_reset(&l3);
 -      strbuf_getline_crlf(&l3, fp);
 +      strbuf_getline(&l3, fp);
  
        /*
         * If the second line is empty and the third is a From, Author or Date
@@@ -802,7 -816,7 +802,7 @@@ static int stgit_patch_to_mail(FILE *ou
        struct strbuf sb = STRBUF_INIT;
        int subject_printed = 0;
  
 -      while (!strbuf_getline(&sb, in, '\n')) {
 +      while (!strbuf_getline_lf(&sb, in)) {
                const char *str;
  
                if (str_isspace(sb.buf))
@@@ -860,7 -874,7 +860,7 @@@ static int split_mail_stgit_series(stru
                return error(_("could not open '%s' for reading: %s"), *paths,
                                strerror(errno));
  
 -      while (!strbuf_getline(&sb, fp, '\n')) {
 +      while (!strbuf_getline_lf(&sb, fp)) {
                if (*sb.buf == '#')
                        continue; /* skip comment lines */
  
@@@ -885,7 -899,7 +885,7 @@@ static int hg_patch_to_mail(FILE *out, 
  {
        struct strbuf sb = STRBUF_INIT;
  
 -      while (!strbuf_getline(&sb, in, '\n')) {
 +      while (!strbuf_getline_lf(&sb, in)) {
                const char *str;
  
                if (skip_prefix(sb.buf, "# User ", &str))
@@@ -1244,65 -1258,62 +1244,65 @@@ static void am_append_signoff(struct am
  static int parse_mail(struct am_state *state, const char *mail)
  {
        FILE *fp;
 -      struct child_process cp = CHILD_PROCESS_INIT;
        struct strbuf sb = STRBUF_INIT;
        struct strbuf msg = STRBUF_INIT;
        struct strbuf author_name = STRBUF_INIT;
        struct strbuf author_date = STRBUF_INIT;
        struct strbuf author_email = STRBUF_INIT;
        int ret = 0;
 +      struct mailinfo mi;
  
 -      cp.git_cmd = 1;
 -      cp.in = xopen(mail, O_RDONLY, 0);
 -      cp.out = xopen(am_path(state, "info"), O_WRONLY | O_CREAT, 0777);
 +      setup_mailinfo(&mi);
  
 -      argv_array_push(&cp.args, "mailinfo");
 -      argv_array_push(&cp.args, state->utf8 ? "-u" : "-n");
 +      if (state->utf8)
 +              mi.metainfo_charset = get_commit_output_encoding();
 +      else
 +              mi.metainfo_charset = NULL;
  
        switch (state->keep) {
        case KEEP_FALSE:
                break;
        case KEEP_TRUE:
 -              argv_array_push(&cp.args, "-k");
 +              mi.keep_subject = 1;
                break;
        case KEEP_NON_PATCH:
 -              argv_array_push(&cp.args, "-b");
 +              mi.keep_non_patch_brackets_in_subject = 1;
                break;
        default:
                die("BUG: invalid value for state->keep");
        }
  
        if (state->message_id)
 -              argv_array_push(&cp.args, "-m");
 +              mi.add_message_id = 1;
  
        switch (state->scissors) {
        case SCISSORS_UNSET:
                break;
        case SCISSORS_FALSE:
 -              argv_array_push(&cp.args, "--no-scissors");
 +              mi.use_scissors = 0;
                break;
        case SCISSORS_TRUE:
 -              argv_array_push(&cp.args, "--scissors");
 +              mi.use_scissors = 1;
                break;
        default:
                die("BUG: invalid value for state->scissors");
        }
  
 -      argv_array_push(&cp.args, am_path(state, "msg"));
 -      argv_array_push(&cp.args, am_path(state, "patch"));
 -
 -      if (run_command(&cp) < 0)
 +      mi.input = fopen(mail, "r");
 +      if (!mi.input)
 +              die("could not open input");
 +      mi.output = fopen(am_path(state, "info"), "w");
 +      if (!mi.output)
 +              die("could not open output 'info'");
 +      if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
                die("could not parse patch");
  
 -      close(cp.in);
 -      close(cp.out);
 +      fclose(mi.input);
 +      fclose(mi.output);
  
        /* Extract message and author information */
        fp = xfopen(am_path(state, "info"), "r");
 -      while (!strbuf_getline(&sb, fp, '\n')) {
 +      while (!strbuf_getline_lf(&sb, fp)) {
                const char *x;
  
                if (skip_prefix(sb.buf, "Subject: ", &x)) {
        }
  
        strbuf_addstr(&msg, "\n\n");
 -      if (strbuf_read_file(&msg, am_path(state, "msg"), 0) < 0)
 -              die_errno(_("could not read '%s'"), am_path(state, "msg"));
 +      strbuf_addbuf(&msg, &mi.log_message);
        strbuf_stripspace(&msg, 0);
  
        if (state->signoff)
@@@ -1354,7 -1366,6 +1354,7 @@@ finish
        strbuf_release(&author_email);
        strbuf_release(&author_name);
        strbuf_release(&sb);
 +      clear_mailinfo(&mi);
        return ret;
  }
  
@@@ -1368,7 -1379,7 +1368,7 @@@ static int get_mail_commit_sha1(unsigne
        FILE *fp = xfopen(mail, "r");
        const char *x;
  
 -      if (strbuf_getline(&sb, fp, '\n'))
 +      if (strbuf_getline_lf(&sb, fp))
                return -1;
  
        if (!skip_prefix(sb.buf, "From ", &x))
@@@ -1426,7 -1437,7 +1426,7 @@@ static void get_commit_info(struct am_s
        assert(!state->msg);
        msg = strstr(buffer, "\n\n");
        if (!msg)
 -              die(_("unable to parse commit %s"), sha1_to_hex(commit->object.sha1));
 +              die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid));
        state->msg = xstrdup(msg + 2);
        state->msg_len = strlen(state->msg);
  }
@@@ -1642,7 -1653,7 +1642,7 @@@ static int fall_back_threeway(const str
  
                init_revisions(&rev_info, NULL);
                rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
-               diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1);
+               diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix);
                add_pending_sha1(&rev_info, "HEAD", our_tree, 0);
                diff_setup_done(&rev_info.diffopt);
                run_diff_index(&rev_info, 1);
@@@ -1924,7 -1935,6 +1924,7 @@@ next
         */
        if (!state->rebasing) {
                am_destroy(state);
 +              close_all_packs();
                run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
        }
  }
diff --combined builtin/diff.c
index ed0acca91fb870d3f773779b34f4e24c401945e5,7b9917b03e63cab68cb18a006bb1d06c2012818e..52c98a9217c60a60f0012dbdafbb193e78ec8a33
@@@ -175,8 -175,8 +175,8 @@@ static int builtin_diff_tree(struct rev
         */
        if (ent1->item->flags & UNINTERESTING)
                swap = 1;
 -      sha1[swap] = ent0->item->sha1;
 -      sha1[1 - swap] = ent1->item->sha1;
 +      sha1[swap] = ent0->item->oid.hash;
 +      sha1[1 - swap] = ent1->item->oid.hash;
        diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt);
        log_tree_diff_flush(revs);
        return 0;
@@@ -196,8 -196,8 +196,8 @@@ static int builtin_diff_combined(struc
        if (!revs->dense_combined_merges && !revs->combine_merges)
                revs->dense_combined_merges = revs->combine_merges = 1;
        for (i = 1; i < ents; i++)
 -              sha1_array_append(&parents, ent[i].item->sha1);
 -      diff_tree_combined(ent[0].item->sha1, &parents,
 +              sha1_array_append(&parents, ent[i].item->oid.hash);
 +      diff_tree_combined(ent[0].item->oid.hash, &parents,
                           revs->dense_combined_merges, revs);
        sha1_array_clear(&parents);
        return 0;
@@@ -341,7 -341,7 +341,7 @@@ int cmd_diff(int argc, const char **arg
        }
        if (no_index)
                /* If this is a no-index diff, just run it and exit there. */
-               diff_no_index(&rev, argc, argv, prefix);
+               diff_no_index(&rev, argc, argv);
  
        /* Otherwise, we are doing the usual "git" diff */
        rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
                const char *name = entry->name;
                int flags = (obj->flags & UNINTERESTING);
                if (!obj->parsed)
 -                      obj = parse_object(obj->sha1);
 +                      obj = parse_object(obj->oid.hash);
                obj = deref_tag(obj, NULL, 0);
                if (!obj)
                        die(_("invalid object '%s' given."), name);
                } else if (obj->type == OBJ_BLOB) {
                        if (2 <= blobs)
                                die(_("more than two blobs given: '%s'"), name);
 -                      hashcpy(blob[blobs].sha1, obj->sha1);
 +                      hashcpy(blob[blobs].sha1, obj->oid.hash);
                        blob[blobs].name = name;
                        blob[blobs].mode = entry->mode;
                        blobs++;
diff --combined diff-no-index.c
index 8e0fd270b5be4d9ab8616ab57202862dd2fc6eda,95057b7a7f2651d351ef569488d646c983ecdb75..03daadb25af835a695c7d0baf466b0e1f82b58c4
@@@ -136,13 -136,15 +136,13 @@@ static int queue_diff(struct diff_optio
  
                if (name1) {
                        strbuf_addstr(&buffer1, name1);
 -                      if (buffer1.len && buffer1.buf[buffer1.len - 1] != '/')
 -                              strbuf_addch(&buffer1, '/');
 +                      strbuf_complete(&buffer1, '/');
                        len1 = buffer1.len;
                }
  
                if (name2) {
                        strbuf_addstr(&buffer2, name2);
 -                      if (buffer2.len && buffer2.buf[buffer2.len - 1] != '/')
 -                              strbuf_addch(&buffer2, '/');
 +                      strbuf_complete(&buffer2, '/');
                        len2 = buffer2.len;
                }
  
@@@ -237,12 -239,12 +237,12 @@@ static void fixup_paths(const char **pa
  }
  
  void diff_no_index(struct rev_info *revs,
-                  int argc, const char **argv,
-                  const char *prefix)
+                  int argc, const char **argv)
  {
        int i, prefixlen;
        const char *paths[2];
        struct strbuf replacement = STRBUF_INIT;
+       const char *prefix = revs->prefix;
  
        diff_setup(&revs->diffopt);
        for (i = 1; i < argc - 2; ) {
                else if (!strcmp(argv[i], "--"))
                        i++;
                else {
-                       j = diff_opt_parse(&revs->diffopt, argv + i, argc - i);
+                       j = diff_opt_parse(&revs->diffopt, argv + i, argc - i,
+                                          revs->prefix);
                        if (j <= 0)
                                die("invalid diff option/value: %s", argv[i]);
                        i += j;
diff --combined diff.c
index 80eb0c2156a0f3727f8a9598f3e83233224539b0,93e9533389fc087317453993376e304e70d571ad..2136b6970b3a9751a3ec420bac61e9baa08df9b0
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -13,6 -13,7 +13,6 @@@
  #include "run-command.h"
  #include "utf8.h"
  #include "userdiff.h"
 -#include "sigchain.h"
  #include "submodule-config.h"
  #include "submodule.h"
  #include "ll-merge.h"
@@@ -321,7 -322,7 +321,7 @@@ static struct diff_tempfile 
         */
        const char *name;
  
 -      char hex[41];
 +      char hex[GIT_SHA1_HEXSZ + 1];
        char mode[10];
  
        /*
@@@ -2881,8 -2882,9 +2881,8 @@@ static void prep_temp_blob(const char *
                die_errno("unable to write temp-file");
        close_tempfile(&temp->tempfile);
        temp->name = get_tempfile_path(&temp->tempfile);
 -      strcpy(temp->hex, sha1_to_hex(sha1));
 -      temp->hex[40] = 0;
 -      sprintf(temp->mode, "%06o", mode);
 +      sha1_to_hex_r(temp->hex, sha1);
 +      xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode);
        strbuf_release(&buf);
        strbuf_release(&template);
        free(path_dup);
@@@ -2899,8 -2901,8 +2899,8 @@@ static struct diff_tempfile *prepare_te
                 * a '+' entry produces this for file-1.
                 */
                temp->name = "/dev/null";
 -              strcpy(temp->hex, ".");
 -              strcpy(temp->mode, ".");
 +              xsnprintf(temp->hex, sizeof(temp->hex), ".");
 +              xsnprintf(temp->mode, sizeof(temp->mode), ".");
                return temp;
        }
  
                        /* we can borrow from the file in the work tree */
                        temp->name = name;
                        if (!one->sha1_valid)
 -                              strcpy(temp->hex, sha1_to_hex(null_sha1));
 +                              sha1_to_hex_r(temp->hex, null_sha1);
                        else
 -                              strcpy(temp->hex, sha1_to_hex(one->sha1));
 +                              sha1_to_hex_r(temp->hex, one->sha1);
                        /* Even though we may sometimes borrow the
                         * contents from the work tree, we always want
                         * one->mode.  mode is trustworthy even when
                         * !(one->sha1_valid), as long as
                         * DIFF_FILE_VALID(one).
                         */
 -                      sprintf(temp->mode, "%06o", one->mode);
 +                      xsnprintf(temp->mode, sizeof(temp->mode), "%06o", one->mode);
                }
                return temp;
        }
@@@ -3693,12 -3695,16 +3693,16 @@@ static int parse_ws_error_highlight(str
        return 1;
  }
  
- int diff_opt_parse(struct diff_options *options, const char **av, int ac)
+ int diff_opt_parse(struct diff_options *options,
+                  const char **av, int ac, const char *prefix)
  {
        const char *arg = av[0];
        const char *optarg;
        int argcount;
  
+       if (!prefix)
+               prefix = "";
        /* Output format options */
        if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch")
            || opt_arg(arg, 'U', "unified", &options->context))
        else if (!strcmp(arg, "--pickaxe-regex"))
                options->pickaxe_opts |= DIFF_PICKAXE_REGEX;
        else if ((argcount = short_opt('O', av, &optarg))) {
-               options->orderfile = optarg;
+               const char *path = prefix_filename(prefix, strlen(prefix), optarg);
+               options->orderfile = xstrdup(path);
                return argcount;
        }
        else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
        else if (!strcmp(arg, "--no-function-context"))
                DIFF_OPT_CLR(options, FUNCCONTEXT);
        else if ((argcount = parse_long_opt("output", av, &optarg))) {
-               options->file = fopen(optarg, "w");
+               const char *path = prefix_filename(prefix, strlen(prefix), optarg);
+               options->file = fopen(path, "w");
                if (!options->file)
-                       die_errno("Could not open '%s'", optarg);
+                       die_errno("Could not open '%s'", path);
                options->close_file = 1;
                return argcount;
        } else
@@@ -4083,9 -4091,9 +4089,9 @@@ const char *diff_unique_abbrev(const un
        if (abblen < 37) {
                static char hex[41];
                if (len < abblen && abblen <= len + 2)
 -                      sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
 +                      xsnprintf(hex, sizeof(hex), "%s%.*s", abbrev, len+3-abblen, "..");
                else
 -                      sprintf(hex, "%s...", abbrev);
 +                      xsnprintf(hex, sizeof(hex), "%s...", abbrev);
                return hex;
        }
        return sha1_to_hex(sha1);
diff --combined diff.h
index 893f4465176686c4cf4505e43fc6879762ed8121,76b5536edb4a1079ff4e30f96699f9ed2fcbe2c5..70b2d70d64e1e47da617f51b8385870a22e92f40
--- 1/diff.h
--- 2/diff.h
+++ b/diff.h
@@@ -91,7 -91,7 +91,7 @@@ typedef struct strbuf *(*diff_prefix_fn
  #define DIFF_OPT_DIRSTAT_BY_LINE     (1 << 28)
  #define DIFF_OPT_FUNCCONTEXT         (1 << 29)
  #define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)
 -#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1 << 31)
 +#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1U << 31)
  
  #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
  #define DIFF_OPT_TOUCHED(opts, flag)    ((opts)->touched_flags & DIFF_OPT_##flag)
@@@ -268,7 -268,7 +268,7 @@@ extern int parse_long_opt(const char *o
  extern int git_diff_basic_config(const char *var, const char *value, void *cb);
  extern int git_diff_ui_config(const char *var, const char *value, void *cb);
  extern void diff_setup(struct diff_options *);
- extern int diff_opt_parse(struct diff_options *, const char **, int);
+ extern int diff_opt_parse(struct diff_options *, const char **, int, const char *);
  extern void diff_setup_done(struct diff_options *);
  
  #define DIFF_DETECT_RENAME    1
@@@ -345,7 -345,7 +345,7 @@@ extern int diff_flush_patch_id(struct d
  
  extern int diff_result_code(struct diff_options *, int);
  
- extern void diff_no_index(struct rev_info *, int, const char **, const char *);
+ extern void diff_no_index(struct rev_info *, int, const char **);
  
  extern int index_differs_from(const char *def, int diff_flags);
  
diff --combined revision.c
index 8df4e117ff0321d73f521cec49285dba638451e9,47e38b6c4648373c58d5d659838101a55e4b79d5..f24ead53d537b05d7819ce53b45b05a15ec60a96
@@@ -38,7 -38,7 +38,7 @@@ char *path_name(const struct name_path 
        }
        n = xmalloc(len);
        m = n + len - (nlen + 1);
 -      strcpy(m, name);
 +      memcpy(m, name, nlen + 1);
        for (p = path; p; p = p->up) {
                if (p->elem_len) {
                        m -= p->elem_len + 1;
@@@ -86,7 -86,7 +86,7 @@@ void show_object_with_name(FILE *out, s
        leaf.elem = component;
        leaf.elem_len = strlen(component);
  
 -      fprintf(out, "%s ", sha1_to_hex(obj->sha1));
 +      fprintf(out, "%s ", oid_to_hex(&obj->oid));
        show_path_truncated(out, &leaf);
        fputc('\n', out);
  }
@@@ -106,10 -106,10 +106,10 @@@ static void mark_tree_contents_unintere
        struct name_entry entry;
        struct object *obj = &tree->object;
  
 -      if (!has_sha1_file(obj->sha1))
 +      if (!has_object_file(&obj->oid))
                return;
        if (parse_tree(tree) < 0)
 -              die("bad tree %s", sha1_to_hex(obj->sha1));
 +              die("bad tree %s", oid_to_hex(&obj->oid));
  
        init_tree_desc(&desc, tree->buffer, tree->size);
        while (tree_entry(&desc, &entry)) {
@@@ -166,7 -166,7 +166,7 @@@ void mark_parents_uninteresting(struct 
                         * it is popped next time around, we won't be trying
                         * to parse it and get an error.
                         */
 -                      if (!has_sha1_file(commit->object.sha1))
 +                      if (!has_object_file(&commit->object.oid))
                                commit->object.parsed = 1;
  
                        if (commit->object.flags & UNINTERESTING)
@@@ -284,11 -284,11 +284,11 @@@ static struct commit *handle_commit(str
                        add_pending_object(revs, object, tag->tag);
                if (!tag->tagged)
                        die("bad tag");
 -              object = parse_object(tag->tagged->sha1);
 +              object = parse_object(tag->tagged->oid.hash);
                if (!object) {
                        if (flags & UNINTERESTING)
                                return NULL;
 -                      die("bad object %s", sha1_to_hex(tag->tagged->sha1));
 +                      die("bad object %s", oid_to_hex(&tag->tagged->oid));
                }
                object->flags |= flags;
                /*
@@@ -511,7 -511,7 +511,7 @@@ static int rev_compare_tree(struct rev_
  
        tree_difference = REV_TREE_SAME;
        DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
 -      if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
 +      if (diff_tree_sha1(t1->object.oid.hash, t2->object.oid.hash, "",
                           &revs->pruning) < 0)
                return REV_TREE_DIFFERENT;
        return tree_difference;
@@@ -527,7 -527,7 +527,7 @@@ static int rev_same_tree_as_empty(struc
  
        tree_difference = REV_TREE_SAME;
        DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
 -      retval = diff_tree_sha1(NULL, t1->object.sha1, "", &revs->pruning);
 +      retval = diff_tree_sha1(NULL, t1->object.oid.hash, "", &revs->pruning);
  
        return retval >= 0 && (tree_difference == REV_TREE_SAME);
  }
@@@ -611,7 -611,7 +611,7 @@@ static unsigned update_treesame(struct 
  
                st = lookup_decoration(&revs->treesame, &commit->object);
                if (!st)
 -                      die("update_treesame %s", sha1_to_hex(commit->object.sha1));
 +                      die("update_treesame %s", oid_to_hex(&commit->object.oid));
                relevant_parents = 0;
                relevant_change = irrelevant_change = 0;
                for (p = commit->parents, n = 0; p; n++, p = p->next) {
@@@ -709,8 -709,8 +709,8 @@@ static void try_to_simplify_commit(stru
                }
                if (parse_commit(p) < 0)
                        die("cannot simplify commit %s (because of %s)",
 -                          sha1_to_hex(commit->object.sha1),
 -                          sha1_to_hex(p->object.sha1));
 +                          oid_to_hex(&commit->object.oid),
 +                          oid_to_hex(&p->object.oid));
                switch (rev_compare_tree(revs, p, commit)) {
                case REV_TREE_SAME:
                        if (!revs->simplify_history || !relevant_commit(p)) {
                                 */
                                if (parse_commit(p) < 0)
                                        die("cannot simplify commit %s (invalid %s)",
 -                                          sha1_to_hex(commit->object.sha1),
 -                                          sha1_to_hex(p->object.sha1));
 +                                          oid_to_hex(&commit->object.oid),
 +                                          oid_to_hex(&p->object.oid));
                                p->parents = NULL;
                        }
                /* fallthrough */
                                irrelevant_change = 1;
                        continue;
                }
 -              die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
 +              die("bad tree compare for commit %s", oid_to_hex(&commit->object.oid));
        }
  
        /*
@@@ -1190,7 -1190,7 +1190,7 @@@ static void add_rev_cmdline_list(struc
  {
        while (commit_list) {
                struct object *object = &commit_list->item->object;
 -              add_rev_cmdline(revs, object, sha1_to_hex(object->sha1),
 +              add_rev_cmdline(revs, object, oid_to_hex(&object->oid),
                                whence, flags);
                commit_list = commit_list->next;
        }
@@@ -1379,7 -1379,7 +1379,7 @@@ static int add_parents_only(struct rev_
                        break;
                if (!((struct tag*)it)->tagged)
                        return 0;
 -              hashcpy(sha1, ((struct tag*)it)->tagged->sha1);
 +              hashcpy(sha1, ((struct tag*)it)->tagged->oid.hash);
        }
        if (it->type != OBJ_COMMIT)
                return 0;
@@@ -1436,7 -1436,7 +1436,7 @@@ static void add_pending_commit_list(str
        while (commit_list) {
                struct object *object = &commit_list->item->object;
                object->flags |= flags;
 -              add_pending_object(revs, object, sha1_to_hex(object->sha1));
 +              add_pending_object(revs, object, oid_to_hex(&object->oid));
                commit_list = commit_list->next;
        }
  }
@@@ -1556,10 -1556,10 +1556,10 @@@ int handle_revision_arg(const char *arg
  
                                a = (a_obj->type == OBJ_COMMIT
                                     ? (struct commit *)a_obj
 -                                   : lookup_commit_reference(a_obj->sha1));
 +                                   : lookup_commit_reference(a_obj->oid.hash));
                                b = (b_obj->type == OBJ_COMMIT
                                     ? (struct commit *)b_obj
 -                                   : lookup_commit_reference(b_obj->sha1));
 +                                   : lookup_commit_reference(b_obj->oid.hash));
                                if (!a || !b)
                                        goto missing;
                                exclude = get_merge_bases(a, b);
@@@ -1635,7 -1635,10 +1635,7 @@@ static void append_prune_data(struct cm
  static void read_pathspec_from_stdin(struct rev_info *revs, struct strbuf *sb,
                                     struct cmdline_pathspec *prune)
  {
 -      while (strbuf_getwholeline(sb, stdin, '\n') != EOF) {
 -              int len = sb->len;
 -              if (len && sb->buf[len - 1] == '\n')
 -                      sb->buf[--len] = '\0';
 +      while (strbuf_getline(sb, stdin) != EOF) {
                ALLOC_GROW(prune->path, prune->nr + 1, prune->alloc);
                prune->path[prune->nr++] = xstrdup(sb->buf);
        }
@@@ -1652,8 -1655,10 +1652,8 @@@ static void read_revisions_from_stdin(s
        warn_on_object_refname_ambiguity = 0;
  
        strbuf_init(&sb, 1000);
 -      while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
 +      while (strbuf_getline(&sb, stdin) != EOF) {
                int len = sb.len;
 -              if (len && sb.buf[len - 1] == '\n')
 -                      sb.buf[--len] = '\0';
                if (!len)
                        break;
                if (sb.buf[0] == '-') {
@@@ -2044,7 -2049,7 +2044,7 @@@ static int handle_revision_opt(struct r
        } else if (!strcmp(arg, "--ignore-missing")) {
                revs->ignore_missing = 1;
        } else {
-               int opts = diff_opt_parse(&revs->diffopt, argv, argc);
+               int opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix);
                if (!opts)
                        unkv[(*unkc)++] = arg;
                return opts;
@@@ -2934,7 -2939,7 +2934,7 @@@ static int commit_match(struct commit *
        if (opt->show_notes) {
                if (!buf.len)
                        strbuf_addstr(&buf, message);
 -              format_display_notes(commit->object.sha1, &buf, encoding, 1);
 +              format_display_notes(commit->object.oid.hash, &buf, encoding, 1);
        }
  
        /*
@@@ -2964,7 -2969,7 +2964,7 @@@ enum commit_action get_commit_action(st
  {
        if (commit->object.flags & SHOWN)
                return commit_ignore;
 -      if (revs->unpacked && has_sha1_pack(commit->object.sha1))
 +      if (revs->unpacked && has_sha1_pack(commit->object.oid.hash))
                return commit_ignore;
        if (revs->show_all)
                return commit_show;
@@@ -3090,7 -3095,7 +3090,7 @@@ static void track_linear(struct rev_inf
                struct commit_list *p;
                for (p = revs->previous_parents; p; p = p->next)
                        if (p->item == NULL || /* first commit */
 -                          !hashcmp(p->item->object.sha1, commit->object.sha1))
 +                          !oidcmp(&p->item->object.oid, &commit->object.oid))
                                break;
                revs->linear = p != NULL;
        }
@@@ -3128,7 -3133,7 +3128,7 @@@ static struct commit *get_revision_1(st
                        if (add_parents_to_list(revs, commit, &revs->commits, NULL) < 0) {
                                if (!revs->ignore_missing_links)
                                        die("Failed to traverse parents of commit %s",
 -                                              sha1_to_hex(commit->object.sha1));
 +                                              oid_to_hex(&commit->object.oid));
                        }
                }
  
                        continue;
                case commit_error:
                        die("Failed to simplify parents of commit %s",
 -                          sha1_to_hex(commit->object.sha1));
 +                          oid_to_hex(&commit->object.oid));
                default:
                        if (revs->track_linear)
                                track_linear(revs, commit);