+# this API is designed to avoid creating self-referential structures;
+# so user_cb never references the SolverGit object
+sub new {
+ my ($class, $ibx, $user_cb, $uarg) = @_;
+
+ bless { # $ibx is undef if coderepo only (see WwwCoderepo)
+ gits => $ibx ? $ibx->{-repo_objs} : undef,
+ user_cb => $user_cb,
+ uarg => $uarg,
+ # -cur_di, -qsp_err, -msg => temp fields for Qspawn callbacks
+
+ # TODO: config option for searching related inboxes
+ inboxes => $ibx ? [ $ibx ] : [],
+ }, $class;
+}
+
+# recreate $oid_want using $hints
+# hints keys: path_a, path_b, oid_a (note: `oid_b' is NOT a hint)
+# Calls {user_cb} with: [ ::Git object, oid_full, type, size, di (diff_info) ]
+# with found object, or undef if nothing was found
+# Calls {user_cb} with a string error on fatal errors
+sub solve ($$$$$) {
+ my ($self, $env, $out, $oid_want, $hints) = @_;
+
+ # should we even get here? Probably not, but somebody
+ # could be manually typing URLs:
+ return done($self, undef) if $oid_want =~ /\A0+\z/;
+
+ $self->{oid_want} = $oid_want;
+ $self->{out} = $out;
+ $self->{seen_oid} = {};
+ $self->{tot} = $self->{nr_p} = 0;
+ $self->{psgi_env} = $env;
+ $self->{have_hints} = 1 if scalar keys %$hints;
+ $self->{todo} = [ { %$hints, oid_b => $oid_want } ];
+ $self->{patches} = []; # [ $di, $di, ... ]
+ $self->{found} = {}; # { abbr => [ ::Git, oid, type, size, $di ] }
+
+ dbg($self, "solving $oid_want ...");
+ if (my $async = $env->{'pi-httpd.async'}) {
+ # PublicInbox::HTTPD::Async->new
+ $async->(undef, undef, $self);
+ } else {
+ event_step($self) while $self->{user_cb};
+ }