website/site/blog/2021-01-09-mutt-inline-patch-macro.md
2022-12-27 22:04:45 +01:00

75 lines
2.6 KiB
Markdown

# Mutt inline patch handling
Developers like to send diffs inline in emails. They do this, because it's fast
and easy to read through them, comment on them and also to apply them. Some
version control systems also take over the email text into the patch description
as well.
Up to now, my workflow was manual. I had to save the email somewhere, then open
a terminal, cd to the direcory the patch shall be applied in and call the patch
utility with the path to the saved email as argument.
No more.
This mutt macro takes the current visible email and copies it to a temporary
file (/tmp/mutt-patch.diff). Then it executes the portpatch.sh shell script. All
with one push on ctrl+s while looking at the email.
The macro must be written in one line and ^S can be entered with the keyboard
sequence ctrl+v ctrl+s:
<pre>
macro pager ^S "&lt;shell-escape&gt;rm -f /tmp/mutt-patch.diff&lt;enter&gt;&lt;copy-message&gt;/tmp/mutt-patch.diff&lt;enter&gt;&lt;enter-command&gt;echo 'Saved as /tmp/mutt-patch.diff'&lt;enter&gt;&lt;shell-escape&gt; ~/.mutt/scripts/portpatch.sh /tmp/mutt-patch.diff&lt;enter&gt;"
</pre>
The portpatch.sh script:
<pre>
#!/bin/sh
# needs converters/qprint
clear
echo '---------------------------------------------------------------------'
grep -E 'Subject: |^Index|^RCS|^diff --git|^file +|^[-+]{3} ' "${1}"
echo '---------------------------------------------------------------------'
printf "Apply patch on path [defaults to /usr/ports]? "
read -r _path
printf "Fix quoted-printable mangeled patch? [y/N]: "
read -r _qprint
case ${_qprint} in
[y|Y]) _catcmd="qprint -d"; ;;
*) _catcmd="cat"; ;;
esac
printf "Strip? [0]: "
read -r _strip
${_catcmd} "${1}" | doas patch -Ep${_strip:=0} -d ${_path:=/usr/ports}
cd ${_path} && ksh
</pre>
The script shows some relvant bits from the email patch that are handy
to determine on which path the patch shall be applied.
Next it allows the user to enter a different path. I mostly use /usr/ports, so
this is the default. Then the patch is applied and a ksh shell is opened for
further work.
Quitting the shell brings me back to mutt to work on the next email.
Sometimes someone sends a mangled patch encoded in quoted-printable. My script
allows to fix this with qprint.
Git diffs mostly need strip 1 to cut off the a/ b/ in front of the file path, so
the script is asking for that too. For most patches on ports@, the defaults are
fine and hitting enter 2 times works as intended.
*...and if everyone would generate patches from the /usr/ports root, it wouldn't
even be necessary to enter the path.*
This is quite friggin handy.