git-fmt-merge-msg: make it usable from other builtins
Move all functionality (except config and option parsing) from cmd_fmt_merge_msg() to fmt_merge_msg(), so that other builtins can use it without a child process. All functions have been changed to use strbufs, and now only cmd_fmt_merge_msg() reads directly from a file / writes anything to stdout. Signed-off-by: Miklos Vajna <vmiklos@frugalware.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
e46bbcf6e8
commit
0b9a969e0f
@ -159,23 +159,24 @@ static int handle_line(char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void print_joined(const char *singular, const char *plural,
|
static void print_joined(const char *singular, const char *plural,
|
||||||
struct list *list)
|
struct list *list, struct strbuf *out)
|
||||||
{
|
{
|
||||||
if (list->nr == 0)
|
if (list->nr == 0)
|
||||||
return;
|
return;
|
||||||
if (list->nr == 1) {
|
if (list->nr == 1) {
|
||||||
printf("%s%s", singular, list->list[0]);
|
strbuf_addf(out, "%s%s", singular, list->list[0]);
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
printf("%s", plural);
|
strbuf_addstr(out, plural);
|
||||||
for (i = 0; i < list->nr - 1; i++)
|
for (i = 0; i < list->nr - 1; i++)
|
||||||
printf("%s%s", i > 0 ? ", " : "", list->list[i]);
|
strbuf_addf(out, "%s%s", i > 0 ? ", " : "", list->list[i]);
|
||||||
printf(" and %s", list->list[list->nr - 1]);
|
strbuf_addf(out, " and %s", list->list[list->nr - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shortlog(const char *name, unsigned char *sha1,
|
static void shortlog(const char *name, unsigned char *sha1,
|
||||||
struct commit *head, struct rev_info *rev, int limit)
|
struct commit *head, struct rev_info *rev, int limit,
|
||||||
|
struct strbuf *out)
|
||||||
{
|
{
|
||||||
int i, count = 0;
|
int i, count = 0;
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
@ -232,15 +233,15 @@ static void shortlog(const char *name, unsigned char *sha1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (count > limit)
|
if (count > limit)
|
||||||
printf("\n* %s: (%d commits)\n", name, count);
|
strbuf_addf(out, "\n* %s: (%d commits)\n", name, count);
|
||||||
else
|
else
|
||||||
printf("\n* %s:\n", name);
|
strbuf_addf(out, "\n* %s:\n", name);
|
||||||
|
|
||||||
for (i = 0; i < subjects.nr; i++)
|
for (i = 0; i < subjects.nr; i++)
|
||||||
if (i >= limit)
|
if (i >= limit)
|
||||||
printf(" ...\n");
|
strbuf_addf(out, " ...\n");
|
||||||
else
|
else
|
||||||
printf(" %s\n", subjects.list[i]);
|
strbuf_addf(out, " %s\n", subjects.list[i]);
|
||||||
|
|
||||||
clear_commit_marks((struct commit *)branch, flags);
|
clear_commit_marks((struct commit *)branch, flags);
|
||||||
clear_commit_marks(head, flags);
|
clear_commit_marks(head, flags);
|
||||||
@ -251,15 +252,105 @@ static void shortlog(const char *name, unsigned char *sha1,
|
|||||||
free_list(&subjects);
|
free_list(&subjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
|
int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
|
||||||
{
|
int limit = 20, i = 0, pos = 0;
|
||||||
int limit = 20, i = 0;
|
|
||||||
char line[1024];
|
char line[1024];
|
||||||
FILE *in = stdin;
|
char *p = line, *sep = "";
|
||||||
const char *sep = "";
|
|
||||||
unsigned char head_sha1[20];
|
unsigned char head_sha1[20];
|
||||||
const char *current_branch;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
strbuf_addstr(out, "Merge ");
|
||||||
|
for (i = 0; i < srcs.nr; i++) {
|
||||||
|
struct src_data *src_data = srcs.payload[i];
|
||||||
|
const char *subsep = "";
|
||||||
|
|
||||||
|
strbuf_addstr(out, sep);
|
||||||
|
sep = "; ";
|
||||||
|
|
||||||
|
if (src_data->head_status == 1) {
|
||||||
|
strbuf_addstr(out, srcs.list[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (src_data->head_status == 3) {
|
||||||
|
subsep = ", ";
|
||||||
|
strbuf_addstr(out, "HEAD");
|
||||||
|
}
|
||||||
|
if (src_data->branch.nr) {
|
||||||
|
strbuf_addstr(out, subsep);
|
||||||
|
subsep = ", ";
|
||||||
|
print_joined("branch ", "branches ", &src_data->branch,
|
||||||
|
out);
|
||||||
|
}
|
||||||
|
if (src_data->r_branch.nr) {
|
||||||
|
strbuf_addstr(out, subsep);
|
||||||
|
subsep = ", ";
|
||||||
|
print_joined("remote branch ", "remote branches ",
|
||||||
|
&src_data->r_branch, out);
|
||||||
|
}
|
||||||
|
if (src_data->tag.nr) {
|
||||||
|
strbuf_addstr(out, subsep);
|
||||||
|
subsep = ", ";
|
||||||
|
print_joined("tag ", "tags ", &src_data->tag, out);
|
||||||
|
}
|
||||||
|
if (src_data->generic.nr) {
|
||||||
|
strbuf_addstr(out, subsep);
|
||||||
|
print_joined("commit ", "commits ", &src_data->generic,
|
||||||
|
out);
|
||||||
|
}
|
||||||
|
if (strcmp(".", srcs.list[i]))
|
||||||
|
strbuf_addf(out, " of %s", srcs.list[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp("master", current_branch))
|
||||||
|
strbuf_addch(out, '\n');
|
||||||
|
else
|
||||||
|
strbuf_addf(out, " into %s\n", current_branch);
|
||||||
|
|
||||||
|
if (merge_summary) {
|
||||||
|
struct commit *head;
|
||||||
|
struct rev_info rev;
|
||||||
|
|
||||||
|
head = lookup_commit(head_sha1);
|
||||||
|
init_revisions(&rev, NULL);
|
||||||
|
rev.commit_format = CMIT_FMT_ONELINE;
|
||||||
|
rev.ignore_merges = 1;
|
||||||
|
rev.limited = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < origins.nr; i++)
|
||||||
|
shortlog(origins.list[i], origins.payload[i],
|
||||||
|
head, &rev, limit, out);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
|
||||||
|
{
|
||||||
|
FILE *in = stdin;
|
||||||
|
struct strbuf input, output;
|
||||||
|
int ret;
|
||||||
|
|
||||||
git_config(fmt_merge_msg_config, NULL);
|
git_config(fmt_merge_msg_config, NULL);
|
||||||
|
|
||||||
while (argc > 1) {
|
while (argc > 1) {
|
||||||
@ -288,82 +379,14 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
|
|||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
usage(fmt_merge_msg_usage);
|
usage(fmt_merge_msg_usage);
|
||||||
|
|
||||||
/* get current branch */
|
strbuf_init(&input, 0);
|
||||||
current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
|
if (strbuf_read(&input, fileno(in), 0) < 0)
|
||||||
if (!current_branch)
|
die("could not read input file %s", strerror(errno));
|
||||||
die("No current branch");
|
strbuf_init(&output, 0);
|
||||||
if (!prefixcmp(current_branch, "refs/heads/"))
|
|
||||||
current_branch += 11;
|
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), in)) {
|
|
||||||
i++;
|
|
||||||
if (line[0] == 0)
|
|
||||||
continue;
|
|
||||||
if (handle_line(line))
|
|
||||||
die ("Error in line %d: %s", i, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Merge ");
|
|
||||||
for (i = 0; i < srcs.nr; i++) {
|
|
||||||
struct src_data *src_data = srcs.payload[i];
|
|
||||||
const char *subsep = "";
|
|
||||||
|
|
||||||
printf(sep);
|
|
||||||
sep = "; ";
|
|
||||||
|
|
||||||
if (src_data->head_status == 1) {
|
|
||||||
printf(srcs.list[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (src_data->head_status == 3) {
|
|
||||||
subsep = ", ";
|
|
||||||
printf("HEAD");
|
|
||||||
}
|
|
||||||
if (src_data->branch.nr) {
|
|
||||||
printf(subsep);
|
|
||||||
subsep = ", ";
|
|
||||||
print_joined("branch ", "branches ", &src_data->branch);
|
|
||||||
}
|
|
||||||
if (src_data->r_branch.nr) {
|
|
||||||
printf(subsep);
|
|
||||||
subsep = ", ";
|
|
||||||
print_joined("remote branch ", "remote branches ",
|
|
||||||
&src_data->r_branch);
|
|
||||||
}
|
|
||||||
if (src_data->tag.nr) {
|
|
||||||
printf(subsep);
|
|
||||||
subsep = ", ";
|
|
||||||
print_joined("tag ", "tags ", &src_data->tag);
|
|
||||||
}
|
|
||||||
if (src_data->generic.nr) {
|
|
||||||
printf(subsep);
|
|
||||||
print_joined("commit ", "commits ", &src_data->generic);
|
|
||||||
}
|
|
||||||
if (strcmp(".", srcs.list[i]))
|
|
||||||
printf(" of %s", srcs.list[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp("master", current_branch))
|
|
||||||
putchar('\n');
|
|
||||||
else
|
|
||||||
printf(" into %s\n", current_branch);
|
|
||||||
|
|
||||||
if (merge_summary) {
|
|
||||||
struct commit *head;
|
|
||||||
struct rev_info rev;
|
|
||||||
|
|
||||||
head = lookup_commit(head_sha1);
|
|
||||||
init_revisions(&rev, prefix);
|
|
||||||
rev.commit_format = CMIT_FMT_ONELINE;
|
|
||||||
rev.ignore_merges = 1;
|
|
||||||
rev.limited = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < origins.nr; i++)
|
|
||||||
shortlog(origins.list[i], origins.payload[i],
|
|
||||||
head, &rev, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No cleanup yet; is standalone anyway */
|
|
||||||
|
|
||||||
|
ret = fmt_merge_msg(merge_summary, &input, &output);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
printf("%s", output.buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define BUILTIN_H
|
#define BUILTIN_H
|
||||||
|
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
|
#include "strbuf.h"
|
||||||
|
|
||||||
extern const char git_version_string[];
|
extern const char git_version_string[];
|
||||||
extern const char git_usage_string[];
|
extern const char git_usage_string[];
|
||||||
@ -11,6 +12,8 @@ extern void list_common_cmds_help(void);
|
|||||||
extern void help_unknown_cmd(const char *cmd);
|
extern void help_unknown_cmd(const char *cmd);
|
||||||
extern void prune_packed_objects(int);
|
extern void prune_packed_objects(int);
|
||||||
extern int read_line_with_nul(char *buf, int size, FILE *file);
|
extern int read_line_with_nul(char *buf, int size, FILE *file);
|
||||||
|
extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
|
||||||
|
struct strbuf *out);
|
||||||
|
|
||||||
extern int cmd_add(int argc, const char **argv, const char *prefix);
|
extern int cmd_add(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_annotate(int argc, const char **argv, const char *prefix);
|
extern int cmd_annotate(int argc, const char **argv, const char *prefix);
|
||||||
|
Reference in New Issue
Block a user