Merge branch 'tc/merge-m-log' into maint

* tc/merge-m-log:
  merge: --log appends shortlog to message if specified
  fmt-merge-msg: add function to append shortlog only
  fmt-merge-msg: refactor merge title formatting
  fmt-merge-msg: minor refactor of fmt_merge_msg()
  merge: rename variable
  merge: update comment
  t7604-merge-custom-message: show that --log doesn't append to -m
  t7604-merge-custom-message: shift expected output creation
This commit is contained in:
Junio C Hamano 2010-06-22 08:31:25 -07:00
commit e3ed7f721c
5 changed files with 87 additions and 41 deletions

View File

@ -58,7 +58,12 @@ include::merge-options.txt[]
-m <msg>:: -m <msg>::
Set the commit message to be used for the merge commit (in Set the commit message to be used for the merge commit (in
case one is created). The 'git fmt-merge-msg' command can be case one is created).
If `--log` is specified, a shortlog of the commits being merged
will be appended to the specified message.
The 'git fmt-merge-msg' command can be
used to give a good default for automated 'git merge' used to give a good default for automated 'git merge'
invocations. invocations.

View File

@ -16,6 +16,7 @@ extern const char *help_unknown_cmd(const char *cmd);
extern void prune_packed_objects(int); extern void prune_packed_objects(int);
extern int fmt_merge_msg(int merge_summary, struct strbuf *in, extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
struct strbuf *out); struct strbuf *out);
extern int fmt_merge_msg_shortlog(struct strbuf *in, struct strbuf *out);
extern int commit_tree(const char *msg, unsigned char *tree, extern int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret, struct commit_list *parents, unsigned char *ret,
const char *author); const char *author);

View File

@ -202,35 +202,10 @@ static void shortlog(const char *name, unsigned char *sha1,
string_list_clear(&subjects, 0); string_list_clear(&subjects, 0);
} }
int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) { static void do_fmt_merge_msg_title(struct strbuf *out,
int limit = 20, i = 0, pos = 0; const char *current_branch) {
int i = 0;
char *sep = ""; char *sep = "";
unsigned char head_sha1[20];
const char *current_branch;
/* get current branch */
current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
if (!current_branch)
die("No current branch");
if (!prefixcmp(current_branch, "refs/heads/"))
current_branch += 11;
/* get a line */
while (pos < in->len) {
int len;
char *newline, *p = in->buf + pos;
newline = strchr(p, '\n');
len = newline ? newline - p : strlen(p);
pos += len + !!newline;
i++;
p[len] = 0;
if (handle_line(p))
die ("Error in line %d: %.*s", i, len, p);
}
if (!srcs.nr)
return 0;
strbuf_addstr(out, "Merge "); strbuf_addstr(out, "Merge ");
for (i = 0; i < srcs.nr; i++) { for (i = 0; i < srcs.nr; i++) {
@ -278,6 +253,40 @@ int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
strbuf_addch(out, '\n'); strbuf_addch(out, '\n');
else else
strbuf_addf(out, " into %s\n", current_branch); strbuf_addf(out, " into %s\n", current_branch);
}
static int do_fmt_merge_msg(int merge_title, int merge_summary,
struct strbuf *in, struct strbuf *out) {
int limit = 20, i = 0, pos = 0;
unsigned char head_sha1[20];
const char *current_branch;
/* get current branch */
current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
if (!current_branch)
die("No current branch");
if (!prefixcmp(current_branch, "refs/heads/"))
current_branch += 11;
/* get a line */
while (pos < in->len) {
int len;
char *newline, *p = in->buf + pos;
newline = strchr(p, '\n');
len = newline ? newline - p : strlen(p);
pos += len + !!newline;
i++;
p[len] = 0;
if (handle_line(p))
die ("Error in line %d: %.*s", i, len, p);
}
if (!srcs.nr)
return 0;
if (merge_title)
do_fmt_merge_msg_title(out, current_branch);
if (merge_summary) { if (merge_summary) {
struct commit *head; struct commit *head;
@ -289,6 +298,9 @@ int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
rev.ignore_merges = 1; rev.ignore_merges = 1;
rev.limited = 1; rev.limited = 1;
if (suffixcmp(out->buf, "\n"))
strbuf_addch(out, '\n');
for (i = 0; i < origins.nr; i++) for (i = 0; i < origins.nr; i++)
shortlog(origins.items[i].string, origins.items[i].util, shortlog(origins.items[i].string, origins.items[i].util,
head, &rev, limit, out); head, &rev, limit, out);
@ -296,6 +308,14 @@ int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
return 0; return 0;
} }
int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
return do_fmt_merge_msg(1, merge_summary, in, out);
}
int fmt_merge_msg_shortlog(struct strbuf *in, struct strbuf *out) {
return do_fmt_merge_msg(0, 1, in, out);
}
int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
{ {
const char *inpath = NULL; const char *inpath = NULL;

View File

@ -973,7 +973,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
reset_hard(remote_head->sha1, 0); reset_hard(remote_head->sha1, 0);
return 0; return 0;
} else { } else {
struct strbuf msg = STRBUF_INIT; struct strbuf merge_names = STRBUF_INIT;
/* We are invoked directly as the first-class UI. */ /* We are invoked directly as the first-class UI. */
head_arg = "HEAD"; head_arg = "HEAD";
@ -986,13 +986,17 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* codepath so we discard the error in this * codepath so we discard the error in this
* loop. * loop.
*/ */
if (!have_message) { for (i = 0; i < argc; i++)
for (i = 0; i < argc; i++) merge_name(argv[i], &merge_names);
merge_name(argv[i], &msg);
fmt_merge_msg(option_log, &msg, &merge_msg); if (have_message && option_log)
if (merge_msg.len) fmt_merge_msg_shortlog(&merge_names, &merge_msg);
strbuf_setlen(&merge_msg, merge_msg.len-1); else if (!have_message)
} fmt_merge_msg(option_log, &merge_names, &merge_msg);
if (!(have_message && !option_log) && merge_msg.len)
strbuf_setlen(&merge_msg, merge_msg.len-1);
} }
if (head_invalid || !argc) if (head_invalid || !argc)

View File

@ -6,6 +6,15 @@ Testing merge when using a custom message for the merge commit.'
. ./test-lib.sh . ./test-lib.sh
create_merge_msgs() {
echo >exp.subject "custom message"
cp exp.subject exp.log &&
echo >>exp.log "" &&
echo >>exp.log "* commit 'c2':" &&
echo >>exp.log " c2"
}
test_expect_success 'setup' ' test_expect_success 'setup' '
echo c0 > c0.c && echo c0 > c0.c &&
git add c0.c && git add c0.c &&
@ -19,16 +28,23 @@ test_expect_success 'setup' '
echo c2 > c2.c && echo c2 > c2.c &&
git add c2.c && git add c2.c &&
git commit -m c2 && git commit -m c2 &&
git tag c2 git tag c2 &&
create_merge_msgs
' '
test_expect_success 'merge c2 with a custom message' ' test_expect_success 'merge c2 with a custom message' '
git reset --hard c1 && git reset --hard c1 &&
echo >expected "custom message" && git merge -m "$(cat exp.subject)" c2 &&
git merge -m "custom message" c2 &&
git cat-file commit HEAD | sed -e "1,/^$/d" >actual && git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
test_cmp expected actual test_cmp exp.subject actual
'
test_expect_success 'merge --log appends to custom message' '
git reset --hard c1 &&
git merge --log -m "$(cat exp.subject)" c2 &&
git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
test_cmp exp.log actual
' '
test_done test_done