Replace xmalloc+memset(0) with xcalloc.
[git.git] / commit.c
1 #include "cache.h"
2 #include "tag.h"
3 #include "commit.h"
4
5 int save_commit_buffer = 1;
6
7 struct sort_node
8 {
9         /*
10          * the number of children of the associated commit
11          * that also occur in the list being sorted.
12          */
13         unsigned int indegree;
14
15         /*
16          * reference to original list item that we will re-use
17          * on output.
18          */
19         struct commit_list * list_item;
20
21 };
22
23 const char *commit_type = "commit";
24
25 enum cmit_fmt get_commit_format(const char *arg)
26 {
27         if (!*arg)
28                 return CMIT_FMT_DEFAULT;
29         if (!strcmp(arg, "=raw"))
30                 return CMIT_FMT_RAW;
31         if (!strcmp(arg, "=medium"))
32                 return CMIT_FMT_MEDIUM;
33         if (!strcmp(arg, "=short"))
34                 return CMIT_FMT_SHORT;
35         if (!strcmp(arg, "=full"))
36                 return CMIT_FMT_FULL;
37         if (!strcmp(arg, "=fuller"))
38                 return CMIT_FMT_FULLER;
39         if (!strcmp(arg, "=oneline"))
40                 return CMIT_FMT_ONELINE;
41         die("invalid --pretty format");
42 }
43
44 static struct commit *check_commit(struct object *obj,
45                                    const unsigned char *sha1,
46                                    int quiet)
47 {
48         if (obj->type != commit_type) {
49                 if (!quiet)
50                         error("Object %s is a %s, not a commit",
51                               sha1_to_hex(sha1), obj->type);
52                 return NULL;
53         }
54         return (struct commit *) obj;
55 }
56
57 struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
58                                               int quiet)
59 {
60         struct object *obj = deref_tag(parse_object(sha1), NULL, 0);
61
62         if (!obj)
63                 return NULL;
64         return check_commit(obj, sha1, quiet);
65 }
66
67 struct commit *lookup_commit_reference(const unsigned char *sha1)
68 {
69         return lookup_commit_reference_gently(sha1, 0);
70 }
71
72 struct commit *lookup_commit(const unsigned char *sha1)
73 {
74         struct object *obj = lookup_object(sha1);
75         if (!obj) {
76                 struct commit *ret = xcalloc(1, sizeof(struct commit));
77                 created_object(sha1, &ret->object);
78                 ret->object.type = commit_type;
79                 return ret;
80         }
81         if (!obj->type)
82                 obj->type = commit_type;
83         return check_commit(obj, sha1, 0);
84 }
85
86 static unsigned long parse_commit_date(const char *buf)
87 {
88         unsigned long date;
89
90         if (memcmp(buf, "author", 6))
91                 return 0;
92         while (*buf++ != '\n')
93                 /* nada */;
94         if (memcmp(buf, "committer", 9))
95                 return 0;
96         while (*buf++ != '>')
97                 /* nada */;
98         date = strtoul(buf, NULL, 10);
99         if (date == ULONG_MAX)
100                 date = 0;
101         return date;
102 }
103
104 static struct commit_graft {
105         unsigned char sha1[20];
106         int nr_parent;
107         unsigned char parent[0][20]; /* more */
108 } **commit_graft;
109 static int commit_graft_alloc, commit_graft_nr;
110
111 static int commit_graft_pos(const unsigned char *sha1)
112 {
113         int lo, hi;
114         lo = 0;
115         hi = commit_graft_nr;
116         while (lo < hi) {
117                 int mi = (lo + hi) / 2;
118                 struct commit_graft *graft = commit_graft[mi];
119                 int cmp = memcmp(sha1, graft->sha1, 20);
120                 if (!cmp)
121                         return mi;
122                 if (cmp < 0)
123                         hi = mi;
124                 else
125                         lo = mi + 1;
126         }
127         return -lo - 1;
128 }
129
130 static void prepare_commit_graft(void)
131 {
132         char *graft_file = get_graft_file();
133         FILE *fp = fopen(graft_file, "r");
134         char buf[1024];
135         if (!fp) {
136                 commit_graft = (struct commit_graft **) "hack";
137                 return;
138         }
139         while (fgets(buf, sizeof(buf), fp)) {
140                 /* The format is just "Commit Parent1 Parent2 ...\n" */
141                 int len = strlen(buf);
142                 int i;
143                 struct commit_graft *graft = NULL;
144
145                 if (buf[len-1] == '\n')
146                         buf[--len] = 0;
147                 if (buf[0] == '#')
148                         continue;
149                 if ((len + 1) % 41) {
150                 bad_graft_data:
151                         error("bad graft data: %s", buf);
152                         free(graft);
153                         continue;
154                 }
155                 i = (len + 1) / 41 - 1;
156                 graft = xmalloc(sizeof(*graft) + 20 * i);
157                 graft->nr_parent = i;
158                 if (get_sha1_hex(buf, graft->sha1))
159                         goto bad_graft_data;
160                 for (i = 40; i < len; i += 41) {
161                         if (buf[i] != ' ')
162                                 goto bad_graft_data;
163                         if (get_sha1_hex(buf + i + 1, graft->parent[i/41]))
164                                 goto bad_graft_data;
165                 }
166                 i = commit_graft_pos(graft->sha1);
167                 if (0 <= i) {
168                         error("duplicate graft data: %s", buf);
169                         free(graft);
170                         continue;
171                 }
172                 i = -i - 1;
173                 if (commit_graft_alloc <= ++commit_graft_nr) {
174                         commit_graft_alloc = alloc_nr(commit_graft_alloc);
175                         commit_graft = xrealloc(commit_graft,
176                                                 sizeof(*commit_graft) *
177                                                 commit_graft_alloc);
178                 }
179                 if (i < commit_graft_nr)
180                         memmove(commit_graft + i + 1,
181                                 commit_graft + i,
182                                 (commit_graft_nr - i - 1) *
183                                 sizeof(*commit_graft));
184                 commit_graft[i] = graft;
185         }
186         fclose(fp);
187 }
188
189 static struct commit_graft *lookup_commit_graft(const unsigned char *sha1)
190 {
191         int pos;
192         if (!commit_graft)
193                 prepare_commit_graft();
194         pos = commit_graft_pos(sha1);
195         if (pos < 0)
196                 return NULL;
197         return commit_graft[pos];
198 }
199
200 int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
201 {
202         char *bufptr = buffer;
203         unsigned char parent[20];
204         struct commit_list **pptr;
205         struct commit_graft *graft;
206         unsigned n_refs = 0;
207
208         if (item->object.parsed)
209                 return 0;
210         item->object.parsed = 1;
211         if (memcmp(bufptr, "tree ", 5))
212                 return error("bogus commit object %s", sha1_to_hex(item->object.sha1));
213         if (get_sha1_hex(bufptr + 5, parent) < 0)
214                 return error("bad tree pointer in commit %s",
215                              sha1_to_hex(item->object.sha1));
216         item->tree = lookup_tree(parent);
217         if (item->tree)
218                 n_refs++;
219         bufptr += 46; /* "tree " + "hex sha1" + "\n" */
220         pptr = &item->parents;
221
222         graft = lookup_commit_graft(item->object.sha1);
223         while (!memcmp(bufptr, "parent ", 7)) {
224                 struct commit *new_parent;
225
226                 if (get_sha1_hex(bufptr + 7, parent) || bufptr[47] != '\n')
227                         return error("bad parents in commit %s", sha1_to_hex(item->object.sha1));
228                 bufptr += 48;
229                 if (graft)
230                         continue;
231                 new_parent = lookup_commit(parent);
232                 if (new_parent) {
233                         pptr = &commit_list_insert(new_parent, pptr)->next;
234                         n_refs++;
235                 }
236         }
237         if (graft) {
238                 int i;
239                 struct commit *new_parent;
240                 for (i = 0; i < graft->nr_parent; i++) {
241                         new_parent = lookup_commit(graft->parent[i]);
242                         if (!new_parent)
243                                 continue;
244                         pptr = &commit_list_insert(new_parent, pptr)->next;
245                         n_refs++;
246                 }
247         }
248         item->date = parse_commit_date(bufptr);
249
250         if (track_object_refs) {
251                 unsigned i = 0;
252                 struct commit_list *p;
253                 struct object_refs *refs = alloc_object_refs(n_refs);
254                 if (item->tree)
255                         refs->ref[i++] = &item->tree->object;
256                 for (p = item->parents; p; p = p->next)
257                         refs->ref[i++] = &p->item->object;
258                 set_object_refs(&item->object, refs);
259         }
260
261         return 0;
262 }
263
264 int parse_commit(struct commit *item)
265 {
266         char type[20];
267         void *buffer;
268         unsigned long size;
269         int ret;
270
271         if (item->object.parsed)
272                 return 0;
273         buffer = read_sha1_file(item->object.sha1, type, &size);
274         if (!buffer)
275                 return error("Could not read %s",
276                              sha1_to_hex(item->object.sha1));
277         if (strcmp(type, commit_type)) {
278                 free(buffer);
279                 return error("Object %s not a commit",
280                              sha1_to_hex(item->object.sha1));
281         }
282         ret = parse_commit_buffer(item, buffer, size);
283         if (save_commit_buffer && !ret) {
284                 item->buffer = buffer;
285                 return 0;
286         }
287         free(buffer);
288         return ret;
289 }
290
291 struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p)
292 {
293         struct commit_list *new_list = xmalloc(sizeof(struct commit_list));
294         new_list->item = item;
295         new_list->next = *list_p;
296         *list_p = new_list;
297         return new_list;
298 }
299
300 void free_commit_list(struct commit_list *list)
301 {
302         while (list) {
303                 struct commit_list *temp = list;
304                 list = temp->next;
305                 free(temp);
306         }
307 }
308
309 struct commit_list * insert_by_date(struct commit *item, struct commit_list **list)
310 {
311         struct commit_list **pp = list;
312         struct commit_list *p;
313         while ((p = *pp) != NULL) {
314                 if (p->item->date < item->date) {
315                         break;
316                 }
317                 pp = &p->next;
318         }
319         return commit_list_insert(item, pp);
320 }
321
322         
323 void sort_by_date(struct commit_list **list)
324 {
325         struct commit_list *ret = NULL;
326         while (*list) {
327                 insert_by_date((*list)->item, &ret);
328                 *list = (*list)->next;
329         }
330         *list = ret;
331 }
332
333 struct commit *pop_most_recent_commit(struct commit_list **list,
334                                       unsigned int mark)
335 {
336         struct commit *ret = (*list)->item;
337         struct commit_list *parents = ret->parents;
338         struct commit_list *old = *list;
339
340         *list = (*list)->next;
341         free(old);
342
343         while (parents) {
344                 struct commit *commit = parents->item;
345                 parse_commit(commit);
346                 if (!(commit->object.flags & mark)) {
347                         commit->object.flags |= mark;
348                         insert_by_date(commit, list);
349                 }
350                 parents = parents->next;
351         }
352         return ret;
353 }
354
355 void clear_commit_marks(struct commit *commit, unsigned int mark)
356 {
357         struct commit_list *parents;
358
359         parents = commit->parents;
360         commit->object.flags &= ~mark;
361         while (parents) {
362                 struct commit *parent = parents->item;
363                 if (parent && parent->object.parsed &&
364                     (parent->object.flags & mark))
365                         clear_commit_marks(parent, mark);
366                 parents = parents->next;
367         }
368 }
369
370 /*
371  * Generic support for pretty-printing the header
372  */
373 static int get_one_line(const char *msg, unsigned long len)
374 {
375         int ret = 0;
376
377         while (len--) {
378                 char c = *msg++;
379                 ret++;
380                 if (c == '\n')
381                         break;
382                 if (!c)
383                         return 0;
384         }
385         return ret;
386 }
387
388 static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const char *line)
389 {
390         char *date;
391         int namelen;
392         unsigned long time;
393         int tz, ret;
394         const char *filler = "    ";
395
396         if (fmt == CMIT_FMT_ONELINE)
397                 return 0;
398         date = strchr(line, '>');
399         if (!date)
400                 return 0;
401         namelen = ++date - line;
402         time = strtoul(date, &date, 10);
403         tz = strtol(date, NULL, 10);
404
405         ret = sprintf(buf, "%s: %.*s%.*s\n", what,
406                       (fmt == CMIT_FMT_FULLER) ? 4 : 0,
407                       filler, namelen, line);
408         switch (fmt) {
409         case CMIT_FMT_MEDIUM:
410                 ret += sprintf(buf + ret, "Date:   %s\n", show_date(time, tz));
411                 break;
412         case CMIT_FMT_FULLER:
413                 ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz));
414                 break;
415         default:
416                 /* notin' */
417                 break;
418         }
419         return ret;
420 }
421
422 static int is_empty_line(const char *line, int len)
423 {
424         while (len && isspace(line[len-1]))
425                 len--;
426         return !len;
427 }
428
429 static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *commit, int abbrev)
430 {
431         struct commit_list *parent = commit->parents;
432         int offset;
433
434         if ((fmt == CMIT_FMT_ONELINE) || !parent || !parent->next)
435                 return 0;
436
437         offset = sprintf(buf, "Merge:");
438
439         while (parent) {
440                 struct commit *p = parent->item;
441                 const char *hex = abbrev
442                         ? find_unique_abbrev(p->object.sha1, abbrev)
443                         : sha1_to_hex(p->object.sha1);
444                 char *dots = (abbrev && strlen(hex) != 40) ? "..." : "";
445                 parent = parent->next;
446
447                 offset += sprintf(buf + offset, " %s%s", hex, dots);
448         }
449         buf[offset++] = '\n';
450         return offset;
451 }
452
453 unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, unsigned long len, char *buf, unsigned long space, int abbrev)
454 {
455         int hdr = 1, body = 0;
456         unsigned long offset = 0;
457         int indent = (fmt == CMIT_FMT_ONELINE) ? 0 : 4;
458         int parents_shown = 0;
459         const char *msg = commit->buffer;
460
461         for (;;) {
462                 const char *line = msg;
463                 int linelen = get_one_line(msg, len);
464
465                 if (!linelen)
466                         break;
467
468                 /*
469                  * We want some slop for indentation and a possible
470                  * final "...". Thus the "+ 20".
471                  */
472                 if (offset + linelen + 20 > space) {
473                         memcpy(buf + offset, "    ...\n", 8);
474                         offset += 8;
475                         break;
476                 }
477
478                 msg += linelen;
479                 len -= linelen;
480                 if (hdr) {
481                         if (linelen == 1) {
482                                 hdr = 0;
483                                 if (fmt != CMIT_FMT_ONELINE)
484                                         buf[offset++] = '\n';
485                                 continue;
486                         }
487                         if (fmt == CMIT_FMT_RAW) {
488                                 memcpy(buf + offset, line, linelen);
489                                 offset += linelen;
490                                 continue;
491                         }
492                         if (!memcmp(line, "parent ", 7)) {
493                                 if (linelen != 48)
494                                         die("bad parent line in commit");
495                                 continue;
496                         }
497
498                         if (!parents_shown) {
499                                 offset += add_merge_info(fmt, buf + offset,
500                                                          commit, abbrev);
501                                 parents_shown = 1;
502                                 continue;
503                         }
504                         /*
505                          * MEDIUM == DEFAULT shows only author with dates.
506                          * FULL shows both authors but not dates.
507                          * FULLER shows both authors and dates.
508                          */
509                         if (!memcmp(line, "author ", 7))
510                                 offset += add_user_info("Author", fmt,
511                                                         buf + offset,
512                                                         line + 7);
513                         if (!memcmp(line, "committer ", 10) &&
514                             (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER))
515                                 offset += add_user_info("Commit", fmt,
516                                                         buf + offset,
517                                                         line + 10);
518                         continue;
519                 }
520
521                 if (is_empty_line(line, linelen)) {
522                         if (!body)
523                                 continue;
524                         if (fmt == CMIT_FMT_SHORT)
525                                 break;
526                 } else {
527                         body = 1;
528                 }
529
530                 memset(buf + offset, ' ', indent);
531                 memcpy(buf + offset + indent, line, linelen);
532                 offset += linelen + indent;
533                 if (fmt == CMIT_FMT_ONELINE)
534                         break;
535         }
536         if (fmt == CMIT_FMT_ONELINE) {
537                 /* We do not want the terminating newline */
538                 if (buf[offset - 1] == '\n')
539                         offset--;
540         }
541         else {
542                 /* Make sure there is an EOLN */
543                 if (buf[offset - 1] != '\n')
544                         buf[offset++] = '\n';
545         }
546         buf[offset] = '\0';
547         return offset;
548 }
549
550 struct commit *pop_commit(struct commit_list **stack)
551 {
552         struct commit_list *top = *stack;
553         struct commit *item = top ? top->item : NULL;
554
555         if (top) {
556                 *stack = top->next;
557                 free(top);
558         }
559         return item;
560 }
561
562 int count_parents(struct commit * commit)
563 {
564         int count = 0;
565         struct commit_list * parents = commit->parents;
566         for (count=0;parents; parents=parents->next,count++)
567           ;
568         return count;
569 }
570
571 void topo_sort_default_setter(struct commit *c, void *data)
572 {
573         c->object.util = data;
574 }
575
576 void *topo_sort_default_getter(struct commit *c)
577 {
578         return c->object.util;
579 }
580
581 /*
582  * Performs an in-place topological sort on the list supplied.
583  */
584 void sort_in_topological_order(struct commit_list ** list, int lifo)
585 {
586         sort_in_topological_order_fn(list, lifo, topo_sort_default_setter,
587                                      topo_sort_default_getter);
588 }
589
590 void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
591                                   topo_sort_set_fn_t setter,
592                                   topo_sort_get_fn_t getter)
593 {
594         struct commit_list * next = *list;
595         struct commit_list * work = NULL, **insert;
596         struct commit_list ** pptr = list;
597         struct sort_node * nodes;
598         struct sort_node * next_nodes;
599         int count = 0;
600
601         /* determine the size of the list */
602         while (next) {
603                 next = next->next;
604                 count++;
605         }
606         
607         if (!count)
608                 return;
609         /* allocate an array to help sort the list */
610         nodes = xcalloc(count, sizeof(*nodes));
611         /* link the list to the array */
612         next_nodes = nodes;
613         next=*list;
614         while (next) {
615                 next_nodes->list_item = next;
616                 setter(next->item, next_nodes);
617                 next_nodes++;
618                 next = next->next;
619         }
620         /* update the indegree */
621         next=*list;
622         while (next) {
623                 struct commit_list * parents = next->item->parents;
624                 while (parents) {
625                         struct commit * parent=parents->item;
626                         struct sort_node * pn = (struct sort_node *) getter(parent);
627
628                         if (pn)
629                                 pn->indegree++;
630                         parents=parents->next;
631                 }
632                 next=next->next;
633         }
634         /* 
635          * find the tips
636          *
637          * tips are nodes not reachable from any other node in the list 
638          * 
639          * the tips serve as a starting set for the work queue.
640          */
641         next=*list;
642         insert = &work;
643         while (next) {
644                 struct sort_node * node = (struct sort_node *) getter(next->item);
645
646                 if (node->indegree == 0) {
647                         insert = &commit_list_insert(next->item, insert)->next;
648                 }
649                 next=next->next;
650         }
651
652         /* process the list in topological order */
653         if (!lifo)
654                 sort_by_date(&work);
655         while (work) {
656                 struct commit * work_item = pop_commit(&work);
657                 struct sort_node * work_node = (struct sort_node *) getter(work_item);
658                 struct commit_list * parents = work_item->parents;
659
660                 while (parents) {
661                         struct commit * parent=parents->item;
662                         struct sort_node * pn = (struct sort_node *) getter(parent);
663
664                         if (pn) {
665                                 /*
666                                  * parents are only enqueued for emission 
667                                  * when all their children have been emitted thereby
668                                  * guaranteeing topological order.
669                                  */
670                                 pn->indegree--;
671                                 if (!pn->indegree) {
672                                         if (!lifo)
673                                                 insert_by_date(parent, &work);
674                                         else
675                                                 commit_list_insert(parent, &work);
676                                 }
677                         }
678                         parents=parents->next;
679                 }
680                 /*
681                  * work_item is a commit all of whose children
682                  * have already been emitted. we can emit it now.
683                  */
684                 *pptr = work_node->list_item;
685                 pptr = &(*pptr)->next;
686                 *pptr = NULL;
687                 setter(work_item, NULL);
688         }
689         free(nodes);
690 }