Merge branch 'bm/interpret-trailers-cut-line-is-eom'
authorJunio C Hamano <gitster@pobox.com>
Mon, 29 May 2017 03:34:52 +0000 (12:34 +0900)
committerJunio C Hamano <gitster@pobox.com>
Mon, 29 May 2017 03:34:53 +0000 (12:34 +0900)
"git interpret-trailers", when used as GIT_EDITOR for "git commit
-v", looked for and appended to a trailer block at the very end,
i.e. at the end of the "diff" output. The command has been
corrected to pay attention to the cut-mark line "commit -v" adds to
the buffer---the real trailer block should appear just before it.

* bm/interpret-trailers-cut-line-is-eom:
interpret-trailers: honor the cut line

1  2 
builtin/commit.c
commit.c
wt-status.c
diff --combined builtin/commit.c
index 1d191a49f8499bc98c008f32ddef8f12f2cf7dda,8d1cac0629e7079daeef57ac049c0c7d7549e6d0..da1ba4c86205ca55ae1880cb768b093b101bd85a
@@@ -313,7 -313,7 +313,7 @@@ static void create_base_index(const str
        opts.dst_index = &the_index;
  
        opts.fn = oneway_merge;
 -      tree = parse_tree_indirect(current_head->object.oid.hash);
 +      tree = parse_tree_indirect(&current_head->object.oid);
        if (!tree)
                die(_("failed to unpack HEAD tree object"));
        parse_tree(tree);
@@@ -1263,10 -1263,6 +1263,10 @@@ static int parse_status_slot(const cha
                return WT_STATUS_NOBRANCH;
        if (!strcasecmp(slot, "unmerged"))
                return WT_STATUS_UNMERGED;
 +      if (!strcasecmp(slot, "localBranch"))
 +              return WT_STATUS_LOCAL_BRANCH;
 +      if (!strcasecmp(slot, "remoteBranch"))
 +              return WT_STATUS_REMOTE_BRANCH;
        return -1;
  }
  
@@@ -1434,7 -1430,7 +1434,7 @@@ static void print_summary(const char *p
        struct strbuf author_ident = STRBUF_INIT;
        struct strbuf committer_ident = STRBUF_INIT;
  
 -      commit = lookup_commit(oid->hash);
 +      commit = lookup_commit(oid);
        if (!commit)
                die(_("couldn't look up newly created commit"));
        if (parse_commit(commit))
@@@ -1658,7 -1654,7 +1658,7 @@@ int cmd_commit(int argc, const char **a
        if (get_sha1("HEAD", oid.hash))
                current_head = NULL;
        else {
 -              current_head = lookup_commit_or_die(oid.hash, "HEAD");
 +              current_head = lookup_commit_or_die(&oid, "HEAD");
                if (parse_commit(current_head))
                        die(_("could not parse HEAD commit"));
        }
  
        if (verbose || /* Truncate the message just before the diff, if any. */
            cleanup_mode == CLEANUP_SCISSORS)
-               wt_status_truncate_message_at_cut_line(&sb);
+               strbuf_setlen(&sb, wt_status_locate_end(sb.buf, sb.len));
  
        if (cleanup_mode != CLEANUP_NONE)
                strbuf_stripspace(&sb, cleanup_mode == CLEANUP_ALL);
                append_merge_tag_headers(parents, &tail);
        }
  
 -      if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->sha1,
 +      if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->oid.hash,
                         parents, oid.hash, author_ident.buf, sign_commit, extra)) {
                rollback_index_files();
                die(_("failed to write commit object"));
diff --combined commit.c
index 2d39dadee1b85259d209c901f8d4cc4bb7b05d10,c14ddf191fbf047607699e562fd85c8046932efb..713f09feb04116fc1529cbca1ca9cbd38e4e4379
+++ b/commit.c
@@@ -11,6 -11,7 +11,7 @@@
  #include "commit-slab.h"
  #include "prio-queue.h"
  #include "sha1-lookup.h"
+ #include "wt-status.h"
  
  static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
  
@@@ -18,38 -19,38 +19,38 @@@ int save_commit_buffer = 1
  
  const char *commit_type = "commit";
  
 -struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
 +struct commit *lookup_commit_reference_gently(const struct object_id *oid,
                                              int quiet)
  {
 -      struct object *obj = deref_tag(parse_object(sha1), NULL, 0);
 +      struct object *obj = deref_tag(parse_object(oid), NULL, 0);
  
        if (!obj)
                return NULL;
        return object_as_type(obj, OBJ_COMMIT, quiet);
  }
  
 -struct commit *lookup_commit_reference(const unsigned char *sha1)
 +struct commit *lookup_commit_reference(const struct object_id *oid)
  {
 -      return lookup_commit_reference_gently(sha1, 0);
 +      return lookup_commit_reference_gently(oid, 0);
  }
  
 -struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name)
 +struct commit *lookup_commit_or_die(const struct object_id *oid, const char *ref_name)
  {
 -      struct commit *c = lookup_commit_reference(sha1);
 +      struct commit *c = lookup_commit_reference(oid);
        if (!c)
                die(_("could not parse %s"), ref_name);
 -      if (hashcmp(sha1, c->object.oid.hash)) {
 +      if (oidcmp(oid, &c->object.oid)) {
                warning(_("%s %s is not a commit!"),
 -                      ref_name, sha1_to_hex(sha1));
 +                      ref_name, oid_to_hex(oid));
        }
        return c;
  }
  
 -struct commit *lookup_commit(const unsigned char *sha1)
 +struct commit *lookup_commit(const struct object_id *oid)
  {
 -      struct object *obj = lookup_object(sha1);
 +      struct object *obj = lookup_object(oid->hash);
        if (!obj)
 -              return create_object(sha1, alloc_commit_node());
 +              return create_object(oid->hash, alloc_commit_node());
        return object_as_type(obj, OBJ_COMMIT, 0);
  }
  
