]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/LeiExportKw.pm
lei: use RENAME_NOREPLACE on Linux 3.15+
[public-inbox.git] / lib / PublicInbox / LeiExportKw.pm
index 8c5fbc13079eedc83445df7382a3432a3f268ec6..ceeef7f21d54e41ab90a868ed5f1b93ffbea4b7d 100644 (file)
@@ -7,6 +7,7 @@ use strict;
 use v5.10.1;
 use parent qw(PublicInbox::IPC PublicInbox::LeiInput);
 use Errno qw(EEXIST ENOENT);
+use PublicInbox::Syscall qw(rename_noreplace);
 
 sub export_kw_md { # LeiMailSync->each_src callback
        my ($oidbin, $id, $self, $mdir) = @_;
@@ -30,30 +31,22 @@ sub export_kw_md { # LeiMailSync->each_src callback
        my $lei = $self->{lei};
        for my $d (@try) {
                my $src = "$mdir/$d/$$id";
-
-               # we use link(2) + unlink(2) since rename(2) may
-               # inadvertently clobber if the "uniquefilename" part wasn't
-               # actually unique.
-               if (link($src, $dst)) { # success
-                       # unlink(2) may ENOENT from parallel invocation,
-                       # ignore it, but not other serious errors
-                       if (!unlink($src) and $! != ENOENT) {
-                               $lei->child_error(1, "E: unlink($src): $!");
-                       }
+               if (rename_noreplace($src, $dst)) { # success
                        $self->{lms}->mv_src("maildir:$mdir",
                                                $oidbin, $id, $bn);
-                       return; # success anyways if link(2) worked
+                       return; # success
                } elsif ($! == EEXIST) { # lost race with lei/store?
                        return;
                } elsif ($! != ENOENT) {
-                       $lei->child_error(1, "E: link($src -> $dst): $!");
+                       $lei->child_error(1,
+                               "E: rename_noreplace($src -> $dst): $!");
                } # else loop @try
        }
        my $e = $!;
        # both tries failed
        my $oidhex = unpack('H*', $oidbin);
        my $src = "$mdir/{".join(',', @try)."}/$$id";
-       $lei->child_error(1, "link($src -> $dst) ($oidhex): $e");
+       $lei->child_error(1, "rename_noreplace($src -> $dst) ($oidhex): $e");
        for (@try) { return if -e "$mdir/$_/$$id" }
        $self->{lms}->clear_src("maildir:$mdir", $id);
 }
@@ -92,9 +85,7 @@ EOM
                $lms->group2folders($lei, $all, \@folders) or return;
                @folders = grep(/\A(?:maildir|imaps?):/i, @folders);
        } else {
-               my $err = $lms->arg2folder($lei, \@folders);
-               $lei->qerr(@{$err->{qerr}}) if $err->{qerr};
-               return $lei->fail($err->{fail}) if $err->{fail};
+               $lms->arg2folder($lei, \@folders); # may die
        }
        $lms->lms_pause;
        my $self = bless { lse => $sto->search, lms => $lms }, __PACKAGE__;
@@ -129,9 +120,13 @@ EOM
 
 sub _complete_export_kw {
        my ($lei, @argv) = @_;
-       my $lms = $lei->lms or return;
+       my $lms = $lei->lms or return ();
        my $match_cb = $lei->complete_url_prepare(\@argv);
-       map { $match_cb->($_) } $lms->folders;
+       # filter-out read-only sources:
+       my @k = grep(!m!(?://;AUTH=ANONYMOUS\@|\A(?:nntps?|s?news)://)!,
+                       $lms->folders($argv[-1] // undef, 1));
+       my @m = map { $match_cb->($_) } @k;
+       @m ? @m : @k;
 }
 
 no warnings 'once';