Merge branch 'jc/conflict-hint' into cc/interpret-trailers-more
authorJunio C Hamano <gitster@pobox.com>
Mon, 10 Nov 2014 17:56:39 +0000 (09:56 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Nov 2014 17:56:39 +0000 (09:56 -0800)
* jc/conflict-hint:
merge & sequencer: turn "Conflicts:" hint into a comment
builtin/commit.c: extract ignore_non_trailer() helper function
merge & sequencer: unify codepaths that write "Conflicts:" hint
builtin/merge.c: drop a parameter that is never used
git-tag.txt: Add a missing hyphen to `-s`

1  2 
Documentation/git-tag.txt
builtin/commit.c
builtin/merge.c
sequencer.c
sequencer.h
Simple merge
index 41f481bd030ba96f8883e64517eda95931344545,0a78e7649b579b3392dcd2958717671d8bf49db4..80a618fe137811fff6e205104297e7158d0572a9
@@@ -627,48 -584,61 +627,94 @@@ static void determine_author_info(struc
        }
  }
  
 -static char *cut_ident_timestamp_part(char *string)
 +static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)
  {
 -      char *ket = strrchr(string, '>');
 -      if (!ket || ket[1] != ' ')
 -              die(_("Malformed ident string: '%s'"), string);
 -      *++ket = '\0';
 -      return ket;
 +      if (split_ident_line(id, buf->buf, buf->len) ||
 +          !sane_ident_split(id))
 +              die(_("Malformed ident string: '%s'"), buf->buf);
 +}
 +
 +static int author_date_is_interesting(void)
 +{
 +      return author_message || force_date;
 +}
 +
 +static void adjust_comment_line_char(const struct strbuf *sb)
 +{
 +      char candidates[] = "#;@!$%^&|:";
 +      char *candidate;
 +      const char *p;
 +
 +      comment_line_char = candidates[0];
 +      if (!memchr(sb->buf, comment_line_char, sb->len))
 +              return;
 +
 +      p = sb->buf;
 +      candidate = strchr(candidates, *p);
 +      if (candidate)
 +              *candidate = ' ';
 +      for (p = sb->buf; *p; p++) {
 +              if ((p[0] == '\n' || p[0] == '\r') && p[1]) {
 +                      candidate = strchr(candidates, p[1]);
 +                      if (candidate)
 +                              *candidate = ' ';
 +              }
 +      }
 +
 +      for (p = candidates; *p == ' '; p++)
 +              ;
 +      if (!*p)
 +              die(_("unable to select a comment character that is not used\n"
 +                    "in the current commit message"));
 +      comment_line_char = *p;
  }
  
 -              } else if (!prefixcmp(sb->buf + bol, "Conflicts:\n")) {
+ /*
+  * Inspect sb 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.
+  *
+  * Returns the number of bytes from the tail to ignore, to be fed as
+  * the second parameter to append_signoff().
+  */
+ static int ignore_non_trailer(struct strbuf *sb)
+ {
+       int boc = 0;
+       int bol = 0;
+       int in_old_conflicts_block = 0;
+       while (bol < sb->len) {
+               char *next_line;
+               if (!(next_line = memchr(sb->buf + bol, '\n', sb->len - bol)))
+                       next_line = sb->buf + sb->len;
+               else
+                       next_line++;
+               if (sb->buf[bol] == comment_line_char || sb->buf[bol] == '\n') {
+                       /* is this the first of the run of comments? */
+                       if (!boc)
+                               boc = bol;
+                       /* otherwise, it is just continuing */
++              } else if (starts_with(sb->buf + bol, "Conflicts:\n")) {
+                       in_old_conflicts_block = 1;
+                       if (!boc)
+                               boc = bol;
+               } else if (in_old_conflicts_block && sb->buf[bol] == '\t') {
+                       ; /* a pathname in the conflicts block */
+               } else if (boc) {
+                       /* the previous was not trailing comment */
+                       boc = 0;
+                       in_old_conflicts_block = 0;
+               }
+               bol = next_line - sb->buf;
+       }
+       return boc ? sb->len - boc : 0;
+ }
  static int prepare_to_commit(const char *index_file, const char *prefix,
                             struct commit *current_head,
                             struct wt_status *s,
diff --cc builtin/merge.c
Simple merge
diff --cc sequencer.c
index 5e8a207474bc6971a0de4f9ff6160a5681ac7b6d,1d97da3ca478f70cee1ccd5a23a0773ca47bec49..f00fd7ce0358a8a8ace379cd874174a0b6b7d2db
@@@ -243,29 -278,32 +243,46 @@@ static int fast_forward_to(const unsign
  
        read_cache();
        if (checkout_fast_forward(from, to, 1))
 -              exit(1); /* the callee should have complained already */
 -      ref_lock = lock_any_ref_for_update("HEAD", unborn ? null_sha1 : from,
 -                                         0, NULL);
 +              exit(128); /* the callee should have complained already */
 +
        strbuf_addf(&sb, "%s: fast-forward", action_name(opts));
 -      ret = write_ref_sha1(ref_lock, to, sb.buf);
 +
 +      transaction = ref_transaction_begin(&err);
 +      if (!transaction ||
 +          ref_transaction_update(transaction, "HEAD",
 +                                 to, unborn ? null_sha1 : from,
 +                                 0, 1, &err) ||
 +          ref_transaction_commit(transaction, sb.buf, &err)) {
 +              ref_transaction_free(transaction);
 +              error("%s", err.buf);
 +              strbuf_release(&sb);
 +              strbuf_release(&err);
 +              return -1;
 +      }
 +
        strbuf_release(&sb);
 -      return ret;
 +      strbuf_release(&err);
 +      ref_transaction_free(transaction);
 +      return 0;
  }
  
+ void append_conflicts_hint(struct strbuf *msgbuf)
+ {
+       int i;
+       strbuf_addch(msgbuf, '\n');
+       strbuf_commented_addf(msgbuf, "Conflicts:\n");
+       for (i = 0; i < active_nr;) {
+               const struct cache_entry *ce = active_cache[i++];
+               if (ce_stage(ce)) {
+                       strbuf_commented_addf(msgbuf, "\t%s\n", ce->name);
+                       while (i < active_nr && !strcmp(ce->name,
+                                                       active_cache[i]->name))
+                               i++;
+               }
+       }
+ }
  static int do_recursive_merge(struct commit *base, struct commit *next,
                              const char *base_label, const char *next_label,
                              unsigned char *head, struct strbuf *msgbuf,
diff --cc sequencer.h
Simple merge