git send-email poast

This commit is contained in:
Jade Lovelace 2022-04-22 22:05:21 -07:00
parent f6444034c3
commit 06091bbbb3
6 changed files with 175 additions and 23 deletions

View file

@ -0,0 +1,131 @@
+++
date = "2022-04-22"
draft = false
path = "/blog/oh-no-git-send-email"
tags = ["git", "tools"]
title = "Oh no, `git send-email`"
+++
Say you have to contribute to some boomer project that doesn't believe in
GitHub or GitLab or Gitea or <...> which would allow for just pushing some
changes and filing a pull request. Instead, they want an *email*. Gross.
For those who are unfamiliar with the email-patch infrastructure, git is
*extremely* picky about emails being the exact format it likes and not getting
modified at all by the client. This means that in practice, you need to send
your patch emails using `git send-email` as your email client.
The patch-emailing features of git are some of its most infamous for poor
usability, which is saying something, because git as a whole is known for being
hard to use.
Theoretically, <https://git-send-email.io/> (by someone who made their own git
source hosting service that strangely uses emails to submit patches) will tell
you how to set it up. Well, except if `git send-email` has other ideas: it
would not send through my email provider for reasons that must have been a bug:
I seem to recall it was something to do with either a TLS or SMTP
implementation being broken.
I ended up needing to use a separate *Mail Transfer Agent* (SMTP-speak for
"SMTP client") and plumb it into git. For this, I used `msmtp`.
{% codesample(desc="`~/.msmtprc`") %}
# Used to identify which account you are using in the msmtp command line
account myaccountname
# Tunneled-TLS email configuration. Probably correct for most modern servers,
# but check your email provider documentation. This is correct for migadu.
host smtp.migadu.com
port 465
tls on
tls_starttls off
auth on
user user@example.com
# From address on the envelope. Probably your email, but not necessarily
# (note that this is distinct from the "from" address in the message body that
# will be shown to recipients. it needs to match the address subscribed to the
# mailing list)
from listsubscriber@example.com
# Use kwallet-query to get the password because kwallet does not support the
# freedesktop secrets protocol
# "mail" is the folder on the left hand side of the "Wallet Manager"
# and user@example.com is the name of the item
passwordeval kwallet-query -r user@example.com kdewallet -f mail
{% end %}
Then configure git (I keep this in `~/.gitconfig` as I don't really want to
check it in for spam reasons, whereas most of my git config is checked in and
stored at `~/.config/git/config`):
{% codesample(desc="`~/.gitconfig`") %}
[sendemail]
sendmailcmd = /usr/bin/msmtp
smtpserveroption = -a
smtpserveroption = myaccountname
confirm = always
{% end %}
Finally, you can send an email:
```
/tmp/nya » git init
Initialized empty Git repository in /tmp/nya/.git/
/tmp/nya - [main] » echo nyaa > README.md
/tmp/nya - [main●] » git add -A
/tmp/nya - [main●] » git commit -m 'initial commit'
[main (root-commit) 5e2e44d] initial commit
1 file changed, 1 insertion(+)
create mode 100644 README.md
/tmp/nya - [main] » echo nyaaaaaaaaaaaaaaaaaaaaa >> README.md
/tmp/nya - [main●] » git commit -am 'more nya'
[main 3df1f2d] more nya
1 file changed, 1 insertion(+)
# NOTE: you probably want to use --compose to write a message to include with
# your patch. You can also use --dry-run to do a dry run.
/tmp/nya - [main] » git send-email --to='somepoorsoul@example.com' --from=message-from@example.com HEAD^
/tmp/jade/jKCO7nnORw/0001-more-nya.patch
(mbox) Adding cc: Jade Lovelace <commitauthor@example.com> from line 'From: Jade Lovelace <commitauthor@example.com>'
From: message-from@example.com
To: somepoorsoul@example.com
Cc: Jade Lovelace <commitauthor@example.com>
Subject: [PATCH] more nya
Date: Fri, 22 Apr 2022 20:45:30 -0700
Message-Id: <20220423034529.3057172-1-message-from@example.com>
X-Mailer: git-send-email 2.35.2
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): y
OK. Log says:
Sendmail: /usr/bin/msmtp -a message-from@example.com -i somepoorsoul@example.com commitauthor@example.com
From: message-from@example.com
To: somepoorsoul@example.com
Cc: Jade Lovelace <commitauthor@example.com>
Subject: [PATCH] more nya
Date: Fri, 22 Apr 2022 20:45:30 -0700
Message-Id: <20220423034529.3057172-1-message-from@example.com>
X-Mailer: git-send-email 2.35.2
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Result: OK
```
And, yes, it was received:
{% image(name="received.png", colocated=true) %}
Screenshot of the email sent by git in an email client.
It shows the patch as you'd see with the output of format-patch.
{% end %}
See? That was ~~sooooo easy~~ very hard for no reason.

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -7,7 +7,7 @@
{% endif %}
<article class="homepage-article" typeof="BlogPosting" resource="{{ page.permalink | safe }}">
<a class="homepage-link" href="{{ page.permalink | safe }}">
<h2 property="headline">{{ page.title }}</h2>
<h2 property="headline">{{ page.title | markdown(inline=true) | safe }}</h2>
</a>
<div class="detail">
<span property="datePublished"
@ -21,4 +21,4 @@
{% if config.extra.debug and config.mode == "Serve" %}
<pre><code>{{ __tera_context | escape | safe }}</code></pre>
{% endif %}
{% endblock content %}
{% endblock content %}

