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