From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 0419D1FA12 for ; Tue, 13 Apr 2021 10:54:47 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 5/5] lei: add "lei up" to complement "lei q --save" Date: Tue, 13 Apr 2021 10:54:46 +0000 Message-Id: <20210413105446.7245-6-e@80x24.org> In-Reply-To: <20210413105446.7245-1-e@80x24.org> References: <20210413105446.7245-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: The command isn't finalized, yet, but it's intended to update an existing saved search. --- MANIFEST | 1 + lib/PublicInbox/LEI.pm | 2 ++ lib/PublicInbox/LeiQuery.pm | 2 +- lib/PublicInbox/LeiSavedSearch.pm | 24 ++++++++++------ lib/PublicInbox/LeiToMail.pm | 12 ++++---- lib/PublicInbox/LeiUp.pm | 46 +++++++++++++++++++++++++++++++ t/lei-q-save.t | 17 ++++++++++-- 7 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 lib/PublicInbox/LeiUp.pm diff --git a/MANIFEST b/MANIFEST index 20615abc..1b7d16ee 100644 --- a/MANIFEST +++ b/MANIFEST @@ -208,6 +208,7 @@ lib/PublicInbox/LeiStoreErr.pm lib/PublicInbox/LeiSucks.pm lib/PublicInbox/LeiTag.pm lib/PublicInbox/LeiToMail.pm +lib/PublicInbox/LeiUp.pm lib/PublicInbox/LeiXSearch.pm lib/PublicInbox/Linkify.pm lib/PublicInbox/Listener.pm diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm index 7292d0f2..4b87c104 100644 --- a/lib/PublicInbox/LEI.pm +++ b/lib/PublicInbox/LEI.pm @@ -135,6 +135,8 @@ our %CMD = ( # sorted in order of importance/use: sort|s=s reverse|r offset=i pretty jobs|j=s globoff|g augment|a import-before! lock=s@ rsyncable alert=s@ mua=s verbose|v+), @c_opt, opt_dash('limit|n=i', '[0-9]+') ], +'up' => [ 'SEARCH_TERMS...', 'update saved search', + qw(jobs|j=s lock=s@ alert=s@ mua=s verbose|v+), @c_opt ], 'blob' => [ 'OID', 'show a git blob, reconstructing from mail if necessary', qw(git-dir=s@ cwd! verbose|v+ mail! oid-a|A=s path-a|a=s path-b|b=s), diff --git a/lib/PublicInbox/LeiQuery.pm b/lib/PublicInbox/LeiQuery.pm index 8bca1020..7456f7f9 100644 --- a/lib/PublicInbox/LeiQuery.pm +++ b/lib/PublicInbox/LeiQuery.pm @@ -12,7 +12,7 @@ sub prep_ext { # externals_each callback $lxs->prepare_external($loc) unless $exclude->{$loc}; } -sub _start_query { +sub _start_query { # used by "lei q" and "lei up" my ($self) = @_; PublicInbox::LeiOverview->new($self) or return; my $opt = $self->{opt}; diff --git a/lib/PublicInbox/LeiSavedSearch.pm b/lib/PublicInbox/LeiSavedSearch.pm index ab9f393b..815008fd 100644 --- a/lib/PublicInbox/LeiSavedSearch.pm +++ b/lib/PublicInbox/LeiSavedSearch.pm @@ -17,18 +17,12 @@ use PublicInbox::Hval qw(to_filename); sub new { my ($cls, $lei, $dir) = @_; my $self = bless { ale => $lei->ale, -cfg => {} }, $cls; - if (defined $dir) { # updating existing saved search + if (defined $dir) { # updating existing saved search via "lei up" my $f = $self->{'-f'} = "$dir/lei.saved-search"; -f $f && -r _ or return $lei->fail("$f non-existent or unreadable"); $self->{-cfg} = PublicInbox::Config::git_config_dump($f); - my $q = $lei->{mset_opt}->{q_raw} = $self->{-cfg}->{'lei.q'} // - return $lei->fail("lei.q unset in $f"); - my $lse = $lei->{lse} // die 'BUG: {lse} missing'; - $lei->{mset_opt}->{qstr} = ref($q) ? - $lse->query_argv_to_string($lse->git, $q) : - $lse->query_approxidate($lse->git, $q); - } else { # new saved search + } else { # new saved search "lei q --save" my $saved_dir = $lei->store_path . '/../saved-searches/'; my (@name) = ($lei->{ovv}->{dst} =~ m{([\w\-\.]+)/*\z}); push @name, to_filename($lei->{mset_opt}->{qstr}); @@ -42,6 +36,20 @@ sub new { } else { cfg_set($self, 'lei.q', $q); } + my $fmt = $lei->{opt}->{'format'}; + cfg_set($self, 'lei.q.format', $fmt) if defined $fmt; + cfg_set($self, 'lei.q.output', $lei->{opt}->{output}); + for my $k (qw(only include exclude)) { + my $ary = $lei->{opt}->{$k} // next; + for my $x (@$ary) { + cfg_set($self, '--add', "lei.q.$k", $x); + } + } + for my $k (qw(external local remote import-remote + import-before threads)) { + my $val = $lei->{opt}->{$k} // next; + cfg_set($self, "lei.q.$k", $val); + } } bless $self->{-cfg}, 'PublicInbox::Config'; $self->{lock_path} = "$self->{-f}.flock"; diff --git a/lib/PublicInbox/LeiToMail.pm b/lib/PublicInbox/LeiToMail.pm index bd2b714a..4ebaf8f3 100644 --- a/lib/PublicInbox/LeiToMail.pm +++ b/lib/PublicInbox/LeiToMail.pm @@ -349,11 +349,13 @@ sub new { die "bad mail --format=$fmt\n"; } $self->{dst} = $dst; - my $dd_cls = 'PublicInbox::'. - ($lei->{opt}->{save} ? 'LeiSavedSearch' : 'LeiDedupe'); - eval "require $dd_cls"; - die "$dd_cls: $@" if $@; - $lei->{dedupe} = $dd_cls->new($lei); + $lei->{dedupe} = $lei->{lss} // do { + my $dd_cls = 'PublicInbox::'. + ($lei->{opt}->{save} ? 'LeiSavedSearch' : 'LeiDedupe'); + eval "require $dd_cls"; + die "$dd_cls: $@" if $@; + $dd_cls->new($lei); + }; $self; } diff --git a/lib/PublicInbox/LeiUp.pm b/lib/PublicInbox/LeiUp.pm new file mode 100644 index 00000000..386a7566 --- /dev/null +++ b/lib/PublicInbox/LeiUp.pm @@ -0,0 +1,46 @@ +# Copyright (C) 2021 all contributors +# License: AGPL-3.0+ + +# "lei up" - updates the result of "lei q --save" +package PublicInbox::LeiUp; +use strict; +use v5.10.1; +use PublicInbox::LeiSavedSearch; +use PublicInbox::LeiOverview; + +sub lei_up { + my ($lei, $dir) = @_; + $lei->{lse} = $lei->_lei_store(1)->search; + my $lss = PublicInbox::LeiSavedSearch->new($lei, $dir) or return; + my $mset_opt = $lei->{mset_opt} = { relevance => -2 }; + $mset_opt->{limit} = $lei->{opt}->{limit} // 10000; + my $q = $mset_opt->{q_raw} = $lss->{-cfg}->{'lei.q'} // + return $lei->fail("lei.q unset in $lss->{-f}"); + my $lse = $lei->{lse} // die 'BUG: {lse} missing'; + if (ref($q)) { + $mset_opt->{qstr} = $lse->query_argv_to_string($lse->git, $q); + } else { + $lse->query_approxidate($lse->git, $mset_opt->{qstr} = $q); + } + $lei->{opt}->{output} = $lss->{-cfg}->{'lei.q.output'} // + return $lei->fail("lei.q.output unset in $lss->{-f}"); + $lei->{opt}->{'format'} //= $lss->{-cfg}->{'lei.q.format'}; # optional + + my $to_avref = $lss->{-cfg}->can('_array'); + for my $k (qw(only include exclude)) { + my $v = $lss->{-cfg}->{"lei.q.$k"} // next; + $lei->{opt}->{$k} = $to_avref->($v); + } + for my $k (qw(external local remote + import-remote import-before threads)) { + my $v = $lss->{-cfg}->{"lei.q.$k"} // next; + $lei->{opt}->{$k} = $v; + } + $lei->{lss} = $lss; # for LeiOverview->new + my $lxs = $lei->lxs_prepare or return; + $lei->ale->refresh_externals($lxs); + $lei->{opt}->{save} = 1; + $lei->_start_query; +} + +1; diff --git a/t/lei-q-save.t b/t/lei-q-save.t index 56f7cb37..a6d579cf 100644 --- a/t/lei-q-save.t +++ b/t/lei-q-save.t @@ -2,11 +2,24 @@ # Copyright (C) 2021 all contributors # License: AGPL-3.0+ use strict; use v5.10.1; use PublicInbox::TestCommon; +my $doc1 = eml_load('t/plack-qp.eml'); +my $doc2 = eml_load('t/utf8.eml'); test_lei(sub { my $home = $ENV{HOME}; - lei_ok qw(import t/plack-qp.eml); - lei_ok qw(q --save z:0..), '-o', "$home/md/"; + lei_ok qw(import -q t/plack-qp.eml); + lei_ok qw(q -q --save z:0..), '-o', "$home/md/"; + my %before = map { $_ => 1 } glob("$home/md/cur/*"); + is_deeply(eml_load((keys %before)[0]), $doc1, 'doc1 matches'); + my @s = glob("$home/.local/share/lei/saved-searches/md-*"); is(scalar(@s), 1, 'got one saved search'); + + # ensure "lei up" works, since it compliments "lei q --save" + lei_ok qw(import t/utf8.eml); + lei_ok qw(up), $s[0]; + my %after = map { $_ => 1 } glob("$home/md/cur/*"); + is(delete $after{(keys(%before))[0]}, 1, 'original message kept'); + is(scalar(keys %after), 1, 'one new message added'); + is_deeply(eml_load((keys %after)[0]), $doc2, 'doc2 matches'); }); done_testing;