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
/*