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 09DFB1F9E5 for ; Fri, 23 Apr 2021 01:45:15 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 2/2] lei up: support symlinked pathnames Date: Fri, 23 Apr 2021 01:45:13 +0000 Message-Id: <20210423014513.73103-3-e@80x24.org> In-Reply-To: <20210423014513.73103-1-e@80x24.org> References: <20210423014513.73103-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: On my default FreeBSD 11.x system, "/home" is a symlink to "/usr/home", which causes "lei up" path resolution to fail when I use outputs in $HOME. Fall back to a slow path of globbing and matching pathnames based on st_ino+st_dev. --- lib/PublicInbox/LeiSavedSearch.pm | 40 ++++++++++++++++++++++++------- t/lei-q-save.t | 6 +++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/lib/PublicInbox/LeiSavedSearch.pm b/lib/PublicInbox/LeiSavedSearch.pm index ed217cf2..af864a50 100644 --- a/lib/PublicInbox/LeiSavedSearch.pm +++ b/lib/PublicInbox/LeiSavedSearch.pm @@ -13,6 +13,7 @@ use PublicInbox::Spawn qw(run_die); use PublicInbox::ContentHash qw(git_sha); use PublicInbox::MID qw(mids_for_index); use Digest::SHA qw(sha256_hex); +my $LOCAL_PFX = qr!\A(?:maildir|mh|mbox.+|mmdf):!i; # TODO: put in LeiToMail? # move this to PublicInbox::Config if other things use it: my %cquote = ("\n" => '\\n', "\t" => '\\t', "\b" => '\\b'); @@ -27,27 +28,50 @@ sub BOOL_FIELDS () { qw(external local remote import-remote import-before threads) } -sub lss_dir_for ($$) { - my ($lei, $dstref) = @_; +sub lss_dir_for ($$;$) { + my ($lei, $dstref, $on_fs) = @_; my @n; if ($$dstref =~ m,\Aimaps?://,i) { # already canonicalized require PublicInbox::URIimap; my $uri = PublicInbox::URIimap->new($$dstref)->canonical; $$dstref = $$uri; @n = ($uri->mailbox); - } else { # basename + } else { + # can't use Cwd::abs_path since dirname($$dstref) may not exist $$dstref = $lei->rel2abs($$dstref); + # Maildirs have trailing '/' internally $$dstref .= '/' if -d $$dstref; $$dstref =~ tr!/!/!s; - @n = ($$dstref =~ m{([^/]+)/*\z}); + @n = ($$dstref =~ m{([^/]+)/*\z}); # basename } push @n, sha256_hex($$dstref); - $lei->share_path . '/saved-searches/' . join('-', @n); + my $lss_dir = $lei->share_path . '/saved-searches/'; + my $d = $lss_dir . join('-', @n); + + # fall-back to looking up by st_ino + st_dev in case we're in + # a symlinked or bind-mounted path + if ($on_fs && !-d $d && -e $$dstref) { + my @cur = stat(_); + my $want = pack('dd', @cur[1,0]); # st_ino + st_dev + my ($c, $o, @st); + for my $g ("$n[0]-*", '*') { + my @maybe = glob("$lss_dir$g/lei.saved-search"); + for my $f (@maybe) { + $c = PublicInbox::Config->git_config_dump($f); + $o = $c->{'lei.q.output'} // next; + $o =~ s!$LOCAL_PFX!! or next; + @st = stat($o) or next; + next if pack('dd', @st[1,0]) ne $want; + $f =~ m!\A(.+?)/[^/]+\z! and return $1; + } + } + } + $d; } sub list { my ($lei, $pfx) = @_; - my $lss_dir = $lei->share_path.'/saved-searches/'; + my $lss_dir = $lei->share_path.'/saved-searches'; return () unless -d $lss_dir; # TODO: persist the cache? Use another format? my $f = $lei->cache_dir."/saved-tmp.$$.".time.'.config'; @@ -61,7 +85,7 @@ sub list { unlink($f); my $out = $cfg->get_all('lei.q.output') or return (); map {; - s!\A(?:maildir|mh|mbox.+|mmdf):!!i; + s!$LOCAL_PFX!!; $_; } @$out } @@ -221,7 +245,7 @@ sub cloneurl { [] } sub output2lssdir { my ($self, $lei, $dir_ref, $fn_ref) = @_; my $dst = $$dir_ref; # imap://$MAILBOX, /path/to/maildir, /path/to/mbox - my $dir = lss_dir_for($lei, \$dst); + my $dir = lss_dir_for($lei, \$dst, 1); my $f = "$dir/lei.saved-search"; if (-f $f && -r _) { $self->{-cfg} = PublicInbox::Config->git_config_dump($f); diff --git a/t/lei-q-save.t b/t/lei-q-save.t index 26ea5cb8..170f7ce5 100644 --- a/t/lei-q-save.t +++ b/t/lei-q-save.t @@ -158,5 +158,11 @@ test_lei(sub { lei_ok('up', $o); @m = glob("$o/cur/*"); is(scalar(@m), 2, 'got 2nd result due to different OID'); + + SKIP: { + symlink($o, "$home/ln -s") or + skip "symlinks not supported in $home?: $!", 1; + lei_ok('up', "$home/ln -s"); + }; }); done_testing;