]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/SolverGit.pm
treewide: "require" + "use" cleanup and docs
[public-inbox.git] / lib / PublicInbox / SolverGit.pm
index c9812b325cb98037cf6c785156d2a73291356f33..8629f0dafeb4216b41ac2c0951c866c8e76c2dcf 100644 (file)
@@ -11,7 +11,7 @@ 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);
@@ -102,7 +102,6 @@ sub extract_diff ($$) {
        my $ct = $part->content_type || 'text/plain';
        my ($s, undef) = msg_part_text($part, $ct);
        defined $s or return;
-       my $di = {};
 
        # Email::MIME::Encodings forces QP to be CRLF upon decoding,
        # change it back to LF:
@@ -112,6 +111,8 @@ sub extract_diff ($$) {
        }
 
        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:
@@ -124,17 +125,16 @@ sub extract_diff ($$) {
                # try to get the pre-and-post filenames as $2 and $3
                (?:^diff\x20--git\x20$FN\x20$FN$LF)
 
-               # old mode $4
-               (?:^old mode\x20(100644|120000|100755)$LF)?
-
-               # ignore other info
-               (?:^(?:copy|rename|deleted|dissimilarity|similarity).*$LF)?
-
-               # new mode (possibly new file) ($5)
-               (?:^new\x20(?:file\x20)?mode\x20(100644|120000|100755)$LF)?
-
-               # ignore other info
-               (?:^(?:copy|rename|deleted|dissimilarity|similarity).*$LF)?
+               (?:^(?: # pass all this to git-apply:
+                       # old mode $4
+                       (?:old\x20mode\x20($MODE))
+                       |
+                       # new mode (possibly new file) ($5)
+                       (?:new\x20(?:file\x20)?mode\x20($MODE))
+                       |
+                       (?:(?:copy|rename|deleted|
+                               dissimilarity|similarity)$ANY)
+               )$LF)*
 
                )? # end of optional stuff, everything below is required
 
@@ -155,15 +155,17 @@ sub extract_diff ($$) {
                # the meat of the diff, including "^\\No newline ..."
                # We also allow for totally blank lines w/o leading spaces,
                # because git-apply(1) handles that case, too
-               (?:^(?:[\@\+\x20\-\\][^\r\n]*|)$LF)+
+               (?:^(?:[\@\+\x20\-\\][^\n]*|)$LF)+
        )!smx or return;
 
-       my $hdr_lines = $1;
+       my $di = {
+               hdr_lines => $1,
+               oid_a => $6,
+               oid_b => $7,
+               mode_a => $5 // $8 // $4, # new (file) // unchanged // old
+       };
        my $path_a = $2 // $10;
        my $path_b = $3 // $11;
-       $di->{oid_a} = $6;
-       $di->{oid_b} = $7;
-       $di->{mode_a} = $5 // $8 // $4; # new (file) // unchanged // old
        my $patch = $9;
 
        # don't care for leading 'a/' and 'b/'
@@ -178,19 +180,16 @@ sub extract_diff ($$) {
        $di->{path_a} = join('/', @a);
        $di->{path_b} = join('/', @b);
 
-       utf8::encode($hdr_lines);
-       utf8::encode($patch);
        my $path = ++$self->{tot};
        $di->{n} = $path;
-       open(my $tmp, '>', $self->{tmp}->dirname . "/$path") or
+       open(my $tmp, '>:utf8', $self->{tmp}->dirname . "/$path") or
                die "open(tmp): $!";
-       print $tmp $hdr_lines, $patch or die "print(tmp): $!";
+       print $tmp $di->{hdr_lines}, $patch or die "print(tmp): $!";
        close $tmp or die "close(tmp): $!";
 
        # for debugging/diagnostics:
        $di->{ibx} = $ibx;
        $di->{smsg} = $smsg;
-       $di->{hdr_lines} = $hdr_lines;
 
        push @$diffs, $di;
 }
@@ -499,7 +498,7 @@ sub do_git_apply ($) {
        } while (@$patches && $len < $ARG_SIZE_MAX &&
                 !oids_same_ish($patches->[0]->{oid_b}, $prv_oid_b));
 
-       my $opt = { 2 => 1, -C => $dn };
+       my $opt = { 2 => 1, -C => $dn, quiet => 1 };
        my $qsp = PublicInbox::Qspawn->new(\@cmd, $self->{git_env}, $opt);
        $self->{-cur_di} = $di;
        $self->{-qsp} = $qsp;