git-pickaxe: do not confuse two origins that are the same.
[git/git.git] / builtin-pickaxe.c
CommitLineData
cee7f245
JH
1/*
2 * Pickaxe
3 *
4 * Copyright (c) 2006, Junio C Hamano
5 */
6
7#include "cache.h"
8#include "builtin.h"
9#include "blob.h"
10#include "commit.h"
11#include "tag.h"
12#include "tree-walk.h"
13#include "diff.h"
14#include "diffcore.h"
15#include "revision.h"
16#include "xdiff-interface.h"
17
18#include <time.h>
19#include <sys/time.h>
20
21static char pickaxe_usage[] =
18abd745 22"git-pickaxe [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [commit] [--] file\n"
cee7f245
JH
23" -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
24" -l, --long Show long commit SHA1 (Default: off)\n"
25" -t, --time Show raw timestamp (Default: off)\n"
26" -f, --show-name Show original filename (Default: auto)\n"
27" -n, --show-number Show original linenumber (Default: off)\n"
28" -p, --porcelain Show in a format designed for machine consumption\n"
29" -L n,m Process only line range n,m, counting from 1\n"
18abd745 30" -M, -C Find line movements within and across files\n"
cee7f245
JH
31" -S revs-file Use revisions from revs-file instead of calling git-rev-list\n";
32
33static int longest_file;
34static int longest_author;
35static int max_orig_digits;
36static int max_digits;
5ff62c30 37static int max_score_digits;
cee7f245 38
d24bba80 39#define PICKAXE_BLAME_MOVE 01
18abd745
JH
40#define PICKAXE_BLAME_COPY 02
41#define PICKAXE_BLAME_COPY_HARDER 04
d24bba80 42
4a0fc95f
JH
43/*
44 * blame for a blame_entry with score lower than these thresholds
45 * is not passed to the parent using move/copy logic.
46 */
47static unsigned blame_move_score;
48static unsigned blame_copy_score;
49#define BLAME_DEFAULT_MOVE_SCORE 20
50#define BLAME_DEFAULT_COPY_SCORE 40
51
cee7f245
JH
52/* bits #0..7 in revision.h, #8..11 used for merge_bases() in commit.c */
53#define METAINFO_SHOWN (1u<<12)
54#define MORE_THAN_ONE_PATH (1u<<13)
55
56/*
57 * One blob in a commit
58 */
59struct origin {
60 struct commit *commit;
61 unsigned char blob_sha1[20];
62 char path[FLEX_ARRAY];
63};
64
65struct blame_entry {
66 struct blame_entry *prev;
67 struct blame_entry *next;
68
69 /* the first line of this group in the final image;
70 * internally all line numbers are 0 based.
71 */
72 int lno;
73
74 /* how many lines this group has */
75 int num_lines;
76
77 /* the commit that introduced this group into the final image */
78 struct origin *suspect;
79
80 /* true if the suspect is truly guilty; false while we have not
81 * checked if the group came from one of its parents.
82 */
83 char guilty;
84
85 /* the line number of the first line of this group in the
86 * suspect's file; internally all line numbers are 0 based.
87 */
88 int s_lno;
5ff62c30
JH
89
90 /* how significant this entry is -- cached to avoid
91 * scanning the lines over and over
92 */
93 unsigned score;
cee7f245
JH
94};
95
96struct scoreboard {
97 /* the final commit (i.e. where we started digging from) */
98 struct commit *final;
99
100 const char *path;
101
102 /* the contents in the final; pointed into by buf pointers of
103 * blame_entries
104 */
105 const char *final_buf;
106 unsigned long final_buf_size;
107
108 /* linked list of blames */
109 struct blame_entry *ent;
110
612702e8 111 /* look-up a line in the final buffer */
cee7f245
JH
112 int num_lines;
113 int *lineno;
114};
115
46014766
JH
116static int cmp_suspect(struct origin *a, struct origin *b)
117{
118 int cmp = hashcmp(a->commit->object.sha1, b->commit->object.sha1);
119 if (cmp)
120 return cmp;
121 return strcmp(a->path, b->path);
122}
123
cee7f245
JH
124static void coalesce(struct scoreboard *sb)
125{
126 struct blame_entry *ent, *next;
127
128 for (ent = sb->ent; ent && (next = ent->next); ent = next) {
46014766 129 if (!cmp_suspect(ent->suspect, next->suspect) &&
cee7f245
JH
130 ent->guilty == next->guilty &&
131 ent->s_lno + ent->num_lines == next->s_lno) {
132 ent->num_lines += next->num_lines;
133 ent->next = next->next;
134 if (ent->next)
135 ent->next->prev = ent;
136 free(next);
46014766 137 ent->score = 0;
cee7f245
JH
138 next = ent; /* again */
139 }
140 }
141}
142
143static void free_origin(struct origin *o)
144{
145 free(o);
146}
147
148static struct origin *find_origin(struct scoreboard *sb,
149 struct commit *commit,
150 const char *path)
151{
152 struct blame_entry *ent;
153 struct origin *o;
154 unsigned mode;
155 char type[10];
156
157 for (ent = sb->ent; ent; ent = ent->next) {
158 if (ent->suspect->commit == commit &&
159 !strcmp(ent->suspect->path, path))
160 return ent->suspect;
161 }
162
163 o = xcalloc(1, sizeof(*o) + strlen(path) + 1);
164 o->commit = commit;
165 strcpy(o->path, path);
166 if (get_tree_entry(commit->object.sha1, path, o->blob_sha1, &mode))
167 goto err_out;
168 if (sha1_object_info(o->blob_sha1, type, NULL) ||
169 strcmp(type, blob_type))
170 goto err_out;
171 return o;
172 err_out:
173 free_origin(o);
174 return NULL;
175}
176
177static struct origin *find_rename(struct scoreboard *sb,
178 struct commit *parent,
179 struct origin *origin)
180{
181 struct origin *porigin = NULL;
182 struct diff_options diff_opts;
183 int i;
184 const char *paths[1];
185
186 diff_setup(&diff_opts);
187 diff_opts.recursive = 1;
188 diff_opts.detect_rename = DIFF_DETECT_RENAME;
189 diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
190 paths[0] = NULL;
191 diff_tree_setup_paths(paths, &diff_opts);
192 if (diff_setup_done(&diff_opts) < 0)
193 die("diff-setup");
194 diff_tree_sha1(origin->commit->tree->object.sha1,
195 parent->tree->object.sha1,
196 "", &diff_opts);
197 diffcore_std(&diff_opts);
198
199 for (i = 0; i < diff_queued_diff.nr; i++) {
200 struct diff_filepair *p = diff_queued_diff.queue[i];
612702e8
JH
201 if ((p->status == 'R' || p->status == 'C') &&
202 !strcmp(p->one->path, origin->path)) {
cee7f245
JH
203 porigin = find_origin(sb, parent, p->two->path);
204 break;
205 }
206 }
207 diff_flush(&diff_opts);
208 return porigin;
209}
210
211struct chunk {
212 /* line number in postimage; up to but not including this
213 * line is the same as preimage
214 */
215 int same;
216
217 /* preimage line number after this chunk */
218 int p_next;
219
220 /* postimage line number after this chunk */
221 int t_next;
222};
223
224struct patch {
225 struct chunk *chunks;
226 int num;
227};
228
229struct blame_diff_state {
230 struct xdiff_emit_state xm;
231 struct patch *ret;
232 unsigned hunk_post_context;
233 unsigned hunk_in_pre_context : 1;
234};
235
236static void process_u_diff(void *state_, char *line, unsigned long len)
237{
238 struct blame_diff_state *state = state_;
239 struct chunk *chunk;
240 int off1, off2, len1, len2, num;
241
cee7f245
JH
242 num = state->ret->num;
243 if (len < 4 || line[0] != '@' || line[1] != '@') {
244 if (state->hunk_in_pre_context && line[0] == ' ')
245 state->ret->chunks[num - 1].same++;
246 else {
247 state->hunk_in_pre_context = 0;
248 if (line[0] == ' ')
249 state->hunk_post_context++;
250 else
251 state->hunk_post_context = 0;
252 }
253 return;
254 }
255
256 if (num && state->hunk_post_context) {
257 chunk = &state->ret->chunks[num - 1];
258 chunk->p_next -= state->hunk_post_context;
259 chunk->t_next -= state->hunk_post_context;
260 }
261 state->ret->num = ++num;
262 state->ret->chunks = xrealloc(state->ret->chunks,
263 sizeof(struct chunk) * num);
264 chunk = &state->ret->chunks[num - 1];
265 if (parse_hunk_header(line, len, &off1, &len1, &off2, &len2)) {
266 state->ret->num--;
267 return;
268 }
269
270 /* Line numbers in patch output are one based. */
271 off1--;
272 off2--;
273
274 chunk->same = len2 ? off2 : (off2 + 1);
275
276 chunk->p_next = off1 + (len1 ? len1 : 1);
277 chunk->t_next = chunk->same + len2;
278 state->hunk_in_pre_context = 1;
279 state->hunk_post_context = 0;
280}
281
282static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
283 int context)
284{
285 struct blame_diff_state state;
286 xpparam_t xpp;
287 xdemitconf_t xecfg;
288 xdemitcb_t ecb;
289
290 xpp.flags = XDF_NEED_MINIMAL;
291 xecfg.ctxlen = context;
292 xecfg.flags = 0;
293 ecb.outf = xdiff_outf;
294 ecb.priv = &state;
295 memset(&state, 0, sizeof(state));
296 state.xm.consume = process_u_diff;
297 state.ret = xmalloc(sizeof(struct patch));
298 state.ret->chunks = NULL;
299 state.ret->num = 0;
300
301 xdl_diff(file_p, file_o, &xpp, &xecfg, &ecb);
302
303 if (state.ret->num) {
304 struct chunk *chunk;
305 chunk = &state.ret->chunks[state.ret->num - 1];
306 chunk->p_next -= state.hunk_post_context;
307 chunk->t_next -= state.hunk_post_context;
308 }
309 return state.ret;
310}
311
312static struct patch *get_patch(struct origin *parent, struct origin *origin)
313{
314 mmfile_t file_p, file_o;
315 char type[10];
316 char *blob_p, *blob_o;
317 struct patch *patch;
318
cee7f245
JH
319 blob_p = read_sha1_file(parent->blob_sha1, type,
320 (unsigned long *) &file_p.size);
321 blob_o = read_sha1_file(origin->blob_sha1, type,
322 (unsigned long *) &file_o.size);
323 file_p.ptr = blob_p;
324 file_o.ptr = blob_o;
325 if (!file_p.ptr || !file_o.ptr) {
326 free(blob_p);
327 free(blob_o);
328 return NULL;
329 }
330
331 patch = compare_buffer(&file_p, &file_o, 0);
332 free(blob_p);
333 free(blob_o);
334 return patch;
335}
336
337static void free_patch(struct patch *p)
338{
339 free(p->chunks);
340 free(p);
341}
342
343static void add_blame_entry(struct scoreboard *sb, struct blame_entry *e)
344{
345 struct blame_entry *ent, *prev = NULL;
346
347 for (ent = sb->ent; ent && ent->lno < e->lno; ent = ent->next)
348 prev = ent;
349
350 /* prev, if not NULL, is the last one that is below e */
351 e->prev = prev;
352 if (prev) {
353 e->next = prev->next;
354 prev->next = e;
355 }
356 else {
357 e->next = sb->ent;
358 sb->ent = e;
359 }
360 if (e->next)
361 e->next->prev = e;
362}
363
364static void dup_entry(struct blame_entry *dst, struct blame_entry *src)
365{
366 struct blame_entry *p, *n;
367 p = dst->prev;
368 n = dst->next;
369 memcpy(dst, src, sizeof(*src));
370 dst->prev = p;
371 dst->next = n;
5ff62c30 372 dst->score = 0;
cee7f245
JH
373}
374
375static const char *nth_line(struct scoreboard *sb, int lno)
376{
377 return sb->final_buf + sb->lineno[lno];
378}
379
380static void split_overlap(struct blame_entry split[3],
381 struct blame_entry *e,
382 int tlno, int plno, int same,
383 struct origin *parent)
384{
385 /* it is known that lines between tlno to same came from
386 * parent, and e has an overlap with that range. it also is
387 * known that parent's line plno corresponds to e's line tlno.
388 *
389 * <---- e ----->
390 * <------>
391 * <------------>
392 * <------------>
393 * <------------------>
394 *
395 * Potentially we need to split e into three parts; before
396 * this chunk, the chunk to be blamed for parent, and after
397 * that portion.
398 */
399 int chunk_end_lno;
400 memset(split, 0, sizeof(struct blame_entry [3]));
401
402 if (e->s_lno < tlno) {
403 /* there is a pre-chunk part not blamed on parent */
404 split[0].suspect = e->suspect;
405 split[0].lno = e->lno;
406 split[0].s_lno = e->s_lno;
407 split[0].num_lines = tlno - e->s_lno;
408 split[1].lno = e->lno + tlno - e->s_lno;
409 split[1].s_lno = plno;
410 }
411 else {
412 split[1].lno = e->lno;
413 split[1].s_lno = plno + (e->s_lno - tlno);
414 }
415
416 if (same < e->s_lno + e->num_lines) {
417 /* there is a post-chunk part not blamed on parent */
418 split[2].suspect = e->suspect;
419 split[2].lno = e->lno + (same - e->s_lno);
420 split[2].s_lno = e->s_lno + (same - e->s_lno);
421 split[2].num_lines = e->s_lno + e->num_lines - same;
422 chunk_end_lno = split[2].lno;
423 }
424 else
425 chunk_end_lno = e->lno + e->num_lines;
426 split[1].num_lines = chunk_end_lno - split[1].lno;
427
428 if (split[1].num_lines < 1)
429 return;
430 split[1].suspect = parent;
431}
432
433static void split_blame(struct scoreboard *sb,
434 struct blame_entry split[3],
435 struct blame_entry *e)
436{
437 struct blame_entry *new_entry;
438
439 if (split[0].suspect && split[2].suspect) {
440 /* we need to split e into two and add another for parent */
441 dup_entry(e, &split[0]);
442
443 new_entry = xmalloc(sizeof(*new_entry));
444 memcpy(new_entry, &(split[2]), sizeof(struct blame_entry));
445 add_blame_entry(sb, new_entry);
446
447 new_entry = xmalloc(sizeof(*new_entry));
448 memcpy(new_entry, &(split[1]), sizeof(struct blame_entry));
449 add_blame_entry(sb, new_entry);
450 }
451 else if (!split[0].suspect && !split[2].suspect)
452 /* parent covers the entire area */
453 dup_entry(e, &split[1]);
454 else if (split[0].suspect) {
455 dup_entry(e, &split[0]);
456
457 new_entry = xmalloc(sizeof(*new_entry));
458 memcpy(new_entry, &(split[1]), sizeof(struct blame_entry));
459 add_blame_entry(sb, new_entry);
460 }
461 else {
462 dup_entry(e, &split[1]);
463
464 new_entry = xmalloc(sizeof(*new_entry));
465 memcpy(new_entry, &(split[2]), sizeof(struct blame_entry));
466 add_blame_entry(sb, new_entry);
467 }
468
5ff62c30 469 if (1) { /* sanity */
cee7f245 470 struct blame_entry *ent;
612702e8 471 int lno = sb->ent->lno, corrupt = 0;
cee7f245
JH
472
473 for (ent = sb->ent; ent; ent = ent->next) {
474 if (lno != ent->lno)
475 corrupt = 1;
476 if (ent->s_lno < 0)
477 corrupt = 1;
478 lno += ent->num_lines;
479 }
480 if (corrupt) {
612702e8 481 lno = sb->ent->lno;
cee7f245
JH
482 for (ent = sb->ent; ent; ent = ent->next) {
483 printf("L %8d l %8d n %8d\n",
484 lno, ent->lno, ent->num_lines);
485 lno = ent->lno + ent->num_lines;
486 }
487 die("oops");
488 }
489 }
490}
491
492static void blame_overlap(struct scoreboard *sb, struct blame_entry *e,
493 int tlno, int plno, int same,
494 struct origin *parent)
495{
496 struct blame_entry split[3];
497
498 split_overlap(split, e, tlno, plno, same, parent);
499 if (!split[1].suspect)
500 return;
501 split_blame(sb, split, e);
502}
503
504static int find_last_in_target(struct scoreboard *sb, struct origin *target)
505{
506 struct blame_entry *e;
507 int last_in_target = -1;
508
509 for (e = sb->ent; e; e = e->next) {
46014766 510 if (e->guilty || cmp_suspect(e->suspect, target))
cee7f245
JH
511 continue;
512 if (last_in_target < e->s_lno + e->num_lines)
513 last_in_target = e->s_lno + e->num_lines;
514 }
515 return last_in_target;
516}
517
518static void blame_chunk(struct scoreboard *sb,
519 int tlno, int plno, int same,
520 struct origin *target, struct origin *parent)
521{
612702e8 522 struct blame_entry *e;
cee7f245 523
612702e8 524 for (e = sb->ent; e; e = e->next) {
46014766 525 if (e->guilty || cmp_suspect(e->suspect, target))
cee7f245
JH
526 continue;
527 if (same <= e->s_lno)
528 continue;
529 if (tlno < e->s_lno + e->num_lines)
530 blame_overlap(sb, e, tlno, plno, same, parent);
531 }
532}
533
534static int pass_blame_to_parent(struct scoreboard *sb,
535 struct origin *target,
536 struct origin *parent)
537{
538 int i, last_in_target, plno, tlno;
539 struct patch *patch;
540
541 last_in_target = find_last_in_target(sb, target);
542 if (last_in_target < 0)
543 return 1; /* nothing remains for this target */
544
545 patch = get_patch(parent, target);
546 plno = tlno = 0;
547 for (i = 0; i < patch->num; i++) {
548 struct chunk *chunk = &patch->chunks[i];
549
cee7f245
JH
550 blame_chunk(sb, tlno, plno, chunk->same, target, parent);
551 plno = chunk->p_next;
552 tlno = chunk->t_next;
553 }
554 /* rest (i.e. anything above tlno) are the same as parent */
555 blame_chunk(sb, tlno, plno, last_in_target, target, parent);
556
557 free_patch(patch);
558 return 0;
559}
560
5ff62c30
JH
561static unsigned ent_score(struct scoreboard *sb, struct blame_entry *e)
562{
563 unsigned score;
564 const char *cp, *ep;
565
566 if (e->score)
567 return e->score;
568
612702e8 569 score = 1;
5ff62c30
JH
570 cp = nth_line(sb, e->lno);
571 ep = nth_line(sb, e->lno + e->num_lines);
572 while (cp < ep) {
573 unsigned ch = *((unsigned char *)cp);
574 if (isalnum(ch))
575 score++;
576 cp++;
577 }
578 e->score = score;
579 return score;
580}
581
582static void copy_split_if_better(struct scoreboard *sb,
583 struct blame_entry best_so_far[3],
d24bba80
JH
584 struct blame_entry this[3])
585{
586 if (!this[1].suspect)
587 return;
5ff62c30
JH
588 if (best_so_far[1].suspect) {
589 if (ent_score(sb, &this[1]) < ent_score(sb, &best_so_far[1]))
590 return;
591 }
d24bba80
JH
592 memcpy(best_so_far, this, sizeof(struct blame_entry [3]));
593}
594
595static void find_copy_in_blob(struct scoreboard *sb,
596 struct blame_entry *ent,
597 struct origin *parent,
598 struct blame_entry split[3],
599 mmfile_t *file_p)
600{
601 const char *cp;
602 int cnt;
603 mmfile_t file_o;
604 struct patch *patch;
605 int i, plno, tlno;
606
607 cp = nth_line(sb, ent->lno);
608 file_o.ptr = (char*) cp;
609 cnt = ent->num_lines;
610
611 while (cnt && cp < sb->final_buf + sb->final_buf_size) {
612 if (*cp++ == '\n')
613 cnt--;
614 }
615 file_o.size = cp - file_o.ptr;
616
617 patch = compare_buffer(file_p, &file_o, 1);
618
619 memset(split, 0, sizeof(struct blame_entry [3]));
620 plno = tlno = 0;
621 for (i = 0; i < patch->num; i++) {
622 struct chunk *chunk = &patch->chunks[i];
623
624 /* tlno to chunk->same are the same as ent */
625 if (ent->num_lines <= tlno)
626 break;
627 if (tlno < chunk->same) {
628 struct blame_entry this[3];
629 split_overlap(this, ent,
630 tlno + ent->s_lno, plno,
631 chunk->same + ent->s_lno,
632 parent);
5ff62c30 633 copy_split_if_better(sb, split, this);
d24bba80
JH
634 }
635 plno = chunk->p_next;
636 tlno = chunk->t_next;
637 }
638 free_patch(patch);
639}
640
641static int find_move_in_parent(struct scoreboard *sb,
642 struct origin *target,
643 struct origin *parent)
644{
645 int last_in_target;
46014766 646 struct blame_entry *e, split[3];
d24bba80
JH
647 mmfile_t file_p;
648 char type[10];
649 char *blob_p;
650
651 last_in_target = find_last_in_target(sb, target);
652 if (last_in_target < 0)
653 return 1; /* nothing remains for this target */
654
655 blob_p = read_sha1_file(parent->blob_sha1, type,
656 (unsigned long *) &file_p.size);
657 file_p.ptr = blob_p;
658 if (!file_p.ptr) {
659 free(blob_p);
660 return 0;
661 }
662
46014766
JH
663 for (e = sb->ent; e; e = e->next) {
664 if (e->guilty || cmp_suspect(e->suspect, target))
d24bba80 665 continue;
46014766 666 find_copy_in_blob(sb, e, parent, split, &file_p);
4a0fc95f
JH
667 if (split[1].suspect &&
668 blame_move_score < ent_score(sb, &split[1]))
46014766 669 split_blame(sb, split, e);
d24bba80
JH
670 }
671 free(blob_p);
672 return 0;
673}
674
18abd745
JH
675static int find_copy_in_parent(struct scoreboard *sb,
676 struct origin *target,
677 struct commit *parent,
678 struct origin *porigin,
679 int opt)
680{
681 struct diff_options diff_opts;
682 const char *paths[1];
46014766 683 struct blame_entry *e;
18abd745
JH
684 int i;
685
686 if (find_last_in_target(sb, target) < 0)
687 return 1; /* nothing remains for this target */
688
689 diff_setup(&diff_opts);
690 diff_opts.recursive = 1;
691 diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
692
693 /* Try "find copies harder" on new path */
694 if ((opt & PICKAXE_BLAME_COPY_HARDER) &&
695 (!porigin || strcmp(target->path, porigin->path))) {
696 diff_opts.detect_rename = DIFF_DETECT_COPY;
697 diff_opts.find_copies_harder = 1;
698 }
699 paths[0] = NULL;
700 diff_tree_setup_paths(paths, &diff_opts);
701 if (diff_setup_done(&diff_opts) < 0)
702 die("diff-setup");
703 diff_tree_sha1(parent->tree->object.sha1,
704 target->commit->tree->object.sha1,
705 "", &diff_opts);
706 diffcore_std(&diff_opts);
707
46014766 708 for (e = sb->ent; e; e = e->next) {
18abd745 709 struct blame_entry split[3];
46014766 710 if (e->guilty || cmp_suspect(e->suspect, target))
18abd745
JH
711 continue;
712
713 memset(split, 0, sizeof(split));
714 for (i = 0; i < diff_queued_diff.nr; i++) {
715 struct diff_filepair *p = diff_queued_diff.queue[i];
716 struct origin *norigin;
717 mmfile_t file_p;
718 char type[10];
719 char *blob;
720 struct blame_entry this[3];
721
722 if (!DIFF_FILE_VALID(p->one))
723 continue; /* does not exist in parent */
724 if (porigin && !strcmp(p->one->path, porigin->path))
725 /* find_move already dealt with this path */
726 continue;
727 norigin = find_origin(sb, parent, p->one->path);
728
729 blob = read_sha1_file(norigin->blob_sha1, type,
730 (unsigned long *) &file_p.size);
731 file_p.ptr = blob;
732 if (!file_p.ptr) {
733 free(blob);
734 continue;
735 }
46014766 736 find_copy_in_blob(sb, e, norigin, this, &file_p);
5ff62c30 737 copy_split_if_better(sb, split, this);
18abd745 738 }
4a0fc95f
JH
739 if (split[1].suspect &&
740 blame_copy_score < ent_score(sb, &split[1]))
46014766 741 split_blame(sb, split, e);
18abd745
JH
742 }
743 diff_flush(&diff_opts);
744
745 return 0;
746}
747
cee7f245
JH
748#define MAXPARENT 16
749
d24bba80 750static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
cee7f245
JH
751{
752 int i;
753 struct commit *commit = origin->commit;
754 struct commit_list *parent;
755 struct origin *parent_origin[MAXPARENT], *porigin;
756
757 memset(parent_origin, 0, sizeof(parent_origin));
758 for (i = 0, parent = commit->parents;
759 i < MAXPARENT && parent;
760 parent = parent->next, i++) {
761 struct commit *p = parent->item;
762
763 if (parse_commit(p))
764 continue;
765 porigin = find_origin(sb, parent->item, origin->path);
766 if (!porigin)
767 porigin = find_rename(sb, parent->item, origin);
768 if (!porigin)
769 continue;
770 if (!hashcmp(porigin->blob_sha1, origin->blob_sha1)) {
771 struct blame_entry *e;
772 for (e = sb->ent; e; e = e->next)
773 if (e->suspect == origin)
774 e->suspect = porigin;
cee7f245
JH
775 return;
776 }
777 parent_origin[i] = porigin;
778 }
779
780 for (i = 0, parent = commit->parents;
781 i < MAXPARENT && parent;
782 parent = parent->next, i++) {
783 struct origin *porigin = parent_origin[i];
784 if (!porigin)
785 continue;
786 if (pass_blame_to_parent(sb, origin, porigin))
787 return;
788 }
d24bba80
JH
789
790 /*
791 * Optionally run "miff" to find moves in parents' files here.
792 */
793 if (opt & PICKAXE_BLAME_MOVE)
794 for (i = 0, parent = commit->parents;
795 i < MAXPARENT && parent;
796 parent = parent->next, i++) {
797 struct origin *porigin = parent_origin[i];
798 if (!porigin)
799 continue;
800 if (find_move_in_parent(sb, origin, porigin))
801 return;
802 }
803
18abd745
JH
804 /*
805 * Optionally run "ciff" to find copies from parents' files here.
806 */
807 if (opt & PICKAXE_BLAME_COPY)
808 for (i = 0, parent = commit->parents;
809 i < MAXPARENT && parent;
810 parent = parent->next, i++) {
811 struct origin *porigin = parent_origin[i];
812 if (find_copy_in_parent(sb, origin, parent->item,
813 porigin, opt))
814 return;
815 }
cee7f245
JH
816}
817
d24bba80 818static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
cee7f245
JH
819{
820 while (1) {
821 struct blame_entry *ent;
822 struct commit *commit;
823 struct origin *suspect = NULL;
824
825 /* find one suspect to break down */
826 for (ent = sb->ent; !suspect && ent; ent = ent->next)
827 if (!ent->guilty)
828 suspect = ent->suspect;
829 if (!suspect)
830 return; /* all done */
831
832 commit = suspect->commit;
833 parse_commit(commit);
834 if (!(commit->object.flags & UNINTERESTING) &&
835 !(revs->max_age != -1 && commit->date < revs->max_age))
d24bba80 836 pass_blame(sb, suspect, opt);
cee7f245
JH
837
838 /* Take responsibility for the remaining entries */
839 for (ent = sb->ent; ent; ent = ent->next)
46014766 840 if (!cmp_suspect(ent->suspect, suspect))
cee7f245 841 ent->guilty = 1;
46014766
JH
842
843 coalesce(sb);
cee7f245
JH
844 }
845}
846
847static const char *format_time(unsigned long time, const char *tz_str,
848 int show_raw_time)
849{
850 static char time_buf[128];
851 time_t t = time;
852 int minutes, tz;
853 struct tm *tm;
854
855 if (show_raw_time) {
856 sprintf(time_buf, "%lu %s", time, tz_str);
857 return time_buf;
858 }
859
860 tz = atoi(tz_str);
861 minutes = tz < 0 ? -tz : tz;
862 minutes = (minutes / 100)*60 + (minutes % 100);
863 minutes = tz < 0 ? -minutes : minutes;
864 t = time + minutes * 60;
865 tm = gmtime(&t);
866
867 strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
868 strcat(time_buf, tz_str);
869 return time_buf;
870}
871
872struct commit_info
873{
874 char *author;
875 char *author_mail;
876 unsigned long author_time;
877 char *author_tz;
878
879 /* filled only when asked for details */
880 char *committer;
881 char *committer_mail;
882 unsigned long committer_time;
883 char *committer_tz;
884
885 char *summary;
886};
887
888static void get_ac_line(const char *inbuf, const char *what,
889 int bufsz, char *person, char **mail,
890 unsigned long *time, char **tz)
891{
892 int len;
893 char *tmp, *endp;
894
895 tmp = strstr(inbuf, what);
896 if (!tmp)
897 goto error_out;
898 tmp += strlen(what);
899 endp = strchr(tmp, '\n');
900 if (!endp)
901 len = strlen(tmp);
902 else
903 len = endp - tmp;
904 if (bufsz <= len) {
905 error_out:
906 /* Ugh */
907 person = *mail = *tz = "(unknown)";
908 *time = 0;
909 return;
910 }
911 memcpy(person, tmp, len);
912
913 tmp = person;
914 tmp += len;
915 *tmp = 0;
916 while (*tmp != ' ')
917 tmp--;
918 *tz = tmp+1;
919
920 *tmp = 0;
921 while (*tmp != ' ')
922 tmp--;
923 *time = strtoul(tmp, NULL, 10);
924
925 *tmp = 0;
926 while (*tmp != ' ')
927 tmp--;
928 *mail = tmp + 1;
929 *tmp = 0;
930}
931
932static void get_commit_info(struct commit *commit,
933 struct commit_info *ret,
934 int detailed)
935{
936 int len;
937 char *tmp, *endp;
938 static char author_buf[1024];
939 static char committer_buf[1024];
940 static char summary_buf[1024];
941
612702e8
JH
942 /* We've operated without save_commit_buffer, so
943 * we now need to populate them for output.
944 */
945 if (!commit->buffer) {
946 char type[20];
947 unsigned long size;
948 commit->buffer =
949 read_sha1_file(commit->object.sha1, type, &size);
950 }
cee7f245
JH
951 ret->author = author_buf;
952 get_ac_line(commit->buffer, "\nauthor ",
953 sizeof(author_buf), author_buf, &ret->author_mail,
954 &ret->author_time, &ret->author_tz);
955
956 if (!detailed)
957 return;
958
959 ret->committer = committer_buf;
960 get_ac_line(commit->buffer, "\ncommitter ",
961 sizeof(committer_buf), committer_buf, &ret->committer_mail,
962 &ret->committer_time, &ret->committer_tz);
963
964 ret->summary = summary_buf;
965 tmp = strstr(commit->buffer, "\n\n");
966 if (!tmp) {
967 error_out:
968 sprintf(summary_buf, "(%s)", sha1_to_hex(commit->object.sha1));
969 return;
970 }
971 tmp += 2;
972 endp = strchr(tmp, '\n');
973 if (!endp)
974 goto error_out;
975 len = endp - tmp;
976 if (len >= sizeof(summary_buf))
977 goto error_out;
978 memcpy(summary_buf, tmp, len);
979 summary_buf[len] = 0;
980}
981
982#define OUTPUT_ANNOTATE_COMPAT 001
983#define OUTPUT_LONG_OBJECT_NAME 002
984#define OUTPUT_RAW_TIMESTAMP 004
985#define OUTPUT_PORCELAIN 010
986#define OUTPUT_SHOW_NAME 020
987#define OUTPUT_SHOW_NUMBER 040
5ff62c30 988#define OUTPUT_SHOW_SCORE 0100
cee7f245
JH
989
990static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent)
991{
992 int cnt;
993 const char *cp;
994 struct origin *suspect = ent->suspect;
995 char hex[41];
996
997 strcpy(hex, sha1_to_hex(suspect->commit->object.sha1));
998 printf("%s%c%d %d %d\n",
999 hex,
1000 ent->guilty ? ' ' : '*', // purely for debugging
1001 ent->s_lno + 1,
1002 ent->lno + 1,
1003 ent->num_lines);
1004 if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
1005 struct commit_info ci;
1006 suspect->commit->object.flags |= METAINFO_SHOWN;
1007 get_commit_info(suspect->commit, &ci, 1);
1008 printf("author %s\n", ci.author);
1009 printf("author-mail %s\n", ci.author_mail);
1010 printf("author-time %lu\n", ci.author_time);
1011 printf("author-tz %s\n", ci.author_tz);
1012 printf("committer %s\n", ci.committer);
1013 printf("committer-mail %s\n", ci.committer_mail);
1014 printf("committer-time %lu\n", ci.committer_time);
1015 printf("committer-tz %s\n", ci.committer_tz);
1016 printf("filename %s\n", suspect->path);
1017 printf("summary %s\n", ci.summary);
1018 }
1019 else if (suspect->commit->object.flags & MORE_THAN_ONE_PATH)
1020 printf("filename %s\n", suspect->path);
1021
1022 cp = nth_line(sb, ent->lno);
1023 for (cnt = 0; cnt < ent->num_lines; cnt++) {
1024 char ch;
1025 if (cnt)
1026 printf("%s %d %d\n", hex,
1027 ent->s_lno + 1 + cnt,
1028 ent->lno + 1 + cnt);
1029 putchar('\t');
1030 do {
1031 ch = *cp++;
1032 putchar(ch);
1033 } while (ch != '\n' &&
1034 cp < sb->final_buf + sb->final_buf_size);
1035 }
1036}
1037
1038static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
1039{
1040 int cnt;
1041 const char *cp;
1042 struct origin *suspect = ent->suspect;
1043 struct commit_info ci;
1044 char hex[41];
1045 int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);
1046
1047 get_commit_info(suspect->commit, &ci, 1);
1048 strcpy(hex, sha1_to_hex(suspect->commit->object.sha1));
1049
1050 cp = nth_line(sb, ent->lno);
1051 for (cnt = 0; cnt < ent->num_lines; cnt++) {
1052 char ch;
1053
1054 printf("%.*s", (opt & OUTPUT_LONG_OBJECT_NAME) ? 40 : 8, hex);
1055 if (opt & OUTPUT_ANNOTATE_COMPAT)
1056 printf("\t(%10s\t%10s\t%d)", ci.author,
1057 format_time(ci.author_time, ci.author_tz,
1058 show_raw_time),
1059 ent->lno + 1 + cnt);
1060 else {
5ff62c30
JH
1061 if (opt & OUTPUT_SHOW_SCORE)
1062 printf(" %*d", max_score_digits, ent->score);
cee7f245
JH
1063 if (opt & OUTPUT_SHOW_NAME)
1064 printf(" %-*.*s", longest_file, longest_file,
1065 suspect->path);
1066 if (opt & OUTPUT_SHOW_NUMBER)
1067 printf(" %*d", max_orig_digits,
1068 ent->s_lno + 1 + cnt);
1069 printf(" (%-*.*s %10s %*d) ",
1070 longest_author, longest_author, ci.author,
1071 format_time(ci.author_time, ci.author_tz,
1072 show_raw_time),
1073 max_digits, ent->lno + 1 + cnt);
1074 }
1075 do {
1076 ch = *cp++;
1077 putchar(ch);
1078 } while (ch != '\n' &&
1079 cp < sb->final_buf + sb->final_buf_size);
1080 }
1081}
1082
1083static void output(struct scoreboard *sb, int option)
1084{
1085 struct blame_entry *ent;
1086
1087 if (option & OUTPUT_PORCELAIN) {
1088 for (ent = sb->ent; ent; ent = ent->next) {
1089 struct blame_entry *oth;
1090 struct origin *suspect = ent->suspect;
1091 struct commit *commit = suspect->commit;
1092 if (commit->object.flags & MORE_THAN_ONE_PATH)
1093 continue;
1094 for (oth = ent->next; oth; oth = oth->next) {
1095 if ((oth->suspect->commit != commit) ||
1096 !strcmp(oth->suspect->path, suspect->path))
1097 continue;
1098 commit->object.flags |= MORE_THAN_ONE_PATH;
1099 break;
1100 }
1101 }
1102 }
1103
1104 for (ent = sb->ent; ent; ent = ent->next) {
1105 if (option & OUTPUT_PORCELAIN)
1106 emit_porcelain(sb, ent);
5ff62c30 1107 else {
cee7f245 1108 emit_other(sb, ent, option);
5ff62c30 1109 }
cee7f245
JH
1110 }
1111}
1112
1113static int prepare_lines(struct scoreboard *sb)
1114{
1115 const char *buf = sb->final_buf;
1116 unsigned long len = sb->final_buf_size;
1117 int num = 0, incomplete = 0, bol = 1;
1118
1119 if (len && buf[len-1] != '\n')
1120 incomplete++; /* incomplete line at the end */
1121 while (len--) {
1122 if (bol) {
1123 sb->lineno = xrealloc(sb->lineno,
1124 sizeof(int* ) * (num + 1));
1125 sb->lineno[num] = buf - sb->final_buf;
1126 bol = 0;
1127 }
1128 if (*buf++ == '\n') {
1129 num++;
1130 bol = 1;
1131 }
1132 }
1ca6ca87
JH
1133 sb->lineno = xrealloc(sb->lineno,
1134 sizeof(int* ) * (num + incomplete + 1));
1135 sb->lineno[num + incomplete] = buf - sb->final_buf;
cee7f245
JH
1136 sb->num_lines = num + incomplete;
1137 return sb->num_lines;
1138}
1139
1140static int read_ancestry(const char *graft_file)
1141{
1142 FILE *fp = fopen(graft_file, "r");
1143 char buf[1024];
1144 if (!fp)
1145 return -1;
1146 while (fgets(buf, sizeof(buf), fp)) {
1147 /* The format is just "Commit Parent1 Parent2 ...\n" */
1148 int len = strlen(buf);
1149 struct commit_graft *graft = read_graft_line(buf, len);
1150 register_commit_graft(graft, 0);
1151 }
1152 fclose(fp);
1153 return 0;
1154}
1155
1156static int lineno_width(int lines)
1157{
1158 int i, width;
1159
1160 for (width = 1, i = 10; i <= lines + 1; width++)
1161 i *= 10;
1162 return width;
1163}
1164
1165static void find_alignment(struct scoreboard *sb, int *option)
1166{
1167 int longest_src_lines = 0;
1168 int longest_dst_lines = 0;
5ff62c30 1169 unsigned largest_score = 0;
cee7f245
JH
1170 struct blame_entry *e;
1171
1172 for (e = sb->ent; e; e = e->next) {
1173 struct origin *suspect = e->suspect;
1174 struct commit_info ci;
1175 int num;
1176
1177 if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
1178 suspect->commit->object.flags |= METAINFO_SHOWN;
1179 get_commit_info(suspect->commit, &ci, 1);
1180 if (strcmp(suspect->path, sb->path))
1181 *option |= OUTPUT_SHOW_NAME;
1182 num = strlen(suspect->path);
1183 if (longest_file < num)
1184 longest_file = num;
1185 num = strlen(ci.author);
1186 if (longest_author < num)
1187 longest_author = num;
1188 }
1189 num = e->s_lno + e->num_lines;
1190 if (longest_src_lines < num)
1191 longest_src_lines = num;
1192 num = e->lno + e->num_lines;
1193 if (longest_dst_lines < num)
1194 longest_dst_lines = num;
5ff62c30
JH
1195 if (largest_score < ent_score(sb, e))
1196 largest_score = ent_score(sb, e);
cee7f245
JH
1197 }
1198 max_orig_digits = lineno_width(longest_src_lines);
1199 max_digits = lineno_width(longest_dst_lines);
5ff62c30 1200 max_score_digits = lineno_width(largest_score);
cee7f245
JH
1201}
1202
1203static int has_path_in_work_tree(const char *path)
1204{
1205 struct stat st;
1206 return !lstat(path, &st);
1207}
1208
4a0fc95f
JH
1209static unsigned parse_score(const char *arg)
1210{
1211 char *end;
1212 unsigned long score = strtoul(arg, &end, 10);
1213 if (*end)
1214 return 0;
1215 return score;
1216}
1217
cee7f245
JH
1218int cmd_pickaxe(int argc, const char **argv, const char *prefix)
1219{
1220 struct rev_info revs;
1221 const char *path;
1222 struct scoreboard sb;
1223 struct origin *o;
1224 struct blame_entry *ent;
d24bba80 1225 int i, seen_dashdash, unk, opt;
cee7f245
JH
1226 long bottom, top, lno;
1227 int output_option = 0;
1228 const char *revs_file = NULL;
1229 const char *final_commit_name = NULL;
1230 char type[10];
1231
612702e8
JH
1232 save_commit_buffer = 0;
1233
d24bba80 1234 opt = 0;
cee7f245
JH
1235 bottom = top = 0;
1236 seen_dashdash = 0;
1237 for (unk = i = 1; i < argc; i++) {
1238 const char *arg = argv[i];
1239 if (*arg != '-')
1240 break;
1241 else if (!strcmp("-c", arg))
1242 output_option |= OUTPUT_ANNOTATE_COMPAT;
1243 else if (!strcmp("-t", arg))
1244 output_option |= OUTPUT_RAW_TIMESTAMP;
1245 else if (!strcmp("-l", arg))
1246 output_option |= OUTPUT_LONG_OBJECT_NAME;
1247 else if (!strcmp("-S", arg) && ++i < argc)
1248 revs_file = argv[i];
4a0fc95f 1249 else if (!strncmp("-M", arg, 2)) {
d24bba80 1250 opt |= PICKAXE_BLAME_MOVE;
4a0fc95f
JH
1251 blame_move_score = parse_score(arg+2);
1252 }
1253 else if (!strncmp("-C", arg, 2)) {
18abd745
JH
1254 if (opt & PICKAXE_BLAME_COPY)
1255 opt |= PICKAXE_BLAME_COPY_HARDER;
1256 opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
4a0fc95f 1257 blame_copy_score = parse_score(arg+2);
18abd745 1258 }
cee7f245
JH
1259 else if (!strcmp("-L", arg) && ++i < argc) {
1260 char *term;
1261 arg = argv[i];
1262 if (bottom || top)
1263 die("More than one '-L n,m' option given");
1264 bottom = strtol(arg, &term, 10);
1265 if (*term == ',') {
1266 top = strtol(term + 1, &term, 10);
1267 if (*term)
1268 usage(pickaxe_usage);
1269 }
1270 if (bottom && top && top < bottom) {
1271 unsigned long tmp;
1272 tmp = top; top = bottom; bottom = tmp;
1273 }
1274 }
5ff62c30
JH
1275 else if (!strcmp("--score-debug", arg))
1276 output_option |= OUTPUT_SHOW_SCORE;
cee7f245
JH
1277 else if (!strcmp("-f", arg) ||
1278 !strcmp("--show-name", arg))
1279 output_option |= OUTPUT_SHOW_NAME;
1280 else if (!strcmp("-n", arg) ||
1281 !strcmp("--show-number", arg))
1282 output_option |= OUTPUT_SHOW_NUMBER;
1283 else if (!strcmp("-p", arg) ||
1284 !strcmp("--porcelain", arg))
1285 output_option |= OUTPUT_PORCELAIN;
1286 else if (!strcmp("--", arg)) {
1287 seen_dashdash = 1;
1288 i++;
1289 break;
1290 }
1291 else
1292 argv[unk++] = arg;
1293 }
1294
4a0fc95f
JH
1295 if (!blame_move_score)
1296 blame_move_score = BLAME_DEFAULT_MOVE_SCORE;
1297 if (!blame_copy_score)
1298 blame_copy_score = BLAME_DEFAULT_COPY_SCORE;
1299
cee7f245
JH
1300 /* We have collected options unknown to us in argv[1..unk]
1301 * which are to be passed to revision machinery if we are
1302 * going to do the "bottom" procesing.
1303 *
1304 * The remaining are:
1305 *
1306 * (1) if seen_dashdash, its either
1307 * "-options -- <path>" or
1308 * "-options -- <path> <rev>".
1309 * but the latter is allowed only if there is no
1310 * options that we passed to revision machinery.
1311 *
1312 * (2) otherwise, we may have "--" somewhere later and
1313 * might be looking at the first one of multiple 'rev'
1314 * parameters (e.g. " master ^next ^maint -- path").
1315 * See if there is a dashdash first, and give the
1316 * arguments before that to revision machinery.
1317 * After that there must be one 'path'.
1318 *
1319 * (3) otherwise, its one of the three:
1320 * "-options <path> <rev>"
1321 * "-options <rev> <path>"
1322 * "-options <path>"
1323 * but again the first one is allowed only if
1324 * there is no options that we passed to revision
1325 * machinery.
1326 */
1327
1328 if (seen_dashdash) {
1329 /* (1) */
1330 if (argc <= i)
1331 usage(pickaxe_usage);
1332 path = argv[i];
1333 if (i + 1 == argc - 1) {
1334 if (unk != 1)
1335 usage(pickaxe_usage);
1336 argv[unk++] = argv[i + 1];
1337 }
1338 else if (i + 1 != argc)
1339 /* garbage at end */
1340 usage(pickaxe_usage);
1341 }
1342 else {
1343 int j;
1344 for (j = i; !seen_dashdash && j < argc; j++)
1345 if (!strcmp(argv[j], "--"))
1346 seen_dashdash = j;
1347 if (seen_dashdash) {
1348 if (seen_dashdash + 1 != argc - 1)
1349 usage(pickaxe_usage);
1350 path = argv[seen_dashdash + 1];
1351 for (j = i; j < seen_dashdash; j++)
1352 argv[unk++] = argv[j];
1353 }
1354 else {
1355 /* (3) */
1356 path = argv[i];
1357 if (i + 1 == argc - 1) {
1358 final_commit_name = argv[i + 1];
1359
1360 /* if (unk == 1) we could be getting
1361 * old-style
1362 */
1363 if (unk == 1 && !has_path_in_work_tree(path)) {
1364 path = argv[i + 1];
1365 final_commit_name = argv[i];
1366 }
1367 }
1368 else if (i != argc - 1)
1369 usage(pickaxe_usage); /* garbage at end */
1370
1371 if (!has_path_in_work_tree(path))
1372 die("cannot stat path %s: %s",
1373 path, strerror(errno));
1374 }
1375 }
1376
1377 if (final_commit_name)
1378 argv[unk++] = final_commit_name;
1379
1380 /* Now we got rev and path. We do not want the path pruning
1381 * but we may want "bottom" processing.
1382 */
1383 argv[unk] = NULL;
1384
1385 init_revisions(&revs, NULL);
1386 setup_revisions(unk, argv, &revs, "HEAD");
1387 memset(&sb, 0, sizeof(sb));
1388
1389 /* There must be one and only one positive commit in the
1390 * revs->pending array.
1391 */
1392 for (i = 0; i < revs.pending.nr; i++) {
1393 struct object *obj = revs.pending.objects[i].item;
1394 if (obj->flags & UNINTERESTING)
1395 continue;
1396 while (obj->type == OBJ_TAG)
1397 obj = deref_tag(obj, NULL, 0);
1398 if (obj->type != OBJ_COMMIT)
1399 die("Non commit %s?",
1400 revs.pending.objects[i].name);
1401 if (sb.final)
1402 die("More than one commit to dig from %s and %s?",
1403 revs.pending.objects[i].name,
1404 final_commit_name);
1405 sb.final = (struct commit *) obj;
1406 final_commit_name = revs.pending.objects[i].name;
1407 }
1408
1409 if (!sb.final) {
1410 /* "--not A B -- path" without anything positive */
1411 unsigned char head_sha1[20];
1412
1413 final_commit_name = "HEAD";
1414 if (get_sha1(final_commit_name, head_sha1))
1415 die("No such ref: HEAD");
1416 sb.final = lookup_commit_reference(head_sha1);
1417 add_pending_object(&revs, &(sb.final->object), "HEAD");
1418 }
1419
1420 /* If we have bottom, this will mark the ancestors of the
1421 * bottom commits we would reach while traversing as
1422 * uninteresting.
1423 */
1424 prepare_revision_walk(&revs);
1425
1426 o = find_origin(&sb, sb.final, path);
1427 if (!o)
1428 die("no such path %s in %s", path, final_commit_name);
1429
1430 sb.final_buf = read_sha1_file(o->blob_sha1, type, &sb.final_buf_size);
1431 lno = prepare_lines(&sb);
1432
1433 if (bottom < 1)
1434 bottom = 1;
1435 if (top < 1)
1436 top = lno;
1437 bottom--;
1438 if (lno < top)
1439 die("file %s has only %lu lines", path, lno);
1440
1441 ent = xcalloc(1, sizeof(*ent));
1442 ent->lno = bottom;
1443 ent->num_lines = top - bottom;
1444 ent->suspect = o;
1445 ent->s_lno = bottom;
1446
1447 sb.ent = ent;
1448 sb.path = path;
1449
1450 if (revs_file && read_ancestry(revs_file))
1451 die("reading graft file %s failed: %s",
1452 revs_file, strerror(errno));
1453
d24bba80 1454 assign_blame(&sb, &revs, opt);
cee7f245
JH
1455
1456 coalesce(&sb);
1457
1458 if (!(output_option & OUTPUT_PORCELAIN))
1459 find_alignment(&sb, &output_option);
1460
1461 output(&sb, output_option);
1462 free((void *)sb.final_buf);
1463 for (ent = sb.ent; ent; ) {
1464 struct blame_entry *e = ent->next;
1465 free(ent);
1466 ent = e;
1467 }
1468 return 0;
1469}