X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FSolverGit.pm;h=a53f28b105df291a1f64bae84d88c813114a95b0;hb=0d38f65c490466837ae091afa7a7b6f59d04ce7c;hp=c54d6d5499b6f86ed9e49c166bfbf9bd00dcccc6;hpb=c2ded5581489a14e5aba14a10954da1a28402c6a;p=public-inbox.git diff --git a/lib/PublicInbox/SolverGit.pm b/lib/PublicInbox/SolverGit.pm index c54d6d54..a53f28b1 100644 --- a/lib/PublicInbox/SolverGit.pm +++ b/lib/PublicInbox/SolverGit.pm @@ -16,6 +16,8 @@ use PublicInbox::Git qw(git_unquote git_quote); use PublicInbox::MsgIter qw(msg_part_text); use PublicInbox::Qspawn; use PublicInbox::Tmpfile; +use PublicInbox::GitAsyncCat; +use PublicInbox::Eml; use URI::Escape qw(uri_escape_utf8); # POSIX requires _POSIX_ARG_MAX >= 4096, and xargs is required to @@ -214,7 +216,7 @@ sub filename_query ($) { sub find_smsgs ($$$) { my ($self, $ibx, $want) = @_; - my $srch = $ibx->search or return; + my $srch = $ibx->isrch or return; my $post = $want->{oid_b} or die 'BUG: no {oid_b}'; $post =~ /\A[a-f0-9]+\z/ or die "BUG: oid_b not hex: $post"; @@ -515,16 +517,16 @@ sub di_url ($$) { } sub retry_current { - # my ($self, $want) = @_; - push @{$_[0]->{todo}}, $_[1]; - goto \&next_step # retry solve_existing + my ($self, $want) = @_; + push @{$self->{todo}}, $want; + next_step($self); # retry solve_existing } -sub try_harder { +sub try_harder ($$) { my ($self, $want) = @_; # do we have more inboxes to try? - goto \&retry_current if scalar @{$want->{try_ibxs}}; + return retry_current($self, $want) if scalar @{$want->{try_ibxs}}; my $cur_want = $want->{oid_b}; if (length($cur_want) > $OID_MIN) { # maybe a shorter OID will work @@ -532,7 +534,7 @@ sub try_harder { chop($cur_want); dbg($self, "retrying $want->{oid_b} as $cur_want"); $want->{oid_b} = $cur_want; - goto \&retry_current; # retry with shorter abbrev + return retry_current($self, $want); # retry with shorter abbrev } dbg($self, "could not find $cur_want"); @@ -540,6 +542,46 @@ sub try_harder { die "E: $@" if $@; } +sub extract_diffs_done { + my ($self, $want) = @_; + + delete $want->{try_smsgs}; + delete $want->{cur_ibx}; + + my $diffs = delete $self->{tmp_diffs}; + if (scalar @$diffs) { + unshift @{$self->{patches}}, @$diffs; + dbg($self, "found $want->{oid_b} in " . join(" ||\n\t", + map { di_url($self, $_) } @$diffs)); + + # good, we can find a path to the oid we $want, now + # lets see if we need to apply more patches: + my $di = $diffs->[0]; + my $src = $di->{oid_a}; + + unless ($src =~ /\A0+\z/) { + # we have to solve it using another oid, fine: + my $job = { oid_b => $src, path_b => $di->{path_a} }; + push @{$self->{todo}}, $job; + } + return next_step($self); # onto the next todo item + } + try_harder($self, $want); +} + +sub extract_diff_async { + my ($bref, $oid, $type, $size, $x) = @_; + my ($self, $want, $smsg) = @$x; + if (defined($oid)) { + $smsg->{blob} eq $oid or + ERR($self, "BUG: $smsg->{blob} != $oid"); + PublicInbox::Eml->new($bref)->each_part(\&extract_diff, $x, 1); + } + + scalar(@{$want->{try_smsgs}}) ? retry_current($self, $want) + : extract_diffs_done($self, $want); +} + sub resolve_patch ($$) { my ($self, $want) = @_; @@ -550,39 +592,20 @@ sub resolve_patch ($$) { if (my $msgs = $want->{try_smsgs}) { my $smsg = shift @$msgs; - if (my $eml = $want->{cur_ibx}->smsg_eml($smsg)) { - $eml->each_part(\&extract_diff, - [ $self, $want, $smsg ], 1); - } - - # try the remaining smsgs later - goto \&retry_current if scalar @$msgs; - - delete $want->{try_smsgs}; - delete $want->{cur_ibx}; - - my $diffs = delete $self->{tmp_diffs}; - if (scalar @$diffs) { - unshift @{$self->{patches}}, @$diffs; - dbg($self, "found $cur_want in " . join(" ||\n\t", - map { di_url($self, $_) } @$diffs)); - - # good, we can find a path to the oid we $want, now - # lets see if we need to apply more patches: - my $di = $diffs->[0]; - my $src = $di->{oid_a}; - - unless ($src =~ /\A0+\z/) { - # we have to solve it using another oid, fine: - my $job = { - oid_b => $src, - path_b => $di->{path_a}, - }; - push @{$self->{todo}}, $job; + if ($self->{psgi_env}->{'pi-httpd.async'}) { + return git_async_cat($want->{cur_ibx}->git, + $smsg->{blob}, + \&extract_diff_async, + [$self, $want, $smsg]); + } else { + if (my $eml = $want->{cur_ibx}->smsg_eml($smsg)) { + $eml->each_part(\&extract_diff, + [ $self, $want, $smsg ], 1); } - goto \&next_step; # onto the next todo item } - goto \&try_harder; + + return scalar(@$msgs) ? retry_current($self, $want) + : extract_diffs_done($self, $want); } # see if we can find the blob in an existing git repo: @@ -603,9 +626,9 @@ sub resolve_patch ($$) { return; } mark_found($self, $cur_want, $existing); - goto \&next_step; # onto patch application + return next_step($self); # onto patch application } elsif ($existing > 0) { - goto \&retry_current; + return retry_current($self, $want); } else { # $existing == 0: we may retry if inbox scan (below) fails delete $want->{try_gits}; } @@ -617,9 +640,9 @@ sub resolve_patch ($$) { $want->{try_smsgs} = $msgs; $want->{cur_ibx} = $ibx; $self->{tmp_diffs} = []; - goto \&retry_current; + return retry_current($self, $want); } - goto \&try_harder; + try_harder($self, $want); } # this API is designed to avoid creating self-referential structures;