]> diplodocus.org Git - minc/commitdiff
Attempt to implement filtering from mh folder proposal.
authorEric Gillespie <epg@pretzelnet.org>
Wed, 10 Dec 2014 08:19:55 +0000 (00:19 -0800)
committerEric Gillespie <epg@pretzelnet.org>
Wed, 10 Dec 2014 08:19:55 +0000 (00:19 -0800)
Default is still to try to use Maildir, but $MAILDIR may be set to a +folder,
or +folder may be the first command-line argument.  Either way, any other
command-line arguments are passed as msgs list to mhpath, or use the default
of 'cur-last' (appropriate directly after inc(1)).

minc

diff --git a/minc b/minc
index eb282b3f0ca6da7be24c1b8cabb18d28543663be..99b39f4e1354e0cdc1e2ec812583b9c417093f38 100755 (executable)
--- a/minc
+++ b/minc
@@ -108,7 +108,6 @@ GetOptions(
            'r' => \$rebuild_dot_folders,
           ) or pod2usage();
 $help and pod2usage(-exitstatus=>0, -verbose=>1);
            'r' => \$rebuild_dot_folders,
           ) or pod2usage();
 $help and pod2usage(-exitstatus=>0, -verbose=>1);
-@ARGV <= 1 or pod2usage();
 }
 
 our $run = !$norun;
 }
 
 our $run = !$norun;
@@ -142,9 +141,6 @@ $COLUMNS ||= 80;
 if (not $HOME) {
     die("HOME environment variable must be set.\n");
 }
 if (not $HOME) {
     die("HOME environment variable must be set.\n");
 }
-if (not $MAILDIR) {
-    $MAILDIR = "$HOME/Maildir";
-}
 
 =head1 FILES
 
 
 =head1 FILES
 
@@ -423,17 +419,26 @@ sub lkopen_fcntl {
     die("failed to lock $fn: $!");
 }
 
     die("failed to lock $fn: $!");
 }
 
