- if ($mm) {
- $dbh->begin_work;
- my $lm = $mm->last_commit || '';
- if ($lm eq $lx) {
- # Common case is the indexes are synced,
- # we only need to run git-log once:
- rlog($self, $xlog, *index_both, *unindex_both, $cb);
- } else {
- # Uncommon case, msgmap and xapian are out-of-sync
- # do not care for performance (but git is fast :>)
- # This happens if we have to reindex Xapian since
- # msgmap is a frozen format and our Xapian format
- # is evolving.
- my $r = $lm eq '' ? $tip : "$lm..$tip";
-
- # first, ensure msgmap is up-to-date:
- my $mkey_prev = $mkey;
- $mkey = undef; # ignore xapian, for now
- my $mlog = _git_log($self, $r);
- $mm_only = 1;
- rlog($self, $mlog, *index_mm, *unindex_mm, $cb);
- $mm_only = $mlog = undef;
-
- # now deal with Xapian
- $mkey = $mkey_prev;
- $dbh = undef;
- rlog($self, $xlog, *index_mm2, *unindex_mm2, $cb);
- }
- } else {
- # user didn't install DBD::SQLite and DBI
- rlog($self, $xlog, *add_message, *unindex_blob, $cb);
- }
-}
-
-# this will create a ghost as necessary
-sub resolve_mid_to_tid {
- my ($self, $mid) = @_;
- my $tid;
- $self->each_smsg_by_mid($mid, sub {
- my ($smsg) = @_;
- my $cur_tid = $smsg->thread_id;
- if (defined $tid) {
- merge_threads($self, $tid, $cur_tid);
- } else {
- $tid = $smsg->thread_id;
- }
- 1;
- });
- return $tid if defined $tid;
-
- $self->create_ghost($mid)->thread_id;
-}
-
-sub create_ghost {
- my ($self, $mid) = @_;
-
- my $tid = $self->next_thread_id;
- my $doc = Search::Xapian::Document->new;
- $doc->add_boolean_term('Q' . $mid);
- $doc->add_boolean_term('G' . $tid);
- $doc->add_boolean_term('T' . 'ghost');
-
- my $smsg = PublicInbox::SearchMsg->wrap($doc, $mid);
- $self->{xdb}->add_document($doc);
-
- $smsg;
-}
-
-sub merge_threads {
- my ($self, $winner_tid, $loser_tid) = @_;
- return if $winner_tid == $loser_tid;
- my $db = $self->{xdb};
- batch_do($self, 'G' . $loser_tid, sub {
- my ($ids) = @_;
- foreach my $docid (@$ids) {
- my $doc = $db->get_document($docid);
- $doc->remove_term('G' . $loser_tid);
- $doc->add_boolean_term('G' . $winner_tid);
- $db->replace_document($docid, $doc);
- }
- });
-}
-
-sub _read_git_config_perm {
- my ($self) = @_;
- my @cmd = qw(config);
- if ($self->{version} == 2) {
- push @cmd, "--file=$self->{mainrepo}/all.git/config";
- }
- my $fh = $self->{git}->popen(@cmd, 'core.sharedRepository');
- local $/ = "\n";
- my $perm = <$fh>;
- chomp $perm if defined $perm;
- $perm;
-}
-
-sub _git_config_perm {
- my $self = shift;
- my $perm = scalar @_ ? $_[0] : _read_git_config_perm($self);
- return PERM_GROUP if (!defined($perm) || $perm eq '');
- return PERM_UMASK if ($perm eq 'umask');
- return PERM_GROUP if ($perm eq 'group');
- if ($perm =~ /\A(?:all|world|everybody)\z/) {
- return PERM_EVERYBODY;
- }
- return PERM_GROUP if ($perm =~ /\A(?:true|yes|on|1)\z/);
- return PERM_UMASK if ($perm =~ /\A(?:false|no|off|0)\z/);
-
- my $i = oct($perm);
- return PERM_UMASK if ($i == PERM_UMASK);
- return PERM_GROUP if ($i == OLD_PERM_GROUP);
- return PERM_EVERYBODY if ($i == OLD_PERM_EVERYBODY);
-
- if (($i & 0600) != 0600) {
- die "core.sharedRepository mode invalid: ".
- sprintf('%.3o', $i) . "\nOwner must have permissions\n";
- }
- ($i & 0666);
-}
-
-sub _umask_for {
- my ($perm) = @_; # _git_config_perm return value
- my $rv = $perm;
- return umask if $rv == 0;
-
- # set +x bit if +r or +w were set
- $rv |= 0100 if ($rv & 0600);
- $rv |= 0010 if ($rv & 0060);
- $rv |= 0001 if ($rv & 0006);
- (~$rv & 0777);
-}
-
-sub with_umask {
- my ($self, $cb) = @_;
- my $old = umask $self->{umask};
- my $rv = eval { $cb->() };
- my $err = $@;
- umask $old;
- die $err if $err;
- $rv;