[PATCH] Fix detection of file modification when editing single messages
There was a recent discussion on the mutt-users list about the
difficulty of using scripts to edit single messages because mutt
would report "message not modified" and reject the changes. This
turned out to be due to a problem with the way that modifications to
the temporary file were detected in the edit_one_message() function,
as I described in the message included below.
I have attached a patch that fixes this problem by using the same
file-modification-detection technique used elsewhere in mutt, in the
mutt_edit_headers() and ci_send_message() functions. The patch also
improves the consistency of error reporting in that function.
The patch was made to mutt-1.5.16.
Regards,
Gary
----- Forwarded message from Gary Johnson <garyjohn@xxxxxxxxxxxxxxx> -----
From: Gary Johnson <garyjohn@xxxxxxxxxxxxxxx>
Subject: Re: changing the subject line of a thread
Date: Wed, 29 Aug 2007 08:57:37 -0700
To: mutt-users@xxxxxxxx
User-Agent: Mutt/1.5.16 (2007-06-09)
On 2007-08-29, Holger Weiss <lists@xxxxxxxxxx> wrote:
> * Kyle Wheeler <kyle-mutt@xxxxxxxxxxxxxx> [2007-08-28 13:58]:
> > On Tuesday, August 28 at 03:14 PM, quoth martin f krafft:
> > > So I wanted to change the subject line on all thread mails. First, I
> > > missed the "pass (Maildir) files of tagged messages to external
> > > command as *arguments*" command in mutt, so I had to create a new
> > > folder and put the files in there, then go to the shell and invoke
> > > sed. An alternative would have of course been to set $editor to the
> > > sed -i command, but I could not get this working. Even setting
> > > editor="sed -i -e '/./d'" just got me "message not modified".
> >
> > HEH. This *would* work, if you were on a much slower machine (or if
> > you just got really lucky). The way mutt determines whether a file is
> > modified is by comparing the mtime of the temp file it created to the
> > mtime of the temp file once the editor is done editing. The mtime is
> > stored in seconds. Sed, of course, executes in less than a second, so
> > the mtime is unchanged in all but the rarest of cases. It would work
> > if you'd piped it to a script like this:
> >
> > #!/bin/sh
> > sleep 1
> > sed -i -e '/./d' "$1"
> >
> > Because then the mtime would be guaranteed (more or less) to be
> > different from when mutt created the tmp file.
>
> I worked around the same problem in some $editor script by incrementing
> the mtime via touch(1) as I didn't want the script to sleep(1).
>
> I guess it would be nice if Mutt (optionally?) used the MD5 sum or
> something instead of the mtime to check whether a file is modified.
I was surprised by Kyle's comment because I thought mutt already did
this, so I looked in the code. It turns out that mutt _sometimes_
does this. In the mutt_edit_headers() and ci_send_message()
functions, mutt sets the mtime of the temporary file back one second
before invoking the editor so that even if the editing occurs
instantaneously, the mtime will be different after editing. Mutt
then checks the mtime after invoking the editor to see if the file
changed.
Oddly, mutt does not do this in the edit_one_message() function
which I think is the one being used in this case. I think this
should be fixed. If folks agree and unless someone else wants to go
for it, I can submit a patch.
Regards,
Gary
----- End forwarded message -----
--- editmsg.c.orig 2007-04-01 14:58:55.000000000 -0700
+++ editmsg.c 2007-08-29 22:27:15.000000000 -0700
@@ -91,8 +91,11 @@
goto bail;
}
- if (stat (tmp, &sb) == 0)
- mtime = sb.st_mtime;
+ if ((rc = stat (tmp, &sb)) == -1)
+ {
+ mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno));
+ goto bail;
+ }
/*
* 2002-09-05 me@xxxxxxxxxxx
@@ -109,6 +112,8 @@
goto bail;
}
+ mtime = mutt_decrease_mtime (tmp, &sb);
+
mutt_edit_file (NONULL(Editor), tmp);
if ((rc = stat (tmp, &sb)) == -1)