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>
Miklos Vajna committed
Jun 27, 2008 at 18:21 UTC
0b9a969e0fbb0a09e9de931cfe27005cbfd6cb7d
2 files changed
+92
-66
builtin-fmt-merge-msg.c
+89
-66
@@ -159,23 +159,24 @@ static int handle_line(char *line)
159
}
160
161
static void print_joined(const char *singular, const char *plural,
162
- struct list *list)
162
+ struct list *list, struct strbuf *out)
163
{
164
if (list->nr == 0)
165
return;
166
if (list->nr == 1) {
167
- printf("%s%s", singular, list->list[0]);
167
+ strbuf_addf(out, "%s%s", singular, list->list[0]);
168
} else {
169
int i;
170
- printf("%s", plural);
170
+ strbuf_addstr(out, plural);
171
for (i = 0; i < list->nr - 1; i++)
172
- printf("%s%s", i > 0 ? ", " : "", list->list[i]);
173
- printf(" and %s", list->list[list->nr - 1]);
172
+ strbuf_addf(out, "%s%s", i > 0 ? ", " : "", list->list[i]);
173
+ strbuf_addf(out, " and %s", list->list[list->nr - 1]);
174
}
175
}
176
177
static void shortlog(const char *name, unsigned char *sha1,
178
- struct commit *head, struct rev_info *rev, int limit)
178
+ struct commit *head, struct rev_info *rev, int limit,
179
+ struct strbuf *out)
180
{
181
int i, count = 0;
182
struct commit *commit;
@@ -232,15 +233,15 @@ static void shortlog(const char *name, unsigned char *sha1,
233
}
234
235
if (count > limit)
235
- printf("\n* %s: (%d commits)\n", name, count);
236
+ strbuf_addf(out, "\n* %s: (%d commits)\n", name, count);
237
else
237
- printf("\n* %s:\n", name);
238
+ strbuf_addf(out, "\n* %s:\n", name);
239
240
for (i = 0; i < subjects.nr; i++)
241
if (i >= limit)
241
- printf(" ...\n");
242
+ strbuf_addf(out, " ...\n");
243
else
243
- printf(" %s\n", subjects.list[i]);
244
+ strbuf_addf(out, " %s\n", subjects.list[i]);
245
246
clear_commit_marks((struct commit *)branch, flags);
247
clear_commit_marks(head, flags);
@@ -251,43 +252,13 @@ static void shortlog(const char *name, unsigned char *sha1,
252
free_list(&subjects);
253
}
254
254
-int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
255
-{
256
- int limit = 20, i = 0;
255
+int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
256
+ int limit = 20, i = 0, pos = 0;
257
char line[1024];
258
- FILE *in = stdin;
259
- const char *sep = "";
258
+ char *p = line, *sep = "";
259
unsigned char head_sha1[20];
260
const char *current_branch;
261
263
- git_config(fmt_merge_msg_config, NULL);
264
-
265
- while (argc > 1) {
266
- if (!strcmp(argv[1], "--log") || !strcmp(argv[1], "--summary"))
267
- merge_summary = 1;
268
- else if (!strcmp(argv[1], "--no-log")
269
- || !strcmp(argv[1], "--no-summary"))
270
- merge_summary = 0;
271
- else if (!strcmp(argv[1], "-F") || !strcmp(argv[1], "--file")) {
272
- if (argc < 3)
273
- die ("Which file?");
274
- if (!strcmp(argv[2], "-"))
275
- in = stdin;
276
- else {
277
- fclose(in);
278
- in = fopen(argv[2], "r");
279
- if (!in)
280
- die("cannot open %s", argv[2]);
281
- }
282
- argc--; argv++;
283
- } else
284
- break;
285
- argc--; argv++;
286
- }
287
-
288
- if (argc > 1)
289
- usage(fmt_merge_msg_usage);
290
-
262
/* get current branch */
263
current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
264
if (!current_branch)
@@ -295,75 +266,127 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
266
if (!prefixcmp(current_branch, "refs/heads/"))
267
current_branch += 11;
268
298
- while (fgets(line, sizeof(line), in)) {
269
+ /* get a line */
270
+ while (pos < in->len) {
271
+ int len;
272
+ char *newline;
273
+
274
+ p = in->buf + pos;
275
+ newline = strchr(p, '\n');
276
+ len = newline ? newline - p : strlen(p);
277
+ pos += len + !!newline;
278
i++;
300
- if (line[0] == 0)
301
- continue;
302
- if (handle_line(line))
303
- die ("Error in line %d: %s", i, line);
279
+ p[len] = 0;
280
+ if (handle_line(p))
281
+ die ("Error in line %d: %.*s", i, len, p);
282
}
283
306
- printf("Merge ");
284
+ strbuf_addstr(out, "Merge ");
285
for (i = 0; i < srcs.nr; i++) {
286
struct src_data *src_data = srcs.payload[i];
287
const char *subsep = "";
288
311
- printf(sep);
289
+ strbuf_addstr(out, sep);
290
sep = "; ";
291
292
if (src_data->head_status == 1) {
315
- printf(srcs.list[i]);
293
+ strbuf_addstr(out, srcs.list[i]);
294
continue;
295
}
296
if (src_data->head_status == 3) {
297
subsep = ", ";
320
- printf("HEAD");
298
+ strbuf_addstr(out, "HEAD");
299
}
300
if (src_data->branch.nr) {
323
- printf(subsep);
301
+ strbuf_addstr(out, subsep);
302
subsep = ", ";
325
- print_joined("branch ", "branches ", &src_data->branch);
303
+ print_joined("branch ", "branches ", &src_data->branch,
304
+ out);
305
}
306
if (src_data->r_branch.nr) {
328
- printf(subsep);
307
+ strbuf_addstr(out, subsep);
308
subsep = ", ";
309
print_joined("remote branch ", "remote branches ",
331
- &src_data->r_branch);
310
+ &src_data->r_branch, out);
311
}
312
if (src_data->tag.nr) {
334
- printf(subsep);
313
+ strbuf_addstr(out, subsep);
314
subsep = ", ";
336
- print_joined("tag ", "tags ", &src_data->tag);
315
+ print_joined("tag ", "tags ", &src_data->tag, out);
316
}
317
if (src_data->generic.nr) {
339
- printf(subsep);
340
- print_joined("commit ", "commits ", &src_data->generic);
318
+ strbuf_addstr(out, subsep);
319
+ print_joined("commit ", "commits ", &src_data->generic,
320
+ out);
321
}
322
if (strcmp(".", srcs.list[i]))
343
- printf(" of %s", srcs.list[i]);
323
+ strbuf_addf(out, " of %s", srcs.list[i]);
324
}
325
326
if (!strcmp("master", current_branch))
347
- putchar('\n');
327
+ strbuf_addch(out, '\n');
328
else
349
- printf(" into %s\n", current_branch);
329
+ strbuf_addf(out, " into %s\n", current_branch);
330
331
if (merge_summary) {
332
struct commit *head;
333
struct rev_info rev;
334
335
head = lookup_commit(head_sha1);
356
- init_revisions(&rev, prefix);
336
+ init_revisions(&rev, NULL);
337
rev.commit_format = CMIT_FMT_ONELINE;
338
rev.ignore_merges = 1;
339
rev.limited = 1;
340
341
for (i = 0; i < origins.nr; i++)
342
shortlog(origins.list[i], origins.payload[i],
363
- head, &rev, limit);
343
+ head, &rev, limit, out);
344
}
345
+ return 0;
346
+}
347
+
348
+int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
349
+{
350
+ FILE *in = stdin;
351
+ struct strbuf input, output;
352
+ int ret;
353
+
354
+ git_config(fmt_merge_msg_config, NULL);
355
+
356
+ while (argc > 1) {
357
+ if (!strcmp(argv[1], "--log") || !strcmp(argv[1], "--summary"))
358
+ merge_summary = 1;
359
+ else if (!strcmp(argv[1], "--no-log")
360
+ || !strcmp(argv[1], "--no-summary"))
361
+ merge_summary = 0;
362
+ else if (!strcmp(argv[1], "-F") || !strcmp(argv[1], "--file")) {
363
+ if (argc < 3)
364
+ die ("Which file?");
365
+ if (!strcmp(argv[2], "-"))
366
+ in = stdin;
367
+ else {
368
+ fclose(in);
369
+ in = fopen(argv[2], "r");
370
+ if (!in)
371
+ die("cannot open %s", argv[2]);
372
+ }
373
+ argc--; argv++;
374
+ } else
375
+ break;
376
+ argc--; argv++;
377
+ }
378
+
379
+ if (argc > 1)
380
+ usage(fmt_merge_msg_usage);
381
366
- /* No cleanup yet; is standalone anyway */
382
+ strbuf_init(&input, 0);
383
+ if (strbuf_read(&input, fileno(in), 0) < 0)
384
+ die("could not read input file %s", strerror(errno));
385
+ strbuf_init(&output, 0);
386
387
+ ret = fmt_merge_msg(merge_summary, &input, &output);
388
+ if (ret)
389
+ return ret;
390
+ printf("%s", output.buf);
391
return 0;
392
}
builtin.h
+3
@@ -2,6 +2,7 @@
2
#define BUILTIN_H
3
4
#include "git-compat-util.h"
5
+#include "strbuf.h"
6
7
extern const char git_version_string[];
8
extern const char git_usage_string[];
@@ -11,6 +12,8 @@ extern void list_common_cmds_help(void);
12
extern void help_unknown_cmd(const char *cmd);
13
extern void prune_packed_objects(int);
14
extern int read_line_with_nul(char *buf, int size, FILE *file);
15
+extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
16
+ struct strbuf *out);
17
18
extern int cmd_add(int argc, const char **argv, const char *prefix);
19
extern int cmd_annotate(int argc, const char **argv, const char *prefix);