+my @filtered;
 sub store_message {
 sub store_message {
-    my $msg = shift;
+    my $inbox = shift;
+    my $msg = shift;            # rename $src_msg
     my $mhfolder = shift;
     my $mhfolder = shift;
-    my $msgnum;
+    my ($msgnum, $mhmsg);       # rename $dst_msg and $dst_msgpath
     my $try;
     my $try;
-    my $mhmsg;
 
     # We must do this even in -n mode because later steps fail without
     # it.  This should be harmless.
     mkfolder($mhfolder);
 
 
     # We must do this even in -n mode because later steps fail without
     # it.  This should be harmless.
     mkfolder($mhfolder);
 
+    if ("+$mhfolder" eq $inbox) {
+        # If @filtered is empty, this message already has the right number.
+        if (!($msgnum = shift(@filtered))) {
+            $msg =~ m|.*/(\d+)$|;
+            return $1;
+        }
+        $mhmsg = "$mh/$mhfolder/$msgnum";
+    } else {
     # This loop is a modified version of the maildir delivery algorithm.
     $msgnum = get_highest_msgnum($mhfolder);
     for ($try = 0; ; $try++) {
     # This loop is a modified version of the maildir delivery algorithm.
     $msgnum = get_highest_msgnum($mhfolder);
     for ($try = 0; ; $try++) {
@@ -480,20 +485,24 @@ sub store_message {
 
         # This algorithm is different; i don't think we need to sleep.
         #sleep(2);
 
         # This algorithm is different; i don't think we need to sleep.
         #sleep(2);
+
+        if ($run) {
+            # Mark each message as soon as we store it and bomb if that
+            # fails.  While it is slow, it is not safe to store multiple
+            # messages and then have a failure before marking some (or
+            # all).
+            if ($mhfolder ne 'SPAM') {
+                mark($mhfolder, $msgnum, 'unseen');
+            }
+        }
     }
     }
+    }
+    push(@filtered, $msg);
 
     if ($run) {
         if (not rename($msg, $mhmsg)) {
             die("rename($msg, $mhmsg): $!");
         }
 
     if ($run) {
         if (not rename($msg, $mhmsg)) {
             die("rename($msg, $mhmsg): $!");
         }
-
-        # Mark each message as soon as we store it and bomb if that
-        # fails.  While it is slow, it is not safe to store multiple
-        # messages and then have a failure before marking some (or
-        # all).
-        if ($mhfolder ne 'SPAM') {
-            mark($mhfolder, $msgnum, 'unseen');
-        }
     }
 
     return $msgnum;
     }
 
     return $msgnum;
@@ -635,6 +644,7 @@ sub scan_line {
 }
 
 sub filter_mail {
 }
 
 sub filter_mail {
+    my $inbox = shift;
     @_ or return ();
     my $msgcount = @_ - 2; # don't count . and ..
     my $len = length($msgcount);
     @_ or return ();
     my $msgcount = @_ - 2; # don't count . and ..
     my $len = length($msgcount);
@@ -646,10 +656,6 @@ sub filter_mail {
     my $msgnum;
     my %folders;
 
     my $msgnum;
     my %folders;
 
-    if (-f "$HOME/.minc") {
-        require "$HOME/.minc";
-    }
-
     # XXX lame names
     my $nf = int($COLUMNS * $SCAN_P_FOLDER);
     my $nm = int($COLUMNS * $SCAN_P_MESSAGE);
     # XXX lame names
     my $nf = int($COLUMNS * $SCAN_P_FOLDER);
     my $nm = int($COLUMNS * $SCAN_P_MESSAGE);
@@ -683,7 +689,7 @@ sub filter_mail {
 
         defined($mhfolder) or ($mhfolder = find_mh_folder($msg, $headers));
 
 
         defined($mhfolder) or ($mhfolder = find_mh_folder($msg, $headers));
 
-        $msgnum = store_message($msg, $mhfolder);
+        $msgnum = store_message($inbox, $msg, $mhfolder);
         $folders{$mhfolder}++;
 
         if ($tty) {
         $folders{$mhfolder}++;
 
         if ($tty) {
@@ -861,60 +867,41 @@ if (!caller()) {
 
     $rebuild_dot_folders and exit(create_dot_folders);
 
 
     $rebuild_dot_folders and exit(create_dot_folders);
 
-    my @files;
-    # XXX some options:
-    # a. take message numbers on stdin
-    # b. take full paths to messages on stdin
-    # c. take standard [msgs] list on command-line
-    # d. assume inc has just finished so cur points to start of new mail and
-    #    just do cur-last
-    # Hacked up b. here, but I'm not happy with it.  I'm renaming files that
-    # stay in inbox for no reason, and leaving gaping holes.  Any of the above
-    # approaches has those problems, and the solution is always the same:
-    # my @filtered;
-    # sub store_message {
-    #     my $msg = shift;        # rename $src_msg
-    #     my $mhfolder = shift;
-    #     my ($msgnum, $mhmsg);   # rename $dst_msg and $dst_msgpath
-    #     # ...
-    #     # XXX don't hard-code inbox
-    #     if ($mhfolder eq 'inbox') {
-    #         # If @filtered is empty, this message already has the right number.
-    #         $msgnum = shift(@filtered) || next;
-    #         $mhmsg = "$mh/$mhfolder/$msgnum";
-    #     } else {
-    #         # $msgnum =  get_highest_msgnum() and search
-    #         # XXX don't hard-code unseen
-    #         mark($mhfolder, $msgnum, 'unseen');
-    #     }
-    #     push(@filtered, $msg);
-    #     rename($msg, $mhmsg);
-    # }
-
-    # The above guess-code takes into account the problem below.
-
-    # XXX I just thought of a problem, but we might be able to get away with it
-    # anyway!  The problem is when mhpath has more message paths to output than
-    # fit in the pipe buffer, it blocks WHILE HOLDING THE SEQUENCE LOCK.
-    # If there's a message in there that stays in inbox, minc renames it, and
-    # tries to lock the sequence file, and we DEADLOCK.  However, if we do
-    # nothing with sequences at all for the inbox folder, I think everything
-    # just works!  inc has added everything to unseen already.  If we don't
-    # touch it, we have an unseen list that includes a bunch of messages that
-    # are gone, and the ones that stayed in inbox are already) included in that
-    # list!  The next inc (or any other sequence-writing operation) should elide
-    # the now-non-existent messages from unseen.  It just might work!
+    if (-f "$HOME/.minc") {
+        require "$HOME/.minc";
+    }
+
+    my $inbox;
+    if ($MAILDIR) {
+        $inbox = $MAILDIR;
+    } elsif (-d "$HOME/Maildir") {
+        $inbox = "$HOME/Maildir";
+    }
 
     if (@ARGV > 0) {
 
     if (@ARGV > 0) {
-        # XXX if sticking with this approach, reject arg other than '-'
-        chomp(@files = <>);
-        @files > 0 || exit 0;
+        $inbox = shift(@ARGV);
+    }
+
+    my @files;
+    if (substr($inbox, 0, 1) eq '+') {
+        my @msgs = @ARGV;
+        if (!@msgs) {
+            @msgs = ('cur-last');
+        }
+        open(my $fh, '-|', 'mhpath', @msgs) or die("open(mhpath|): $!");
+        chomp(@files = <$fh>);
+        if (!close($fh)) {
+            $! == 0 or die("open(mhpath|): $!");
+            die("mhpath exited $?");
+        }
+        @files > 0 or exit 0;
     } else {
     } else {
-        chdir("$MAILDIR/new") or die("chdir($MAILDIR/new): $!");
+        @ARGV == 0 or pod2usage();
+        chdir("$inbox/new") or die("chdir($inbox/new): $!");
         @files = getfiles('.');
     }
 
         @files = getfiles('.');
     }
 
-    my %folders = filter_mail(map { $_->[1] }
+    my %folders = filter_mail($inbox, map { $_->[1] }
                 sort { $a->[0] <=> $b->[0] }
                 map {
                     if (not ($st = stat($_))) {
                 sort { $a->[0] <=> $b->[0] }
                 map {
                     if (not ($st = stat($_))) {