diff options
author | Eric Wong <e@80x24.org> | 2019-01-19 05:25:30 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2019-01-20 04:24:54 +0000 |
commit | 915cd090798069a44dbb4b4c243bff9af2ae1b76 (patch) | |
tree | 5899b4cc1df3f5b57c989fe75d4dcc35b9a2f406 /lib | |
parent | 7fa037d0be9d1a8b891084a3c1215a1af5aa886b (diff) | |
download | public-inbox-915cd090798069a44dbb4b4c243bff9af2ae1b76.tar.gz |
A bit messy at the moment, but we need to break this up into smaller steps for fairness with other clients, as applying dozens of patches can take several hundred milliseconds.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/PublicInbox/SolverGit.pm | 70 |
1 files changed, 31 insertions, 39 deletions
diff --git a/lib/PublicInbox/SolverGit.pm b/lib/PublicInbox/SolverGit.pm index 71494e07..70d8a934 100644 --- a/lib/PublicInbox/SolverGit.pm +++ b/lib/PublicInbox/SolverGit.pm @@ -290,16 +290,35 @@ sub di_url ($) { defined($url) ? "$url$mid/" : "<$mid>"; } -sub apply_patches ($$$$$) { - my ($self, $out, $wt, $found, $patches) = @_; +sub apply_patches_cb ($$$$$) { + my ($self, $out, $found, $patches, $oid_b) = @_; + my $wt = do_git_init_wt($self); my $wt_dir = $wt->dirname; my $wt_git = PublicInbox::Git->new("$wt_dir/.git"); $wt_git->{-wt} = $wt; my $cur = 0; my $tot = scalar @$patches; + my ($apply_pid, $rd, $di); + + # returns an empty string if in progress, undef if not found, + # or the final [ ::Git, oid_full, type, size, $di ] arrayref + # if found + sub { + if ($rd) { + $found->{$di->{oid_b}} = + do_apply_end($out, $wt_git, $rd, $di); + $rd = undef; + # continue to shift @$patches + } elsif ($apply_pid) { + $rd = do_apply_continue($wt_dir, $apply_pid); + $apply_pid = undef; + return ''; # $rd => do_apply_ned + } + + # may return undef here + $di = shift @$patches or return $found->{$oid_b}; - foreach my $di (@$patches) { my $i = ++$cur; my $oid_a = $di->{oid_a}; my $existing = $found->{$oid_a}; @@ -321,29 +340,10 @@ sub apply_patches ($$$$$) { join('', @{$di->{hdr_lines}}), "\n" or die "print \$out failed: $!"; - # apply the patch! - my $apply_pid = do_apply_begin($out, $wt_dir, $di); - my $rd = do_apply_continue($wt_dir, $apply_pid); - $found->{$di->{oid_b}} = do_apply_end($out, $wt_git, $rd, $di); - } -} - -sub dump_found ($$) { - my ($out, $found) = @_; - foreach my $oid (sort keys %$found) { - my ($git, $oid, undef, undef, $di) = @{$found->{$oid}}; - my $loc = $di ? di_url($di) : $git->src_blob_url($oid); - print $out "$oid from $loc\n"; - } -} - -sub dump_patches ($$) { - my ($out, $patches) = @_; - my $tot = scalar(@$patches); - my $i = 0; - foreach my $di (@$patches) { - ++$i; - print $out "[$i/$tot] ", di_url($di), "\n"; + # begin the patch application patch! + $apply_pid = do_apply_begin($out, $wt_dir, $di); + # next call to this callback will call do_apply_continue + ''; } } @@ -415,24 +415,16 @@ sub solve ($$$$) { unless (scalar(@$patches)) { print $out "no patch(es) for $oid_b\n"; - dump_found($out, $found); return; } # reconstruct the oid_b blob using patches we found: - eval { - my $wt = do_git_init_wt($self); - apply_patches($self, $out, $wt, $found, $patches); - }; - if ($@) { - print $out "E: $@\nfound: "; - dump_found($out, $found); - print $out "patches: "; - dump_patches($out, $patches); - return; + my $cb = apply_patches_cb($self, $out, $found, $patches, $oid_b); + my $ret; + while (1) { + $ret = $cb->(); + return $ret if (ref($ret) || !defined($ret)); } - - $found->{$oid_b}; } 1; |