about summary refs log tree commit homepage
path: root/lib/PublicInbox/SolverGit.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-12-25 07:51:03 +0000
committerEric Wong <e@80x24.org>2019-12-28 19:38:10 +0000
commitb316f7541ec263fd04ea50530a1d500f43773299 (patch)
treed78a59ef1cd86a61481b91dba3020b41e8365688 /lib/PublicInbox/SolverGit.pm
parentbc23e3dc4b252dc7e9b6f3824afe74d85456b689 (diff)
downloadpublic-inbox-b316f7541ec263fd04ea50530a1d500f43773299.tar.gz
This allows us to get rid of the requirement to capture
on-stack variables with an anonymous sub, as illustrated
with the update to viewvcs to take advantage of this.

v2: fix error handling for missing OIDs
Diffstat (limited to 'lib/PublicInbox/SolverGit.pm')
-rw-r--r--lib/PublicInbox/SolverGit.pm38
1 files changed, 21 insertions, 17 deletions
diff --git a/lib/PublicInbox/SolverGit.pm b/lib/PublicInbox/SolverGit.pm
index 9266fb08..17a43060 100644
--- a/lib/PublicInbox/SolverGit.pm
+++ b/lib/PublicInbox/SolverGit.pm
@@ -55,11 +55,16 @@ sub dbg ($$) {
         print { $_[0]->{out} } $_[1], "\n" or ERR($_[0], "print(dbg): $!");
 }
 
+sub done ($$) {
+        my ($self, $res) = @_;
+        my $ucb = delete($self->{user_cb}) or return;
+        $ucb->($res, $self->{uarg});
+}
+
 sub ERR ($$) {
         my ($self, $err) = @_;
         print { $self->{out} } $err, "\n";
-        my $ucb = delete($self->{user_cb});
-        eval { $ucb->($err) } if $ucb;
+        eval { done($self, $err) };
         die $err;
 }
 
@@ -311,24 +316,23 @@ sub extract_old_mode ($) {
         '100644';
 }
 
-sub do_finish ($$) {
-        my ($self, $user_cb) = @_;
-        my $found = $self->{found};
-        my $oid_want = $self->{oid_want};
+sub do_finish ($) {
+        my ($self) = @_;
+        my ($found, $oid_want) = @$self{qw(found oid_want)};
         if (my $exists = $found->{$oid_want}) {
-                return $user_cb->($exists);
+                return done($self, $exists);
         }
 
         # let git disambiguate if oid_want was too short,
         # but long enough to be unambiguous:
         my $tmp_git = $self->{tmp_git};
         if (my @res = $tmp_git->check($oid_want)) {
-                return $user_cb->($found->{$res[0]});
+                return done($self, $found->{$res[0]});
         }
         if (my $err = $tmp_git->last_check_err) {
                 dbg($self, $err);
         }
-        $user_cb->(undef);
+        done($self, undef);
 }
 
 sub event_step ($) {
@@ -352,8 +356,8 @@ sub event_step ($) {
                 # our result: (which may be undef)
                 # Other steps may call user_cb to terminate prematurely
                 # on error
-                } elsif (my $user_cb = delete($self->{user_cb})) {
-                        do_finish($self, $user_cb);
+                } elsif (exists $self->{user_cb}) {
+                        do_finish($self);
                 } else {
                         die 'about to call user_cb twice'; # Oops :x
                 }
@@ -362,8 +366,7 @@ sub event_step ($) {
         if ($err) {
                 $err =~ s/^\s*Exception:\s*//; # bad word to show users :P
                 dbg($self, "E: $err");
-                my $ucb = delete($self->{user_cb});
-                eval { $ucb->($err) } if $ucb;
+                eval { done($self, $err) };
         }
 }
 
@@ -524,7 +527,7 @@ sub resolve_patch ($$) {
                         join("\n", $found_git->pub_urls($self->{psgi_env})));
 
                 if ($cur_want eq $self->{oid_want} || $type ne 'blob') {
-                        eval { delete($self->{user_cb})->($existing) };
+                        eval { done($self, $existing) };
                         die "E: $@" if $@;
                         return;
                 }
@@ -562,18 +565,19 @@ sub resolve_patch ($$) {
         }
 
         dbg($self, "could not find $cur_want");
-        eval { delete($self->{user_cb})->(undef) }; # not found! :<
+        eval { done($self, undef) };
         die "E: $@" if $@;
 }
 
 # 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) = @_;
+        my ($class, $ibx, $user_cb, $uarg) = @_;
 
         bless {
                 gits => $ibx->{-repo_objs},
                 user_cb => $user_cb,
+                uarg => $uarg,
                 # -cur_di, -qsp, -msg => temporary fields for Qspawn callbacks
 
                 # TODO: config option for searching related inboxes
@@ -591,7 +595,7 @@ sub solve ($$$$$) {
 
         # should we even get here? Probably not, but somebody
         # could be manually typing URLs:
-        return (delete $self->{user_cb})->(undef) if $oid_want =~ /\A0+\z/;
+        return done($self, undef) if $oid_want =~ /\A0+\z/;
 
         $self->{oid_want} = $oid_want;
         $self->{out} = $out;