@matheusbsbs / matheus-bagliano / commits / 96e117099c
Fork 0

blame: show "previous" information in --porcelain/--incremental format

When the final blame is laid for a line to a <commit, path> pair, it also gives a "previous" information to --porcelain and --incremental output format. It gives the parent commit of the blamed commit, _and_ a path in that parent commit that corresponds to the blamed path --- in short, it is the origin that would have been blamed (or passed blame through) for the line _if_ the blamed commit did not change that line. This unfortunately makes sanity checking of refcount quite complex, so I ripped it out for now. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Jun 4, 2008 at 22:58 UTC 96e117099c0e4f7d508eb071f60b6275038f6f37
1 file changed +12 -30
builtin-blame.c
+12 -30
@@ -73,6 +73,7 @@ static unsigned blame_copy_score;
73 */
74 struct origin {
75 int refcnt;
76 + struct origin *previous;
77 struct commit *commit;
78 mmfile_t file;
79 unsigned char blob_sha1[20];
@@ -114,6 +115,8 @@ static inline struct origin *origin_incref(struct origin *o)
115 static void origin_decref(struct origin *o)
116 {
117 if (o && --o->refcnt <= 0) {
118 + if (o->previous)
119 + origin_decref(o->previous);
120 free(o->file.ptr);
121 free(o);
122 }
@@ -1292,6 +1295,10 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
1295 struct origin *porigin = sg_origin[i];
1296 if (!porigin)
1297 continue;
1298 + if (!origin->previous) {
1299 + origin_incref(porigin);
1300 + origin->previous = porigin;
1301 + }
1302 if (pass_blame_to_parent(sb, origin, porigin))
1303 goto finish;
1304 }
@@ -1515,6 +1522,11 @@ static int emit_one_suspect_detail(struct origin *suspect)
1522 printf("summary %s\n", ci.summary);
1523 if (suspect->commit->object.flags & UNINTERESTING)
1524 printf("boundary\n");
1525 + if (suspect->previous) {
1526 + struct origin *prev = suspect->previous;
1527 + printf("previous %s ", sha1_to_hex(prev->commit->object.sha1));
1528 + write_name_quoted(prev->path, stdout, '\n');
1529 + }
1530 return 1;
1531 }
1532
@@ -1878,36 +1890,6 @@ static void sanity_check_refcnt(struct scoreboard *sb)
1890 baa = 1;
1891 }
1892 }
1881 - for (ent = sb->ent; ent; ent = ent->next) {
1882 - /* Mark the ones that haven't been checked */
1883 - if (0 < ent->suspect->refcnt)
1884 - ent->suspect->refcnt = -ent->suspect->refcnt;
1885 - }
1886 - for (ent = sb->ent; ent; ent = ent->next) {
1887 - /*
1888 - * ... then pick each and see if they have the the
1889 - * correct refcnt.
1890 - */
1891 - int found;
1892 - struct blame_entry *e;
1893 - struct origin *suspect = ent->suspect;
1894 -
1895 - if (0 < suspect->refcnt)
1896 - continue;
1897 - suspect->refcnt = -suspect->refcnt; /* Unmark */
1898 - for (found = 0, e = sb->ent; e; e = e->next) {
1899 - if (e->suspect != suspect)
1900 - continue;
1901 - found++;
1902 - }
1903 - if (suspect->refcnt != found) {
1904 - fprintf(stderr, "%s in %s has refcnt %d, not %d\n",
1905 - ent->suspect->path,
1906 - sha1_to_hex(ent->suspect->commit->object.sha1),
1907 - ent->suspect->refcnt, found);
1908 - baa = 2;
1909 - }
1910 - }
1893 if (baa) {
1894 int opt = 0160;
1895 find_alignment(sb, &opt);