Add API access to shortlog
Shortlog is gives a pretty simple API for cases where you're already identifying all of the individual commits. Make this available to other code instead of requiring them to use the revision API and command line. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Daniel Barkalow committed
Feb 25, 2008 at 18:24 UTC
552bcac3f9f34833cf546f8c197da4c1985a0b84
2 files changed
+106
-68
builtin-shortlog.c
+80
-68
@@ -6,13 +6,11 @@
6
#include "revision.h"
7
#include "utf8.h"
8
#include "mailmap.h"
9
+#include "shortlog.h"
10
11
static const char shortlog_usage[] =
12
"git-shortlog [-n] [-s] [-e] [<commit-id>... ]";
13
13
-static char *common_repo_prefix;
14
-static int email;
15
-
14
static int compare_by_number(const void *a1, const void *a2)
15
{
16
const struct path_list_item *i1 = a1, *i2 = a2;
@@ -26,13 +24,11 @@ static int compare_by_number(const void *a1, const void *a2)
24
return -1;
25
}
26
29
-static struct path_list mailmap = {NULL, 0, 0, 0};
30
-
31
-static void insert_one_record(struct path_list *list,
27
+static void insert_one_record(struct shortlog *log,
28
const char *author,
29
const char *oneline)
30
{
35
- const char *dot3 = common_repo_prefix;
31
+ const char *dot3 = log->common_repo_prefix;
32
char *buffer, *p;
33
struct path_list_item *item;
34
struct path_list *onelines;
@@ -47,7 +43,7 @@ static void insert_one_record(struct path_list *list,
43
eoemail = strchr(boemail, '>');
44
if (!eoemail)
45
return;
50
- if (!map_email(&mailmap, boemail+1, namebuf, sizeof(namebuf))) {
46
+ if (!map_email(&log->mailmap, boemail+1, namebuf, sizeof(namebuf))) {
47
while (author < boemail && isspace(*author))
48
author++;
49
for (len = 0;
@@ -61,14 +57,14 @@ static void insert_one_record(struct path_list *list,
57
else
58
len = strlen(namebuf);
59
64
- if (email) {
60
+ if (log->email) {
61
size_t room = sizeof(namebuf) - len - 1;
62
int maillen = eoemail - boemail + 1;
63
snprintf(namebuf + len, room, " %.*s", maillen, boemail);
64
}
65
66
buffer = xstrdup(namebuf);
71
- item = path_list_insert(buffer, list);
67
+ item = path_list_insert(buffer, &log->list);
68
if (item->util == NULL)
69
item->util = xcalloc(1, sizeof(struct path_list));
70
else
@@ -114,7 +110,7 @@ static void insert_one_record(struct path_list *list,
110
onelines->items[onelines->nr++].path = buffer;
111
}
112
117
-static void read_from_stdin(struct path_list *list)
113
+static void read_from_stdin(struct shortlog *log)
114
{
115
char author[1024], oneline[1024];
116
@@ -128,38 +124,43 @@ static void read_from_stdin(struct path_list *list)
124
while (fgets(oneline, sizeof(oneline), stdin) &&
125
oneline[0] == '\n')
126
; /* discard blanks */
131
- insert_one_record(list, author + 8, oneline);
127
+ insert_one_record(log, author + 8, oneline);
128
}
129
}
130
135
-static void get_from_rev(struct rev_info *rev, struct path_list *list)
131
+void shortlog_add_commit(struct shortlog *log, struct commit *commit)
132
{
137
- struct commit *commit;
138
-
139
- prepare_revision_walk(rev);
140
- while ((commit = get_revision(rev)) != NULL) {
141
- const char *author = NULL, *buffer;
133
+ const char *author = NULL, *buffer;
134
143
- buffer = commit->buffer;
144
- while (*buffer && *buffer != '\n') {
145
- const char *eol = strchr(buffer, '\n');
135
+ buffer = commit->buffer;
136
+ while (*buffer && *buffer != '\n') {
137
+ const char *eol = strchr(buffer, '\n');
138
147
- if (eol == NULL)
148
- eol = buffer + strlen(buffer);
149
- else
150
- eol++;
139
+ if (eol == NULL)
140
+ eol = buffer + strlen(buffer);
141
+ else
142
+ eol++;
143
152
- if (!prefixcmp(buffer, "author "))
153
- author = buffer + 7;
154
- buffer = eol;
155
- }
156
- if (!author)
157
- die("Missing author: %s",
158
- sha1_to_hex(commit->object.sha1));
159
- if (*buffer)
160
- buffer++;
161
- insert_one_record(list, author, !*buffer ? "<none>" : buffer);
144
+ if (!prefixcmp(buffer, "author "))
145
+ author = buffer + 7;
146
+ buffer = eol;
147
}
148
+ if (!author)
149
+ die("Missing author: %s",
150
+ sha1_to_hex(commit->object.sha1));
151
+ if (*buffer)
152
+ buffer++;
153
+ insert_one_record(log, author, !*buffer ? "<none>" : buffer);
154
+}
155
+
156
+static void get_from_rev(struct rev_info *rev, struct shortlog *log)
157
+{
158
+ struct commit *commit;
159
+
160
+ if (prepare_revision_walk(rev))
161
+ die("revision walk setup failed");
162
+ while ((commit = get_revision(rev)) != NULL)
163
+ shortlog_add_commit(log, commit);
164
}
165
166
static int parse_uint(char const **arg, int comma)
@@ -211,29 +212,38 @@ static void parse_wrap_args(const char *arg, int *in1, int *in2, int *wrap)
212
die(wrap_arg_usage);
213
}
214
215
+void shortlog_init(struct shortlog *log)
216
+{
217
+ memset(log, 0, sizeof(*log));
218
+
219
+ read_mailmap(&log->mailmap, ".mailmap", &log->common_repo_prefix);
220
+
221
+ log->list.strdup_paths = 1;
222
+ log->wrap = DEFAULT_WRAPLEN;
223
+ log->in1 = DEFAULT_INDENT1;
224
+ log->in2 = DEFAULT_INDENT2;
225
+}
226
+
227
int cmd_shortlog(int argc, const char **argv, const char *prefix)
228
{
229
+ struct shortlog log;
230
struct rev_info rev;
217
- struct path_list list = { NULL, 0, 0, 1 };
218
- int i, j, sort_by_number = 0, summary = 0;
219
- int wrap_lines = 0;
220
- int wrap = DEFAULT_WRAPLEN;
221
- int in1 = DEFAULT_INDENT1;
222
- int in2 = DEFAULT_INDENT2;
231
+
232
+ shortlog_init(&log);
233
234
/* since -n is a shadowed rev argument, parse our args first */
235
while (argc > 1) {
236
if (!strcmp(argv[1], "-n") || !strcmp(argv[1], "--numbered"))
227
- sort_by_number = 1;
237
+ log.sort_by_number = 1;
238
else if (!strcmp(argv[1], "-s") ||
239
!strcmp(argv[1], "--summary"))
230
- summary = 1;
240
+ log.summary = 1;
241
else if (!strcmp(argv[1], "-e") ||
242
!strcmp(argv[1], "--email"))
233
- email = 1;
243
+ log.email = 1;
244
else if (!prefixcmp(argv[1], "-w")) {
235
- wrap_lines = 1;
236
- parse_wrap_args(argv[1], &in1, &in2, &wrap);
245
+ log.wrap_lines = 1;
246
+ parse_wrap_args(argv[1], &log.in1, &log.in2, &log.wrap);
247
}
248
else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
249
usage(shortlog_usage);
@@ -247,34 +257,38 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
257
if (argc > 1)
258
die ("unrecognized argument: %s", argv[1]);
259
250
- read_mailmap(&mailmap, ".mailmap", &common_repo_prefix);
251
-
260
/* assume HEAD if from a tty */
261
if (!rev.pending.nr && isatty(0))
262
add_head_to_pending(&rev);
263
if (rev.pending.nr == 0) {
256
- read_from_stdin(&list);
264
+ read_from_stdin(&log);
265
}
266
else
259
- get_from_rev(&rev, &list);
267
+ get_from_rev(&rev, &log);
268
261
- if (sort_by_number)
262
- qsort(list.items, list.nr, sizeof(struct path_list_item),
263
- compare_by_number);
269
+ shortlog_output(&log);
270
+ return 0;
271
+}
272
265
- for (i = 0; i < list.nr; i++) {
266
- struct path_list *onelines = list.items[i].util;
273
+void shortlog_output(struct shortlog *log)
274
+{
275
+ int i, j;
276
+ if (log->sort_by_number)
277
+ qsort(log->list.items, log->list.nr, sizeof(struct path_list_item),
278
+ compare_by_number);
279
+ for (i = 0; i < log->list.nr; i++) {
280
+ struct path_list *onelines = log->list.items[i].util;
281
268
- if (summary) {
269
- printf("%6d\t%s\n", onelines->nr, list.items[i].path);
282
+ if (log->summary) {
283
+ printf("%6d\t%s\n", onelines->nr, log->list.items[i].path);
284
} else {
271
- printf("%s (%d):\n", list.items[i].path, onelines->nr);
285
+ printf("%s (%d):\n", log->list.items[i].path, onelines->nr);
286
for (j = onelines->nr - 1; j >= 0; j--) {
287
const char *msg = onelines->items[j].path;
288
275
- if (wrap_lines) {
276
- int col = print_wrapped_text(msg, in1, in2, wrap);
277
- if (col != wrap)
289
+ if (log->wrap_lines) {
290
+ int col = print_wrapped_text(msg, log->in1, log->in2, log->wrap);
291
+ if (col != log->wrap)
292
putchar('\n');
293
}
294
else
@@ -286,13 +300,11 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
300
onelines->strdup_paths = 1;
301
path_list_clear(onelines, 1);
302
free(onelines);
289
- list.items[i].util = NULL;
303
+ log->list.items[i].util = NULL;
304
}
305
292
- list.strdup_paths = 1;
293
- path_list_clear(&list, 1);
294
- mailmap.strdup_paths = 1;
295
- path_list_clear(&mailmap, 1);
296
-
297
- return 0;
306
+ log->list.strdup_paths = 1;
307
+ path_list_clear(&log->list, 1);
308
+ log->mailmap.strdup_paths = 1;
309
+ path_list_clear(&log->mailmap, 1);
310
}
shortlog.h
new
+26
@@ -0,0 +1,26 @@
1
+#ifndef SHORTLOG_H
2
+#define SHORTLOG_H
3
+
4
+#include "path-list.h"
5
+
6
+struct shortlog {
7
+ struct path_list list;
8
+ int summary;
9
+ int wrap_lines;
10
+ int sort_by_number;
11
+ int wrap;
12
+ int in1;
13
+ int in2;
14
+
15
+ char *common_repo_prefix;
16
+ int email;
17
+ struct path_list mailmap;
18
+};
19
+
20
+void shortlog_init(struct shortlog *log);
21
+
22
+void shortlog_add_commit(struct shortlog *log, struct commit *commit);
23
+
24
+void shortlog_output(struct shortlog *log);
25
+
26
+#endif