+sub check_unindexed ($$$) {
+ my ($self, $num, $mid0) = @_;
+ my $unindexed = $self->{unindexed} // {};
+ my $n = delete($unindexed->{$mid0});
+ defined $n or return;
+ if ($n != $num) {
+ die "BUG: unindexed $n != $num <$mid0>\n";
+ } else {
+ $self->{mm}->mid_set($num, $mid0);
+ }
+}
+
+# reuse Msgmap to store num => oid mapping (rather than num => mid)
+sub multi_mid_q_new () {
+ my ($fh, $fn) = tempfile('multi_mid-XXXXXXX', EXLOCK => 0, TMPDIR => 1);
+ my $multi_mid = PublicInbox::Msgmap->new_file($fn, 1);
+ $multi_mid->{dbh}->do('PRAGMA synchronous = OFF');
+ # for Msgmap->DESTROY:
+ $multi_mid->{tmp_name} = $fn;
+ $multi_mid->{pid} = $$;
+ close $fh or die "failed to close $fn: $!";
+ $multi_mid
+}
+
+sub multi_mid_q_push ($$) {
+ my ($sync, $oid) = @_;
+ my $multi_mid = $sync->{multi_mid} //= multi_mid_q_new();
+ if ($sync->{reindex}) { # no regen on reindex
+ $multi_mid->mid_insert($oid);
+ } else {
+ my $num = $sync->{regen}--;
+ die "BUG: ran out of article numbers" if $num <= 0;
+ $multi_mid->mid_set($num, $oid);
+ }
+}
+
+sub reindex_oid ($$$$) {
+ my ($self, $sync, $git, $oid) = @_;
+ my ($num, $mid0, $len);
+ my $msgref = $git->cat_file($oid, \$len);
+ return if $len == 0; # purged
+ my $mime = PublicInbox::MIME->new($$msgref);
+ my $mids = mids($mime->header_obj);
+ my $cid = content_id($mime);
+
+ if (scalar(@$mids) == 0) {
+ warn "E: $oid has no Message-ID, skipping\n";
+ return;
+ } elsif (scalar(@$mids) == 1) {
+ my $mid = $mids->[0];
+
+ # was the file previously marked as deleted?, skip if so
+ if (delete($sync->{D}->{"$mid\0$cid"})) {
+ if (!$sync->{reindex}) {
+ $num = $sync->{regen}--;
+ $self->{mm}->num_highwater($num);
+ }
+ return;