View file

@ -0,0 +1,32 @@
{%- import "macros/colocated_asset.html" as colocated_asset -%}
{%- macro image(name, alt, colocated, height) -%}
{%- set name_sanitized = name | replace(from=".", to="-") | replace(from="/", to="-") -%}
{%- set image_id = "image" ~ name_sanitized -%}
{%- if colocated == true -%}
{%- set image_path = colocated_asset::colocated_asset(path=name) -%}
{%- set image_url = name -%}
{%- else -%}
{%- set image_path = "/static/images/" ~ name -%}
{%- set image_url = get_url(path=image_path) -%}
{%- endif -%}
{%- set image = resize_image(path=image_path, width=800, height=height, op="fit") -%}
<div class="image">
<a href="{{ image_url }}">
<img src="{{ image.url }}"
alt="{{ alt }}"
title="{{ alt }}"
{% if label %}
aria-describedby="{{ image_id }}"
{% endif %}
>
</a>
{% if label %}
<span class="image-label" id="{{ image_id }}">
{{ label }}
</span>
{% endif %}
</div>
{%- endmacro image -%}

View file

@ -18,7 +18,7 @@
{% block content %}
<div class="post" typeof="BlogPosting">
<header class="page-header">
<h1 property="headline">{{ page.title }}</h1>
<h1 property="headline">{{ page.title | markdown(inline=true) | safe }}</h1>
{% if not page.extra.isPage %}
<div class="detail page-detail">

View file

@ -1,20 +1,9 @@
{% set name_sanitized = name | replace(from=".", to="-") | replace(from="/", to="-") %}
{% set image_id = "image" ~ name_sanitized %}
{% set alt = alt | default(value=body) %}
{% set height = height | default(value=600) %}
<div class="image">
<a href="{{ get_url(path="images/" ~ name) }}">
<img src="{{ resize_image(path="../static/images/" ~ name, width=800, height=height, op="fit") }}"
alt="{{ alt }}"
title="{{ alt }}"
{% if label %}
aria-describedby="{{ image_id }}"
{% endif %}
>
</a>
{% if label %}
<span class="image-label" id="{{ image_id }}">
{{ label }}
</span>
{% endif %}
</div>
{%- import "macros/image.html" as image -%}
{{ image::image(
name=name,
colocated=colocated | default(value=false),
alt=alt | default(value=body),
height=height | default(value=600)
) }}