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