pack-bitmap: remember pseudo-merge parents

write_pseudo_merges() currently builds an array of temporary bitmaps for the parent set of each pseudo-merge, then serializes those bitmaps later while writing the extension. Move those parent bitmaps onto the corresponding bitmapped_commit entries instead. This keeps the on-disk output unchanged, but gives the parent bitmap the same lifetime and access pattern that later changes will use when pseudo-merge object bitmaps are built before the write step. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed May 27, 2026 at 15:56 UTC b04d26607de35b88cf9c62ca11931d4f8cc4ac05
1 file changed +17 -13
pack-bitmap-write.c
+17 -13
@@ -32,6 +32,7 @@ struct bitmapped_commit {
32 struct commit *commit;
33 struct ewah_bitmap *bitmap;
34 struct ewah_bitmap *write_as;
35 + struct ewah_bitmap *pseudo_merge_parents;
36 int flags;
37 int xor_offset;
38 uint32_t commit_pos;
@@ -102,6 +103,7 @@ void bitmap_writer_free(struct bitmap_writer *writer)
103 if (bc->write_as != bc->bitmap)
104 ewah_free(bc->write_as);
105 ewah_free(bc->bitmap);
106 + ewah_free(bc->pseudo_merge_parents);
107 }
108 free(writer->selected);
109 }
@@ -210,6 +212,7 @@ void bitmap_writer_push_commit(struct bitmap_writer *writer,
212 writer->selected[writer->selected_nr].write_as = NULL;
213 writer->selected[writer->selected_nr].flags = 0;
214 writer->selected[writer->selected_nr].pseudo_merge = pseudo_merge;
215 + writer->selected[writer->selected_nr].pseudo_merge_parents = NULL;
216
217 writer->selected_nr++;
218 }
@@ -1004,42 +1007,47 @@ static void write_pseudo_merges(struct bitmap_writer *writer,
1007 struct hashfile *f)
1008 {
1009 struct oid_array commits = OID_ARRAY_INIT;
1007 - struct bitmap **commits_bitmap = NULL;
1010 off_t *pseudo_merge_ofs = NULL;
1011 off_t start, table_start, next_ext;
1012
1013 uint32_t base = bitmap_writer_nr_selected_commits(writer);
1014 size_t i, j = 0;
1015
1014 - CALLOC_ARRAY(commits_bitmap, writer->pseudo_merges_nr);
1016 CALLOC_ARRAY(pseudo_merge_ofs, writer->pseudo_merges_nr);
1017
1018 for (i = 0; i < writer->pseudo_merges_nr; i++) {
1019 struct bitmapped_commit *merge = &writer->selected[base + i];
1020 struct commit_list *p;
1021 + struct bitmap *parents = bitmap_new();
1022
1023 if (!merge->pseudo_merge)
1024 BUG("found non-pseudo merge commit at %"PRIuMAX, (uintmax_t)i);
1025
1024 - commits_bitmap[i] = bitmap_new();
1025 -
1026 for (p = merge->commit->parents; p; p = p->next)
1027 - bitmap_set(commits_bitmap[i],
1027 + bitmap_set(parents,
1028 find_object_pos(writer, &p->item->object.oid,
1029 NULL));
1030 +
1031 + merge->pseudo_merge_parents = bitmap_to_ewah(parents);
1032 + bitmap_free(parents);
1033 }
1034
1035 start = hashfile_total(f);
1036
1037 for (i = 0; i < writer->pseudo_merges_nr; i++) {
1035 - struct ewah_bitmap *commits_ewah = bitmap_to_ewah(commits_bitmap[i]);
1038 + struct bitmapped_commit *merge = &writer->selected[base + i];
1039 +
1040 + if (!merge->pseudo_merge)
1041 + BUG("found non-pseudo merge commit at %"PRIuMAX, (uintmax_t)i);
1042 +
1043 + if (!merge->pseudo_merge_parents)
1044 + BUG("missing pseudo-merge parents bitmap for commit %s",
1045 + oid_to_hex(&merge->commit->object.oid));
1046
1047 pseudo_merge_ofs[i] = hashfile_total(f);
1048
1039 - dump_bitmap(f, commits_ewah);
1049 + dump_bitmap(f, merge->pseudo_merge_parents);
1050 dump_bitmap(f, writer->selected[base+i].write_as);
1041 -
1042 - ewah_free(commits_ewah);
1051 }
1052
1053 next_ext = st_add(hashfile_total(f),
@@ -1122,12 +1130,8 @@ static void write_pseudo_merges(struct bitmap_writer *writer,
1130 hashwrite_be64(f, table_start - start);
1131 hashwrite_be64(f, hashfile_total(f) - start + sizeof(uint64_t));
1132
1125 - for (i = 0; i < writer->pseudo_merges_nr; i++)
1126 - bitmap_free(commits_bitmap[i]);
1127 -
1133 oid_array_clear(&commits);
1134 free(pseudo_merge_ofs);
1130 - free(commits_bitmap);
1135 }
1136
1137 static int table_cmp(const void *_va, const void *_vb, void *_data)