442
return porigin;
443
}
444
445
-/*
446
- * Parsing of patch chunks...
447
- */
448
-struct chunk {
449
- /* line number in postimage; up to but not including this
450
- * line is the same as preimage
451
- */
452
- int same;
453
-
454
- /* preimage line number after this chunk */
455
- int p_next;
456
-
457
- /* postimage line number after this chunk */
458
- int t_next;
459
-};
460
-
461
-struct patch {
462
- struct chunk *chunks;
463
- int num;
464
-};
465
-
466
-struct blame_diff_state {
467
- struct patch *ret;
468
- unsigned hunk_post_context;
469
- unsigned hunk_in_pre_context : 1;
470
-};
471
-
472
-static void process_u_diff(void *state_, char *line, unsigned long len)
473
-{
474
- struct blame_diff_state *state = state_;
475
- struct chunk *chunk;
476
- int off1, off2, len1, len2, num;
477
-
478
- num = state->ret->num;
479
- if (len < 4 || line[0] != '@' || line[1] != '@') {
480
- if (state->hunk_in_pre_context && line[0] == ' ')
481
- state->ret->chunks[num - 1].same++;
482
- else {
483
- state->hunk_in_pre_context = 0;
484
- if (line[0] == ' ')
485
- state->hunk_post_context++;
486
- else
487
- state->hunk_post_context = 0;
488
- }
489
- return;
490
- }
491
-
492
- if (num && state->hunk_post_context) {
493
- chunk = &state->ret->chunks[num - 1];
494
- chunk->p_next -= state->hunk_post_context;
495
- chunk->t_next -= state->hunk_post_context;
496
- }
497
- state->ret->num = ++num;
498
- state->ret->chunks = xrealloc(state->ret->chunks,
499
- sizeof(struct chunk) * num);
500
- chunk = &state->ret->chunks[num - 1];
501
- if (parse_hunk_header(line, len, &off1, &len1, &off2, &len2)) {
502
- state->ret->num--;
503
- return;
504
- }
505
-
506
- /* Line numbers in patch output are one based. */
507
- off1--;
508
- off2--;
509
-
510
- chunk->same = len2 ? off2 : (off2 + 1);
511
-
512
- chunk->p_next = off1 + (len1 ? len1 : 1);
513
- chunk->t_next = chunk->same + len2;
514
- state->hunk_in_pre_context = 1;
515
- state->hunk_post_context = 0;
516
-}
517
-
518
-static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
519
- int context)
520
-{
521
- struct blame_diff_state state;
522
- xpparam_t xpp;
523
- xdemitconf_t xecfg;
524
- xdemitcb_t ecb;
525
-
526
- memset(&xpp, 0, sizeof(xpp));
527
- xpp.flags = xdl_opts;
528
- memset(&xecfg, 0, sizeof(xecfg));
529
- xecfg.ctxlen = context;
530
- memset(&state, 0, sizeof(state));
531
- state.ret = xmalloc(sizeof(struct patch));
532
- state.ret->chunks = NULL;
533
- state.ret->num = 0;
534
-
535
- xdi_diff_outf(file_p, file_o, process_u_diff, &state, &xpp, &xecfg, &ecb);
536
-
537
- if (state.ret->num) {
538
- struct chunk *chunk;
539
- chunk = &state.ret->chunks[state.ret->num - 1];
540
- chunk->p_next -= state.hunk_post_context;
541
- chunk->t_next -= state.hunk_post_context;
542
- }
543
- return state.ret;
544
-}
545
-
546
-static void free_patch(struct patch *p)
547
-{
548
- free(p->chunks);
549
- free(p);
550
-}
551
-
445
/*
446
* Link in a new blame entry to the scoreboard. Entries that cover the
447
* same line range have been removed from the scoreboard previously.
688
}
689
}
690
691
+struct blame_chunk_cb_data {
692
+ struct scoreboard *sb;
693
+ struct origin *target;
694
+ struct origin *parent;
695
+ long plno;
696
+ long tlno;
697
+};
698
+
699
+static void blame_chunk_cb(void *data, long same, long p_next, long t_next)
700
+{
701
+ struct blame_chunk_cb_data *d = data;
702
+ blame_chunk(d->sb, d->tlno, d->plno, same, d->target, d->parent);
703
+ d->plno = p_next;
704
+ d->tlno = t_next;
705
+}
706
+
707
/*
708
* We are looking at the origin 'target' and aiming to pass blame
709
* for the lines it is suspected to its parent. Run diff to find
713
struct origin *target,
714
struct origin *parent)
715
{
807
- int i, last_in_target, plno, tlno;
808
- struct patch *patch;
716
+ int last_in_target;
717
mmfile_t file_p, file_o;
718
+ struct blame_chunk_cb_data d = { sb, target, parent, 0, 0 };
719
+ xpparam_t xpp;
720
+ xdemitconf_t xecfg;
721
722
last_in_target = find_last_in_target(sb, target);
723
if (last_in_target < 0)
724
return 1; /* nothing remains for this target */
725
815
- /*
816
- * Run diff between two origins and grab the patch output, so that
817
- * we can pass blame for lines origin is currently suspected for
818
- * to its parent.
819
- */
726
fill_origin_blob(parent, &file_p);
727
fill_origin_blob(target, &file_o);
822
- patch = compare_buffer(&file_p, &file_o, 0);
728
num_get_patch++;
729
825
- plno = tlno = 0;
826
- for (i = 0; i < patch->num; i++) {
827
- struct chunk *chunk = &patch->chunks[i];
828
-
829
- blame_chunk(sb, tlno, plno, chunk->same, target, parent);
830
- plno = chunk->p_next;
831
- tlno = chunk->t_next;
832
- }
730
+ memset(&xpp, 0, sizeof(xpp));
731
+ xpp.flags = xdl_opts;
732
+ memset(&xecfg, 0, sizeof(xecfg));
733
+ xecfg.ctxlen = 0;
734
+ xdi_diff_hunks(&file_p, &file_o, blame_chunk_cb, &d, &xpp, &xecfg);
735
/* The rest (i.e. anything after tlno) are the same as the parent */
834
- blame_chunk(sb, tlno, plno, last_in_target, target, parent);
736
+ blame_chunk(sb, d.tlno, d.plno, last_in_target, target, parent);
737
836
- free_patch(patch);
738
return 0;
739
}
740
826
}
827
}
828
829
+struct handle_split_cb_data {
830
+ struct scoreboard *sb;
831
+ struct blame_entry *ent;
832
+ struct origin *parent;
833
+ struct blame_entry *split;
834
+ long plno;
835
+ long tlno;
836
+};
837
+
838
+static void handle_split_cb(void *data, long same, long p_next, long t_next)
839
+{
840
+ struct handle_split_cb_data *d = data;
841
+ handle_split(d->sb, d->ent, d->tlno, d->plno, same, d->parent, d->split);
842
+ d->plno = p_next;
843
+ d->tlno = t_next;
844
+}
845
+
846
/*
847
* Find the lines from parent that are the same as ent so that
848
* we can pass blames to it. file_p has the blob contents for
857
const char *cp;
858
int cnt;
859
mmfile_t file_o;
942
- struct patch *patch;
943
- int i, plno, tlno;
860
+ struct handle_split_cb_data d = { sb, ent, parent, split, 0, 0 };
861
+ xpparam_t xpp;
862
+ xdemitconf_t xecfg;
863
864
/*
865
* Prepare mmfile that contains only the lines in ent.
874
}
875
file_o.size = cp - file_o.ptr;
876
958
- patch = compare_buffer(file_p, &file_o, 1);
959
-
877
/*
878
* file_o is a part of final image we are annotating.
879
* file_p partially may match that image.
880
*/
881
+ memset(&xpp, 0, sizeof(xpp));
882
+ xpp.flags = xdl_opts;
883
+ memset(&xecfg, 0, sizeof(xecfg));
884
+ xecfg.ctxlen = 1;
885
memset(split, 0, sizeof(struct blame_entry [3]));
965
- plno = tlno = 0;
966
- for (i = 0; i < patch->num; i++) {
967
- struct chunk *chunk = &patch->chunks[i];
968
-
969
- handle_split(sb, ent, tlno, plno, chunk->same, parent, split);
970
- plno = chunk->p_next;
971
- tlno = chunk->t_next;
972
- }
886
+ xdi_diff_hunks(file_p, &file_o, handle_split_cb, &d, &xpp, &xecfg);
887
/* remainder, if any, all match the preimage */
974
- handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split);
975
- free_patch(patch);
888
+ handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split);
889
}
890
891
/*