Code

Make show_entry void
[git.git] / blame.c
1 /*
2  * Copyright (C) 2006, Fredrik Kuivinen <freku045@student.liu.se>
3  */
5 #include <assert.h>
6 #include <time.h>
7 #include <sys/time.h>
8 #include <math.h>
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 #include "xdiff-interface.h"
21 #define DEBUG 0
23 static const char blame_usage[] = "git-blame [-c] [-l] [-t] [-S <revs-file>] [--] file [commit]\n"
24         "  -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
25         "  -l, --long          Show long commit SHA1 (Default: off)\n"
26         "  -t, --time          Show raw timestamp (Default: off)\n"
27         "  -S, --revs-file     Use revisions from revs-file instead of calling git-rev-list\n"
28         "  -h, --help          This message";
30 static struct commit **blame_lines;
31 static int num_blame_lines;
32 static char* blame_contents;
33 static int blame_len;
35 struct util_info {
36         int *line_map;
37         unsigned char sha1[20]; /* blob sha, not commit! */
38         char *buf;
39         unsigned long size;
40         int num_lines;
41         const char* pathname;
43         void* topo_data;
44 };
46 struct chunk {
47         int off1, len1; /* --- */
48         int off2, len2; /* +++ */
49 };
51 struct patch {
52         struct chunk *chunks;
53         int num;
54 };
56 static void get_blob(struct commit *commit);
58 /* Only used for statistics */
59 static int num_get_patch = 0;
60 static int num_commits = 0;
61 static int patch_time = 0;
63 struct blame_diff_state {
64         struct xdiff_emit_state xm;
65         struct patch *ret;
66 };
68 static void process_u0_diff(void *state_, char *line, unsigned long len)
69 {
70         struct blame_diff_state *state = state_;
71         struct chunk *chunk;
73         if (len < 4 || line[0] != '@' || line[1] != '@')
74                 return;
76         if (DEBUG)
77                 printf("chunk line: %.*s", (int)len, line);
78         state->ret->num++;
79         state->ret->chunks = xrealloc(state->ret->chunks,
80                                       sizeof(struct chunk) * state->ret->num);
81         chunk = &state->ret->chunks[state->ret->num - 1];
83         assert(!strncmp(line, "@@ -", 4));
85         if (parse_hunk_header(line, len,
86                               &chunk->off1, &chunk->len1,
87                               &chunk->off2, &chunk->len2)) {
88                 state->ret->num--;
89                 return;
90         }
92         if (chunk->len1 == 0)
93                 chunk->off1++;
94         if (chunk->len2 == 0)
95                 chunk->off2++;
97         if (chunk->off1 > 0)
98                 chunk->off1--;
99         if (chunk->off2 > 0)
100                 chunk->off2--;
102         assert(chunk->off1 >= 0);
103         assert(chunk->off2 >= 0);
106 static struct patch *get_patch(struct commit *commit, struct commit *other)
108         struct blame_diff_state state;
109         xpparam_t xpp;
110         xdemitconf_t xecfg;
111         mmfile_t file_c, file_o;
112         xdemitcb_t ecb;
113         struct util_info *info_c = (struct util_info *)commit->util;
114         struct util_info *info_o = (struct util_info *)other->util;
115         struct timeval tv_start, tv_end;
117         get_blob(commit);
118         file_c.ptr = info_c->buf;
119         file_c.size = info_c->size;
121         get_blob(other);
122         file_o.ptr = info_o->buf;
123         file_o.size = info_o->size;
125         gettimeofday(&tv_start, NULL);
127         xpp.flags = XDF_NEED_MINIMAL;
128         xecfg.ctxlen = 0;
129         xecfg.flags = 0;
130         ecb.outf = xdiff_outf;
131         ecb.priv = &state;
132         memset(&state, 0, sizeof(state));
133         state.xm.consume = process_u0_diff;
134         state.ret = xmalloc(sizeof(struct patch));
135         state.ret->chunks = NULL;
136         state.ret->num = 0;
138         xdl_diff(&file_c, &file_o, &xpp, &xecfg, &ecb);
140         gettimeofday(&tv_end, NULL);
141         patch_time += 1000000 * (tv_end.tv_sec - tv_start.tv_sec) +
142                 tv_end.tv_usec - tv_start.tv_usec;
144         num_get_patch++;
145         return state.ret;
148 static void free_patch(struct patch *p)
150         free(p->chunks);
151         free(p);
154 static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
155                                   int baselen, const char *pathname,
156                                   unsigned mode, int stage);
158 static unsigned char blob_sha1[20];
159 static const char* blame_file;
160 static int get_blob_sha1(struct tree *t, const char *pathname,
161                          unsigned char *sha1)
163         int i;
164         const char *pathspec[2];
165         blame_file = pathname;
166         pathspec[0] = pathname;
167         pathspec[1] = NULL;
168         memset(blob_sha1, 0, sizeof(blob_sha1));
169         read_tree_recursive(t, "", 0, 0, pathspec, get_blob_sha1_internal);
171         for (i = 0; i < 20; i++) {
172                 if (blob_sha1[i] != 0)
173                         break;
174         }
176         if (i == 20)
177                 return -1;
179         memcpy(sha1, blob_sha1, 20);
180         return 0;
183 static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
184                                   int baselen, const char *pathname,
185                                   unsigned mode, int stage)
187         if (S_ISDIR(mode))
188                 return READ_TREE_RECURSIVE;
190         if (strncmp(blame_file, base, baselen) ||
191             strcmp(blame_file + baselen, pathname))
192                 return -1;
194         memcpy(blob_sha1, sha1, 20);
195         return -1;
198 static void get_blob(struct commit *commit)
200         struct util_info *info = commit->util;
201         char type[20];
203         if (info->buf)
204                 return;
206         info->buf = read_sha1_file(info->sha1, type, &info->size);
208         assert(!strcmp(type, blob_type));
211 /* For debugging only */
212 static void print_patch(struct patch *p)
214         int i;
215         printf("Num chunks: %d\n", p->num);
216         for (i = 0; i < p->num; i++) {
217                 printf("%d,%d %d,%d\n", p->chunks[i].off1, p->chunks[i].len1,
218                        p->chunks[i].off2, p->chunks[i].len2);
219         }
222 #if DEBUG
223 /* For debugging only */
224 static void print_map(struct commit *cmit, struct commit *other)
226         struct util_info *util = cmit->util;
227         struct util_info *util2 = other->util;
229         int i;
230         int max =
231             util->num_lines >
232             util2->num_lines ? util->num_lines : util2->num_lines;
233         int num;
235         for (i = 0; i < max; i++) {
236                 printf("i: %d ", i);
237                 num = -1;
239                 if (i < util->num_lines) {
240                         num = util->line_map[i];
241                         printf("%d\t", num);
242                 } else
243                         printf("\t");
245                 if (i < util2->num_lines) {
246                         int num2 = util2->line_map[i];
247                         printf("%d\t", num2);
248                         if (num != -1 && num2 != num)
249                                 printf("---");
250                 } else
251                         printf("\t");
253                 printf("\n");
254         }
256 #endif
258 /* p is a patch from commit to other. */
259 static void fill_line_map(struct commit *commit, struct commit *other,
260                           struct patch *p)
262         struct util_info *util = commit->util;
263         struct util_info *util2 = other->util;
264         int *map = util->line_map;
265         int *map2 = util2->line_map;
266         int cur_chunk = 0;
267         int i1, i2;
269         if (p->num && DEBUG)
270                 print_patch(p);
272         if (DEBUG)
273                 printf("num lines 1: %d num lines 2: %d\n", util->num_lines,
274                        util2->num_lines);
276         for (i1 = 0, i2 = 0; i1 < util->num_lines; i1++, i2++) {
277                 struct chunk *chunk = NULL;
278                 if (cur_chunk < p->num)
279                         chunk = &p->chunks[cur_chunk];
281                 if (chunk && chunk->off1 == i1) {
282                         if (DEBUG && i2 != chunk->off2)
283                                 printf("i2: %d off2: %d\n", i2, chunk->off2);
285                         assert(i2 == chunk->off2);
287                         i1--;
288                         i2--;
289                         if (chunk->len1 > 0)
290                                 i1 += chunk->len1;
292                         if (chunk->len2 > 0)
293                                 i2 += chunk->len2;
295                         cur_chunk++;
296                 } else {
297                         if (i2 >= util2->num_lines)
298                                 break;
300                         if (map[i1] != map2[i2] && map[i1] != -1) {
301                                 if (DEBUG)
302                                         printf("map: i1: %d %d %p i2: %d %d %p\n",
303                                                i1, map[i1],
304                                                (void *) (i1 != -1 ? blame_lines[map[i1]] : NULL),
305                                                i2, map2[i2],
306                                                (void *) (i2 != -1 ? blame_lines[map2[i2]] : NULL));
307                                 if (map2[i2] != -1 &&
308                                     blame_lines[map[i1]] &&
309                                     !blame_lines[map2[i2]])
310                                         map[i1] = map2[i2];
311                         }
313                         if (map[i1] == -1 && map2[i2] != -1)
314                                 map[i1] = map2[i2];
315                 }
317                 if (DEBUG > 1)
318                         printf("l1: %d l2: %d i1: %d i2: %d\n",
319                                map[i1], map2[i2], i1, i2);
320         }
323 static int map_line(struct commit *commit, int line)
325         struct util_info *info = commit->util;
326         assert(line >= 0 && line < info->num_lines);
327         return info->line_map[line];
330 static struct util_info* get_util(struct commit *commit)
332         struct util_info *util = commit->util;
334         if (util)
335                 return util;
337         util = xmalloc(sizeof(struct util_info));
338         util->buf = NULL;
339         util->size = 0;
340         util->line_map = NULL;
341         util->num_lines = -1;
342         util->pathname = NULL;
343         commit->util = util;
344         return util;
347 static int fill_util_info(struct commit *commit)
349         struct util_info *util = commit->util;
351         assert(util);
352         assert(util->pathname);
354         return !!get_blob_sha1(commit->tree, util->pathname, util->sha1);
357 static void alloc_line_map(struct commit *commit)
359         struct util_info *util = commit->util;
360         int i;
362         if (util->line_map)
363                 return;
365         get_blob(commit);
367         util->num_lines = 0;
368         for (i = 0; i < util->size; i++) {
369                 if (util->buf[i] == '\n')
370                         util->num_lines++;
371         }
372         if(util->buf[util->size - 1] != '\n')
373                 util->num_lines++;
375         util->line_map = xmalloc(sizeof(int) * util->num_lines);
377         for (i = 0; i < util->num_lines; i++)
378                 util->line_map[i] = -1;
381 static void init_first_commit(struct commit* commit, const char* filename)
383         struct util_info* util = commit->util;
384         int i;
386         util->pathname = filename;
387         if (fill_util_info(commit))
388                 die("fill_util_info failed");
390         alloc_line_map(commit);
392         util = commit->util;
394         for (i = 0; i < util->num_lines; i++)
395                 util->line_map[i] = i;
399 static void process_commits(struct rev_info *rev, const char *path,
400                             struct commit** initial)
402         int i;
403         struct util_info* util;
404         int lines_left;
405         int *blame_p;
406         int *new_lines;
407         int new_lines_len;
409         struct commit* commit = get_revision(rev);
410         assert(commit);
411         init_first_commit(commit, path);
413         util = commit->util;
414         num_blame_lines = util->num_lines;
415         blame_lines = xmalloc(sizeof(struct commit *) * num_blame_lines);
416         blame_contents = util->buf;
417         blame_len = util->size;
419         for (i = 0; i < num_blame_lines; i++)
420                 blame_lines[i] = NULL;
422         lines_left = num_blame_lines;
423         blame_p = xmalloc(sizeof(int) * num_blame_lines);
424         new_lines = xmalloc(sizeof(int) * num_blame_lines);
425         do {
426                 struct commit_list *parents;
427                 int num_parents;
428                 struct util_info *util;
430                 if (DEBUG)
431                         printf("\nProcessing commit: %d %s\n", num_commits,
432                                sha1_to_hex(commit->object.sha1));
434                 if (lines_left == 0)
435                         return;
437                 num_commits++;
438                 memset(blame_p, 0, sizeof(int) * num_blame_lines);
439                 new_lines_len = 0;
440                 num_parents = 0;
441                 for (parents = commit->parents;
442                      parents != NULL; parents = parents->next)
443                         num_parents++;
445                 if(num_parents == 0)
446                         *initial = commit;
448                 if (fill_util_info(commit))
449                         continue;
451                 alloc_line_map(commit);
452                 util = commit->util;
454                 for (parents = commit->parents;
455                      parents != NULL; parents = parents->next) {
456                         struct commit *parent = parents->item;
457                         struct patch *patch;
459                         if (parse_commit(parent) < 0)
460                                 die("parse_commit error");
462                         if (DEBUG)
463                                 printf("parent: %s\n",
464                                        sha1_to_hex(parent->object.sha1));
466                         if (fill_util_info(parent)) {
467                                 num_parents--;
468                                 continue;
469                         }
471                         patch = get_patch(parent, commit);
472                         alloc_line_map(parent);
473                         fill_line_map(parent, commit, patch);
475                         for (i = 0; i < patch->num; i++) {
476                             int l;
477                             for (l = 0; l < patch->chunks[i].len2; l++) {
478                                 int mapped_line =
479                                     map_line(commit, patch->chunks[i].off2 + l);
480                                 if (mapped_line != -1) {
481                                     blame_p[mapped_line]++;
482                                     if (blame_p[mapped_line] == num_parents)
483                                         new_lines[new_lines_len++] = mapped_line;
484                                 }
485                             }
486                         }
487                         free_patch(patch);
488                 }
490                 if (DEBUG)
491                         printf("parents: %d\n", num_parents);
493                 for (i = 0; i < new_lines_len; i++) {
494                         int mapped_line = new_lines[i];
495                         if (blame_lines[mapped_line] == NULL) {
496                                 blame_lines[mapped_line] = commit;
497                                 lines_left--;
498                                 if (DEBUG)
499                                         printf("blame: mapped: %d i: %d\n",
500                                                mapped_line, i);
501                         }
502                 }
503         } while ((commit = get_revision(rev)) != NULL);
507 static int compare_tree_path(struct rev_info* revs,
508                              struct commit* c1, struct commit* c2)
510         int ret;
511         const char* paths[2];
512         struct util_info* util = c2->util;
513         paths[0] = util->pathname;
514         paths[1] = NULL;
516         diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
517                               &revs->pruning);
518         ret = rev_compare_tree(revs, c1->tree, c2->tree);
519         diff_tree_release_paths(&revs->pruning);
520         return ret;
524 static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1,
525                                    const char* path)
527         int ret;
528         const char* paths[2];
529         paths[0] = path;
530         paths[1] = NULL;
532         diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
533                               &revs->pruning);
534         ret = rev_same_tree_as_empty(revs, t1);
535         diff_tree_release_paths(&revs->pruning);
536         return ret;
539 static const char* find_rename(struct commit* commit, struct commit* parent)
541         struct util_info* cutil = commit->util;
542         struct diff_options diff_opts;
543         const char *paths[1];
544         int i;
546         if (DEBUG) {
547                 printf("find_rename commit: %s ",
548                        sha1_to_hex(commit->object.sha1));
549                 puts(sha1_to_hex(parent->object.sha1));
550         }
552         diff_setup(&diff_opts);
553         diff_opts.recursive = 1;
554         diff_opts.detect_rename = DIFF_DETECT_RENAME;
555         paths[0] = NULL;
556         diff_tree_setup_paths(paths, &diff_opts);
557         if (diff_setup_done(&diff_opts) < 0)
558                 die("diff_setup_done failed");
560         diff_tree_sha1(commit->tree->object.sha1, parent->tree->object.sha1,
561                        "", &diff_opts);
562         diffcore_std(&diff_opts);
564         for (i = 0; i < diff_queued_diff.nr; i++) {
565                 struct diff_filepair *p = diff_queued_diff.queue[i];
567                 if (p->status == 'R' && !strcmp(p->one->path, cutil->pathname)) {
568                         if (DEBUG)
569                                 printf("rename %s -> %s\n", p->one->path, p->two->path);
570                         return p->two->path;
571                 }
572         }
574         return 0;
577 static void simplify_commit(struct rev_info *revs, struct commit *commit)
579         struct commit_list **pp, *parent;
581         if (!commit->tree)
582                 return;
584         if (!commit->parents) {
585                 struct util_info* util = commit->util;
586                 if (!same_tree_as_empty_path(revs, commit->tree,
587                                              util->pathname))
588                         commit->object.flags |= TREECHANGE;
589                 return;
590         }
592         pp = &commit->parents;
593         while ((parent = *pp) != NULL) {
594                 struct commit *p = parent->item;
596                 if (p->object.flags & UNINTERESTING) {
597                         pp = &parent->next;
598                         continue;
599                 }
601                 parse_commit(p);
602                 switch (compare_tree_path(revs, p, commit)) {
603                 case REV_TREE_SAME:
604                         parent->next = NULL;
605                         commit->parents = parent;
606                         get_util(p)->pathname = get_util(commit)->pathname;
607                         return;
609                 case REV_TREE_NEW:
610                 {
612                         struct util_info* util = commit->util;
613                         if (revs->remove_empty_trees &&
614                             same_tree_as_empty_path(revs, p->tree,
615                                                     util->pathname)) {
616                                 const char* new_name = find_rename(commit, p);
617                                 if (new_name) {
618                                         struct util_info* putil = get_util(p);
619                                         if (!putil->pathname)
620                                                 putil->pathname = strdup(new_name);
621                                 } else {
622                                         *pp = parent->next;
623                                         continue;
624                                 }
625                         }
626                 }
628                 /* fallthrough */
629                 case REV_TREE_DIFFERENT:
630                         pp = &parent->next;
631                         if (!get_util(p)->pathname)
632                                 get_util(p)->pathname =
633                                         get_util(commit)->pathname;
634                         continue;
635                 }
636                 die("bad tree compare for commit %s",
637                     sha1_to_hex(commit->object.sha1));
638         }
639         commit->object.flags |= TREECHANGE;
643 struct commit_info
645         char* author;
646         char* author_mail;
647         unsigned long author_time;
648         char* author_tz;
649 };
651 static void get_commit_info(struct commit* commit, struct commit_info* ret)
653         int len;
654         char* tmp;
655         static char author_buf[1024];
657         tmp = strstr(commit->buffer, "\nauthor ") + 8;
658         len = strchr(tmp, '\n') - tmp;
659         ret->author = author_buf;
660         memcpy(ret->author, tmp, len);
662         tmp = ret->author;
663         tmp += len;
664         *tmp = 0;
665         while(*tmp != ' ')
666                 tmp--;
667         ret->author_tz = tmp+1;
669         *tmp = 0;
670         while(*tmp != ' ')
671                 tmp--;
672         ret->author_time = strtoul(tmp, NULL, 10);
674         *tmp = 0;
675         while(*tmp != ' ')
676                 tmp--;
677         ret->author_mail = tmp + 1;
679         *tmp = 0;
682 static const char* format_time(unsigned long time, const char* tz_str,
683                                int show_raw_time)
685         static char time_buf[128];
686         time_t t = time;
687         int minutes, tz;
688         struct tm *tm;
690         if (show_raw_time) {
691                 sprintf(time_buf, "%lu %s", time, tz_str);
692                 return time_buf;
693         }
695         tz = atoi(tz_str);
696         minutes = tz < 0 ? -tz : tz;
697         minutes = (minutes / 100)*60 + (minutes % 100);
698         minutes = tz < 0 ? -minutes : minutes;
699         t = time + minutes * 60;
700         tm = gmtime(&t);
702         strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
703         strcat(time_buf, tz_str);
704         return time_buf;
707 static void topo_setter(struct commit* c, void* data)
709         struct util_info* util = c->util;
710         util->topo_data = data;
713 static void* topo_getter(struct commit* c)
715         struct util_info* util = c->util;
716         return util->topo_data;
719 static int read_ancestry(const char *graft_file,
720                          unsigned char **start_sha1)
722         FILE *fp = fopen(graft_file, "r");
723         char buf[1024];
724         if (!fp)
725                 return -1;
726         while (fgets(buf, sizeof(buf), fp)) {
727                 /* The format is just "Commit Parent1 Parent2 ...\n" */
728                 int len = strlen(buf);
729                 struct commit_graft *graft = read_graft_line(buf, len);
730                 register_commit_graft(graft, 0);
731                 if (!*start_sha1)
732                         *start_sha1 = graft->sha1;
733         }
734         fclose(fp);
735         return 0;
738 int main(int argc, const char **argv)
740         int i;
741         struct commit *initial = NULL;
742         unsigned char sha1[20], *sha1_p = NULL;
744         const char *filename = NULL, *commit = NULL;
745         char filename_buf[256];
746         int sha1_len = 8;
747         int compatibility = 0;
748         int show_raw_time = 0;
749         int options = 1;
750         struct commit* start_commit;
752         const char* args[10];
753         struct rev_info rev;
755         struct commit_info ci;
756         const char *buf;
757         int max_digits;
758         int longest_file, longest_author;
759         int found_rename;
761         const char* prefix = setup_git_directory();
762         git_config(git_default_config);
764         for(i = 1; i < argc; i++) {
765                 if(options) {
766                         if(!strcmp(argv[i], "-h") ||
767                            !strcmp(argv[i], "--help"))
768                                 usage(blame_usage);
769                         else if(!strcmp(argv[i], "-l") ||
770                                 !strcmp(argv[i], "--long")) {
771                                 sha1_len = 40;
772                                 continue;
773                         } else if(!strcmp(argv[i], "-c") ||
774                                   !strcmp(argv[i], "--compatibility")) {
775                                 compatibility = 1;
776                                 continue;
777                         } else if(!strcmp(argv[i], "-t") ||
778                                   !strcmp(argv[i], "--time")) {
779                                 show_raw_time = 1;
780                                 continue;
781                         } else if(!strcmp(argv[i], "-S")) {
782                                 if (i + 1 < argc &&
783                                     !read_ancestry(argv[i + 1], &sha1_p)) {
784                                         compatibility = 1;
785                                         i++;
786                                         continue;
787                                 }
788                                 usage(blame_usage);
789                         } else if(!strcmp(argv[i], "--")) {
790                                 options = 0;
791                                 continue;
792                         } else if(argv[i][0] == '-')
793                                 usage(blame_usage);
794                         else
795                                 options = 0;
796                 }
798                 if(!options) {
799                         if(!filename)
800                                 filename = argv[i];
801                         else if(!commit)
802                                 commit = argv[i];
803                         else
804                                 usage(blame_usage);
805                 }
806         }
808         if(!filename)
809                 usage(blame_usage);
810         if (commit && sha1_p)
811                 usage(blame_usage);
812         else if(!commit)
813                 commit = "HEAD";
815         if(prefix)
816                 sprintf(filename_buf, "%s%s", prefix, filename);
817         else
818                 strcpy(filename_buf, filename);
819         filename = filename_buf;
821         if (!sha1_p) {
822                 if (get_sha1(commit, sha1))
823                         die("get_sha1 failed, commit '%s' not found", commit);
824                 sha1_p = sha1;
825         }
826         start_commit = lookup_commit_reference(sha1_p);
827         get_util(start_commit)->pathname = filename;
828         if (fill_util_info(start_commit)) {
829                 printf("%s not found in %s\n", filename, commit);
830                 return 1;
831         }
834         init_revisions(&rev, setup_git_directory());
835         rev.remove_empty_trees = 1;
836         rev.topo_order = 1;
837         rev.prune_fn = simplify_commit;
838         rev.topo_setter = topo_setter;
839         rev.topo_getter = topo_getter;
840         rev.parents = 1;
841         rev.limited = 1;
843         commit_list_insert(start_commit, &rev.commits);
845         args[0] = filename;
846         args[1] = NULL;
847         diff_tree_setup_paths(args, &rev.pruning);
848         prepare_revision_walk(&rev);
849         process_commits(&rev, filename, &initial);
851         buf = blame_contents;
852         for (max_digits = 1, i = 10; i <= num_blame_lines + 1; max_digits++)
853                 i *= 10;
855         longest_file = 0;
856         longest_author = 0;
857         found_rename = 0;
858         for (i = 0; i < num_blame_lines; i++) {
859                 struct commit *c = blame_lines[i];
860                 struct util_info* u;
861                 if (!c)
862                         c = initial;
863                 u = c->util;
865                 if (!found_rename && strcmp(filename, u->pathname))
866                         found_rename = 1;
867                 if (longest_file < strlen(u->pathname))
868                         longest_file = strlen(u->pathname);
869                 get_commit_info(c, &ci);
870                 if (longest_author < strlen(ci.author))
871                         longest_author = strlen(ci.author);
872         }
874         for (i = 0; i < num_blame_lines; i++) {
875                 struct commit *c = blame_lines[i];
876                 struct util_info* u;
878                 if (!c)
879                         c = initial;
881                 u = c->util;
882                 get_commit_info(c, &ci);
883                 fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
884                 if(compatibility) {
885                         printf("\t(%10s\t%10s\t%d)", ci.author,
886                                format_time(ci.author_time, ci.author_tz,
887                                            show_raw_time),
888                                i+1);
889                 } else {
890                         if (found_rename)
891                                 printf(" %-*.*s", longest_file, longest_file,
892                                        u->pathname);
893                         printf(" (%-*.*s %10s %*d) ",
894                                longest_author, longest_author, ci.author,
895                                format_time(ci.author_time, ci.author_tz,
896                                            show_raw_time),
897                                max_digits, i+1);
898                 }
900                 if(i == num_blame_lines - 1) {
901                         fwrite(buf, blame_len - (buf - blame_contents),
902                                1, stdout);
903                         if(blame_contents[blame_len-1] != '\n')
904                                 putc('\n', stdout);
905                 } else {
906                         char* next_buf = strchr(buf, '\n') + 1;
907                         fwrite(buf, next_buf - buf, 1, stdout);
908                         buf = next_buf;
909                 }
910         }
912         if (DEBUG) {
913                 printf("num get patch: %d\n", num_get_patch);
914                 printf("num commits: %d\n", num_commits);
915                 printf("patch time: %f\n", patch_time / 1000000.0);
916                 printf("initial: %s\n", sha1_to_hex(initial->object.sha1));
917         }
919         return 0;