Merge branch 'lt/diff' into next
[git.git] / blame.c
1 /*
2  * Copyright (C) 2006, Fredrik Kuivinen <freku045@student.liu.se>
3  */
4
5 #include <assert.h>
6 #include <time.h>
7 #include <sys/time.h>
8 #include <math.h>
9
10 #include "cache.h"
11 #include "refs.h"
12 #include "tag.h"
13 #include "commit.h"
14 #include "tree.h"
15 #include "blob.h"
16 #include "diff.h"
17 #include "diffcore.h"
18 #include "revision.h"
19
20 #define DEBUG 0
21
22 static const char blame_usage[] = "[-c] [-l] [--] file [commit]\n"
23         "  -c, --compability Use the same output mode as git-annotate (Default: off)\n"
24         "  -l, --long        Show long commit SHA1 (Default: off)\n"
25         "  -h, --help        This message";
26
27 static struct commit **blame_lines;
28 static int num_blame_lines;
29 static char* blame_contents;
30 static int blame_len;
31
32 struct util_info {
33         int *line_map;
34         unsigned char sha1[20]; /* blob sha, not commit! */
35         char *buf;
36         unsigned long size;
37         int num_lines;
38         const char* pathname;
39
40         void* topo_data;
41 };
42
43 struct chunk {
44         int off1, len1; // ---
45         int off2, len2; // +++
46 };
47
48 struct patch {
49         struct chunk *chunks;
50         int num;
51 };
52
53 static void get_blob(struct commit *commit);
54
55 /* Only used for statistics */
56 static int num_get_patch = 0;
57 static int num_commits = 0;
58 static int patch_time = 0;
59
60 #define TEMPFILE_PATH_LEN 60
61 static struct patch *get_patch(struct commit *commit, struct commit *other)
62 {
63         struct patch *ret;
64         struct util_info *info_c = (struct util_info *)commit->object.util;
65         struct util_info *info_o = (struct util_info *)other->object.util;
66         char tmp_path1[TEMPFILE_PATH_LEN], tmp_path2[TEMPFILE_PATH_LEN];
67         char diff_cmd[TEMPFILE_PATH_LEN*2 + 20];
68         struct timeval tv_start, tv_end;
69         int fd;
70         FILE *fin;
71         char buf[1024];
72
73         ret = xmalloc(sizeof(struct patch));
74         ret->chunks = NULL;
75         ret->num = 0;
76
77         get_blob(commit);
78         get_blob(other);
79
80         gettimeofday(&tv_start, NULL);
81
82         fd = git_mkstemp(tmp_path1, TEMPFILE_PATH_LEN, "git-blame-XXXXXX");
83         if (fd < 0)
84                 die("unable to create temp-file: %s", strerror(errno));
85
86         if (xwrite(fd, info_c->buf, info_c->size) != info_c->size)
87                 die("write failed: %s", strerror(errno));
88         close(fd);
89
90         fd = git_mkstemp(tmp_path2, TEMPFILE_PATH_LEN, "git-blame-XXXXXX");
91         if (fd < 0)
92                 die("unable to create temp-file: %s", strerror(errno));
93
94         if (xwrite(fd, info_o->buf, info_o->size) != info_o->size)
95                 die("write failed: %s", strerror(errno));
96         close(fd);
97
98         sprintf(diff_cmd, "diff -U 0 %s %s", tmp_path1, tmp_path2);
99         fin = popen(diff_cmd, "r");
100         if (!fin)
101                 die("popen failed: %s", strerror(errno));
102
103         while (fgets(buf, sizeof(buf), fin)) {
104                 struct chunk *chunk;
105                 char *start, *sp;
106
107                 if (buf[0] != '@' || buf[1] != '@')
108                         continue;
109
110                 if (DEBUG)
111                         printf("chunk line: %s", buf);
112                 ret->num++;
113                 ret->chunks = xrealloc(ret->chunks,
114                                        sizeof(struct chunk) * ret->num);
115                 chunk = &ret->chunks[ret->num - 1];
116
117                 assert(!strncmp(buf, "@@ -", 4));
118
119                 start = buf + 4;
120                 sp = index(start, ' ');
121                 *sp = '\0';
122                 if (index(start, ',')) {
123                         int ret =
124                             sscanf(start, "%d,%d", &chunk->off1, &chunk->len1);
125                         assert(ret == 2);
126                 } else {
127                         int ret = sscanf(start, "%d", &chunk->off1);
128                         assert(ret == 1);
129                         chunk->len1 = 1;
130                 }
131                 *sp = ' ';
132
133                 start = sp + 1;
134                 sp = index(start, ' ');
135                 *sp = '\0';
136                 if (index(start, ',')) {
137                         int ret =
138                             sscanf(start, "%d,%d", &chunk->off2, &chunk->len2);
139                         assert(ret == 2);
140                 } else {
141                         int ret = sscanf(start, "%d", &chunk->off2);
142                         assert(ret == 1);
143                         chunk->len2 = 1;
144                 }
145                 *sp = ' ';
146
147                 if (chunk->len1 == 0)
148                         chunk->off1++;
149                 if (chunk->len2 == 0)
150                         chunk->off2++;
151
152                 if (chunk->off1 > 0)
153                         chunk->off1--;
154                 if (chunk->off2 > 0)
155                         chunk->off2--;
156
157                 assert(chunk->off1 >= 0);
158                 assert(chunk->off2 >= 0);
159         }
160         pclose(fin);
161         unlink(tmp_path1);
162         unlink(tmp_path2);
163
164         gettimeofday(&tv_end, NULL);
165         patch_time += 1000000 * (tv_end.tv_sec - tv_start.tv_sec) +
166                 tv_end.tv_usec - tv_start.tv_usec;
167
168         num_get_patch++;
169         return ret;
170 }
171
172 static void free_patch(struct patch *p)
173 {
174         free(p->chunks);
175         free(p);
176 }
177
178 static int get_blob_sha1_internal(unsigned char *sha1, const char *base,
179                                   int baselen, const char *pathname,
180                                   unsigned mode, int stage);
181
182 static unsigned char blob_sha1[20];
183 static int get_blob_sha1(struct tree *t, const char *pathname,
184                          unsigned char *sha1)
185 {
186         int i;
187         const char *pathspec[2];
188         pathspec[0] = pathname;
189         pathspec[1] = NULL;
190         memset(blob_sha1, 0, sizeof(blob_sha1));
191         read_tree_recursive(t, "", 0, 0, pathspec, get_blob_sha1_internal);
192
193         for (i = 0; i < 20; i++) {
194                 if (blob_sha1[i] != 0)
195                         break;
196         }
197
198         if (i == 20)
199                 return -1;
200
201         memcpy(sha1, blob_sha1, 20);
202         return 0;
203 }
204
205 static int get_blob_sha1_internal(unsigned char *sha1, const char *base,
206                                   int baselen, const char *pathname,
207                                   unsigned mode, int stage)
208 {
209         if (S_ISDIR(mode))
210                 return READ_TREE_RECURSIVE;
211
212         memcpy(blob_sha1, sha1, 20);
213         return -1;
214 }
215
216 static void get_blob(struct commit *commit)
217 {
218         struct util_info *info = commit->object.util;
219         char type[20];
220
221         if (info->buf)
222                 return;
223
224         info->buf = read_sha1_file(info->sha1, type, &info->size);
225
226         assert(!strcmp(type, "blob"));
227 }
228
229 /* For debugging only */
230 static void print_patch(struct patch *p)
231 {
232         int i;
233         printf("Num chunks: %d\n", p->num);
234         for (i = 0; i < p->num; i++) {
235                 printf("%d,%d %d,%d\n", p->chunks[i].off1, p->chunks[i].len1,
236                        p->chunks[i].off2, p->chunks[i].len2);
237         }
238 }
239
240 #if DEBUG
241 /* For debugging only */
242 static void print_map(struct commit *cmit, struct commit *other)
243 {
244         struct util_info *util = cmit->object.util;
245         struct util_info *util2 = other->object.util;
246
247         int i;
248         int max =
249             util->num_lines >
250             util2->num_lines ? util->num_lines : util2->num_lines;
251         int num;
252
253         for (i = 0; i < max; i++) {
254                 printf("i: %d ", i);
255                 num = -1;
256
257                 if (i < util->num_lines) {
258                         num = util->line_map[i];
259                         printf("%d\t", num);
260                 } else
261                         printf("\t");
262
263                 if (i < util2->num_lines) {
264                         int num2 = util2->line_map[i];
265                         printf("%d\t", num2);
266                         if (num != -1 && num2 != num)
267                                 printf("---");
268                 } else
269                         printf("\t");
270
271                 printf("\n");
272         }
273 }
274 #endif
275
276 // p is a patch from commit to other.
277 static void fill_line_map(struct commit *commit, struct commit *other,
278                           struct patch *p)
279 {
280         struct util_info *util = commit->object.util;
281         struct util_info *util2 = other->object.util;
282         int *map = util->line_map;
283         int *map2 = util2->line_map;
284         int cur_chunk = 0;
285         int i1, i2;
286
287         if (p->num && DEBUG)
288                 print_patch(p);
289
290         if (DEBUG)
291                 printf("num lines 1: %d num lines 2: %d\n", util->num_lines,
292                        util2->num_lines);
293
294         for (i1 = 0, i2 = 0; i1 < util->num_lines; i1++, i2++) {
295                 struct chunk *chunk = NULL;
296                 if (cur_chunk < p->num)
297                         chunk = &p->chunks[cur_chunk];
298
299                 if (chunk && chunk->off1 == i1) {
300                         if (DEBUG && i2 != chunk->off2)
301                                 printf("i2: %d off2: %d\n", i2, chunk->off2);
302
303                         assert(i2 == chunk->off2);
304
305                         i1--;
306                         i2--;
307                         if (chunk->len1 > 0)
308                                 i1 += chunk->len1;
309
310                         if (chunk->len2 > 0)
311                                 i2 += chunk->len2;
312
313                         cur_chunk++;
314                 } else {
315                         if (i2 >= util2->num_lines)
316                                 break;
317
318                         if (map[i1] != map2[i2] && map[i1] != -1) {
319                                 if (DEBUG)
320                                         printf("map: i1: %d %d %p i2: %d %d %p\n",
321                                                i1, map[i1],
322                                                i1 != -1 ? blame_lines[map[i1]] : NULL,
323                                                i2, map2[i2],
324                                                i2 != -1 ? blame_lines[map2[i2]] : NULL);
325                                 if (map2[i2] != -1 &&
326                                     blame_lines[map[i1]] &&
327                                     !blame_lines[map2[i2]])
328                                         map[i1] = map2[i2];
329                         }
330
331                         if (map[i1] == -1 && map2[i2] != -1)
332                                 map[i1] = map2[i2];
333                 }
334
335                 if (DEBUG > 1)
336                         printf("l1: %d l2: %d i1: %d i2: %d\n",
337                                map[i1], map2[i2], i1, i2);
338         }
339 }
340
341 static int map_line(struct commit *commit, int line)
342 {
343         struct util_info *info = commit->object.util;
344         assert(line >= 0 && line < info->num_lines);
345         return info->line_map[line];
346 }
347
348 static struct util_info* get_util(struct commit *commit)
349 {
350         struct util_info *util = commit->object.util;
351
352         if (util)
353                 return util;
354
355         util = xmalloc(sizeof(struct util_info));
356         util->buf = NULL;
357         util->size = 0;
358         util->line_map = NULL;
359         util->num_lines = -1;
360         util->pathname = NULL;
361         commit->object.util = util;
362         return util;
363 }
364
365 static int fill_util_info(struct commit *commit)
366 {
367         struct util_info *util = commit->object.util;
368
369         assert(util);
370         assert(util->pathname);
371
372         if (get_blob_sha1(commit->tree, util->pathname, util->sha1))
373                 return 1;
374         else
375                 return 0;
376 }
377
378 static void alloc_line_map(struct commit *commit)
379 {
380         struct util_info *util = commit->object.util;
381         int i;
382
383         if (util->line_map)
384                 return;
385
386         get_blob(commit);
387
388         util->num_lines = 0;
389         for (i = 0; i < util->size; i++) {
390                 if (util->buf[i] == '\n')
391                         util->num_lines++;
392         }
393         if(util->buf[util->size - 1] != '\n')
394                 util->num_lines++;
395
396         util->line_map = xmalloc(sizeof(int) * util->num_lines);
397
398         for (i = 0; i < util->num_lines; i++)
399                 util->line_map[i] = -1;
400 }
401
402 static void init_first_commit(struct commit* commit, const char* filename)
403 {
404         struct util_info* util = commit->object.util;
405         int i;
406
407         util->pathname = filename;
408         if (fill_util_info(commit))
409                 die("fill_util_info failed");
410
411         alloc_line_map(commit);
412
413         util = commit->object.util;
414
415         for (i = 0; i < util->num_lines; i++)
416                 util->line_map[i] = i;
417 }
418
419
420 static void process_commits(struct rev_info *rev, const char *path,
421                             struct commit** initial)
422 {
423         int i;
424         struct util_info* util;
425         int lines_left;
426         int *blame_p;
427         int *new_lines;
428         int new_lines_len;
429
430         struct commit* commit = get_revision(rev);
431         assert(commit);
432         init_first_commit(commit, path);
433
434         util = commit->object.util;
435         num_blame_lines = util->num_lines;
436         blame_lines = xmalloc(sizeof(struct commit *) * num_blame_lines);
437         blame_contents = util->buf;
438         blame_len = util->size;
439
440         for (i = 0; i < num_blame_lines; i++)
441                 blame_lines[i] = NULL;
442
443         lines_left = num_blame_lines;
444         blame_p = xmalloc(sizeof(int) * num_blame_lines);
445         new_lines = xmalloc(sizeof(int) * num_blame_lines);
446         do {
447                 struct commit_list *parents;
448                 int num_parents;
449                 struct util_info *util;
450
451                 if (DEBUG)
452                         printf("\nProcessing commit: %d %s\n", num_commits,
453                                sha1_to_hex(commit->object.sha1));
454
455                 if (lines_left == 0)
456                         return;
457
458                 num_commits++;
459                 memset(blame_p, 0, sizeof(int) * num_blame_lines);
460                 new_lines_len = 0;
461                 num_parents = 0;
462                 for (parents = commit->parents;
463                      parents != NULL; parents = parents->next)
464                         num_parents++;
465
466                 if(num_parents == 0)
467                         *initial = commit;
468
469                 if (fill_util_info(commit))
470                         continue;
471
472                 alloc_line_map(commit);
473                 util = commit->object.util;
474
475                 for (parents = commit->parents;
476                      parents != NULL; parents = parents->next) {
477                         struct commit *parent = parents->item;
478                         struct patch *patch;
479
480                         if (parse_commit(parent) < 0)
481                                 die("parse_commit error");
482
483                         if (DEBUG)
484                                 printf("parent: %s\n",
485                                        sha1_to_hex(parent->object.sha1));
486
487                         if (fill_util_info(parent)) {
488                                 num_parents--;
489                                 continue;
490                         }
491
492                         patch = get_patch(parent, commit);
493                         alloc_line_map(parent);
494                         fill_line_map(parent, commit, patch);
495
496                         for (i = 0; i < patch->num; i++) {
497                             int l;
498                             for (l = 0; l < patch->chunks[i].len2; l++) {
499                                 int mapped_line =
500                                     map_line(commit, patch->chunks[i].off2 + l);
501                                 if (mapped_line != -1) {
502                                     blame_p[mapped_line]++;
503                                     if (blame_p[mapped_line] == num_parents)
504                                         new_lines[new_lines_len++] = mapped_line;
505                                 }
506                             }
507                         }
508                         free_patch(patch);
509                 }
510
511                 if (DEBUG)
512                         printf("parents: %d\n", num_parents);
513
514                 for (i = 0; i < new_lines_len; i++) {
515                         int mapped_line = new_lines[i];
516                         if (blame_lines[mapped_line] == NULL) {
517                                 blame_lines[mapped_line] = commit;
518                                 lines_left--;
519                                 if (DEBUG)
520                                         printf("blame: mapped: %d i: %d\n",
521                                                mapped_line, i);
522                         }
523                 }
524         } while ((commit = get_revision(rev)) != NULL);
525 }
526
527
528 static int compare_tree_path(struct rev_info* revs,
529                              struct commit* c1, struct commit* c2)
530 {
531         const char* paths[2];
532         struct util_info* util = c2->object.util;
533         paths[0] = util->pathname;
534         paths[1] = NULL;
535
536         diff_tree_setup_paths(get_pathspec(revs->prefix, paths));
537         return rev_compare_tree(c1->tree, c2->tree);
538 }
539
540
541 static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1,
542                                    const char* path)
543 {
544         const char* paths[2];
545         paths[0] = path;
546         paths[1] = NULL;
547
548         diff_tree_setup_paths(get_pathspec(revs->prefix, paths));
549         return rev_same_tree_as_empty(t1);
550 }
551
552 static const char* find_rename(struct commit* commit, struct commit* parent)
553 {
554         struct util_info* cutil = commit->object.util;
555         struct diff_options diff_opts;
556         const char *paths[1];
557         int i;
558
559         if (DEBUG) {
560                 printf("find_rename commit: %s ",
561                        sha1_to_hex(commit->object.sha1));
562                 puts(sha1_to_hex(parent->object.sha1));
563         }
564
565         diff_setup(&diff_opts);
566         diff_opts.recursive = 1;
567         diff_opts.detect_rename = DIFF_DETECT_RENAME;
568         paths[0] = NULL;
569         diff_tree_setup_paths(paths);
570         if (diff_setup_done(&diff_opts) < 0)
571                 die("diff_setup_done failed");
572
573         diff_tree_sha1(commit->tree->object.sha1, parent->tree->object.sha1,
574                        "", &diff_opts);
575         diffcore_std(&diff_opts);
576
577         for (i = 0; i < diff_queued_diff.nr; i++) {
578                 struct diff_filepair *p = diff_queued_diff.queue[i];
579
580                 if (p->status == 'R' && !strcmp(p->one->path, cutil->pathname)) {
581                         if (DEBUG)
582                                 printf("rename %s -> %s\n", p->one->path, p->two->path);
583                         return p->two->path;
584                 }
585         }
586
587         return 0;
588 }
589
590 static void simplify_commit(struct rev_info *revs, struct commit *commit)
591 {
592         struct commit_list **pp, *parent;
593
594         if (!commit->tree)
595                 return;
596
597         if (!commit->parents) {
598                 struct util_info* util = commit->object.util;
599                 if (!same_tree_as_empty_path(revs, commit->tree,
600                                              util->pathname))
601                         commit->object.flags |= TREECHANGE;
602                 return;
603         }
604
605         pp = &commit->parents;
606         while ((parent = *pp) != NULL) {
607                 struct commit *p = parent->item;
608
609                 if (p->object.flags & UNINTERESTING) {
610                         pp = &parent->next;
611                         continue;
612                 }
613
614                 parse_commit(p);
615                 switch (compare_tree_path(revs, p, commit)) {
616                 case REV_TREE_SAME:
617                         parent->next = NULL;
618                         commit->parents = parent;
619                         get_util(p)->pathname = get_util(commit)->pathname;
620                         return;
621
622                 case REV_TREE_NEW:
623                 {
624
625                         struct util_info* util = commit->object.util;
626                         if (revs->remove_empty_trees &&
627                             same_tree_as_empty_path(revs, p->tree,
628                                                     util->pathname)) {
629                                 const char* new_name = find_rename(commit, p);
630                                 if (new_name) {
631                                         struct util_info* putil = get_util(p);
632                                         if (!putil->pathname)
633                                                 putil->pathname = strdup(new_name);
634                                 } else {
635                                         *pp = parent->next;
636                                         continue;
637                                 }
638                         }
639                 }
640
641                 /* fallthrough */
642                 case REV_TREE_DIFFERENT:
643                         pp = &parent->next;
644                         if (!get_util(p)->pathname)
645                                 get_util(p)->pathname =
646                                         get_util(commit)->pathname;
647                         continue;
648                 }
649                 die("bad tree compare for commit %s",
650                     sha1_to_hex(commit->object.sha1));
651         }
652         commit->object.flags |= TREECHANGE;
653 }
654
655
656 struct commit_info
657 {
658         char* author;
659         char* author_mail;
660         unsigned long author_time;
661         char* author_tz;
662 };
663
664 static void get_commit_info(struct commit* commit, struct commit_info* ret)
665 {
666         int len;
667         char* tmp;
668         static char author_buf[1024];
669
670         tmp = strstr(commit->buffer, "\nauthor ") + 8;
671         len = index(tmp, '\n') - tmp;
672         ret->author = author_buf;
673         memcpy(ret->author, tmp, len);
674
675         tmp = ret->author;
676         tmp += len;
677         *tmp = 0;
678         while(*tmp != ' ')
679                 tmp--;
680         ret->author_tz = tmp+1;
681
682         *tmp = 0;
683         while(*tmp != ' ')
684                 tmp--;
685         ret->author_time = strtoul(tmp, NULL, 10);
686
687         *tmp = 0;
688         while(*tmp != ' ')
689                 tmp--;
690         ret->author_mail = tmp + 1;
691
692         *tmp = 0;
693 }
694
695 static const char* format_time(unsigned long time, const char* tz_str)
696 {
697         static char time_buf[128];
698         time_t t = time;
699         int minutes, tz;
700         struct tm *tm;
701
702         tz = atoi(tz_str);
703         minutes = tz < 0 ? -tz : tz;
704         minutes = (minutes / 100)*60 + (minutes % 100);
705         minutes = tz < 0 ? -minutes : minutes;
706         t = time + minutes * 60;
707         tm = gmtime(&t);
708
709         strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
710         strcat(time_buf, tz_str);
711         return time_buf;
712 }
713
714 static void topo_setter(struct commit* c, void* data)
715 {
716         struct util_info* util = c->object.util;
717         util->topo_data = data;
718 }
719
720 static void* topo_getter(struct commit* c)
721 {
722         struct util_info* util = c->object.util;
723         return util->topo_data;
724 }
725
726 int main(int argc, const char **argv)
727 {
728         int i;
729         struct commit *initial = NULL;
730         unsigned char sha1[20];
731
732         const char *filename = NULL, *commit = NULL;
733         char filename_buf[256];
734         int sha1_len = 8;
735         int compability = 0;
736         int options = 1;
737         struct commit* start_commit;
738
739         const char* args[10];
740         struct rev_info rev;
741
742         struct commit_info ci;
743         const char *buf;
744         int max_digits;
745
746         const char* prefix = setup_git_directory();
747
748         for(i = 1; i < argc; i++) {
749                 if(options) {
750                         if(!strcmp(argv[i], "-h") ||
751                            !strcmp(argv[i], "--help"))
752                                 usage(blame_usage);
753                         else if(!strcmp(argv[i], "-l") ||
754                                 !strcmp(argv[i], "--long")) {
755                                 sha1_len = 40;
756                                 continue;
757                         } else if(!strcmp(argv[i], "-c") ||
758                                   !strcmp(argv[i], "--compability")) {
759                                 compability = 1;
760                                 continue;
761                         } else if(!strcmp(argv[i], "--")) {
762                                 options = 0;
763                                 continue;
764                         } else if(argv[i][0] == '-')
765                                 usage(blame_usage);
766                         else
767                                 options = 0;
768                 }
769
770                 if(!options) {
771                         if(!filename)
772                                 filename = argv[i];
773                         else if(!commit)
774                                 commit = argv[i];
775                         else
776                                 usage(blame_usage);
777                 }
778         }
779
780         if(!filename)
781                 usage(blame_usage);
782         if(!commit)
783                 commit = "HEAD";
784
785         if(prefix)
786                 sprintf(filename_buf, "%s%s", prefix, filename);
787         else
788                 strcpy(filename_buf, filename);
789         filename = filename_buf;
790
791         if (get_sha1(commit, sha1))
792                 die("get_sha1 failed, commit '%s' not found", commit);
793         start_commit = lookup_commit_reference(sha1);
794         get_util(start_commit)->pathname = filename;
795         if (fill_util_info(start_commit)) {
796                 printf("%s not found in %s\n", filename, commit);
797                 return 1;
798         }
799
800
801         init_revisions(&rev);
802         rev.remove_empty_trees = 1;
803         rev.topo_order = 1;
804         rev.prune_fn = simplify_commit;
805         rev.topo_setter = topo_setter;
806         rev.topo_getter = topo_getter;
807         rev.limited = 1;
808
809         commit_list_insert(start_commit, &rev.commits);
810
811         args[0] = filename;
812         args[1] = NULL;
813         diff_tree_setup_paths(args);
814         prepare_revision_walk(&rev);
815         process_commits(&rev, filename, &initial);
816
817         buf = blame_contents;
818         for (max_digits = 1, i = 10; i <= num_blame_lines + 1; max_digits++)
819                 i *= 10;
820
821         for (i = 0; i < num_blame_lines; i++) {
822                 struct commit *c = blame_lines[i];
823                 struct util_info* u;
824
825                 if (!c)
826                         c = initial;
827
828                 u = c->object.util;
829                 get_commit_info(c, &ci);
830                 fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
831                 if(compability)
832                         printf("\t(%10s\t%10s\t%d)", ci.author,
833                                format_time(ci.author_time, ci.author_tz), i+1);
834                 else
835                         printf(" %s (%-15.15s %10s %*d) ", u->pathname,
836                                ci.author, format_time(ci.author_time,
837                                                       ci.author_tz),
838                                max_digits, i+1);
839
840                 if(i == num_blame_lines - 1) {
841                         fwrite(buf, blame_len - (buf - blame_contents),
842                                1, stdout);
843                         if(blame_contents[blame_len-1] != '\n')
844                                 putc('\n', stdout);
845                 } else {
846                         char* next_buf = index(buf, '\n') + 1;
847                         fwrite(buf, next_buf - buf, 1, stdout);
848                         buf = next_buf;
849                 }
850         }
851
852         if (DEBUG) {
853                 printf("num get patch: %d\n", num_get_patch);
854                 printf("num commits: %d\n", num_commits);
855                 printf("patch time: %f\n", patch_time / 1000000.0);
856                 printf("initial: %s\n", sha1_to_hex(initial->object.sha1));
857         }
858
859         return 0;
860 }