X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FSolverGit.pm;h=ff8a49460b6fca00b0741f72f8431edec063d939;hb=80b887f29b2ec71d025b4c266a1c26314758994c;hp=5ac27988591c961a9335735727d8b3cf80f825a4;hpb=aa1e96cd44f6d5cd77a96648ac1f2dbcca9dc367;p=public-inbox.git diff --git a/lib/PublicInbox/SolverGit.pm b/lib/PublicInbox/SolverGit.pm index 5ac27988..ff8a4946 100644 --- a/lib/PublicInbox/SolverGit.pm +++ b/lib/PublicInbox/SolverGit.pm @@ -1,20 +1,20 @@ -# Copyright (C) 2019 all contributors +# Copyright (C) 2019-2020 all contributors # License: AGPL-3.0+ # "Solve" blobs which don't exist in git code repositories by # searching inboxes for post-image blobs. # this emits a lot of debugging/tracing information which may be -# publically viewed over HTTP(S). Be careful not to expose +# publicly viewed over HTTP(S). Be careful not to expose # local filesystem layouts in the process. package PublicInbox::SolverGit; use strict; use warnings; use 5.010_001; -use File::Temp 0.19 (); +use File::Temp 0.19 (); # 0.19 for ->newdir use Fcntl qw(SEEK_SET); use PublicInbox::Git qw(git_unquote git_quote); -use PublicInbox::MsgIter qw(msg_iter msg_part_text); +use PublicInbox::MsgIter qw(msg_part_text); use PublicInbox::Qspawn; use PublicInbox::Tmpfile; use URI::Escape qw(uri_escape_utf8); @@ -34,6 +34,12 @@ my $OID_MIN = 7; # work fairly. Other PSGI servers may have trouble, though. my $MAX_PATCH = 9999; +my $LF = qr!\r?\n!; +my $ANY = qr![^\r\n]+!; +my $MODE = '100644|120000|100755'; +my $FN = qr!(?:("?[^/\n]+/[^\r\n]+)|/dev/null)!; +my %BAD_COMPONENT = ('' => 1, '.' => 1, '..' => 1); + # di = diff info / a hashref with information about a diff ($di): # { # oid_a => abbreviated pre-image oid, @@ -42,7 +48,7 @@ my $MAX_PATCH = 9999; # hdr_lines => string of various header lines for mode information # mode_a => original mode of oid_a (string, not integer), # ibx => PublicInbox::Inbox object containing the diff -# smsg => PublicInbox::SearchMsg object containing diff +# smsg => PublicInbox::Smsg object containing diff # path_a => pre-image path # path_b => post-image path # n => numeric path of the patch (relative to worktree) @@ -110,10 +116,6 @@ sub extract_diff ($$) { $s =~ s/\r\n/\n/sg; } - state $LF = qr!\r?\n!; - state $ANY = qr![^\r\n]+!; - state $MODE = '100644|120000|100755'; - state $FN = qr!(?:("?[^/\n]+/[^\r\n]+)|/dev/null)!; $s =~ m!( # $1 start header lines we save for debugging: @@ -169,15 +171,14 @@ sub extract_diff ($$) { my $patch = $9; # don't care for leading 'a/' and 'b/' - my (undef, @a) = split(m{/}, git_unquote($path_a)); + my (undef, @a) = split(m{/}, git_unquote($path_a)) if defined($path_a); my (undef, @b) = split(m{/}, git_unquote($path_b)); # get rid of path-traversal attempts and junk patches: # it's junk at best, an attack attempt at worse: - state $bad_component = { map { $_ => 1 } ('', '.', '..') }; - foreach (@a, @b) { return if $bad_component->{$_} } + foreach (@a, @b) { return if $BAD_COMPONENT{$_} } - $di->{path_a} = join('/', @a); + $di->{path_a} = join('/', @a) if @a; $di->{path_b} = join('/', @b); my $path = ++$self->{tot}; @@ -228,14 +229,12 @@ sub find_extract_diffs ($$$) { } } - my $msgs = $srch->query($q, { relevance => 1 }); - + my $mset = $srch->mset($q, { relevance => 1 }); my $diffs = []; - foreach my $smsg (@$msgs) { - $ibx->smsg_mime($smsg) or next; - my $mime = delete $smsg->{mime}; - msg_iter($mime, \&extract_diff, - [$self, $diffs, $pre, $post, $ibx, $smsg]); + for my $smsg (@{$srch->mset_to_smsg($ibx, $mset)}) { + my $eml = $ibx->smsg_eml($smsg) or next; + $eml->each_part(\&extract_diff, + [$self, $diffs, $pre, $post, $ibx, $smsg], 1); } @$diffs ? $diffs : undef; } @@ -531,7 +530,8 @@ sub resolve_patch ($$) { if (my $existing = solve_existing($self, $want)) { my ($found_git, undef, $type, undef) = @$existing; dbg($self, "found $cur_want in " . - join("\n", $found_git->pub_urls($self->{psgi_env}))); + join(" ||\n\t", + $found_git->pub_urls($self->{psgi_env}))); if ($cur_want eq $self->{oid_want} || $type ne 'blob') { eval { done($self, $existing) }; @@ -549,7 +549,7 @@ sub resolve_patch ($$) { unshift @{$self->{patches}}, @$diffs; dbg($self, "found $cur_want in ". - join("\n\t", map { di_url($self, $_) } @$diffs)); + 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: @@ -593,7 +593,7 @@ sub new { } # recreate $oid_want using $hints -# hints keys: path_a, path_b, oid_a +# 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