diff options
Diffstat (limited to 'lib/PublicInbox/LeiRediff.pm')
-rw-r--r-- | lib/PublicInbox/LeiRediff.pm | 134 |
1 files changed, 61 insertions, 73 deletions
diff --git a/lib/PublicInbox/LeiRediff.pm b/lib/PublicInbox/LeiRediff.pm index 1e95e55a..35728330 100644 --- a/lib/PublicInbox/LeiRediff.pm +++ b/lib/PublicInbox/LeiRediff.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2021 all contributors <meta@public-inbox.org> +# Copyright (C) all contributors <meta@public-inbox.org> # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> # The "lei rediff" sub-command, regenerates diffs with new options @@ -7,7 +7,7 @@ use strict; use v5.10.1; use parent qw(PublicInbox::IPC PublicInbox::LeiInput); use File::Temp 0.19 (); # 0.19 for ->newdir -use PublicInbox::Spawn qw(spawn which); +use PublicInbox::Spawn qw(run_wait popen_wr which); use PublicInbox::MsgIter qw(msg_part_text); use PublicInbox::ViewDiff; use PublicInbox::LeiBlob; @@ -30,7 +30,7 @@ sub rediff_user_cb { # called by solver when done # don't try to support all the git-show(1) options for non-blob, # this is just a convenience: - $type ne 'blob' and return $lei->err(<<EOF); + $type ne 'blob' and return warn(<<EOF); # $oid is a $type of $size bytes in: # $git->{git_dir} (wanted: $oid_want) EOF @@ -56,6 +56,35 @@ sub solve_1 ($$$) { $self->{blob}->{$oid_want}; # full OID } +sub _lei_diff_prepare ($$) { + my ($lei, $cmd) = @_; + my $opt = $lei->{opt}; + push @$cmd, '--'.($opt->{color} && !$opt->{'no-color'} ? '' : 'no-'). + 'color'; + for my $o (@PublicInbox::LEI::diff_opt) { + my $c = ''; + # remove single char short option + $o =~ s/\|([a-z0-9])\b//i and $c = $1; + if ($o =~ s/=[is]@\z//) { + my $v = $opt->{$o} or next; + push @$cmd, map { $c ? "-$c$_" : "--$o=$_" } @$v; + } elsif ($o =~ s/=[is]\z//) { + my $v = $opt->{$o} // next; + push @$cmd, $c ? "-$c$v" : "--$o=$v"; + } elsif ($o =~ s/:[is]\z//) { + my $v = $opt->{$o} // next; + push @$cmd, $c ? "-$c$v" : + ($v eq '' ? "--$o" : "--$o=$v"); + } elsif ($o =~ s/!\z//) { + my $v = $opt->{$o} // next; + push @$cmd, $v ? "--$o" : "--no-$o"; + } elsif ($opt->{$o}) { + push @$cmd, $c ? "-$c" : "--$o"; + } + } + push(@$cmd, "-O$opt->{'order-file'}") if $opt->{'order-file'}; +} + sub diff_ctxq ($$) { my ($self, $ctxq) = @_; return unless $ctxq; @@ -85,88 +114,51 @@ EOM if (!$rw->{-tmp}) { my $d = "$self->{rdtmp}/for_tree.git"; -d $d or PublicInbox::Import::init_bare($d); - my $f = "$d/objects/info/alternates"; # always overwrite - open my $fh, '>', $f or die "open $f: $!"; - for my $git (@{$self->{gits}}) { - print $fh $git->git_path('objects'),"\n"; - } - close $fh or die "close $f: $!"; + # always overwrite + PublicInbox::IO::write_file '>', "$d/objects/info/alternates", + map { $_->git_path('objects')."\n" } @{$self->{gits}}; $rw = PublicInbox::Git->new($d); } - pipe(my ($r, $w)) or die "pipe: $!"; - my $pid = spawn(['git', "--git-dir=$rw->{git_dir}", + my $w = popen_wr(['git', "--git-dir=$rw->{git_dir}", qw(fast-import --quiet --done --date-format=raw)], - $lei->{env}, { 2 => $lei->{2}, 0 => $r }); - close $r or die "close r fast-import: $!"; + $lei->{env}, { 2 => $lei->{2} }); print $w $ta, "\n", $tb, "\ndone\n" or die "print fast-import: $!"; - close $w or die "close w fast-import: $!"; - waitpid($pid, 0); - die "fast-import failed: \$?=$?" if $?; + $w->close or die "close w fast-import: \$?=$? \$!=$!"; - my @cmd = qw(diff); - my $opt = $lei->{opt}; - push @cmd, '--'.($opt->{color} && !$opt->{'no-color'} ? '' : 'no-'). - 'color'; - for my $o (@PublicInbox::LEI::diff_opt) { - my $c = ''; - # remove single char short option - $o =~ s/\|([a-z0-9])\b//i and $c = $1; - if ($o =~ s/=[is]@\z//) { - my $v = $opt->{$o} or next; - push @cmd, map { $c ? "-$c$_" : "--$o=$_" } @$v; - } elsif ($o =~ s/=[is]\z//) { - my $v = $opt->{$o} // next; - push @cmd, $c ? "-$c$v" : "--$o=$v"; - } elsif ($o =~ s/:[is]\z//) { - my $v = $opt->{$o} // next; - push @cmd, $c ? "-$c$v" : - ($v eq '' ? "--$o" : "--$o=$v"); - } elsif ($o =~ s/!\z//) { - my $v = $opt->{$o} // next; - push @cmd, $v ? "--$o" : "--no-$o"; - } elsif ($opt->{$o}) { - push @cmd, $c ? "-$c" : "--$o"; - } - } - $lei->qerr("# git @cmd"); - push @cmd, qw(A B); - unshift @cmd, 'git', "--git-dir=$rw->{git_dir}"; - $pid = spawn(\@cmd, $lei->{env}, { 2 => $lei->{2}, 1 => $lei->{1} }); - waitpid($pid, 0); - $lei->child_error($?) if $?; # for git diff --exit-code + my $cmd = [ 'diff' ]; + _lei_diff_prepare($lei, $cmd); + $lei->qerr("# git @$cmd"); + push @$cmd, qw(A B); + unshift @$cmd, 'git', "--git-dir=$rw->{git_dir}"; + run_wait($cmd, $lei->{env}, { 2 => $lei->{2}, 1 => $lei->{1} }) and + $lei->child_error($?); # for git diff --exit-code undef; } -sub wait_requote ($$$) { # OnDestroy callback - my ($lei, $pid, $old_1) = @_; - $lei->{1} = $old_1; # closes stdin of `perl -pE 's/^/> /'` - waitpid($pid, 0) == $pid or die "BUG(?) waitpid: \$!=$! \$?=$?"; - $lei->child_error($?) if $?; -} +# awaitpid callback +sub wait_requote { $_[1]->child_error($?) if $? } -sub requote ($$) { +sub requote ($$) { # '> ' prefix(es) lei->{1} my ($lei, $pfx) = @_; - pipe(my($r, $w)) or die "pipe: $!"; - my $rdr = { 0 => $r, 1 => $lei->{1}, 2 => $lei->{2} }; + my $opt = { 1 => $lei->{1}, 2 => $lei->{2} }; # $^X (perl) is overkill, but maybe there's a weird system w/o sed - my $pid = spawn([$^X, '-pE', "s/^/$pfx/"], $lei->{env}, $rdr); - my $old_1 = $lei->{1}; - $w->autoflush(1); + my $w = popen_wr([$^X, '-pe', "s/^/$pfx/"], $lei->{env}, $opt, + \&wait_requote, $lei); binmode $w, ':utf8'; - $lei->{1} = $w; - PublicInbox::OnDestroy->new(\&wait_requote, $lei, $pid, $old_1); + $w; } sub extract_oids { # Eml each_part callback my ($ary, $self) = @_; + my $lei = $self->{lei}; my ($p, undef, $idx) = @$ary; - $self->{lei}->out($p->header_obj->as_string, "\n"); + $lei->out($p->header_obj->as_string, "\n"); my ($s, undef) = msg_part_text($p, $p->content_type || 'text/plain'); defined $s or return; - my $rq; - if ($self->{dqre} && $s =~ s/$self->{dqre}//g) { # '> ' prefix(es) - $rq = requote($self->{lei}, $1) if $self->{lei}->{opt}->{drq}; - } + + $self->{dqre} && $s =~ s/$self->{dqre}//g && $lei->{opt}->{drq} and + local $lei->{1} = requote($lei, $1); + my @top = split($PublicInbox::ViewDiff::EXTRACT_DIFFS, $s); undef $s; my $blobs = $self->{blobs}; # blobs to resolve @@ -251,7 +243,7 @@ sub lei_rediff { ($lei->{opt}->{drq} && !$lei->{opt}->{verbose}) and $lei->{opt}->{quiet} //= 1; $lei->_lei_store(1)->write_prepare($lei); - $lei->{opt}->{'in-format'} //= 'eml'; + $lei->{opt}->{'in-format'} //= 'eml' if $lei->{opt}->{stdin}; # maybe it's a non-email (code) blob from a coderepo my $git_dirs = $lei->{opt}->{'git-dir'} //= []; if ($lei->{opt}->{cwd} // 1) { @@ -263,7 +255,7 @@ sub lei_rediff { if ($lxs->remotes) { require PublicInbox::LeiRemote; $lei->{curl} //= which('curl') or return - $lei->fail('curl needed for', $lxs->remotes); + $lei->fail('curl needed for '.join(', ',$lxs->remotes)); } $lei->ale->refresh_externals($lxs, $lei); my $self = bless { @@ -274,10 +266,7 @@ sub lei_rediff { my $isatty = -t $lei->{1}; $lei->{opt}->{color} //= $isatty; $lei->start_pager if $isatty; - my ($op_c, $ops) = $lei->workers_start($self, 1); - $lei->{wq1} = $self; - net_merge_all_done($self) unless $lei->{auth}; - $lei->wait_wq_events($op_c, $ops); + $lei->wq1_start($self); } sub ipc_atfork_child { @@ -298,7 +287,6 @@ sub ipc_atfork_child { $self->{gits} = [ map { PublicInbox::Git->new($lei->rel2abs($_)) } @{$self->{lei}->{opt}->{'git-dir'}} ]; - $lei->{env}->{'psgi.errors'} = $lei->{2}; # ugh... $lei->{env}->{TMPDIR} = $self->{rdtmp}->dirname; if (my $nr = ($lei->{opt}->{drq} || $lei->{opt}->{'dequote-only'})) { my $re = '\s*> ' x $nr; |