2 * Copyright (C) 2006, Fredrik Kuivinen <freku045@student.liu.se>
19 #include "xdiff-interface.h"
26 static const char blame_usage
[] =
27 "git-blame [-c] [-l] [-t] [-f] [-n] [-p] [-S <revs-file>] [--] file [commit]\n"
28 " -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
29 " -l, --long Show long commit SHA1 (Default: off)\n"
30 " -t, --time Show raw timestamp (Default: off)\n"
31 " -f, --show-name Show original filename (Default: auto)\n"
32 " -n, --show-number Show original linenumber (Default: off)\n"
33 " -p, --porcelain Show in a format designed for machine consumption\n"
34 " -S revs-file Use revisions from revs-file instead of calling git-rev-list\n"
35 " -h, --help This message";
37 static struct commit
**blame_lines
;
38 static int num_blame_lines
;
39 static char *blame_contents
;
44 unsigned char sha1
[20]; /* blob sha, not commit! */
49 unsigned meta_given
:1;
55 int off1
, len1
; /* --- */
56 int off2
, len2
; /* +++ */
64 static void get_blob(struct commit
*commit
);
66 /* Only used for statistics */
67 static int num_get_patch
;
68 static int num_commits
;
69 static int patch_time
;
70 static int num_read_blob
;
72 struct blame_diff_state
{
73 struct xdiff_emit_state xm
;
77 static void process_u0_diff(void *state_
, char *line
, unsigned long len
)
79 struct blame_diff_state
*state
= state_
;
82 if (len
< 4 || line
[0] != '@' || line
[1] != '@')
86 printf("chunk line: %.*s", (int)len
, line
);
88 state
->ret
->chunks
= xrealloc(state
->ret
->chunks
,
89 sizeof(struct chunk
) * state
->ret
->num
);
90 chunk
= &state
->ret
->chunks
[state
->ret
->num
- 1];
92 assert(!strncmp(line
, "@@ -", 4));
94 if (parse_hunk_header(line
, len
,
95 &chunk
->off1
, &chunk
->len1
,
96 &chunk
->off2
, &chunk
->len2
)) {
101 if (chunk
->len1
== 0)
103 if (chunk
->len2
== 0)
111 assert(chunk
->off1
>= 0);
112 assert(chunk
->off2
>= 0);
115 static struct patch
*get_patch(struct commit
*commit
, struct commit
*other
)
117 struct blame_diff_state state
;
120 mmfile_t file_c
, file_o
;
122 struct util_info
*info_c
= (struct util_info
*)commit
->util
;
123 struct util_info
*info_o
= (struct util_info
*)other
->util
;
124 struct timeval tv_start
, tv_end
;
127 file_c
.ptr
= info_c
->buf
;
128 file_c
.size
= info_c
->size
;
131 file_o
.ptr
= info_o
->buf
;
132 file_o
.size
= info_o
->size
;
134 gettimeofday(&tv_start
, NULL
);
136 xpp
.flags
= XDF_NEED_MINIMAL
;
139 ecb
.outf
= xdiff_outf
;
141 memset(&state
, 0, sizeof(state
));
142 state
.xm
.consume
= process_u0_diff
;
143 state
.ret
= xmalloc(sizeof(struct patch
));
144 state
.ret
->chunks
= NULL
;
147 xdl_diff(&file_c
, &file_o
, &xpp
, &xecfg
, &ecb
);
149 gettimeofday(&tv_end
, NULL
);
150 patch_time
+= 1000000 * (tv_end
.tv_sec
- tv_start
.tv_sec
) +
151 tv_end
.tv_usec
- tv_start
.tv_usec
;
157 static void free_patch(struct patch
*p
)
163 static int get_blob_sha1_internal(const unsigned char *sha1
, const char *base
,
164 int baselen
, const char *pathname
,
165 unsigned mode
, int stage
);
167 static unsigned char blob_sha1
[20];
168 static const char *blame_file
;
169 static int get_blob_sha1(struct tree
*t
, const char *pathname
,
172 const char *pathspec
[2];
173 blame_file
= pathname
;
174 pathspec
[0] = pathname
;
177 read_tree_recursive(t
, "", 0, 0, pathspec
, get_blob_sha1_internal
);
179 if (is_null_sha1(blob_sha1
))
182 hashcpy(sha1
, blob_sha1
);
186 static int get_blob_sha1_internal(const unsigned char *sha1
, const char *base
,
187 int baselen
, const char *pathname
,
188 unsigned mode
, int stage
)
191 return READ_TREE_RECURSIVE
;
193 if (strncmp(blame_file
, base
, baselen
) ||
194 strcmp(blame_file
+ baselen
, pathname
))
197 hashcpy(blob_sha1
, sha1
);
201 static void get_blob(struct commit
*commit
)
203 struct util_info
*info
= commit
->util
;
209 info
->buf
= read_sha1_file(info
->sha1
, type
, &info
->size
);
212 assert(!strcmp(type
, blob_type
));
215 /* For debugging only */
216 static void print_patch(struct patch
*p
)
219 printf("Num chunks: %d\n", p
->num
);
220 for (i
= 0; i
< p
->num
; i
++) {
221 printf("%d,%d %d,%d\n", p
->chunks
[i
].off1
, p
->chunks
[i
].len1
,
222 p
->chunks
[i
].off2
, p
->chunks
[i
].len2
);
227 /* For debugging only */
228 static void print_map(struct commit
*cmit
, struct commit
*other
)
230 struct util_info
*util
= cmit
->util
;
231 struct util_info
*util2
= other
->util
;
236 util2
->num_lines
? util
->num_lines
: util2
->num_lines
;
239 if (print_map
== NULL
)
240 ; /* to avoid "unused function" warning */
242 for (i
= 0; i
< max
; i
++) {
246 if (i
< util
->num_lines
) {
247 num
= util
->line_map
[i
];
253 if (i
< util2
->num_lines
) {
254 int num2
= util2
->line_map
[i
];
255 printf("%d\t", num2
);
256 if (num
!= -1 && num2
!= num
)
267 /* p is a patch from commit to other. */
268 static void fill_line_map(struct commit
*commit
, struct commit
*other
,
271 struct util_info
*util
= commit
->util
;
272 struct util_info
*util2
= other
->util
;
273 int *map
= util
->line_map
;
274 int *map2
= util2
->line_map
;
281 printf("num lines 1: %d num lines 2: %d\n", util
->num_lines
,
285 for (i1
= 0, i2
= 0; i1
< util
->num_lines
; i1
++, i2
++) {
286 struct chunk
*chunk
= NULL
;
287 if (cur_chunk
< p
->num
)
288 chunk
= &p
->chunks
[cur_chunk
];
290 if (chunk
&& chunk
->off1
== i1
) {
291 if (DEBUG
&& i2
!= chunk
->off2
)
292 printf("i2: %d off2: %d\n", i2
, chunk
->off2
);
294 assert(i2
== chunk
->off2
);
307 if (i2
>= util2
->num_lines
)
310 if (map
[i1
] != map2
[i2
] && map
[i1
] != -1) {
312 printf("map: i1: %d %d %p i2: %d %d %p\n",
314 (void *) (i1
!= -1 ? blame_lines
[map
[i1
]] : NULL
),
316 (void *) (i2
!= -1 ? blame_lines
[map2
[i2
]] : NULL
));
317 if (map2
[i2
] != -1 &&
318 blame_lines
[map
[i1
]] &&
319 !blame_lines
[map2
[i2
]])
323 if (map
[i1
] == -1 && map2
[i2
] != -1)
328 printf("l1: %d l2: %d i1: %d i2: %d\n",
329 map
[i1
], map2
[i2
], i1
, i2
);
333 static int map_line(struct commit
*commit
, int line
)
335 struct util_info
*info
= commit
->util
;
336 assert(line
>= 0 && line
< info
->num_lines
);
337 return info
->line_map
[line
];
340 static struct util_info
*get_util(struct commit
*commit
)
342 struct util_info
*util
= commit
->util
;
347 util
= xcalloc(1, sizeof(struct util_info
));
348 util
->num_lines
= -1;
353 static int fill_util_info(struct commit
*commit
)
355 struct util_info
*util
= commit
->util
;
358 assert(util
->pathname
);
360 return !!get_blob_sha1(commit
->tree
, util
->pathname
, util
->sha1
);
363 static void alloc_line_map(struct commit
*commit
)
365 struct util_info
*util
= commit
->util
;
374 for (i
= 0; i
< util
->size
; i
++) {
375 if (util
->buf
[i
] == '\n')
378 if (util
->buf
[util
->size
- 1] != '\n')
381 util
->line_map
= xmalloc(sizeof(int) * util
->num_lines
);
383 for (i
= 0; i
< util
->num_lines
; i
++)
384 util
->line_map
[i
] = -1;
387 static void init_first_commit(struct commit
*commit
, const char *filename
)
389 struct util_info
*util
= commit
->util
;
392 util
->pathname
= filename
;
393 if (fill_util_info(commit
))
394 die("fill_util_info failed");
396 alloc_line_map(commit
);
400 for (i
= 0; i
< util
->num_lines
; i
++)
401 util
->line_map
[i
] = i
;
404 static void process_commits(struct rev_info
*rev
, const char *path
,
405 struct commit
**initial
)
408 struct util_info
*util
;
414 struct commit
*commit
= get_revision(rev
);
416 init_first_commit(commit
, path
);
419 num_blame_lines
= util
->num_lines
;
420 blame_lines
= xmalloc(sizeof(struct commit
*) * num_blame_lines
);
421 blame_contents
= util
->buf
;
422 blame_len
= util
->size
;
424 for (i
= 0; i
< num_blame_lines
; i
++)
425 blame_lines
[i
] = NULL
;
427 lines_left
= num_blame_lines
;
428 blame_p
= xmalloc(sizeof(int) * num_blame_lines
);
429 new_lines
= xmalloc(sizeof(int) * num_blame_lines
);
431 struct commit_list
*parents
;
433 struct util_info
*util
;
436 printf("\nProcessing commit: %d %s\n", num_commits
,
437 sha1_to_hex(commit
->object
.sha1
));
443 memset(blame_p
, 0, sizeof(int) * num_blame_lines
);
446 for (parents
= commit
->parents
;
447 parents
!= NULL
; parents
= parents
->next
)
450 if (num_parents
== 0)
453 if (fill_util_info(commit
))
456 alloc_line_map(commit
);
459 for (parents
= commit
->parents
;
460 parents
!= NULL
; parents
= parents
->next
) {
461 struct commit
*parent
= parents
->item
;
464 if (parse_commit(parent
) < 0)
465 die("parse_commit error");
468 printf("parent: %s\n",
469 sha1_to_hex(parent
->object
.sha1
));
471 if (fill_util_info(parent
)) {
476 patch
= get_patch(parent
, commit
);
477 alloc_line_map(parent
);
478 fill_line_map(parent
, commit
, patch
);
480 for (i
= 0; i
< patch
->num
; i
++) {
482 for (l
= 0; l
< patch
->chunks
[i
].len2
; l
++) {
484 map_line(commit
, patch
->chunks
[i
].off2
+ l
);
485 if (mapped_line
!= -1) {
486 blame_p
[mapped_line
]++;
487 if (blame_p
[mapped_line
] == num_parents
)
488 new_lines
[new_lines_len
++] = mapped_line
;
496 printf("parents: %d\n", num_parents
);
498 for (i
= 0; i
< new_lines_len
; i
++) {
499 int mapped_line
= new_lines
[i
];
500 if (blame_lines
[mapped_line
] == NULL
) {
501 blame_lines
[mapped_line
] = commit
;
504 printf("blame: mapped: %d i: %d\n",
508 } while ((commit
= get_revision(rev
)) != NULL
);
511 static int compare_tree_path(struct rev_info
*revs
,
512 struct commit
*c1
, struct commit
*c2
)
515 const char *paths
[2];
516 struct util_info
*util
= c2
->util
;
517 paths
[0] = util
->pathname
;
520 diff_tree_setup_paths(get_pathspec(revs
->prefix
, paths
),
522 ret
= rev_compare_tree(revs
, c1
->tree
, c2
->tree
);
523 diff_tree_release_paths(&revs
->pruning
);
527 static int same_tree_as_empty_path(struct rev_info
*revs
, struct tree
*t1
,
531 const char *paths
[2];
535 diff_tree_setup_paths(get_pathspec(revs
->prefix
, paths
),
537 ret
= rev_same_tree_as_empty(revs
, t1
);
538 diff_tree_release_paths(&revs
->pruning
);
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];
550 printf("find_rename commit: %s ",
551 sha1_to_hex(commit
->object
.sha1
));
552 puts(sha1_to_hex(parent
->object
.sha1
));
555 diff_setup(&diff_opts
);
556 diff_opts
.recursive
= 1;
557 diff_opts
.detect_rename
= DIFF_DETECT_RENAME
;
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
,
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' &&
571 !strcmp(p
->one
->path
, cutil
->pathname
)) {
573 printf("rename %s -> %s\n",
574 p
->one
->path
, p
->two
->path
);
582 static void simplify_commit(struct rev_info
*revs
, struct commit
*commit
)
584 struct commit_list
**pp
, *parent
;
589 if (!commit
->parents
) {
590 struct util_info
*util
= commit
->util
;
591 if (!same_tree_as_empty_path(revs
, commit
->tree
,
593 commit
->object
.flags
|= TREECHANGE
;
597 pp
= &commit
->parents
;
598 while ((parent
= *pp
) != NULL
) {
599 struct commit
*p
= parent
->item
;
601 if (p
->object
.flags
& UNINTERESTING
) {
607 switch (compare_tree_path(revs
, p
, commit
)) {
610 commit
->parents
= parent
;
611 get_util(p
)->pathname
= get_util(commit
)->pathname
;
616 struct util_info
*util
= commit
->util
;
617 if (revs
->remove_empty_trees
&&
618 same_tree_as_empty_path(revs
, p
->tree
,
620 const char *new_name
= find_rename(commit
, p
);
622 struct util_info
*putil
= get_util(p
);
623 if (!putil
->pathname
)
624 putil
->pathname
= xstrdup(new_name
);
634 case REV_TREE_DIFFERENT
:
636 if (!get_util(p
)->pathname
)
637 get_util(p
)->pathname
=
638 get_util(commit
)->pathname
;
641 die("bad tree compare for commit %s",
642 sha1_to_hex(commit
->object
.sha1
));
644 commit
->object
.flags
|= TREECHANGE
;
651 unsigned long author_time
;
654 /* filled only when asked for details */
656 char *committer_mail
;
657 unsigned long committer_time
;
663 static void get_ac_line(const char *inbuf
, const char *what
,
664 int bufsz
, char *person
, char **mail
,
665 unsigned long *time
, char **tz
)
670 tmp
= strstr(inbuf
, what
);
674 endp
= strchr(tmp
, '\n');
682 person
= *mail
= *tz
= "(unknown)";
686 memcpy(person
, tmp
, len
);
698 *time
= strtoul(tmp
, NULL
, 10);
707 static void get_commit_info(struct commit
*commit
, struct commit_info
*ret
, int detailed
)
711 static char author_buf
[1024];
712 static char committer_buf
[1024];
713 static char summary_buf
[1024];
715 ret
->author
= author_buf
;
716 get_ac_line(commit
->buffer
, "\nauthor ",
717 sizeof(author_buf
), author_buf
, &ret
->author_mail
,
718 &ret
->author_time
, &ret
->author_tz
);
723 ret
->committer
= committer_buf
;
724 get_ac_line(commit
->buffer
, "\ncommitter ",
725 sizeof(committer_buf
), committer_buf
, &ret
->committer_mail
,
726 &ret
->committer_time
, &ret
->committer_tz
);
728 ret
->summary
= summary_buf
;
729 tmp
= strstr(commit
->buffer
, "\n\n");
732 sprintf(summary_buf
, "(%s)", sha1_to_hex(commit
->object
.sha1
));
736 endp
= strchr(tmp
, '\n');
740 if (len
>= sizeof(summary_buf
))
742 memcpy(summary_buf
, tmp
, len
);
743 summary_buf
[len
] = 0;
746 static const char *format_time(unsigned long time
, const char *tz_str
,
749 static char time_buf
[128];
755 sprintf(time_buf
, "%lu %s", time
, tz_str
);
760 minutes
= tz
< 0 ? -tz
: tz
;
761 minutes
= (minutes
/ 100)*60 + (minutes
% 100);
762 minutes
= tz
< 0 ? -minutes
: minutes
;
763 t
= time
+ minutes
* 60;
766 strftime(time_buf
, sizeof(time_buf
), "%Y-%m-%d %H:%M:%S ", tm
);
767 strcat(time_buf
, tz_str
);
771 static void topo_setter(struct commit
*c
, void *data
)
773 struct util_info
*util
= c
->util
;
774 util
->topo_data
= data
;
777 static void *topo_getter(struct commit
*c
)
779 struct util_info
*util
= c
->util
;
780 return util
->topo_data
;
783 static int read_ancestry(const char *graft_file
,
784 unsigned char **start_sha1
)
786 FILE *fp
= fopen(graft_file
, "r");
790 while (fgets(buf
, sizeof(buf
), fp
)) {
791 /* The format is just "Commit Parent1 Parent2 ...\n" */
792 int len
= strlen(buf
);
793 struct commit_graft
*graft
= read_graft_line(buf
, len
);
794 register_commit_graft(graft
, 0);
796 *start_sha1
= graft
->sha1
;
802 static int lineno_width(int lines
)
806 for (width
= 1, i
= 10; i
<= lines
+ 1; width
++)
811 static int find_orig_linenum(struct util_info
*u
, int lineno
)
815 for (i
= 0; i
< u
->num_lines
; i
++)
816 if (lineno
== u
->line_map
[i
])
821 static void emit_meta(struct commit
*c
, int lno
,
822 int sha1_len
, int compatibility
, int porcelain
,
823 int show_name
, int show_number
, int show_raw_time
,
824 int longest_file
, int longest_author
,
825 int max_digits
, int max_orig_digits
)
829 struct commit_info ci
;
832 lineno
= find_orig_linenum(u
, lno
);
836 struct commit
*cc
= (lno
== 0) ? NULL
: blame_lines
[lno
-1];
838 /* This is the beginning of this group */
840 for (i
= lno
+ 1; i
< num_blame_lines
; i
++)
841 if (blame_lines
[i
] != c
)
843 group_size
= i
- lno
;
846 printf("%s %d %d %d\n", sha1_to_hex(c
->object
.sha1
),
847 lineno
, lno
+ 1, group_size
);
849 printf("%s %d %d\n", sha1_to_hex(c
->object
.sha1
),
851 if (!u
->meta_given
) {
852 get_commit_info(c
, &ci
, 1);
853 printf("author %s\n", ci
.author
);
854 printf("author-mail %s\n", ci
.author_mail
);
855 printf("author-time %lu\n", ci
.author_time
);
856 printf("author-tz %s\n", ci
.author_tz
);
857 printf("committer %s\n", ci
.committer
);
858 printf("committer-mail %s\n", ci
.committer_mail
);
859 printf("committer-time %lu\n", ci
.committer_time
);
860 printf("committer-tz %s\n", ci
.committer_tz
);
862 if (quote_c_style(u
->pathname
, NULL
, NULL
, 0))
863 quote_c_style(u
->pathname
, NULL
, stdout
, 0);
865 fputs(u
->pathname
, stdout
);
866 printf("\nsummary %s\n", ci
.summary
);
874 get_commit_info(c
, &ci
, 0);
875 fwrite(sha1_to_hex(c
->object
.sha1
), sha1_len
, 1, stdout
);
877 printf("\t(%10s\t%10s\t%d)", ci
.author
,
878 format_time(ci
.author_time
, ci
.author_tz
,
884 printf(" %-*.*s", longest_file
, longest_file
,
887 printf(" %*d", max_orig_digits
,
889 printf(" (%-*.*s %10s %*d) ",
890 longest_author
, longest_author
, ci
.author
,
891 format_time(ci
.author_time
, ci
.author_tz
,
893 max_digits
, lno
+ 1);
897 int main(int argc
, const char **argv
)
900 struct commit
*initial
= NULL
;
901 unsigned char sha1
[20], *sha1_p
= NULL
;
903 const char *filename
= NULL
, *commit
= NULL
;
904 char filename_buf
[256];
906 int compatibility
= 0;
907 int show_raw_time
= 0;
909 struct commit
*start_commit
;
911 const char *args
[10];
914 struct commit_info ci
;
916 int max_digits
, max_orig_digits
;
917 int longest_file
, longest_author
, longest_file_lines
;
922 const char *prefix
= setup_git_directory();
923 git_config(git_default_config
);
925 for (i
= 1; i
< argc
; i
++) {
927 if (!strcmp(argv
[i
], "-h") ||
928 !strcmp(argv
[i
], "--help"))
930 if (!strcmp(argv
[i
], "-l") ||
931 !strcmp(argv
[i
], "--long")) {
935 if (!strcmp(argv
[i
], "-c") ||
936 !strcmp(argv
[i
], "--compatibility")) {
940 if (!strcmp(argv
[i
], "-t") ||
941 !strcmp(argv
[i
], "--time")) {
945 if (!strcmp(argv
[i
], "-S")) {
947 !read_ancestry(argv
[i
+ 1], &sha1_p
)) {
954 if (!strcmp(argv
[i
], "-f") ||
955 !strcmp(argv
[i
], "--show-name")) {
959 if (!strcmp(argv
[i
], "-n") ||
960 !strcmp(argv
[i
], "--show-number")) {
964 if (!strcmp(argv
[i
], "-p") ||
965 !strcmp(argv
[i
], "--porcelain")) {
971 if (!strcmp(argv
[i
], "--")) {
975 if (argv
[i
][0] == '-')
992 if (commit
&& sha1_p
)
998 sprintf(filename_buf
, "%s%s", prefix
, filename
);
1000 strcpy(filename_buf
, filename
);
1001 filename
= filename_buf
;
1004 if (get_sha1(commit
, sha1
))
1005 die("get_sha1 failed, commit '%s' not found", commit
);
1008 start_commit
= lookup_commit_reference(sha1_p
);
1009 get_util(start_commit
)->pathname
= filename
;
1010 if (fill_util_info(start_commit
)) {
1011 printf("%s not found in %s\n", filename
, commit
);
1015 init_revisions(&rev
, setup_git_directory());
1016 rev
.remove_empty_trees
= 1;
1018 rev
.prune_fn
= simplify_commit
;
1019 rev
.topo_setter
= topo_setter
;
1020 rev
.topo_getter
= topo_getter
;
1024 commit_list_insert(start_commit
, &rev
.commits
);
1028 diff_tree_setup_paths(args
, &rev
.pruning
);
1029 prepare_revision_walk(&rev
);
1030 process_commits(&rev
, filename
, &initial
);
1032 for (i
= 0; i
< num_blame_lines
; i
++)
1033 if (!blame_lines
[i
])
1034 blame_lines
[i
] = initial
;
1036 buf
= blame_contents
;
1037 max_digits
= lineno_width(num_blame_lines
);
1041 longest_file_lines
= 0;
1042 for (i
= 0; i
< num_blame_lines
; i
++) {
1043 struct commit
*c
= blame_lines
[i
];
1044 struct util_info
*u
;
1047 if (!show_name
&& strcmp(filename
, u
->pathname
))
1049 if (longest_file
< strlen(u
->pathname
))
1050 longest_file
= strlen(u
->pathname
);
1051 if (longest_file_lines
< u
->num_lines
)
1052 longest_file_lines
= u
->num_lines
;
1053 get_commit_info(c
, &ci
, 0);
1054 if (longest_author
< strlen(ci
.author
))
1055 longest_author
= strlen(ci
.author
);
1058 max_orig_digits
= lineno_width(longest_file_lines
);
1060 for (i
= 0; i
< num_blame_lines
; i
++) {
1061 emit_meta(blame_lines
[i
], i
,
1062 sha1_len
, compatibility
, porcelain
,
1063 show_name
, show_number
, show_raw_time
,
1064 longest_file
, longest_author
,
1065 max_digits
, max_orig_digits
);
1067 if (i
== num_blame_lines
- 1) {
1068 fwrite(buf
, blame_len
- (buf
- blame_contents
),
1070 if (blame_contents
[blame_len
-1] != '\n')
1074 char *next_buf
= strchr(buf
, '\n') + 1;
1075 fwrite(buf
, next_buf
- buf
, 1, stdout
);
1081 printf("num read blob: %d\n", num_read_blob
);
1082 printf("num get patch: %d\n", num_get_patch
);
1083 printf("num commits: %d\n", num_commits
);
1084 printf("patch time: %f\n", patch_time
/ 1000000.0);
1085 printf("initial: %s\n", sha1_to_hex(initial
->object
.sha1
));