X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FV2Writable.pm;h=8ad71b54ee6fe7088a64e95637309ce914e9c790;hb=8122bd3803b7520ab5421df264406e670e3f902b;hp=02f313b022c01dc7a52140016a4b1715a20f0f37;hpb=b32b47fb12a3043d748f723802de923d9043d7ff;p=public-inbox.git diff --git a/lib/PublicInbox/V2Writable.pm b/lib/PublicInbox/V2Writable.pm index 02f313b0..8ad71b54 100644 --- a/lib/PublicInbox/V2Writable.pm +++ b/lib/PublicInbox/V2Writable.pm @@ -16,9 +16,9 @@ use PublicInbox::ContentId qw(content_id content_digest); use PublicInbox::Inbox; use PublicInbox::OverIdx; use PublicInbox::Msgmap; -use PublicInbox::Spawn qw(spawn); +use PublicInbox::Spawn qw(spawn popen_rd); use PublicInbox::SearchIdx; -use IO::Handle; +use IO::Handle; # ->autoflush use File::Temp qw(tempfile); # an estimate of the post-packed size to the raw uncompressed size @@ -62,10 +62,13 @@ sub count_shards ($) { # Also, shard count may change while -watch is running # due to "xcpdb --reshard" if (-d $xpfx) { + require PublicInbox::Search; + PublicInbox::Search::load_xapian(); + my $XapianDatabase = $PublicInbox::Search::X{Database}; foreach my $shard (<$xpfx/*>) { -d $shard && $shard =~ m!/[0-9]+\z! or next; eval { - Search::Xapian::Database->new($shard)->close; + $XapianDatabase->new($shard)->close; $n++; }; } @@ -468,17 +471,12 @@ sub git_hash_raw ($$) { print $tmp_fh $$raw or die "print \$tmp_fh: $!"; sysseek($tmp_fh, 0, 0) or die "seek failed: $!"; - my ($r, $w); - pipe($r, $w) or die "failed to create pipe: $!"; - my $rdr = { 0 => fileno($tmp_fh), 1 => fileno($w) }; my $git_dir = $self->{-inbox}->git->{git_dir}; my $cmd = ['git', "--git-dir=$git_dir", qw(hash-object --stdin)]; - my $pid = spawn($cmd, undef, $rdr); - close $w; + my $r = popen_rd($cmd, undef, { 0 => $tmp_fh }); local $/ = "\n"; chomp(my $oid = <$r>); - waitpid($pid, 0) == $pid or die "git hash-object did not finish"; - die "git hash-object failed: $?" if $?; + close $r or die "git hash-object failed: $?"; $oid =~ /\A[a-f0-9]{40}\z/ or die "OID not expected: $oid"; $oid; } @@ -665,23 +663,43 @@ sub fill_alternates ($$) { unless (-d $all) { PublicInbox::Import::init_bare($all); } - my $alt = "$all/objects/info/alternates"; - my %alts; - my @add; + my $info_dir = "$all/objects/info"; + my $alt = "$info_dir/alternates"; + my (%alt, $new); + my $mode = 0644; if (-e $alt) { open(my $fh, '<', $alt) or die "open < $alt: $!\n"; - %alts = map { chomp; $_ => 1 } (<$fh>); + $mode = (stat($fh))[2] & 07777; + + # we assign a sort score to every alternate and favor + # the newest (highest numbered) one when we + my $score; + my $other = 0; # in case admin adds non-epoch repos + %alt = map {; + if (m!\A\Q../../\E([0-9]+)\.git/objects\z!) { + $score = $1 + 0; + } else { + $score = --$other; + } + $_ => $score; + } split(/\n+/, do { local $/; <$fh> }); } + foreach my $i (0..$epoch) { my $dir = "../../git/$i.git/objects"; - push @add, $dir if !$alts{$dir} && -d "$pfx/$i.git"; - } - return unless @add; - open my $fh, '>>', $alt or die "open >> $alt: $!\n"; - foreach my $dir (@add) { - print $fh "$dir\n" or die "print >> $alt: $!\n"; + if (!exists($alt{$dir}) && -d "$pfx/$i.git") { + $alt{$dir} = $i; + $new = 1; + } } - close $fh or die "close $alt: $!\n"; + return unless $new; + + my ($fh, $tmp) = tempfile('alt-XXXXXXXX', DIR => $info_dir); + print $fh join("\n", sort { $alt{$b} <=> $alt{$a} } keys %alt), "\n" + or die "print $tmp: $!\n"; + chmod($mode, $fh) or die "fchmod $tmp: $!\n"; + close $fh or die "close $tmp $!\n"; + rename($tmp, $alt) or die "rename $tmp => $alt: $!\n"; } sub git_init { @@ -774,7 +792,6 @@ sub diff ($$$) { my $cmd = [ qw(diff -u), $an, $bn ]; print STDERR "# MID conflict <$mid>\n"; my $pid = spawn($cmd, undef, { 1 => 2 }); - defined $pid or die "diff failed to spawn $!"; waitpid($pid, 0) == $pid or die "diff did not finish"; unlink($an, $bn); } @@ -1204,7 +1221,7 @@ sub unindex ($$$$) { # ensure any blob can not longer be accessed via dumb HTTP PublicInbox::Import::run_die(['git', "--git-dir=$git->{git_dir}", - qw(-c gc.reflogExpire=now gc --prune=all)]); + qw(-c gc.reflogExpire=now gc --prune=all --quiet)]); } sub sync_ranges ($$$) {