@matheusbsbs / matheus-bagliano / commits / 69264f46a1
Fork 0

builtin-blame.c: allow more than 16 parents

This removes the hardcoded 16 parents limit from git-blame by allowing the parent array to be allocated dynamically. As the ultimate objective is not about allowing dodecapus, but about annotating the history upside down, it also renames "parent" in the code to "scapegoat"; the name of the game used to be "pass blame to your parents", but now it is "find a scapegoat to pass blame on". Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Apr 3, 2008 at 00:56 UTC 69264f46a193ae9dec5761984b4bae32f4810916
1 file changed +61 -32
builtin-blame.c
+61 -32
@@ -1191,18 +1191,45 @@ static void pass_whole_blame(struct scoreboard *sb,
1191 }
1192 }
1193
1194 -#define MAXPARENT 16
1194 +/*
1195 + * We pass blame from the current commit to its parents. We keep saying
1196 + * "parent" (and "porigin"), but what we mean is to find scapegoat to
1197 + * exonerate ourselves.
1198 + */
1199 +static struct commit_list *first_scapegoat(struct commit *commit)
1200 +{
1201 + return commit->parents;
1202 +}
1203 +
1204 +static int num_scapegoats(struct commit *commit)
1205 +{
1206 + int cnt;
1207 + struct commit_list *l = first_scapegoat(commit);
1208 + for (cnt = 0; l; l = l->next)
1209 + cnt++;
1210 + return cnt;
1211 +}
1212 +
1213 +#define MAXSG 16
1214
1215 static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
1216 {
1198 - int i, pass;
1217 + int i, pass, num_sg;
1218 struct commit *commit = origin->commit;
1200 - struct commit_list *parent;
1201 - struct origin *parent_origin[MAXPARENT], *porigin;
1202 -
1203 - memset(parent_origin, 0, sizeof(parent_origin));
1219 + struct commit_list *sg;
1220 + struct origin *sg_buf[MAXSG];
1221 + struct origin *porigin, **sg_origin = sg_buf;
1222 +
1223 + num_sg = num_scapegoats(commit);
1224 + if (!num_sg)
1225 + goto finish;
1226 + else if (num_sg < ARRAY_SIZE(sg_buf))
1227 + memset(sg_buf, 0, sizeof(sg_buf));
1228 + else
1229 + sg_origin = xcalloc(num_sg, sizeof(*sg_origin));
1230
1205 - /* The first pass looks for unrenamed path to optimize for
1231 + /*
1232 + * The first pass looks for unrenamed path to optimize for
1233 * common cases, then we look for renames in the second pass.
1234 */
1235 for (pass = 0; pass < 2; pass++) {
@@ -1210,13 +1237,13 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
1237 struct commit *, struct origin *);
1238 find = pass ? find_rename : find_origin;
1239
1213 - for (i = 0, parent = commit->parents;
1214 - i < MAXPARENT && parent;
1215 - parent = parent->next, i++) {
1216 - struct commit *p = parent->item;
1240 + for (i = 0, sg = first_scapegoat(commit);
1241 + i < num_sg && sg;
1242 + sg = sg->next, i++) {
1243 + struct commit *p = sg->item;
1244 int j, same;
1245
1219 - if (parent_origin[i])
1246 + if (sg_origin[i])
1247 continue;
1248 if (parse_commit(p))
1249 continue;
@@ -1229,24 +1256,24 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
1256 goto finish;
1257 }
1258 for (j = same = 0; j < i; j++)
1232 - if (parent_origin[j] &&
1233 - !hashcmp(parent_origin[j]->blob_sha1,
1259 + if (sg_origin[j] &&
1260 + !hashcmp(sg_origin[j]->blob_sha1,
1261 porigin->blob_sha1)) {
1262 same = 1;
1263 break;
1264 }
1265 if (!same)
1239 - parent_origin[i] = porigin;
1266 + sg_origin[i] = porigin;
1267 else
1268 origin_decref(porigin);
1269 }
1270 }
1271
1272 num_commits++;
1246 - for (i = 0, parent = commit->parents;
1247 - i < MAXPARENT && parent;
1248 - parent = parent->next, i++) {
1249 - struct origin *porigin = parent_origin[i];
1273 + for (i = 0, sg = first_scapegoat(commit);
1274 + i < num_sg && sg;
1275 + sg = sg->next, i++) {
1276 + struct origin *porigin = sg_origin[i];
1277 if (!porigin)
1278 continue;
1279 if (pass_blame_to_parent(sb, origin, porigin))
@@ -1257,10 +1284,10 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
1284 * Optionally find moves in parents' files.
1285 */
1286 if (opt & PICKAXE_BLAME_MOVE)
1260 - for (i = 0, parent = commit->parents;
1261 - i < MAXPARENT && parent;
1262 - parent = parent->next, i++) {
1263 - struct origin *porigin = parent_origin[i];
1287 + for (i = 0, sg = first_scapegoat(commit);
1288 + i < num_sg && sg;
1289 + sg = sg->next, i++) {
1290 + struct origin *porigin = sg_origin[i];
1291 if (!porigin)
1292 continue;
1293 if (find_move_in_parent(sb, origin, porigin))
@@ -1271,23 +1298,25 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
1298 * Optionally find copies from parents' files.
1299 */
1300 if (opt & PICKAXE_BLAME_COPY)
1274 - for (i = 0, parent = commit->parents;
1275 - i < MAXPARENT && parent;
1276 - parent = parent->next, i++) {
1277 - struct origin *porigin = parent_origin[i];
1278 - if (find_copy_in_parent(sb, origin, parent->item,
1301 + for (i = 0, sg = first_scapegoat(commit);
1302 + i < num_sg && sg;
1303 + sg = sg->next, i++) {
1304 + struct origin *porigin = sg_origin[i];
1305 + if (find_copy_in_parent(sb, origin, sg->item,
1306 porigin, opt))
1307 goto finish;
1308 }
1309
1310 finish:
1284 - for (i = 0; i < MAXPARENT; i++) {
1285 - if (parent_origin[i]) {
1286 - drop_origin_blob(parent_origin[i]);
1287 - origin_decref(parent_origin[i]);
1311 + for (i = 0; i < num_sg; i++) {
1312 + if (sg_origin[i]) {
1313 + drop_origin_blob(sg_origin[i]);
1314 + origin_decref(sg_origin[i]);
1315 }
1316 }
1317 drop_origin_blob(origin);
1318 + if (sg_buf != sg_origin)
1319 + free(sg_origin);
1320 }
1321
1322 /*