+}
+
+sub _git_log {
+ my ($self, $range) = @_;
+ $self->{git}->popen(qw/log --reverse --no-notes --no-color
+ --raw -r --no-abbrev/, $range);
+}
+
+# indexes all unindexed messages
+sub _index_sync {
+ my ($self, $opts) = @_;
+ my $tip = $opts->{ref} || 'HEAD';
+ my $reindex = $opts->{reindex};
+ my ($mkey, $last_commit, $lx, $xlog);
+ $self->{git}->batch_prepare;
+ my $xdb = _xdb_acquire($self);
+ $xdb->begin_transaction;
+ do {
+ $xlog = undef;
+ $mkey = 'last_commit';
+ $last_commit = $xdb->get_metadata('last_commit');
+ $lx = $last_commit;
+ if ($reindex) {
+ $lx = '';
+ $mkey = undef if $last_commit ne '';
+ }
+ $xdb->cancel_transaction;
+ $xdb = _xdb_release($self);
+
+ # ensure we leak no FDs to "git log"
+ my $range = $lx eq '' ? $tip : "$lx..$tip";
+ $xlog = _git_log($self, $range);
+
+ $xdb = _xdb_acquire($self);
+ $xdb->begin_transaction;
+ } while ($xdb->get_metadata('last_commit') ne $last_commit);
+
+ my $mm = _msgmap_init($self);
+ my $dbh = $mm->{dbh} if $mm;
+ my $mm_only;
+ my $cb = sub {
+ my ($commit, $more) = @_;
+ if ($dbh) {
+ $mm->last_commit($commit) if $commit;
+ $dbh->commit;
+ }
+ if (!$mm_only) {
+ $xdb->set_metadata($mkey, $commit) if $mkey && $commit;
+ $xdb->commit_transaction;
+ $xdb = _xdb_release($self);
+ }
+ # let another process do some work... <
+ if ($more) {
+ if (!$mm_only) {
+ $xdb = _xdb_acquire($self);
+ $xdb->begin_transaction;
+ }
+ $dbh->begin_work if $dbh;
+ }
+ };