JPPA Annotated and Explained (version -1)
Note: This post covers JPPA version -1. It hasn’t been updated yet for the new version -1.1. That version only has minor changes compared to the previous version.
In my previous post, I wrote about why I chose to create Jason’s Public-inbox Posting Agreement. In this post, I’m going to go through each part of the agreement and explain why I wrote it the way I did. Specifically, this post will break down the first version of the agreement. In the future, if I update the agreement, I might make another blog post breaking down the new version.
Hello! Your message was received, but there’s something that I need you to do before I make it public. I want to make sure that: • anyone can legally use the patches posted here and that • anyone can legally mirror this public-inbox.
People should be suspicious of legal agreements. That sentence explains why I’m asking people to agree to JPPA so that they can judge for themselves whether or not I’m trying to pull one over on them.
If you want your message be put into this public-inbox, then you need to agree to the following:
That sentence gives me the opportunity to indent the main portion of the agreement. Indenting the main portion of the agreement makes the important parts of this message stand out.
Definitions: “GPLed” — available under some version of the GNU General Public License. See <https://www.gnu.org/licenses/gpl.html>. “MIT Licensed” — available under some version of the MIT License. See <https://fedoraproject.org/wiki/Licensing:MIT>.
These two definitions aren’t necessary, but I included them for clarity. I only use them in the examples for number 1 bullet 1. That bullet point is the part of the agreement that’s most difficult to understand.
“proposed addition” — data that indicates that a file should be created or that something should be added to a file. “proposed removal” — data that indicates that a file should be deleted or that something should be removed from a file. “proposed change” — a proposed addition or proposed removal.
Technically, I didn’t need to define proposed removal or proposed change. “Proposed removal” only gets used in the definition for “proposed change”, and “proposed change” only gets used in the definition for “patch”. I chose to define “patch” in terms of proposed changes because I felt like it made the agreement easier to understand.
“patch” — a set of proposed changes optionally with extra data. The extra data might include a commit message, the names of any authors, file attributes or the version of Git used. “patch metadata” — the parts of a patch that aren’t proposed changes and aren’t quoting files to give context to proposed changes.
I defined these two terms carefully. I wanted there to be a clear distinction between these different parts of a patch:
- the parts that the contributor has to release as 🅭🄍 (the patch metadata),
- the parts that the contributor has to release under whatever terms the repo indicates (the proposed additions) and
- the parts that were potentially created by someone else (the proposed removals and the parts that are quoting files to give context).
Additionally, I tried to define “proposed addition”, “proposed removal”, “proposed change”, “patch” and “patch metadata” in a technology neutral way. I don’t want JPPA to be an obstacle if I ever decide to experiment with a new VCS or patch format.
“repo” — repository.
This definition is probably unnecessary. When I was considering including this definition, I did a Web search for “repo definition” and got information about repurchase agreements. That’s the only reason I chose to keep this definition.
1. Any patches submitted to this address will be available under appropriate legal terms. Specifically: • The legal terms that apply to a submitted patch’s proposed additions will be the legal terms that the repo indicates after the patch has been applied. Examples:
This is the trickiest part right here. The goal of this part is to make sure that the inbound=outbound rule applies. In one draft, this provision applied to entire hunks rather than just proposed additions. I changed it when I considered hunks like this one:
Most of that hunk is lines that were created by someone else. I shouldn’t ask contributors to apply legal terms to something that they didn’t create, so I changed number 1 bullet 1 to only apply to proposed additions. I also made sure that JPPA doesn’t explicitly mention what the legal terms for proposed removals and context lines should be. The thought is that the repo itself should have already provided legal terms for those lines.
You may have noticed that I keep using the phrase “legal terms” instead of “license”. This in on purpose. Many of the files in my projects are dedicated to the public domain using 🅭🄍 which isn’t a license. Additionally, many software licenses are more than just licenses. In the FOSS world, the term “license” is generally understood to mean “copyright license”, but some FOSS licenses contain patent licenses. Even if the term “FOSS license” did refer to both copyright and patent licenses, it’s a stretch to say that it refers to contracts as well. In fact, the free software definition discourages the use of contracts despite the fact that the GNU Project’s own GPL is a contract.
[…]after the patch has been applied. Examples: ◦ Repo A indicates that all of its files are GPLed. A patch for repo A is submitted. The patch doesn’t mention anything about copying information. In this situation, all of the patch’s proposed additions are GPLed. ◦ Repo B indicates that all of its files are GPLed. A patch for repo B is submitted. Applying the patch changes repo B’s copying information. It makes repo B indicate that every file, except for foo.txt, is GPLed. It also makes repo B indicate that foo.txt is MIT Licensed. In this situation, the patch’s proposed additions to foo.txt would be MIT Licensed. Any other proposed additions would be GPLed. ◦ Repo C indicates that everything in foo.c is GPLed except for the bar() function. Repo C also indicates that bar() is MIT Licensed. A patch for repo C is submitted. The patch doesn’t mention anything about copying information. In this situation, any proposed additions to foo.c would be GPLed unless they add to bar(). Any proposed additions to the bar() function would be MIT Licensed.
Like I mentioned before, number 1 bullet 1 is the most difficult part of the agreement. I included these examples to (hopefully) make the agreement more clear.
1. Any patches submitted to this address will be available under appropriate legal terms. Specifically: […] • All submitted patch metadata will be dedicated to the public domain under 🅭🄍1.0 (see <https://creativecommons.org/publicdomain/zero/1.0/>).
The goal of this bullet is to align the law with contributor expectations. Contributors generally don’t think about the copyright of commit messages. They might make sure they have the right to mirror the software itself somewhere, but they don’t make sure they have the right to mirror the commit messages. Using 🅭🄍 here makes sure that they don’t have to think about commit message copyright before they push.
2. Emails sent to this address that aren’t patches will be available under 🅭🅯🄏🄎4.0 (see <https://creativecommons.org/licenses/by-nc-sa/4.0/>).
The actual legal provision here is pretty simple. The reason why I chose 🅭🅯🄏🄎 is a little bit complicated. I chose that license by balancing two competing values. The first is The Little Red Hen principle: if I spend time creating a valuable work, then it’s fair for me to decide what I do with the work. The second is the forkability principle: a project should be forkable to keep its leadership in check. The Little Red Hen principle is easy to satisfy. Copyright gives authors a lot of power over their works by default. That power is mainly used as leverage to help authors make deals. The question is: how much of that power do we take away to satisfy the forkability principle? Firstly, others have to be able to redistribute the emails (see reproducibility => forkability). Secondly, others would probably benefit from being able to modify the emails. A fork might want to retroactively censor foul language. A fork might want to automatically reformat messages and turn them into pull requests and bug tracker tickets. Plus, regular participants are probably going to cut up quotes while replying to emails. Importantly, giving others those two powers doesn’t take very much leverage away from authors at the bargaining table (it’s unlikely that someone would pay for a copy of an email or pay for rights to modify an email). That’s why I chose 🅭🅯🄏🄎. It gives just enough permission and no more.
3. If an email sent to this address contains one or more patches, but also contains stuff that isn’t part of a patch, then the stuff that isn’t part of a patch will be available under 🅭🅯🄏🄎4.0 (see <https://creativecommons.org/licenses/by-nc-sa/4.0/>).
This provision was originally written to accommodate Git’s scissors notation. Later, I realized that it also helps in the following situations:
- When a patch is submitted using
git-send-email
. At first glance, it looks like the entire email itself is a patch. In reality, each of those emails contains extra metadata that isn’t part of the patch (example: the CC list). - When a patch is submitted as an attachment. In this situation, the main portion of the email would be something other than a patch.
If you agree, reply to this email with the magic phrase: “Yes, I agree.” Put the phrase on its own line. Don’t include any whitespace before the word “yes” or any quotation marks.
At the moment, the current plan is to manually read every message, see if the author needs to agree to JPPA, and then only move their message into the public-inbox if they agree. In the future, I would like to automate the process. Most people will quote the message they’re replying to when they reply, meaning that the magic phrase “Yes, I agree.” will be present in their message whether or not they added it themselves. The special instructions (Don’t include any whitespace before the word ‘yes’ or any quotation marks.
) are there to make it easy for a program to tell the difference between an actual “Yes, I agree.” and a quoted one.
Once you do so, I’ll add your email address to the list of people who have agreed and make your original message public. You won’t have to go through this process again, unless I update this agreement. (This is version -1 by the way).
I want to make sure that I have a good way of updating JPPA. This way I can, for example, switch to new versions of the Creative Commons legal tools (I know that there’s a 🅭🄍1.1 in the works, but it appears to be stalled while CC works on their new Web site). Also, I made this first version version -1 as a test. I’m going to arbitrarily bump it to version 0 at some point to test out my system to keeping track of who agreed to what version.
If you don’t agree, that’s OK. You can still contribute by sending feedback and pull requests to Jason Yundt <jason@jasonyundt.email> Use git-request-pull to create pull requests. See <https://www.git-scm.com/docs/git-request-pull>.
No matter what, people are going to be suspicious of or have objections to JPPA, and I don’t blame them. I think that it’s important to allow everyone to contribute, especially when they disagree. Interestingly, this part would allow someone to have an objection to JPPA and then submit a pull request that fixes their objection. I don’t know of any other CLAs that allow you to do that.
Sorry for writing War and Peace, Jason Yundt
This last part is just a reference to the fact that JPPA (like most of what I write) is so long that people aren’t likely to read it. Here are some emails that I sent to the Git project’s mailing list. Pretend that these emails were sent to my public-inbox. Here’s what JPPA would do to them. One thing to note is that (for clarity) I’m presenting the raw messages themselves. If you’re not an email expert, then these will probably be a bit difficult to read at first.Highlighted examples
Email #1 ([PATCH v3 0/2] gitweb: remove invalid http-equiv="content-type")
From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path: <git-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by smtp.lore.kernel.org (Postfix) with ESMTP id 19773C433EF
for <git@archiver.kernel.org>; Tue, 8 Mar 2022 15:59:01 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S1344618AbiCHP7y (ORCPT <rfc822;git@archiver.kernel.org>);
Tue, 8 Mar 2022 10:59:54 -0500
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34680 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S1348890AbiCHP6s (ORCPT <rfc822;git@vger.kernel.org>);
Tue, 8 Mar 2022 10:58:48 -0500
Received: from box.jasonyundt.email (box.jasonyundt.email [206.189.182.84])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9A8917E38
for <git@vger.kernel.org>; Tue, 8 Mar 2022 07:57:49 -0800 (PST)
Received: from authenticated-user (box.jasonyundt.email [206.189.182.84])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
(No client certificate requested)
by box.jasonyundt.email (Postfix) with ESMTPSA id CDAE77E74B;
Tue, 8 Mar 2022 10:57:15 -0500 (EST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=jasonyundt.email;
s=mail; t=1646755037;
bh=zCx2flGBIpny1UFiEgIznxuJoy4t17Oh7vY6amcIy68=;
h=From:To:Cc:Subject:Date:In-Reply-To:References:From;
b=fHHMVMX/R99+nv6fi3nQ1JmQGfocvg5z0LnFAZMsDrIV6qJmE4KxDP/Ya9E/aMCh3
b4OK36qISrYaBzHB3b+sGGpDkkAHQ7uy6z0MJmyimRnnEnlB+oQeGN3n88Vw/HWARp
qBRlYbP8cWk3i1rGXfxi8eJSlmfPwz6Xwlj0yXWT7WLmIVvROegMRAdPXvMXNGe+xG
S5cKqcnrS9HLfLE0Pmtxs4MqTio+AxG2hgLoX1XEsbGauNoHZ5GY8V3UoBTMZcN2++
eKrE8F7XrzAGIFdDzQ1azqVcvIs+Du3AcBSYPbdoIc+uxLQNG/cbpsVlu1XiPYSvo9
O4bhiaKAqXj7g==
From: Jason Yundt <jason@jasonyundt.email>
To: git@vger.kernel.org
Cc: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?=
<avarab@gmail.com>,
"brian m. carlson" <sandals@crustytoothpaste.net>,
Junio C Hamano <gitster@pobox.com>,
Jeff King <peff@peff.net>, Jason Yundt <jason@jasonyundt.email>
Subject: [PATCH v3 0/2] gitweb: remove invalid http-equiv="content-type"
Date: Tue, 8 Mar 2022 10:56:10 -0500
Message-Id: <20220308155612.105957-1-jason@jasonyundt.email>
In-Reply-To: <20220308010711.61817-1-jason@jasonyundt.email>
References: <20220308010711.61817-1-jason@jasonyundt.email>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Precedence: bulk
List-ID: <git.vger.kernel.org>
X-Mailing-List: git@vger.kernel.org
See the second commit's message for more details. Compared to the second
version of this patch, this one
- removes the extra variable again,
- doesn't include a <meta charset="utf-8"/> and
- corrects a technical error in the second commit’s message.
Jason Yundt (2):
comment: fix typo
gitweb: remove invalid http-equiv="content-type"
gitweb/gitweb.perl | 4 +---
t/t9502-gitweb-standalone-parse-output.sh | 15 ++++++++++++++-
2 files changed, 15 insertions(+), 4 deletions(-)
--
2.35.1
Email #2 ([PATCH v3 1/2] comment: fix typo)
From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path: <git-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by smtp.lore.kernel.org (Postfix) with ESMTP id 52292C433F5
for <git@archiver.kernel.org>; Tue, 8 Mar 2022 15:59:02 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S1348116AbiCHP75 (ORCPT <rfc822;git@archiver.kernel.org>);
Tue, 8 Mar 2022 10:59:57 -0500
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34682 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S1348889AbiCHP6s (ORCPT <rfc822;git@vger.kernel.org>);
Tue, 8 Mar 2022 10:58:48 -0500
Received: from box.jasonyundt.email (box.jasonyundt.email [206.189.182.84])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9C291A397
for <git@vger.kernel.org>; Tue, 8 Mar 2022 07:57:50 -0800 (PST)
Received: from authenticated-user (box.jasonyundt.email [206.189.182.84])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
(No client certificate requested)
by box.jasonyundt.email (Postfix) with ESMTPSA id 28F247E74F;
Tue, 8 Mar 2022 10:57:18 -0500 (EST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=jasonyundt.email;
s=mail; t=1646755039;
bh=95BIkyMQt6Z4KiVGKY5Jx7I4AEIXX/lRj9IdAUbikY0=;
h=From:To:Cc:Subject:Date:In-Reply-To:References:From;
b=kfKZsp9fM2EcD1vRzHm3syK/0DHo9W4fh3248boQz9rxiGbZjYiQdJAwJHG1FDaGl
K1l3N7dzxdZz1o3Tq0vUquB9Gvzfwmpvwr6bOUB79E4M8DKtKH0wkfIOpkWI5nz6Ee
2VGlYOacl83qrC0v//wUYsQ43T/RwGglbCGsN4wgPXTr8ZVHthKNLJ7571tT+7uvas
+4stWSAmRSXZ1Hr19VCowMiZLMK6cT/BwCSeD61ofjuRlqLJwRh/ymvr2ZIbm2O8nS
47KAnoyNKLKVmcrjzT1eqiTwQw+UC6v77f+6v4yZm7gCYPOR35fNw+IC8rBmnb3phe
lS49aMn1oKWQA==
From: Jason Yundt <jason@jasonyundt.email>
To: git@vger.kernel.org
Cc: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?=
<avarab@gmail.com>,
"brian m. carlson" <sandals@crustytoothpaste.net>,
Junio C Hamano <gitster@pobox.com>,
Jeff King <peff@peff.net>, Jason Yundt <jason@jasonyundt.email>
Subject: [PATCH v3 1/2] comment: fix typo
Date: Tue, 8 Mar 2022 10:56:11 -0500
Message-Id: <20220308155612.105957-2-jason@jasonyundt.email>
In-Reply-To: <20220308155612.105957-1-jason@jasonyundt.email>
References: <20220308010711.61817-1-jason@jasonyundt.email>
<20220308155612.105957-1-jason@jasonyundt.email>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Precedence: bulk
List-ID: <git.vger.kernel.org>
X-Mailing-List: git@vger.kernel.org
Signed-off-by: Jason Yundt <jason@jasonyundt.email>
---
t/t9502-gitweb-standalone-parse-output.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh
index 3167473b30..e7363511dd 100755
--- a/t/t9502-gitweb-standalone-parse-output.sh
+++ b/t/t9502-gitweb-standalone-parse-output.sh
@@ -34,7 +34,7 @@ EOF
#
# This will check that gitweb HTTP header contains proposed filename
# as <basename> with '.tar' suffix added, and that generated tarfile
-# (gitweb message body) has <prefix> as prefix for al files in tarfile
+# (gitweb message body) has <prefix> as prefix for all files in tarfile
#
# <prefix> default to <basename>
check_snapshot () {
--
2.35.1
Email #3 ([PATCH v3 2/2] gitweb: remove invalid http-equiv="content-type")
From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path: <git-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by smtp.lore.kernel.org (Postfix) with ESMTP id D0EF4C433EF
for <git@archiver.kernel.org>; Tue, 8 Mar 2022 15:58:24 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S1348059AbiCHP7S (ORCPT <rfc822;git@archiver.kernel.org>);
Tue, 8 Mar 2022 10:59:18 -0500
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34740 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S1348901AbiCHP6t (ORCPT <rfc822;git@vger.kernel.org>);
Tue, 8 Mar 2022 10:58:49 -0500
Received: from box.jasonyundt.email (box.jasonyundt.email [206.189.182.84])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F2D06BC81
for <git@vger.kernel.org>; Tue, 8 Mar 2022 07:57:51 -0800 (PST)
Received: from authenticated-user (box.jasonyundt.email [206.189.182.84])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
(No client certificate requested)
by box.jasonyundt.email (Postfix) with ESMTPSA id 764CA7E750;
Tue, 8 Mar 2022 10:57:19 -0500 (EST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=jasonyundt.email;
s=mail; t=1646755040;
bh=FuOnXb8KScr1/NHpF2ybAY9UsDefTEcbtqLu1BTn41w=;
h=From:To:Cc:Subject:Date:In-Reply-To:References:From;
b=dJ/FG7kfDNWTUZC4BAAEkrUCNDh9+kWGjWrfRoyYYIQPOfi669XhPTgU46LaADzp7
RPSoGzrslGf9OQcVVoQl31i5aEBukhzNMsE73t475usMrcms3jIaCq9BzfvSEgEMht
wZ/J2vxjEiQCA/N9B6plx0mnyrvRvXeX9mVpIUeRMpIuqvVuTvSiit0BPTWdjlmXzJ
uRIArT142jiDt3qG/9tpiX54Fu4Vw3V0t6yE3mdyvZmvjglmOUWz3HEcgADKUVKgap
Bsg0Dw5eyGqWo0lr/XVGMOWhCpqc+9k1hwg6hIESWGvYnYYJ8VcKkidpM8t4cKDNMH
FW3GoA6GpZrcA==
From: Jason Yundt <jason@jasonyundt.email>
To: git@vger.kernel.org
Cc: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?=
<avarab@gmail.com>,
"brian m. carlson" <sandals@crustytoothpaste.net>,
Junio C Hamano <gitster@pobox.com>,
Jeff King <peff@peff.net>, Jason Yundt <jason@jasonyundt.email>
Subject: [PATCH v3 2/2] gitweb: remove invalid http-equiv="content-type"
Date: Tue, 8 Mar 2022 10:56:12 -0500
Message-Id: <20220308155612.105957-3-jason@jasonyundt.email>
In-Reply-To: <20220308155612.105957-1-jason@jasonyundt.email>
References: <20220308010711.61817-1-jason@jasonyundt.email>
<20220308155612.105957-1-jason@jasonyundt.email>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Precedence: bulk
List-ID: <git.vger.kernel.org>
X-Mailing-List: git@vger.kernel.org
Before this change, gitweb would generate pages which included:
<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8"/>
When a meta's http-equiv equals "content-type", the http-equiv is said
to be in the "Encoding declaration state". According to the HTML
Standard,
The Encoding declaration state may be used in HTML documents,
but elements with an http-equiv attribute in that state must not
be used in XML documents.
Source: <https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type>
This change removes that meta element since gitweb always generates XML
documents.
Signed-off-by: Jason Yundt <jason@jasonyundt.email>
---
gitweb/gitweb.perl | 4 +---
t/t9502-gitweb-standalone-parse-output.sh | 13 +++++++++++++
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index fbd1c20a23..606b50104c 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -4213,8 +4213,7 @@ sub git_header_html {
my %opts = @_;
my $title = get_page_title();
- my $content_type = get_content_type_html();
- print $cgi->header(-type=>$content_type, -charset => 'utf-8',
+ print $cgi->header(-type=>get_content_type_html(), -charset => 'utf-8',
-status=> $status, -expires => $expires)
unless ($opts{'-no_http_header'});
my $mod_perl_version = $ENV{'MOD_PERL'} ? " $ENV{'MOD_PERL'}" : '';
@@ -4225,7 +4224,6 @@ sub git_header_html {
<!-- git web interface version $version, (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
<!-- git core binaries version $git_version -->
<head>
-<meta http-equiv="content-type" content="$content_type; charset=utf-8"/>
<meta name="generator" content="gitweb/$version git/$git_version$mod_perl_version"/>
<meta name="robots" content="index, nofollow"/>
<title>$title</title>
diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh
index e7363511dd..8cb582f0e6 100755
--- a/t/t9502-gitweb-standalone-parse-output.sh
+++ b/t/t9502-gitweb-standalone-parse-output.sh
@@ -207,4 +207,17 @@ test_expect_success 'xss checks' '
xss "" "$TAG+"
'
+no_http_equiv_content_type() {
+ gitweb_run "$@" &&
+ ! grep -E "http-equiv=['\"]?content-type" gitweb.body
+}
+
+# See: <https://html.spec.whatwg.org/dev/semantics.html#attr-meta-http-equiv-content-type>
+test_expect_success 'no http-equiv="content-type" in XHTML' '
+ no_http_equiv_content_type &&
+ no_http_equiv_content_type "p=.git" &&
+ no_http_equiv_content_type "p=.git;a=log" &&
+ no_http_equiv_content_type "p=.git;a=tree"
+'
+
test_done
--
2.35.1