-sub reindex {
- my ($self, $regen) = @_;
- my $ibx = $self->{-inbox};
- my $pfx = "$ibx->{mainrepo}/git";
- my $max_git;
- my $latest = git_dir_latest($self, \$max_git);
- return unless defined $latest;
- my $head = $ibx->{ref_head} || 'refs/heads/master';
- $self->idx_init; # acquire lock
- my $x40 = qr/[a-f0-9]{40}/;
- my $mm_tmp = $self->{skel}->{mm}->tmp_clone;
- if (!$regen) {
- my (undef, $max) = $mm_tmp->minmax;
- unless (defined $max) {
- $regen = 1;
- warn
-"empty msgmap.sqlite3, regenerating article numbers\n";
+# only update last_commit for $i on reindex iff newer than current
+sub update_last_commit {
+ my ($self, $git, $i, $cmt) = @_;
+ my $last = last_commit_part($self, $i);
+ if (defined $last && is_ancestor($git, $last, $cmt)) {
+ my @cmd = (qw(rev-list --count), "$last..$cmt");
+ chomp(my $n = $git->qx(@cmd));
+ return if $n ne '' && $n == 0;
+ }
+ last_commit_part($self, $i, $cmt);
+}
+
+sub git_dir_n ($$) { "$_[0]->{-inbox}->{mainrepo}/git/$_[1].git" }
+
+sub last_commits {
+ my ($self, $epoch_max) = @_;
+ my $heads = [];
+ for (my $i = $epoch_max; $i >= 0; $i--) {
+ $heads->[$i] = last_commit_part($self, $i);
+ }
+ $heads;
+}
+
+*is_ancestor = *PublicInbox::SearchIdx::is_ancestor;
+
+sub index_prepare {
+ my ($self, $opts, $epoch_max, $ranges) = @_;
+ my $regen_max = 0;
+ my $head = $self->{-inbox}->{ref_head} || 'refs/heads/master';
+ for (my $i = $epoch_max; $i >= 0; $i--) {
+ die "already indexing!\n" if $self->{index_pipe};
+ my $git_dir = git_dir_n($self, $i);
+ -d $git_dir or next; # missing parts are fine
+ my $git = PublicInbox::Git->new($git_dir);
+ chomp(my $tip = $git->qx('rev-parse', $head));
+ my $range;
+ if (defined(my $cur = $ranges->[$i])) {
+ $range = "$cur..$tip";
+ if (is_ancestor($git, $cur, $tip)) { # common case
+ my $n = $git->qx(qw(rev-list --count), $range);
+ chomp($n);
+ if ($n == 0) {
+ $ranges->[$i] = undef;
+ next;
+ }
+ } else {
+ warn <<"";
+discontiguous range: $range
+Rewritten history? (in $git_dir)
+
+ my $base = $git->qx('merge-base', $tip, $cur);
+ chomp $base;
+ if ($base) {
+ $range = "$base..$tip";
+ warn "found merge-base: $base\n"
+ } else {
+ $range = $tip;
+ warn <<"";
+discarding history at $cur
+
+ }
+ warn <<"";
+reindexing $git_dir starting at
+$range
+
+ $self->{"unindex-range.$i"} = "$base..$cur";
+ }
+ } else {
+ $range = $tip; # all of it