@@@ -60,13 -61,13 +61,13 @@@ struct commit *lookup_commit_reference_
  
        if (get_sha1_committish(name, oid.hash))
                return NULL;
 -      commit = lookup_commit_reference(oid.hash);
 +      commit = lookup_commit_reference(&oid);
        if (parse_commit(commit))
                return NULL;
        return commit;
  }
  
 -static unsigned long parse_commit_date(const char *buf, const char *tail)
 +static timestamp_t parse_commit_date(const char *buf, const char *tail)
  {
        const char *dateptr;
  
@@@ -89,8 -90,8 +90,8 @@@
                /* nada */;
        if (buf >= tail)
                return 0;
 -      /* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */
 -      return strtoul(dateptr, NULL, 10);
 +      /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */
 +      return parse_timestamp(dateptr, NULL, 10);
  }
  
  static struct commit_graft **commit_graft;
@@@ -216,9 -217,9 +217,9 @@@ int for_each_commit_graft(each_commit_g
        return ret;
  }
  
 -int unregister_shallow(const unsigned char *sha1)
 +int unregister_shallow(const struct object_id *oid)
  {
 -      int pos = commit_graft_pos(sha1);
 +      int pos = commit_graft_pos(oid->hash);
        if (pos < 0)
                return -1;
        if (pos + 1 < commit_graft_nr)
@@@ -331,7 -332,7 +332,7 @@@ int parse_commit_buffer(struct commit *
        if (get_sha1_hex(bufptr + 5, parent.hash) < 0)
                return error("bad tree pointer in commit %s",
                             oid_to_hex(&item->object.oid));
 -      item->tree = lookup_tree(parent.hash);
 +      item->tree = lookup_tree(&parent);
        bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */
        pptr = &item->parents;
  
                 */
                if (graft && (graft->nr_parent < 0 || grafts_replace_parents))
                        continue;
 -              new_parent = lookup_commit(parent.hash);
 +              new_parent = lookup_commit(&parent);
                if (new_parent)
                        pptr = &commit_list_insert(new_parent, pptr)->next;
        }
                int i;
                struct commit *new_parent;
                for (i = 0; i < graft->nr_parent; i++) {
 -                      new_parent = lookup_commit(graft->parent[i].hash);
 +                      new_parent = lookup_commit(&graft->parent[i]);
                        if (!new_parent)
                                continue;
                        pptr = &commit_list_insert(new_parent, pptr)->next;
@@@ -473,8 -474,8 +474,8 @@@ struct commit_list * commit_list_insert
  
  static int commit_list_compare_by_date(const void *a, const void *b)
  {
 -      unsigned long a_date = ((const struct commit_list *)a)->item->date;
 -      unsigned long b_date = ((const struct commit_list *)b)->item->date;
 +      timestamp_t a_date = ((const struct commit_list *)a)->item->date;
 +      timestamp_t b_date = ((const struct commit_list *)b)->item->date;
        if (a_date < b_date)
                return 1;
        if (a_date > b_date)
@@@ -562,7 -563,7 +563,7 @@@ void clear_commit_marks_for_object_arra
  
        for (i = 0; i < a->nr; i++) {
                object = a->objects[i].item;
 -              commit = lookup_commit_reference_gently(object->oid.hash, 1);
 +              commit = lookup_commit_reference_gently(&object->oid, 1);
                if (commit)
                        clear_commit_marks(commit, mark);
        }
@@@ -598,7 -599,7 +599,7 @@@ static void record_author_date(struct a
        const char *ident_line;
        size_t ident_len;
        char *date_end;
 -      unsigned long date;
 +      timestamp_t date;
  
        ident_line = find_commit_header(buffer, "author", &ident_len);
        if (!ident_line)
            !ident.date_begin || !ident.date_end)
                goto fail_exit; /* malformed "author" line */
  
 -      date = strtoul(ident.date_begin, &date_end, 10);
 +      date = parse_timestamp(ident.date_begin, &date_end, 10);
        if (date_end != ident.date_end)
                goto fail_exit; /* malformed date */
        *(author_date_slab_at(author_date, commit)) = date;
@@@ -621,8 -622,8 +622,8 @@@ static int compare_commits_by_author_da
  {
        const struct commit *a = a_, *b = b_;
        struct author_date_slab *author_date = cb_data;
 -      unsigned long a_date = *(author_date_slab_at(author_date, a));
 -      unsigned long b_date = *(author_date_slab_at(author_date, b));
 +      timestamp_t a_date = *(author_date_slab_at(author_date, a));
 +      timestamp_t b_date = *(author_date_slab_at(author_date, b));
  
        /* newer commits with larger date first */
        if (a_date < b_date)
@@@ -1589,7 -1590,7 +1590,7 @@@ struct commit *get_merge_parent(const c
        struct object_id oid;
        if (get_sha1(name, oid.hash))
                return NULL;
 -      obj = parse_object(oid.hash);
 +      obj = parse_object(&oid);
        commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
        if (commit && !commit->util)
                set_merge_remote_desc(commit, name, obj);
@@@ -1648,10 -1649,9 +1649,9 @@@ const char *find_commit_header(const ch
  /*
   * Inspect the given string and determine the true "end" of the log message, in
   * order to find where to put a new Signed-off-by: line.  Ignored are
-  * trailing comment lines and blank lines, and also the traditional
-  * "Conflicts:" block that is not commented out, so that we can use
-  * "git commit -s --amend" on an existing commit that forgot to remove
-  * it.
+  * trailing comment lines and blank lines.  To support "git commit -s
+  * --amend" on an existing commit, we also ignore "Conflicts:".  To
+  * support "git commit -v", we truncate at cut lines.
   *
   * Returns the number of bytes from the tail to ignore, to be fed as
   * the second parameter to append_signoff().
@@@ -1661,8 -1661,9 +1661,9 @@@ int ignore_non_trailer(const char *buf
        int boc = 0;
        int bol = 0;
        int in_old_conflicts_block = 0;
+       size_t cutoff = wt_status_locate_end(buf, len);
  
-       while (bol < len) {
+       while (bol < cutoff) {
                const char *next_line = memchr(buf + bol, '\n', len - bol);
  
                if (!next_line)
                }
                bol = next_line - buf;
        }
-       return boc ? len - boc : 0;
+       return boc ? len - boc : len - cutoff;
  }
diff --combined wt-status.c
index c43d17355c60677720173e495f0dc1a808ce2c6c,f4e198e5ca0c99ab97f859d99bda223ddaab68ba..25aafc35c8332a311ce89002e7c17b200ccbfde6
@@@ -665,7 -665,7 +665,7 @@@ static void wt_status_collect_untracked
                dir.untracked = the_index.untracked;
        setup_standard_excludes(&dir);
  
 -      fill_directory(&dir, &s->pathspec);
 +      fill_directory(&dir, &the_index, &s->pathspec);
  
        for (i = 0; i < dir.nr; i++) {
                struct dir_entry *ent = dir.entries[i];
@@@ -896,17 -896,18 +896,18 @@@ conclude
        status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
  }
  
void wt_status_truncate_message_at_cut_line(struct strbuf *buf)
size_t wt_status_locate_end(const char *s, size_t len)
  {
        const char *p;
        struct strbuf pattern = STRBUF_INIT;
  
        strbuf_addf(&pattern, "\n%c %s", comment_line_char, cut_line);
-       if (starts_with(buf->buf, pattern.buf + 1))
-               strbuf_setlen(buf, 0);
-       else if ((p = strstr(buf->buf, pattern.buf)))
-               strbuf_setlen(buf, p - buf->buf + 1);
+       if (starts_with(s, pattern.buf + 1))
+               len = 0;
+       else if ((p = strstr(s, pattern.buf)))
+               len = p - s + 1;
        strbuf_release(&pattern);
+       return len;
  }
  
  void wt_status_add_cut_line(FILE *fp)
@@@ -1002,7 -1003,7 +1003,7 @@@ static void wt_longstatus_print_trackin
                color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "%c",
                                 comment_line_char);
        else
 -              fputs("", s->fp);
 +              fputs("\n", s->fp);
  }
  
  static int has_unmerged(struct wt_status *s)
@@@ -1082,29 -1083,29 +1083,29 @@@ static char *read_line_from_git_path(co
  static int split_commit_in_progress(struct wt_status *s)
  {
        int split_in_progress = 0;
 -      char *head = read_line_from_git_path("HEAD");
 -      char *orig_head = read_line_from_git_path("ORIG_HEAD");
 -      char *rebase_amend = read_line_from_git_path("rebase-merge/amend");
 -      char *rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
 +      char *head, *orig_head, *rebase_amend, *rebase_orig_head;
  
 -      if (!head || !orig_head || !rebase_amend || !rebase_orig_head ||
 +      if ((!s->amend && !s->nowarn && !s->workdir_dirty) ||
            !s->branch || strcmp(s->branch, "HEAD"))
 -              return split_in_progress;
 +              return 0;
  
 -      if (!strcmp(rebase_amend, rebase_orig_head)) {
 -              if (strcmp(head, rebase_amend))
 -                      split_in_progress = 1;
 -      } else if (strcmp(orig_head, rebase_orig_head)) {
 -              split_in_progress = 1;
 -      }
 +      head = read_line_from_git_path("HEAD");
 +      orig_head = read_line_from_git_path("ORIG_HEAD");
 +      rebase_amend = read_line_from_git_path("rebase-merge/amend");
 +      rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
  
 -      if (!s->amend && !s->nowarn && !s->workdir_dirty)
 -              split_in_progress = 0;
 +      if (!head || !orig_head || !rebase_amend || !rebase_orig_head)
 +              ; /* fall through, no split in progress */
 +      else if (!strcmp(rebase_amend, rebase_orig_head))
 +              split_in_progress = !!strcmp(head, rebase_amend);
 +      else if (strcmp(orig_head, rebase_orig_head))
 +              split_in_progress = 1;
  
        free(head);
        free(orig_head);
        free(rebase_amend);
        free(rebase_orig_head);
 +
        return split_in_progress;
  }
  
@@@ -1168,7 -1169,6 +1169,7 @@@ static int read_rebase_todolist(const c
                abbrev_sha1_in_line(&line);
                string_list_append(lines, line.buf);
        }
 +      fclose(f);
        return 0;
  }
  
@@@ -1388,7 -1388,7 +1389,7 @@@ struct grab_1st_switch_cbdata 
  };
  
  static int grab_1st_switch(struct object_id *ooid, struct object_id *noid,
 -                         const char *email, unsigned long timestamp, int tz,
 +                         const char *email, timestamp_t timestamp, int tz,
                           const char *message, void *cb_data)
  {
        struct grab_1st_switch_cbdata *cb = cb_data;
@@@ -1429,7 -1429,7 +1430,7 @@@ static void wt_status_get_detached_from
            /* sha1 is a commit? match without further lookup */
            (!oidcmp(&cb.noid, &oid) ||
             /* perhaps sha1 is a tag, try to dereference to a commit */
 -           ((commit = lookup_commit_reference_gently(oid.hash, 1)) != NULL &&
 +           ((commit = lookup_commit_reference_gently(&oid, 1)) != NULL &&
              !oidcmp(&cb.noid, &commit->object.oid)))) {
                const char *from = ref;
                if (!skip_prefix(from, "refs/tags/", &from))