Code

Fix git-diff A...B
[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         if (get_blob_sha1(commit->tree, util->pathname, util->sha1))
355                 return 1;
356         else
357                 return 0;
360 static void alloc_line_map(struct commit *commit)
362         struct util_info *util = commit->util;
363         int i;
365         if (util->line_map)
366                 return;
368         get_blob(commit);
370         util->num_lines = 0;
371         for (i = 0; i < util->size; i++) {
372                 if (util->buf[i] == '\n')
373                         util->num_lines++;
374         }
375         if(util->buf[util->size - 1] != '\n')
376                 util->num_lines++;
378         util->line_map = xmalloc(sizeof(int) * util->num_lines);
380         for (i = 0; i < util->num_lines; i++)
381                 util->line_map[i] = -1;
384 static void init_first_commit(struct commit* commit, const char* filename)
386         struct util_info* util = commit->util;
387         int i;
389         util->pathname = filename;
390         if (fill_util_info(commit))
391                 die("fill_util_info failed");
393         alloc_line_map(commit);
395         util = commit->util;
397         for (i = 0; i < util->num_lines; i++)
398                 util->line_map[i] = i;
402 static void process_commits(struct rev_info *rev, const char *path,
403                             struct commit** initial)
405         int i;
406         struct util_info* util;
407         int lines_left;
408         int *blame_p;
409         int *new_lines;
410         int new_lines_len;
412         struct commit* commit = get_revision(rev);
413         assert(commit);
414         init_first_commit(commit, path);
416         util = commit->util;
417         num_blame_lines = util->num_lines;
418         blame_lines = xmalloc(sizeof(struct commit *) * num_blame_lines);
419         blame_contents = util->buf;
420         blame_len = util->size;
422         for (i = 0; i < num_blame_lines; i++)
423                 blame_lines[i] = NULL;
425         lines_left = num_blame_lines;
426         blame_p = xmalloc(sizeof(int) * num_blame_lines);
427         new_lines = xmalloc(sizeof(int) * num_blame_lines);
428         do {
429                 struct commit_list *parents;
430                 int num_parents;
431                 struct util_info *util;
433                 if (DEBUG)
434                         printf("\nProcessing commit: %d %s\n", num_commits,
435                                sha1_to_hex(commit->object.sha1));
437                 if (lines_left == 0)
438                         return;
440                 num_commits++;
441                 memset(blame_p, 0, sizeof(int) * num_blame_lines);
442                 new_lines_len = 0;
443                 num_parents = 0;
444                 for (parents = commit->parents;
445                      parents != NULL; parents = parents->next)
446                         num_parents++;
448                 if(num_parents == 0)
449                         *initial = commit;
451                 if (fill_util_info(commit))
452                         continue;
454                 alloc_line_map(commit);
455                 util = commit->util;
457                 for (parents = commit->parents;
458                      parents != NULL; parents = parents->next) {
459                         struct commit *parent = parents->item;
460                         struct patch *patch;
462                         if (parse_commit(parent) < 0)
463                                 die("parse_commit error");
465                         if (DEBUG)
466                                 printf("parent: %s\n",
467                                        sha1_to_hex(parent->object.sha1));
469                         if (fill_util_info(parent)) {
470                                 num_parents--;
471                                 continue;
472                         }
474                         patch = get_patch(parent, commit);
475                         alloc_line_map(parent);
476                         fill_line_map(parent, commit, patch);
478                         for (i = 0; i < patch->num; i++) {
479                             int l;
480                             for (l = 0; l < patch->chunks[i].len2; l++) {
481                                 int mapped_line =
482                                     map_line(commit, patch->chunks[i].off2 + l);
483                                 if (mapped_line != -1) {
484                                     blame_p[mapped_line]++;
485                                     if (blame_p[mapped_line] == num_parents)
486                                         new_lines[new_lines_len++] = mapped_line;
487                                 }
488                             }
489                         }
490                         free_patch(patch);
491                 }
493                 if (DEBUG)
494                         printf("parents: %d\n", num_parents);
496                 for (i = 0; i < new_lines_len; i++) {
497                         int mapped_line = new_lines[i];
498                         if (blame_lines[mapped_line] == NULL) {
499                                 blame_lines[mapped_line] = commit;
500                                 lines_left--;
501                                 if (DEBUG)
502                                         printf("blame: mapped: %d i: %d\n",
503                                                mapped_line, i);
504                         }
505                 }
506         } while ((commit = get_revision(rev)) != NULL);
510 static int compare_tree_path(struct rev_info* revs,
511                              struct commit* c1, struct commit* c2)
513         int ret;
514         const char* paths[2];
515         struct util_info* util = c2->util;
516         paths[0] = util->pathname;
517         paths[1] = NULL;
519         diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
520                               &revs->pruning);
521         ret = rev_compare_tree(revs, c1->tree, c2->tree);
522         diff_tree_release_paths(&revs->pruning);
523         return ret;
527 static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1,
528                                    const char* path)
530         int ret;
531         const char* paths[2];
532         paths[0] = path;
533         paths[1] = NULL;
535         diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
536                               &revs->pruning);
537         ret = rev_same_tree_as_empty(revs, t1);
538         diff_tree_release_paths(&revs->pruning);
539         return ret;
542 static const char* find_rename(struct commit* commit, struct commit* parent)
544         struct util_info* cutil = commit->util;
545         struct diff_options diff_opts;
546         const char *paths[1];
547         int i;
549         if (DEBUG) {
550                 printf("find_rename commit: %s ",
551                        sha1_to_hex(commit->object.sha1));
552                 puts(sha1_to_hex(parent->object.sha1));
553         }
555         diff_setup(&diff_opts);
556         diff_opts.recursive = 1;
557         diff_opts.detect_rename = DIFF_DETECT_RENAME;
558         paths[0] = NULL;
559         diff_tree_setup_paths(paths, &diff_opts);
560         if (diff_setup_done(&diff_opts) < 0)
561                 die("diff_setup_done failed");
563         diff_tree_sha1(commit->tree->object.sha1, parent->tree->object.sha1,
564                        "", &diff_opts);
565         diffcore_std(&diff_opts);
567         for (i = 0; i < diff_queued_diff.nr; i++) {
568                 struct diff_filepair *p = diff_queued_diff.queue[i];
570                 if (p->status == 'R' && !strcmp(p->one->path, cutil->pathname)) {
571                         if (DEBUG)
572                                 printf("rename %s -> %s\n", p->one->path, p->two->path);
573                         return p->two->path;
574                 }
575         }
577         return 0;
580 static void simplify_commit(struct rev_info *revs, struct commit *commit)
582         struct commit_list **pp, *parent;
584         if (!commit->tree)
585                 return;
587         if (!commit->parents) {
588                 struct util_info* util = commit->util;
589                 if (!same_tree_as_empty_path(revs, commit->tree,
590                                              util->pathname))
591                         commit->object.flags |= TREECHANGE;
592                 return;
593         }
595         pp = &commit->parents;
596         while ((parent = *pp) != NULL) {
597                 struct commit *p = parent->item;
599                 if (p->object.flags & UNINTERESTING) {
600                         pp = &parent->next;
601                         continue;
602                 }
604                 parse_commit(p);
605                 switch (compare_tree_path(revs, p, commit)) {
606                 case REV_TREE_SAME:
607                         parent->next = NULL;
608                         commit->parents = parent;
609                         get_util(p)->pathname = get_util(commit)->pathname;
610                         return;
612                 case REV_TREE_NEW:
613                 {
615                         struct util_info* util = commit->util;
616                         if (revs->remove_empty_trees &&
617                             same_tree_as_empty_path(revs, p->tree,
618                                                     util->pathname)) {
619                                 const char* new_name = find_rename(commit, p);
620                                 if (new_name) {
621                                         struct util_info* putil = get_util(p);
622                                         if (!putil->pathname)
623                                                 putil->pathname = strdup(new_name);
624                                 } else {
625                                         *pp = parent->next;
626                                         continue;
627                                 }
628                         }
629                 }
631                 /* fallthrough */
632                 case REV_TREE_DIFFERENT:
633                         pp = &parent->next;
634                         if (!get_util(p)->pathname)
635                                 get_util(p)->pathname =
636                                         get_util(commit)->pathname;
637                         continue;
638                 }
639                 die("bad tree compare for commit %s",
640                     sha1_to_hex(commit->object.sha1));
641         }
642         commit->object.flags |= TREECHANGE;
646 struct commit_info
648         char* author;
649         char* author_mail;
650         unsigned long author_time;
651         char* author_tz;
652 };
654 static void get_commit_info(struct commit* commit, struct commit_info* ret)
656         int len;
657         char* tmp;
658         static char author_buf[1024];
660         tmp = strstr(commit->buffer, "\nauthor ") + 8;
661         len = strchr(tmp, '\n') - tmp;
662         ret->author = author_buf;
663         memcpy(ret->author, tmp, len);
665         tmp = ret->author;
666         tmp += len;
667         *tmp = 0;
668         while(*tmp != ' ')
669                 tmp--;
670         ret->author_tz = tmp+1;
672         *tmp = 0;
673         while(*tmp != ' ')
674                 tmp--;
675         ret->author_time = strtoul(tmp, NULL, 10);
677         *tmp = 0;
678         while(*tmp != ' ')
679                 tmp--;
680         ret->author_mail = tmp + 1;
682         *tmp = 0;
685 static const char* format_time(unsigned long time, const char* tz_str,
686                                int show_raw_time)
688         static char time_buf[128];
689         time_t t = time;
690         int minutes, tz;
691         struct tm *tm;
693         if (show_raw_time) {
694                 sprintf(time_buf, "%lu %s", time, tz_str);
695                 return time_buf;
696         }
698         tz = atoi(tz_str);
699         minutes = tz < 0 ? -tz : tz;
700         minutes = (minutes / 100)*60 + (minutes % 100);
701         minutes = tz < 0 ? -minutes : minutes;
702         t = time + minutes * 60;
703         tm = gmtime(&t);
705         strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
706         strcat(time_buf, tz_str);
707         return time_buf;
710 static void topo_setter(struct commit* c, void* data)
712         struct util_info* util = c->util;
713         util->topo_data = data;
716 static void* topo_getter(struct commit* c)
718         struct util_info* util = c->util;
719         return util->topo_data;
722 static int read_ancestry(const char *graft_file,
723                          unsigned char **start_sha1)
725         FILE *fp = fopen(graft_file, "r");
726         char buf[1024];
727         if (!fp)
728                 return -1;
729         while (fgets(buf, sizeof(buf), fp)) {
730                 /* The format is just "Commit Parent1 Parent2 ...\n" */
731                 int len = strlen(buf);
732                 struct commit_graft *graft = read_graft_line(buf, len);
733                 register_commit_graft(graft, 0);
734                 if (!*start_sha1)
735                         *start_sha1 = graft->sha1;
736         }
737         fclose(fp);
738         return 0;
741 int main(int argc, const char **argv)
743         int i;
744         struct commit *initial = NULL;
745         unsigned char sha1[20], *sha1_p = NULL;
747         const char *filename = NULL, *commit = NULL;
748         char filename_buf[256];
749         int sha1_len = 8;
750         int compatibility = 0;
751         int show_raw_time = 0;
752         int options = 1;
753         struct commit* start_commit;
755         const char* args[10];
756         struct rev_info rev;
758         struct commit_info ci;
759         const char *buf;
760         int max_digits;
761         int longest_file, longest_author;
762         int found_rename;
764         const char* prefix = setup_git_directory();
765         git_config(git_default_config);
767         for(i = 1; i < argc; i++) {
768                 if(options) {
769                         if(!strcmp(argv[i], "-h") ||
770                            !strcmp(argv[i], "--help"))
771                                 usage(blame_usage);
772                         else if(!strcmp(argv[i], "-l") ||
773                                 !strcmp(argv[i], "--long")) {
774                                 sha1_len = 40;
775                                 continue;
776                         } else if(!strcmp(argv[i], "-c") ||
777                                   !strcmp(argv[i], "--compatibility")) {
778                                 compatibility = 1;
779                                 continue;
780                         } else if(!strcmp(argv[i], "-t") ||
781                                   !strcmp(argv[i], "--time")) {
782                                 show_raw_time = 1;
783                                 continue;
784                         } else if(!strcmp(argv[i], "-S")) {
785                                 if (i + 1 < argc &&
786                                     !read_ancestry(argv[i + 1], &sha1_p)) {
787                                         compatibility = 1;
788                                         i++;
789                                         continue;
790                                 }
791                                 usage(blame_usage);
792                         } else if(!strcmp(argv[i], "--")) {
793                                 options = 0;
794                                 continue;
795                         } else if(argv[i][0] == '-')
796                                 usage(blame_usage);
797                         else
798                                 options = 0;
799                 }
801                 if(!options) {
802                         if(!filename)
803                                 filename = argv[i];
804                         else if(!commit)
805                                 commit = argv[i];
806                         else
807                                 usage(blame_usage);
808                 }
809         }
811         if(!filename)
812                 usage(blame_usage);
813         if (commit && sha1_p)
814                 usage(blame_usage);
815         else if(!commit)
816                 commit = "HEAD";
818         if(prefix)
819                 sprintf(filename_buf, "%s%s", prefix, filename);
820         else
821                 strcpy(filename_buf, filename);
822         filename = filename_buf;
824         if (!sha1_p) {
825                 if (get_sha1(commit, sha1))
826                         die("get_sha1 failed, commit '%s' not found", commit);
827                 sha1_p = sha1;
828         }
829         start_commit = lookup_commit_reference(sha1_p);
830         get_util(start_commit)->pathname = filename;
831         if (fill_util_info(start_commit)) {
832                 printf("%s not found in %s\n", filename, commit);
833                 return 1;
834         }
837         init_revisions(&rev, setup_git_directory());
838         rev.remove_empty_trees = 1;
839         rev.topo_order = 1;
840         rev.prune_fn = simplify_commit;
841         rev.topo_setter = topo_setter;
842         rev.topo_getter = topo_getter;
843         rev.parents = 1;
844         rev.limited = 1;
846         commit_list_insert(start_commit, &rev.commits);
848         args[0] = filename;
849         args[1] = NULL;
850         diff_tree_setup_paths(args, &rev.pruning);
851         prepare_revision_walk(&rev);
852         process_commits(&rev, filename, &initial);
854         buf = blame_contents;
855         for (max_digits = 1, i = 10; i <= num_blame_lines + 1; max_digits++)
856                 i *= 10;
858         longest_file = 0;
859         longest_author = 0;
860         found_rename = 0;
861         for (i = 0; i < num_blame_lines; i++) {
862                 struct commit *c = blame_lines[i];
863                 struct util_info* u;
864                 if (!c)
865                         c = initial;
866                 u = c->util;
868                 if (!found_rename && strcmp(filename, u->pathname))
869                         found_rename = 1;
870                 if (longest_file < strlen(u->pathname))
871                         longest_file = strlen(u->pathname);
872                 get_commit_info(c, &ci);
873                 if (longest_author < strlen(ci.author))
874                         longest_author = strlen(ci.author);
875         }
877         for (i = 0; i < num_blame_lines; i++) {
878                 struct commit *c = blame_lines[i];
879                 struct util_info* u;
881                 if (!c)
882                         c = initial;
884                 u = c->util;
885                 get_commit_info(c, &ci);
886                 fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
887                 if(compatibility) {
888                         printf("\t(%10s\t%10s\t%d)", ci.author,
889                                format_time(ci.author_time, ci.author_tz,
890                                            show_raw_time),
891                                i+1);
892                 } else {
893                         if (found_rename)
894                                 printf(" %-*.*s", longest_file, longest_file,
895                                        u->pathname);
896                         printf(" (%-*.*s %10s %*d) ",
897                                longest_author, longest_author, ci.author,
898                                format_time(ci.author_time, ci.author_tz,
899                                            show_raw_time),
900                                max_digits, i+1);
901                 }
903                 if(i == num_blame_lines - 1) {
904                         fwrite(buf, blame_len - (buf - blame_contents),
905                                1, stdout);
906                         if(blame_contents[blame_len-1] != '\n')
907                                 putc('\n', stdout);
908                 } else {
909                         char* next_buf = strchr(buf, '\n') + 1;
910                         fwrite(buf, next_buf - buf, 1, stdout);
911                         buf = next_buf;
912                 }
913         }
915         if (DEBUG) {
916                 printf("num get patch: %d\n", num_get_patch);
917                 printf("num commits: %d\n", num_commits);
918                 printf("patch time: %f\n", patch_time / 1000000.0);
919                 printf("initial: %s\n", sha1_to_hex(initial->object.sha1));
920         }
922         return 0;