This is mostly a proof of concept/RFC patch. The idea is for
git-send-email to store the message-ids it generates, along with the
Subject and Date headers of the message. When prompting for which
Message-ID should be used in In-Reply-To, display a list of recent
emails (identifed using the Date/Subject pairs; the message-ids
themselves are not for human consumption). Choosing from that list
will then use the corresponding message-id; otherwise, the behaviour
is as usual.

When composing v2 or v3 of a patch or patch series, this avoids the
need to get one's MUA to display the Message-ID of the earlier email
(which is cumbersome in some MUAs) and then copy-paste that.

If this idea is accepted, I'm certain I'll get to use the feature
immediately, since the patch is not quite ready for inclusion :-)

Signed-off-by: Rasmus Villemoes <r...@rasmusvillemoes.dk>
---
 git-send-email.perl | 101 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 96 insertions(+), 5 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index f608d9b..2e3685c 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -26,6 +26,7 @@ use Data::Dumper;
 use Term::ANSIColor;
 use File::Temp qw/ tempdir tempfile /;
 use File::Spec::Functions qw(catfile);
+use Date::Parse;
 use Error qw(:try);
 use Git;
 
@@ -203,6 +204,7 @@ my ($validate, $confirm);
 my (@suppress_cc);
 my ($auto_8bit_encoding);
 my ($compose_encoding);
+my ($msgid_cache_file, $msgid_maxprompt);
 
 my ($debug_net_smtp) = 0;              # Net::SMTP, see send_message()
 
@@ -214,7 +216,7 @@ my %config_bool_settings = (
     "signedoffcc" => [\$signed_off_by_cc, undef],      # Deprecated
     "validate" => [\$validate, 1],
     "multiedit" => [\$multiedit, undef],
-    "annotate" => [\$annotate, undef]
+    "annotate" => [\$annotate, undef],
 );
 
 my %config_settings = (
@@ -237,6 +239,7 @@ my %config_settings = (
     "from" => \$sender,
     "assume8bitencoding" => \$auto_8bit_encoding,
     "composeencoding" => \$compose_encoding,
+    "msgidcachefile" => \$msgid_cache_file,
 );
 
 my %config_path_settings = (
@@ -311,6 +314,7 @@ my $rc = GetOptions("h" => \$help,
                    "8bit-encoding=s" => \$auto_8bit_encoding,
                    "compose-encoding=s" => \$compose_encoding,
                    "force" => \$force,
+                   "msgid-cache-file=s" => \$msgid_cache_file,
         );
 
 usage() if $help;
@@ -784,10 +788,31 @@ sub expand_one_alias {
 @bcclist = validate_address_list(sanitize_address_list(@bcclist));
 
 if ($thread && !defined $initial_reply_to) {
-       $initial_reply_to = ask(
-               "Message-ID to be used as In-Reply-To for the first email (if 
any)? ",
-               default => "",
-               valid_re => qr/\@.*\./, confirm_only => 1);
+       my @choices;
+       if ($msgid_cache_file) {
+               @choices = msgid_cache_getmatches();
+       }
+       if (@choices) {
+               my $prompt = '';
+               my $i = 0;
+               $prompt .= sprintf "(%d) [%s] %s\n", $i++, $_->{date}, 
$_->{subject}
+                   for (@choices);
+               $prompt .= sprintf "Answer 0-%d to use the Message-ID of one of 
the above\n", $#choices;
+               $prompt .= "Message-ID to be used as In-Reply-To for the first 
email (if any)? ";
+               $initial_reply_to = 
+                   ask($prompt,
+                       default => "",
+                       valid_re => qr/\@.*\.|^[0-9]+$/, confirm_only => 1);
+               if ($initial_reply_to =~ /^[0-9]+$/ && $initial_reply_to < 
@choices) {
+                       $initial_reply_to = $choices[$initial_reply_to]{id};
+               }
+       }
+       else {
+               $initial_reply_to = 
+                   ask("Message-ID to be used as In-Reply-To for the first 
email (if any)? ",
+                       default => "",
+                       valid_re => qr/\@.*\./, confirm_only => 1);
+       }
 }
 if (defined $initial_reply_to) {
        $initial_reply_to =~ s/^\s*<?//;
@@ -1282,6 +1307,8 @@ X-Mailer: git-send-email $gitversion
                }
        }
 
+       msgid_cache_this($message_id, $subject, $date) if ($msgid_cache_file && 
!$dry_run);
+
        return 1;
 }
 
@@ -1508,6 +1535,8 @@ sub cleanup_compose_files {
 
 $smtp->quit if $smtp;
 
+msgid_cache_write() if $msgid_cache_file;
+
 sub unique_email_list {
        my %seen;
        my @emails;
@@ -1556,3 +1585,65 @@ sub body_or_subject_has_nonascii {
        }
        return 0;
 }
+
+my @msgid_new_entries;
+
+# For now, use a simple tab-separated format:
+#
+#    $id\t$date\t$subject\n
+sub msgid_cache_read {
+       my $fh;
+       my $line;
+       my @entries;
+       if (not open ($fh, '<', $msgid_cache_file)) {
+               # A non-existing cache file is ok, but should we warn if errno 
!= ENOENT?
+               return ();
+       }
+       while ($line = <$fh>) {
+               chomp($line);
+               my ($id, $date, $subject) = split /\t/, $line;
+               my $epoch = str2time($date);
+               push @entries, {id=>$id, date=>$date, epoch=>$epoch, 
subject=>$subject};
+       }
+       close($fh);
+       return @entries;
+}
+sub msgid_cache_write {
+       my $fh;
+       if (not open($fh, '>>', $msgid_cache_file)) {
+           warn "cannot open $msgid_cache_file for appending: $!";
+           return;
+       }
+       printf $fh "%s\t%s\t%s\n", $_->{id}, $_->{date}, $_->{subject} for 
(@msgid_new_entries);
+       close($fh);
+}
+# Return an array of cached message-ids, ordered by "relevance". It
+# might make sense to take the Subject of the new mail as an extra
+# argument and do some kind of fuzzy matching against the old
+# subjects, but for now "more relevant" simply means "newer".
+sub msgid_cache_getmatches {
+       my ($maxentries) = @_;
+       $maxentries //= 10;
+       my @list = msgid_cache_read();
+       @list = sort {$b->{epoch} <=> $a->{epoch}} @list;
+       @list = @list[0 .. $maxentries-1] if (@list > $maxentries);
+       return @list;
+}
+
+sub msgid_cache_this {
+       my $msgid = shift;
+       my $subject = shift;
+       my $date = shift;
+       # Make sure there are no tabs which will confuse us, and save
+       # some valuable horizontal real-estate by removing redundant
+       # whitespace.
+       if ($subject) {
+               $subject =~ s/^\s+|\s+$//g;
+               $subject =~ s/\s+/ /g;
+       }
+       # Replace undef or the empty string by an actual string. Nobody uses 
"0" as the subject...
+       $subject ||= '(none)';
+       $date //= format_2822_time(time());
+       $date =~ s/\s+/ /g;
+       push @msgid_new_entries, {id => $msgid, subject => $subject, date => 
$date};
+}
-- 
1.8.4.rc3.2.gb900fc8

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to