+ scalar(@{$want->{try_smsgs}}) ? retry_current($self, $want)
+ : extract_diffs_done($self, $want);
+}
+
+sub resolve_patch ($$) {
+ my ($self, $want) = @_;
+
+ my $cur_want = $want->{oid_b};
+ if (scalar(@{$self->{patches}}) > $MAX_PATCH) {
+ die "Aborting, too many steps to $self->{oid_want}";
+ }
+
+ if (my $msgs = $want->{try_smsgs}) {
+ my $smsg = shift @$msgs;
+ if ($self->{psgi_env}->{'pi-httpd.async'}) {
+ return ibx_async_cat($want->{cur_ibx}, $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);
+ }
+ }
+
+ return scalar(@$msgs) ? retry_current($self, $want)
+ : extract_diffs_done($self, $want);
+ }
+
+ # see if we can find the blob in an existing git repo:
+ if (!$want->{try_ibxs} && $self->{seen_oid}->{$cur_want}++) {
+ die "Loop detected solving $cur_want\n";
+ }
+ $want->{try_ibxs} //= [ @{$self->{inboxes}} ]; # array copy
+ my $existing = solve_existing($self, $want);
+ if (ref $existing) {
+ my ($found_git, undef, $type, undef) = @$existing;
+ dbg($self, "found $cur_want in " .
+ join(" ||\n\t",
+ $found_git->pub_urls($self->{psgi_env})));
+
+ if ($cur_want eq $self->{oid_want} || $type ne 'blob') {
+ eval { done($self, $existing) };
+ die "E: $@" if $@;
+ return;
+ }
+ mark_found($self, $cur_want, $existing);
+ return next_step($self); # onto patch application
+ } elsif ($existing > 0) {
+ return retry_current($self, $want);
+ } else { # $existing == 0: we may retry if inbox scan (below) fails
+ delete $want->{try_gits};
+ }
+
+ # scan through inboxes to look for emails which results in
+ # the oid we want:
+ my $ibx = shift(@{$want->{try_ibxs}}) or return done($self, undef);
+ if (my $msgs = find_smsgs($self, $ibx, $want)) {
+ $want->{try_smsgs} = $msgs;
+ $want->{cur_ibx} = $ibx;
+ $self->{tmp_diffs} = [];
+ return retry_current($self, $want);
+ }
+ try_harder($self, $want);