about summary refs log tree commit diff
path: root/overlays
diff options
context:
space:
mode:
Diffstat (limited to 'overlays')
-rw-r--r--overlays/patches/cgit/default.nix36
-rw-r--r--overlays/patches/cgit/ui-commit-use-Git-raw-note-format.patch195
-rw-r--r--overlays/patches/cgit/use-buffered-stdio.patch161
-rw-r--r--overlays/patches/default.nix33
-rw-r--r--overlays/patches/dino/0001-add-an-option-to-enable-omemo-by-default-in-new-conv.patch115
-rw-r--r--overlays/patches/dino/default.nix21
-rw-r--r--overlays/patches/firefox/beta/D6995.diff272
-rw-r--r--overlays/patches/firefox/esr/D6995.diff282
-rw-r--r--overlays/patches/firefox/packages.nix27
-rw-r--r--overlays/patches/firefox/profiles.ini8
-rw-r--r--overlays/patches/firefox/release/D6995.diff249
-rw-r--r--overlays/patches/firefox/user.js1
-rw-r--r--overlays/patches/mailman/web.nix7
-rw-r--r--overlays/patches/public-inbox/0001-wwwtext-make-source-info-configurable.patch69
-rw-r--r--overlays/patches/public-inbox/default.nix7
-rw-r--r--overlays/patches/python/default.nix18
-rw-r--r--overlays/patches/python/packages/hyperkitty/0001-Improve-look-of-fixed-width-messages.patch29
-rw-r--r--overlays/patches/python/packages/hyperkitty/default.nix7
-rw-r--r--overlays/patches/thunderbird/default.nix5
-rw-r--r--overlays/patches/tmux/default.nix7
-rw-r--r--overlays/patches/youtube-dl/default.nix8
-rw-r--r--overlays/patches/youtube-dl/fix-youtube-bitrate.diff15
-rw-r--r--overlays/personal/choose/choose.in20
-rw-r--r--overlays/personal/choose/choosebin.in17
-rw-r--r--overlays/personal/choose/default.nix8
-rw-r--r--overlays/personal/declarative-git-repository/default.nix55
-rw-r--r--overlays/personal/default.nix6
27 files changed, 1678 insertions, 0 deletions
diff --git a/overlays/patches/cgit/default.nix b/overlays/patches/cgit/default.nix
new file mode 100644
index 000000000000..d200e5aed43e
--- /dev/null
+++ b/overlays/patches/cgit/default.nix
@@ -0,0 +1,36 @@
+{ cgit, fetchpatch }:
+
+cgit.overrideAttrs ({ patches ? [], ... }: {
+  patches = patches ++ [
+    ./ui-commit-use-Git-raw-note-format.patch
+    (fetchpatch {
+      url = "https://inbox.vuxu.org/cgit/20200723210744.10221-1-hi@alyssa.is/raw";
+      sha256 = "1kxwph84n2la612r8cphy9fkbd851k0cys3mqp5ij3a69qkfdcg9";
+    })
+    (fetchpatch {
+      url = "https://inbox.vuxu.org/cgit/20190101114453.4876-2-e@80x24.org/raw";
+      sha256 = "1s3hpbj3r25wqis2rnjqmm0ld9cvnfaml76l90wm4yc5pymi894d";
+    })
+    (fetchpatch {
+      url = "https://inbox.vuxu.org/cgit/20190101114453.4876-3-e@80x24.org/raw";
+      sha256 = "03gw981bix86b2il6nl98z6dbk1c0hsrgbpc3p4rv5iz122c6kfl";
+    })
+    (fetchpatch {
+      url = "https://inbox.vuxu.org/cgit/20190101114453.4876-4-e@80x24.org/raw";
+      sha256 = "19k2qbqr8iwsslmjgvyjy5hah7mrqvcw1dj8axbk8nyvqd3njw1q";
+    })
+    (fetchpatch {
+      url = "https://inbox.vuxu.org/cgit/20190101114453.4876-5-e@80x24.org/raw";
+      sha256 = "12kbwfkxnlzf86n35p60h6y83mf82zdw0hiq01i6fl4pimg72bly";
+    })
+    (fetchpatch {
+      url = "https://inbox.vuxu.org/cgit/20210319202337.21676-6-e@80x24.org/raw";
+      sha256 = "1zn247v0scab3xbnzgzl52b7p02wdh8c5jl45q7a9iszn6rhk3m3";
+    })
+    (fetchpatch {
+      url = "https://git.causal.agency/cgit-pink/patch/?id=8f9034884bb592a0514d85771bd0096b1584b552";
+      sha256 = "0wvckndjmxar3vgqdc3jdnpzy0xgrdlqgfaasixl3x87sdnf4kg7";
+    })
+    ./use-buffered-stdio.patch
+  ];
+})
diff --git a/overlays/patches/cgit/ui-commit-use-Git-raw-note-format.patch b/overlays/patches/cgit/ui-commit-use-Git-raw-note-format.patch
new file mode 100644
index 000000000000..ce1a5aa559cc
--- /dev/null
+++ b/overlays/patches/cgit/ui-commit-use-Git-raw-note-format.patch
@@ -0,0 +1,195 @@
+Return-Path: <cgit-bounces@lists.zx2c4.com>
+Received: from compute4.internal (compute4.nyi.internal [10.202.2.44])
+	 by sloti36d2t04 (Cyrus 3.1.6-553-gc304556-fmstable-20190524v1) with LMTPA;
+	 Sun, 26 May 2019 12:57:16 -0400
+X-Cyrus-Session-Id: sloti36d2t04-1558889836-2458433-2-14112916921354509248
+X-Sieve: CMU Sieve 3.0
+X-Spam-known-sender: no
+X-Spam-score: 0.0
+X-Spam-hits: BAYES_00 -1.9, FORGED_GMAIL_RCVD 1, FREEMAIL_FORGED_FROMDOMAIN 0.001,
+  FREEMAIL_FROM 0.001, HEADER_FROM_DIFFERENT_DOMAINS 0.001,
+  MAILING_LIST_MULTI -1, ME_ZS_CLEAN -0.001, RCVD_IN_DNSWL_NONE -0.0001,
+  SPF_HELO_NONE 0.001, SPF_PASS -0.001, LANGUAGES enfr, BAYES_USED user,
+  SA_VERSION 3.4.2
+X-Spam-source: IP='192.95.5.69', Host='krantz.zx2c4.com', Country='US', FromHeader='com',
+  MailFrom='com'
+X-Spam-charsets: plain='us-ascii'
+X-Resolved-to: alyssa@fastmail.com
+X-Delivered-to: hi@alyssa.is
+X-Mail-from: cgit-bounces@lists.zx2c4.com
+Received: from mx6 ([10.202.2.205])
+  by compute4.internal (LMTPProxy); Sun, 26 May 2019 12:57:16 -0400
+Received: from mx6.messagingengine.com (localhost [127.0.0.1])
+	by mailmx.nyi.internal (Postfix) with ESMTP id C0158A2008C
+	for <hi@alyssa.is>; Sun, 26 May 2019 12:57:15 -0400 (EDT)
+Received: from mx6.messagingengine.com (localhost [127.0.0.1])
+    by mx6.messagingengine.com (Authentication Milter) with ESMTP
+    id D6950A237B8;
+    Sun, 26 May 2019 12:57:15 -0400
+ARC-Seal: i=1; a=rsa-sha256; cv=none; d=messagingengine.com; s=fm2; t=
+    1558889835; b=B7I3OXdhlHrdrasWp1rFG7Jjk+h0sxqdku2fN7+USIl8d3vp12
+    muXmMQxDMOOsEoeVd4hI8tipG7pGUmZSW8zetR+jYztp8rQATypbIbixctfVxwls
+    s0Ef0IPTEpyFn9YFOOQKLat5Ul7Qr5z5XGBjVi8LYocsnJBTSk5yHHeRrJBWWl5V
+    RGqLWse1Ldf8qEOy/b/th18XGbRpJFCVPxV9jZkoaSiF585wGKkEeoI4dfNJ3SRh
+    vktPXDJqVoU72cDyIa71fhxlWR/hOaf2Ca9n27URIPFxBuBz3b6s6faf2pEsFY2E
+    5dM2DH1WwTTf1Mooe5t2RrZWOKshkEL3Tojw==
+ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=
+    messagingengine.com; h=from:to:subject:date:message-id
+    :mime-version:list-id:list-unsubscribe:list-archive:list-post
+    :list-help:list-subscribe:content-type:content-transfer-encoding
+    :sender; s=fm2; t=1558889835; bh=VlVjl7sSy403Efad4r51sLCJz3cq/zu
+    Le82anVQc3Yk=; b=TkUYZjyqgEFkmEI5GSiRJq1ELkPP0WKcVMOuI/01v2lkWeu
+    wU/i8o4QxKYxpDTwvk8Y+OmaqTW3MJ9YoRAcIgbaaMz7NgD54BuZi7zb8QJTUQtH
+    WGycNVev/OZEoN8//53TZMTVzPtA41l32/cIQ6cZW6IhMSQ1HgTBX8hhyOjlUY6c
+    rzq2e/e0Jvuv2Z5xIOjGNOBRbmsJ4liQOJmW7oDLX83EKP+87DzlB6chPIqwhZ9E
+    XOaX0uCRdj2GaOJAF4/RD8hzG4Ya8fI3zpK28qonZN6XDentjWtIRb+kBSCsGYm6
+    iD7X9tYrNk192KU1jGasGCQpDhkt0EMk18Axd6Q==
+ARC-Authentication-Results: i=1; mx6.messagingengine.com; arc=none (no signatures found);
+    dkim=none (no signatures found);
+    dmarc=fail policy.published-domain-policy=none
+    policy.published-subdomain-policy=quarantine
+    policy.applied-disposition=none policy.evaluated-disposition=none
+    policy.override-reason=mailing_list policy.arc-aware-result=fail
+    (p=none,sp=quarantine,has-list-id=yes,d=none,d.eval=none,override=mailing_list,arc_aware_result=fail)
+    policy.policy-from=p header.from=gmail.com;
+    iprev=pass smtp.remote-ip=192.95.5.69 (krantz.zx2c4.com);
+    spf=pass smtp.mailfrom=cgit-bounces@lists.zx2c4.com
+    smtp.helo=krantz.zx2c4.com;
+    x-aligned-from=fail;
+    x-ptr=pass smtp.helo=krantz.zx2c4.com policy.ptr=krantz.zx2c4.com;
+    x-return-mx=pass header.domain=gmail.com policy.is_org=yes
+    (MX Record found);
+    x-return-mx=pass smtp.domain=lists.zx2c4.com policy.org_domain=zx2c4.com
+    policy.is_org=no (MX Record found);
+    x-tls=pass smtp.version=TLSv1.2 smtp.cipher=ECDHE-RSA-AES128-GCM-SHA256
+    smtp.bits=128/128;
+    x-vs=clean score=0 state=0;
+    x-zs=clean
+Authentication-Results: mx6.messagingengine.com;
+    arc=none (no signatures found);
+    dkim=none (no signatures found);
+    dmarc=fail policy.published-domain-policy=none
+      policy.published-subdomain-policy=quarantine
+      policy.applied-disposition=none policy.evaluated-disposition=none
+      policy.override-reason=mailing_list policy.arc-aware-result=fail
+      (p=none,sp=quarantine,has-list-id=yes,d=none,d.eval=none,override=mailing_list,arc_aware_result=fail)
+      policy.policy-from=p header.from=gmail.com;
+    iprev=pass smtp.remote-ip=192.95.5.69 (krantz.zx2c4.com);
+    spf=pass smtp.mailfrom=cgit-bounces@lists.zx2c4.com
+      smtp.helo=krantz.zx2c4.com;
+    x-aligned-from=fail;
+    x-ptr=pass smtp.helo=krantz.zx2c4.com policy.ptr=krantz.zx2c4.com;
+    x-return-mx=pass header.domain=gmail.com policy.is_org=yes
+      (MX Record found);
+    x-return-mx=pass smtp.domain=lists.zx2c4.com policy.org_domain=zx2c4.com
+      policy.is_org=no (MX Record found);
+    x-tls=pass smtp.version=TLSv1.2 smtp.cipher=ECDHE-RSA-AES128-GCM-SHA256
+      smtp.bits=128/128;
+    x-vs=clean score=0 state=0;
+    x-zs=clean
+X-ME-VSSU: VW5zdWI9bWFpbHRvOmNnaXQtcmVxdWVzdEBsaXN0cy56eDJjNC5jb20_c3ViamVjdD11bn
+    N1YnNjcmliZQ
+X-ME-VSSU: VW5zdWI9aHR0cHM6Ly9saXN0cy56eDJjNC5jb20vbWFpbG1hbi9vcHRpb25zL2NnaXQ
+X-ME-VSCause: gggruggvucftvghtrhhoucdtuddrgeduuddruddvtddguddtkecutefuodetggdotefrod
+    ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp
+    uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvuf
+    ffkffogghpjefjgedufedttgfgvghssehtjeertdertddvnecuhfhrohhmpeevhhhrihhs
+    ucforgihohcuoegrkhhlhhhfvgigsehgmhgrihhlrdgtohhmqeenucffohhmrghinhepii
+    igvdgtgedrtghomhenucfkphepudelvddrleehrdehrdeiledpvddtledrleefrddufeej
+    rddvtdelnecurfgrrhgrmhepihhnvghtpeduledvrdelhedrhedrieelpdhhvghlohepkh
+    hrrghnthiirdiigidvtgegrdgtohhmpdhmrghilhhfrhhomhepoegtghhithdqsghouhhn
+    tggvsheslhhishhtshdriiigvdgtgedrtghomheqnecuvehluhhsthgvrhfuihiivgeptd
+X-ME-VSScore: 0
+X-ME-VSCategory: clean
+X-ME-ZSResult: clean
+Received-SPF: pass
+    (lists.zx2c4.com: 192.95.5.69 is authorized to use 'cgit-bounces@lists.zx2c4.com' in 'mfrom' identity (mechanism 'mx' matched))
+    receiver=mx6.messagingengine.com;
+    identity=mailfrom;
+    envelope-from="cgit-bounces@lists.zx2c4.com";
+    helo=krantz.zx2c4.com;
+    client-ip=192.95.5.69
+Received: from krantz.zx2c4.com (krantz.zx2c4.com [192.95.5.69])
+	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
+	(No client certificate requested)
+	by mx6.messagingengine.com (Postfix) with ESMTPS
+	for <hi@alyssa.is>; Sun, 26 May 2019 12:57:13 -0400 (EDT)
+Received: from krantz.zx2c4.com (localhost [IPv6:::1])
+	by krantz.zx2c4.com (ZX2C4 Mail Server) with ESMTP id 6360ad08;
+	Sun, 26 May 2019 16:57:12 +0000 (UTC)
+X-Remote-Delivered-To: cgit@lists.zx2c4.com
+Received: from krantz.zx2c4.com (localhost [127.0.0.1])
+ by krantz.zx2c4.com (ZX2C4 Mail Server) with ESMTP id 94ab4c5e
+ for <cgit@lists.zx2c4.com>; Sun, 26 May 2019 16:57:10 +0000 (UTC)
+Received: from avasout02.plus.net (avasout02.plus.net [212.159.14.17])
+ by krantz.zx2c4.com (ZX2C4 Mail Server) with ESMTP id 151b7cee
+ for <cgit@lists.zx2c4.com>; Sun, 26 May 2019 16:57:10 +0000 (UTC)
+Received: from mailserver ([209.93.137.209]) by smtp with ESMTP
+ id UwSFhu7pnpYZWUwSGhosYl; Sun, 26 May 2019 17:57:06 +0100
+X-CM-Score: 0.00
+X-CNFS-Analysis: v=2.3 cv=cd2sUULM c=1 sm=1 tr=0
+ a=u68OYVRc/Z2sxEGkPHj3Dw==:117 a=u68OYVRc/Z2sxEGkPHj3Dw==:17
+ a=x7bEGLp0ZPQA:10 a=YbTMELGUhT8A:10 a=pGLkceISAAAA:8 a=HzQmFnjoOBWeq84yEp4A:9
+From: Chris Mayo <aklhfex@gmail.com>
+To: cgit@lists.zx2c4.com
+Subject: [PATCH] ui-commit: use Git raw note format
+Date: Sun, 26 May 2019 17:57:01 +0100
+Message-Id: <20190526165701.28904-1-aklhfex@gmail.com>
+X-Mailer: git-send-email 2.21.0
+MIME-Version: 1.0
+X-CMAE-Envelope: MS4wfP0CKvHqBVrlItMYLboOh+RL0e032hTB6uaiaMMwhAjdzE++e0bjO/pa6p0htCiM3UnX4Z2U0JMo1hqMzjz6Fvn9UDKX/K3SZq+SO3in/Ef8asqzdu/i
+ +D4sjBdxh3JSqvmeqsDZQIthJNuQTPajW0uaVQrKRHhx3qXMtgNqpj1J
+X-BeenThere: cgit@lists.zx2c4.com
+X-Mailman-Version: 2.1.15
+Precedence: list
+List-Id: List for cgit developers and users <cgit.lists.zx2c4.com>
+List-Unsubscribe: <https://lists.zx2c4.com/mailman/options/cgit>,
+ <mailto:cgit-request@lists.zx2c4.com?subject=unsubscribe>
+List-Archive: <http://lists.zx2c4.com/pipermail/cgit/>
+List-Post: <mailto:cgit@lists.zx2c4.com>
+List-Help: <mailto:cgit-request@lists.zx2c4.com?subject=help>
+List-Subscribe: <https://lists.zx2c4.com/mailman/listinfo/cgit>,
+ <mailto:cgit-request@lists.zx2c4.com?subject=subscribe>
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+Errors-To: cgit-bounces@lists.zx2c4.com
+Sender: "CGit" <cgit-bounces@lists.zx2c4.com>
+X-TUID: seh0e1Lgy6q2
+
+Currently a commit note is shown as:
+
+Notes
+
+  Notes:
+      <note text>
+
+Change to:
+
+Notes
+  <note text>
+
+Signed-off-by: Chris Mayo <aklhfex@gmail.com>
+---
+ ui-commit.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ui-commit.c b/ui-commit.c
+index 9a47b54..52b4c2a 100644
+--- a/ui-commit.c
++++ b/ui-commit.c
+@@ -39,7 +39,7 @@ void cgit_print_commit(char *hex, const char *prefix)
+ 	}
+ 	info = cgit_parse_commit(commit);
+ 
+-	format_display_notes(&oid, &notes, PAGE_ENCODING, 0);
++	format_display_notes(&oid, &notes, PAGE_ENCODING, 1);
+ 
+ 	load_ref_decorations(NULL, DECORATE_FULL_REFS);
+ 
+-- 
+2.21.0
+
+_______________________________________________
+CGit mailing list
+CGit@lists.zx2c4.com
+https://lists.zx2c4.com/mailman/listinfo/cgit
diff --git a/overlays/patches/cgit/use-buffered-stdio.patch b/overlays/patches/cgit/use-buffered-stdio.patch
new file mode 100644
index 000000000000..4fa5db70edd9
--- /dev/null
+++ b/overlays/patches/cgit/use-buffered-stdio.patch
@@ -0,0 +1,161 @@
+From 98237819a417bf81a393b893e84c76ddb6dd36f5 Mon Sep 17 00:00:00 2001
+From: Eric Wong <e@80x24.org>
+Date: Fri, 19 Mar 2021 20:38:22 +0000
+Subject: [PATCH] use buffered stdio
+
+Our generation of HTML triggers many small write(2) syscalls
+which is inefficient.
+
+Time output on a horrible query against my git.git mirror
+shows significant performance improvement:
+
+QUERY_STRING='id=2b93bfac0f5bcabbf60f174f4e7bfa9e318e64d5&id2=d6da71a9d16b8cf27f9d8f90692d3625c849cbc8'
+PATH_INFO=/mirrors/git.git/diff
+export QUERY_STRING PATH_INFO
+time ./cgit >/dev/null
+
+Before:
+real    0m1.585s
+user    0m0.904s
+sys     0m0.658s
+
+After:
+real    0m0.750s
+user    0m0.666s
+sys     0m0.076s
+
+Signed-off-by: Eric Wong <e@80x24.org>
+Message-Id: <20210319203822.GA30217@dcvr>
+---
+ cache.c       |  7 +++++++
+ cgit.c        |  2 +-
+ filter.c      | 22 +++++++++++++++++++++-
+ html.c        |  2 +-
+ ui-snapshot.c |  3 +++
+ 5 files changed, 33 insertions(+), 3 deletions(-)
+
+diff --git a/cache.c b/cache.c
+index 2c70be78..580c0e80 100644
+--- a/cache.c
++++ b/cache.c
+@@ -265,6 +265,13 @@ static int process_slot(struct cache_slot *slot)
+ {
+ 	int err;
+ 
++	/*
++	 * Make sure any buffered data is flushed before we redirect,
++	 * do sendfile(2) or write(2)
++	 */
++	if (fflush(stdout))
++		return errno;
++
+ 	err = open_slot(slot);
+ 	if (!err && slot->match) {
+ 		if (is_expired(slot)) {
+diff --git a/cgit.c b/cgit.c
+index c4320f04..d8ea2212 100644
+--- a/cgit.c
++++ b/cgit.c
+@@ -674,7 +674,7 @@ static inline void authenticate_post(void)
+ 		len = MAX_AUTHENTICATION_POST_BYTES;
+ 	if ((len = read(STDIN_FILENO, buffer, len)) < 0)
+ 		die_errno("Could not read POST from stdin");
+-	if (write(STDOUT_FILENO, buffer, len) < 0)
++	if (fwrite(buffer, 1, len, stdout) < len)
+ 		die_errno("Could not write POST to stdout");
+ 	cgit_close_filter(ctx.cfg.auth_filter);
+ 	exit(0);
+diff --git a/filter.c b/filter.c
+index 70f5b749..fba26aa0 100644
+--- a/filter.c
++++ b/filter.c
+@@ -48,6 +48,7 @@ static int open_exec_filter(struct cgit_filter *base, va_list ap)
+ 	for (i = 0; i < filter->base.argument_count; i++)
+ 		filter->argv[i + 1] = va_arg(ap, char *);
+ 
++	chk_zero(fflush(stdout), "unable to flush STDOUT");
+ 	filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
+ 		"Unable to duplicate STDOUT");
+ 	chk_zero(pipe(pipe_fh), "Unable to create pipe to subprocess");
+@@ -71,6 +72,7 @@ static int close_exec_filter(struct cgit_filter *base)
+ 	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
+ 	int i, exit_status = 0;
+ 
++	chk_zero(fflush(stdout), "unable to flush STDOUT");
+ 	chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO),
+ 		"Unable to restore STDOUT");
+ 	close(filter->old_stdout);
+@@ -143,17 +145,32 @@ void cgit_init_filters(void)
+ #endif
+ 
+ #ifndef NO_LUA
+-static ssize_t (*libc_write)(int fd, const void *buf, size_t count);
++static size_t (*libc_fwrite)(const void *buf, size_t size, size_t n, FILE *);
++static ssize_t (*libc_write)(int fd, const void *buf, size_t size);
+ static ssize_t (*filter_write)(struct cgit_filter *base, const void *buf, size_t count) = NULL;
+ static struct cgit_filter *current_write_filter = NULL;
+ 
+ void cgit_init_filters(void)
+ {
++	/*
++	 * we need to wrap both functions since the Lua filter may
++	 * have code which calls write(2) directly, bypassing fwrite(3)
++	 */
++	libc_fwrite = dlsym(RTLD_NEXT, "fwrite");
++	if (!libc_fwrite)
++		die("Could not locate libc's write function");
+ 	libc_write = dlsym(RTLD_NEXT, "write");
+ 	if (!libc_write)
+ 		die("Could not locate libc's write function");
+ }
+ 
++size_t fwrite(const void *buf, size_t size, size_t n, FILE *f)
++{
++	if (f != stdout || !filter_write)
++		return libc_fwrite(buf, size, n, f);
++	return filter_write(current_write_filter, buf, size * n);
++}
++
+ ssize_t write(int fd, const void *buf, size_t count)
+ {
+ 	if (fd != STDOUT_FILENO || !filter_write)
+@@ -305,6 +322,9 @@ static int open_lua_filter(struct cgit_filter *base, va_list ap)
+ 	struct lua_filter *filter = (struct lua_filter *)base;
+ 	int i;
+ 
++	if (fflush(stdout))
++		return 1;
++
+ 	if (init_lua_filter(filter))
+ 		return 1;
+ 
+diff --git a/html.c b/html.c
+index 138c649e..ca9db91d 100644
+--- a/html.c
++++ b/html.c
+@@ -80,7 +80,7 @@ char *fmtalloc(const char *format, ...)
+ 
+ void html_raw(const char *data, size_t size)
+ {
+-	if (write(STDOUT_FILENO, data, size) != size)
++	if (fwrite(data, 1, size, stdout) != size)
+ 		die_errno("write error on html output");
+ }
+ 
+diff --git a/ui-snapshot.c b/ui-snapshot.c
+index 556d3ed4..8b81e374 100644
+--- a/ui-snapshot.c
++++ b/ui-snapshot.c
+@@ -37,6 +37,9 @@ static int write_archive_type(const char *format, const char *hex, const char *p
+ 	/* argv_array guarantees a trailing NULL entry. */
+ 	memcpy(nargv, argv.argv, sizeof(char *) * (argv.argc + 1));
+ 
++	if (fflush(stdout))
++		return errno;
++
+ 	result = write_archive(argv.argc, nargv, NULL, the_repository, NULL, 0);
+ 	argv_array_clear(&argv);
+ 	free(nargv);
+-- 
+2.32.0
+
diff --git a/overlays/patches/default.nix b/overlays/patches/default.nix
new file mode 100644
index 000000000000..b57a87683f87
--- /dev/null
+++ b/overlays/patches/default.nix
@@ -0,0 +1,33 @@
+self: super: {
+  cgit = self.callPackage ./cgit { inherit (super) cgit; };
+
+  dino = self.callPackage ./dino { inherit (super) dino; };
+
+  firefoxPackages = self.callPackage ./firefox/packages.nix {
+    inherit (super) firefoxPackages;
+    llvmPackages = self.llvmPackages_latest;
+  };
+
+  mailmanPackages = super.mailmanPackages.extend (self: super: {
+    web = self.callPackage mailman/web.nix { inherit (super) web; };
+  });
+
+  public-inbox = self.callPackage ./public-inbox {
+    inherit (super) public-inbox;
+  };
+
+  python3 = self.callPackage ./python { python = super.python3; };
+
+  thunderbird = self.callPackage ./thunderbird {
+    inherit (super) thunderbird;
+    llvmPackages = self.llvmPackages_8;
+  };
+  thunderbird-68 = self.callPackage ./thunderbird {
+    thunderbird = super.thunderbird-68;
+    llvmPackages = self.llvmPackages_latest;
+  };
+
+  tmux = self.callPackage ./tmux { inherit (super) tmux; };
+
+  youtube-dl = self.callPackage ./youtube-dl { inherit (super) youtube-dl; };
+}
diff --git a/overlays/patches/dino/0001-add-an-option-to-enable-omemo-by-default-in-new-conv.patch b/overlays/patches/dino/0001-add-an-option-to-enable-omemo-by-default-in-new-conv.patch
new file mode 100644
index 000000000000..030c165d87b8
--- /dev/null
+++ b/overlays/patches/dino/0001-add-an-option-to-enable-omemo-by-default-in-new-conv.patch
@@ -0,0 +1,115 @@
+From cee5e27b157081a3ce55869bd5f649560a6127ea Mon Sep 17 00:00:00 2001
+From: lumi <lumi@pew.im>
+Date: Thu, 17 Oct 2019 16:43:40 +0200
+Subject: [PATCH] add an option to enable omemo by default in new conversations
+
+---
+ libdino/src/entity/settings.vala              | 10 ++++++++++
+ libdino/src/service/conversation_manager.vala |  5 +++++
+ main/data/settings_dialog.ui                  | 12 ++++++++++++
+ main/src/ui/settings_dialog.vala              |  3 +++
+ 4 files changed, 30 insertions(+)
+
+diff --git a/libdino/src/entity/settings.vala b/libdino/src/entity/settings.vala
+index bf1ebed..f9cd734 100644
+--- a/libdino/src/entity/settings.vala
++++ b/libdino/src/entity/settings.vala
+@@ -11,6 +11,7 @@ public class Settings : Object {
+         send_marker_ = col_to_bool_or_default("send_marker", true);
+         notifications_ = col_to_bool_or_default("notifications", true);
+         convert_utf8_smileys_ = col_to_bool_or_default("convert_utf8_smileys", true);
++        omemo_default_ = col_to_bool_or_default("omemo_default", false);
+     }
+ 
+     private bool col_to_bool_or_default(string key, bool def) {
+@@ -53,6 +54,15 @@ public class Settings : Object {
+             convert_utf8_smileys_ = value;
+         }
+     }
++
++    private bool omemo_default_;
++    public bool omemo_default {
++        get { return omemo_default_; }
++        set {
++            db.settings.insert().or("REPLACE").value(db.settings.key, "omemo_default").value(db.settings.value, value.to_string()).perform();
++            omemo_default_ = value;
++        }
++    }
+ }
+ 
+ }
+diff --git a/libdino/src/service/conversation_manager.vala b/libdino/src/service/conversation_manager.vala
+index c473ea7..e980e08 100644
+--- a/libdino/src/service/conversation_manager.vala
++++ b/libdino/src/service/conversation_manager.vala
+@@ -8,6 +8,8 @@ public class ConversationManager : StreamInteractionModule, Object {
+     public static ModuleIdentity<ConversationManager> IDENTITY = new ModuleIdentity<ConversationManager>("conversation_manager");
+     public string id { get { return IDENTITY.id; } }
+ 
++    private Dino.Entities.Settings settings = Dino.Application.get_default().settings;
++
+     public signal void conversation_activated(Conversation conversation);
+     public signal void conversation_deactivated(Conversation conversation);
+ 
+@@ -46,6 +48,9 @@ public class ConversationManager : StreamInteractionModule, Object {
+ 
+         // Create a new converation
+         Conversation conversation = new Conversation(jid, account, type);
++        if (settings.omemo_default) {
++            conversation.encryption = Encryption.OMEMO;
++        }
+         add_conversation(conversation);
+         conversation.persist(db);
+         return conversation;
+diff --git a/main/data/settings_dialog.ui b/main/data/settings_dialog.ui
+index c76f347..23ee7b8 100644
+--- a/main/data/settings_dialog.ui
++++ b/main/data/settings_dialog.ui
+@@ -65,6 +65,18 @@
+                                 <property name="height">1</property>
+                             </packing>
+                         </child>
++                        <child>
++                          <object class="GtkCheckButton" id="omemo_default_checkbutton">
++                            <property name="label" translatable="yes">Enable OMEMO by default</property>
++                            <property name="visible">True</property>
++                          </object>
++                          <packing>
++                              <property name="left_attach">0</property>
++                              <property name="top_attach">4</property>
++                              <property name="width">1</property>
++                              <property name="height">1</property>
++                          </packing>
++                        </child>
+                     </object>
+                 </child>
+             </object>
+diff --git a/main/src/ui/settings_dialog.vala b/main/src/ui/settings_dialog.vala
+index 68c711d..6401a2d 100644
+--- a/main/src/ui/settings_dialog.vala
++++ b/main/src/ui/settings_dialog.vala
+@@ -9,6 +9,7 @@ class SettingsDialog : Dialog {
+     [GtkChild] private CheckButton marker_checkbutton;
+     [GtkChild] private CheckButton notification_checkbutton;
+     [GtkChild] private CheckButton emoji_checkbutton;
++    [GtkChild] private CheckButton omemo_default_checkbutton;
+ 
+     Dino.Entities.Settings settings = Dino.Application.get_default().settings;
+ 
+@@ -19,11 +20,13 @@ class SettingsDialog : Dialog {
+         marker_checkbutton.active = settings.send_marker;
+         notification_checkbutton.active = settings.notifications;
+         emoji_checkbutton.active = settings.convert_utf8_smileys;
++        omemo_default_checkbutton.active = settings.omemo_default;
+ 
+         typing_checkbutton.toggled.connect(() => { settings.send_typing = typing_checkbutton.active; } );
+         marker_checkbutton.toggled.connect(() => { settings.send_marker = marker_checkbutton.active; } );
+         notification_checkbutton.toggled.connect(() => { settings.notifications = notification_checkbutton.active; } );
+         emoji_checkbutton.toggled.connect(() => { settings.convert_utf8_smileys = emoji_checkbutton.active; });
++        omemo_default_checkbutton.toggled.connect(() => { settings.omemo_default = omemo_default_checkbutton.active; });
+     }
+ }
+ 
+-- 
+2.23.0
+
diff --git a/overlays/patches/dino/default.nix b/overlays/patches/dino/default.nix
new file mode 100644
index 000000000000..0ca4220f2f42
--- /dev/null
+++ b/overlays/patches/dino/default.nix
@@ -0,0 +1,21 @@
+{ lib, dino, fetchpatch, ... } @ args:
+
+(dino.override (builtins.removeAttrs args [
+  "dino" "fetchpatch"
+])).overrideAttrs ({ patches ? [], ... }: {
+  patches = patches ++ [
+    (fetchpatch {
+      url = "https://github.com/dino/dino/commit/6be319f8f9b1f19d2b775aa04660d9f2c3a04dd0.patch";
+      sha256 = "sha256-i7lJk5/1y/qwI53kChocWjlvS2ThRGrUTLxCMbyBgqs=";
+    })
+    (fetchpatch {
+      url = "https://github.com/dino/dino/commit/f85bf7af3d355794a2a5208aea21efeb5b6e529d.patch";
+      sha256 = "0y8dldydvj75i2n53brki9czvzw1qwlk5646k3xrx5pnl31c7p5b";
+    })
+  ];
+
+  postInstall = ''
+    mkdir -p $out/share/man/man1
+    mv ../doc/dino.1 $out/share/man/man1
+  '';
+})
diff --git a/overlays/patches/firefox/beta/D6995.diff b/overlays/patches/firefox/beta/D6995.diff
new file mode 100644
index 000000000000..9d0c9f9d0cb1
--- /dev/null
+++ b/overlays/patches/firefox/beta/D6995.diff
@@ -0,0 +1,272 @@
+diff --git a/toolkit/moz.build b/toolkit/moz.build
+index b6f792da7124..672d43957bed 100644
+--- a/toolkit/moz.build
++++ b/toolkit/moz.build
+@@ -87,3 +87,6 @@ with Files('pluginproblem/**'):
+ 
+ with Files('l10n-registry.manifest'):
+     BUG_COMPONENT = ('Core', 'Localization')
++
++if CONFIG['ENABLE_TESTS']:
++    DIRS += ['tests/gtest']
+diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
+index 197d29a85106..24b2d00bc8c2 100644
+--- a/toolkit/xre/nsXREDirProvider.cpp
++++ b/toolkit/xre/nsXREDirProvider.cpp
+@@ -405,13 +405,6 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
+     nsCOMPtr<nsIFile> localDir;
+     rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
+     if (NS_SUCCEEDED(rv)) {
+-#  if defined(XP_MACOSX)
+-      rv = localDir->AppendNative("Mozilla"_ns);
+-#  else
+-      rv = localDir->AppendNative(".mozilla"_ns);
+-#  endif
+-    }
+-    if (NS_SUCCEEDED(rv)) {
+       localDir.swap(file);
+     }
+   }
+@@ -1429,6 +1422,9 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   localDir = dirFileMac;
++
++  rv = localDir->AppendRelativeNativePath(nsDependentCString("Mozilla"));
++  NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_IOS)
+   nsAutoCString userDir;
+   if (GetUIKitDirectory(aLocal, userDir)) {
+@@ -1452,6 +1448,9 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
++  NS_ENSURE_SUCCESS(rv, rv);
++  rv = localDir->AppendRelativeNativePath(nsDependentCString("Mozilla"));
++  NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_UNIX)
+   const char* homeDir = getenv("HOME");
+   if (!homeDir || !*homeDir) return NS_ERROR_FAILURE;
+@@ -1472,8 +1471,51 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+       if (NS_SUCCEEDED(rv)) rv = localDir->AppendNative(".cache"_ns);
+     }
+   } else {
++    bool exists;
++    // check old config ~/.mozilla
+     rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+                                getter_AddRefs(localDir));
++    NS_ENSURE_SUCCESS(rv, rv);
++    rv = localDir->AppendRelativeNativePath(nsDependentCString(".mozilla"));
++    NS_ENSURE_SUCCESS(rv, rv);
++    rv = localDir->Exists(&exists);
++    NS_ENSURE_SUCCESS(rv, rv);
++    // otherwise, use new config
++    if (!exists) {
++      const char* xdghomedir = getenv("XDG_DATA_HOME");
++      if (!xdghomedir || !*xdghomedir) {
++        rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
++                                   getter_AddRefs(localDir));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->AppendRelativeNativePath(nsDependentCString(".local"));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->Exists(&exists);
++        if (NS_SUCCEEDED(rv) && !exists) {
++          rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++          NS_ENSURE_SUCCESS(rv, rv);
++        }
++        rv = localDir->AppendRelativeNativePath(nsDependentCString("share"));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->Exists(&exists);
++        if (NS_SUCCEEDED(rv) && !exists) {
++          rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++        }
++      }
++      else {
++        rv = NS_NewNativeLocalFile(nsDependentCString(xdghomedir), true,
++                               getter_AddRefs(localDir));
++      }
++      NS_ENSURE_SUCCESS(rv, rv);
++
++      rv = localDir->AppendRelativeNativePath(nsDependentCString("mozilla"));
++      NS_ENSURE_SUCCESS(rv, rv);
++      rv = localDir->Exists(&exists);
++      NS_ENSURE_SUCCESS(rv, rv);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
++        NS_ENSURE_SUCCESS(rv, rv);
++      }
++    }
+   }
+ #else
+ #  error "Don't know how to get product dir on your platform"
+@@ -1594,20 +1636,12 @@ nsresult nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile) {
+ 
+ #if defined(XP_MACOSX) || defined(XP_WIN)
+ 
+-  static const char* const sXR = "Mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "Extensions";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+ #elif defined(XP_UNIX)
+ 
+-  static const char* const sXR = ".mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "extensions";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+@@ -1625,20 +1659,12 @@ nsresult nsXREDirProvider::AppendSysUserExtensionsDevPath(nsIFile* aFile) {
+ 
+ #if defined(XP_MACOSX) || defined(XP_WIN)
+ 
+-  static const char* const sXR = "Mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "SystemExtensionsDev";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+ #elif defined(XP_UNIX)
+ 
+-  static const char* const sXR = ".mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "systemextensionsdev";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+@@ -1703,9 +1729,6 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
+   NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_UNIX)
+   nsAutoCString folder;
+-  // Make it hidden (by starting with "."), except when local (the
+-  // profile is already under ~/.cache or XDG_CACHE_HOME).
+-  if (!aLocal) folder.Assign('.');
+ 
+   if (!profile.IsEmpty()) {
+     // Skip any leading path characters
+@@ -1725,8 +1748,12 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
+       folder.Append(vendor);
+       ToLowerCase(folder);
+ 
+-      rv = aFile->AppendNative(folder);
+-      NS_ENSURE_SUCCESS(rv, rv);
++      // Keep the 'mozilla' path for cache:
++      // Use ${XDG_DATA_HOME:-$HOME/.cache}/mozilla/firefox
++      if (aLocal) {
++        rv = aFile->AppendNative(folder);
++        NS_ENSURE_SUCCESS(rv, rv);
++      }
+ 
+       folder.Truncate();
+     }
+diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp
+index b8699fecc4b7..a91eba2cbbbd 100644
+--- a/xpcom/io/nsAppFileLocationProvider.cpp
++++ b/xpcom/io/nsAppFileLocationProvider.cpp
+@@ -233,7 +233,7 @@ nsresult nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile** aLocalFile) {
+ // GetProductDirectory - Gets the directory which contains the application data
+ // folder
+ //
+-// UNIX   : ~/.mozilla/
++// UNIX   : ~/.mozilla/ or ${XDG_DATA_HOME:-~/.local/share}/mozilla
+ // WIN    : <Application Data folder on user's machine>\Mozilla
+ // Mac    : :Documents:Mozilla:
+ //----------------------------------------------------------------------------------------
+@@ -277,19 +277,80 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
+     return rv;
+   }
+ #elif defined(XP_UNIX)
+-  rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), true,
++  const char* homeDir = PR_GetEnv("HOME");
++  /* check old config ~/.mozilla */
++  rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+                              getter_AddRefs(localDir));
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
++  rv = localDir->AppendRelativeNativePath(nsDependentCString(".mozilla"));
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++  rv = localDir->Exists(&exists);
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++  /* otherwise, use new config */
++  if (!exists) {
++    const char* xdghomedir = PR_GetEnv("XDG_DATA_HOME");
++    if (!xdghomedir || !*xdghomedir) {
++      /* XDG_DATA_HOME=$HOME/.local/share */
++      rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
++                                 getter_AddRefs(localDir));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->AppendRelativeNativePath(nsDependentCString(".local"));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->Exists(&exists);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++        if (NS_FAILED(rv)) {
++          return rv;
++        }
++      }
++      rv = localDir->AppendRelativeNativePath(nsDependentCString("share"));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->Exists(&exists);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++      }
++    }
++    else {
++      rv = NS_NewNativeLocalFile(nsDependentCString(xdghomedir), true,
++                                 getter_AddRefs(localDir));
++    }
++    if (NS_FAILED(rv)) {
++      return rv;
++    }
++    rv = localDir->AppendRelativeNativePath(nsDependentCString("mozilla"));
++    if (NS_FAILED(rv)) {
++      return rv;
++    }
++  }
+ #else
+ #  error dont_know_how_to_get_product_dir_on_your_platform
+ #endif
+ 
++#if !defined(XP_UNIX) || defined(XP_MACOSX)
++  // Since we have to check for legacy configuration, we have
++  // the complete path for Linux already, so this is not
++  // needed. If we stop checking for legacy at some point,
++  // then we can change this to not be protected by
++  // this clause.
+   rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR);
++
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
++#endif
++
+   rv = localDir->Exists(&exists);
+ 
+   if (NS_SUCCEEDED(rv) && !exists) {
+@@ -309,7 +370,7 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
+ // GetDefaultUserProfileRoot - Gets the directory which contains each user
+ // profile dir
+ //
+-// UNIX   : ~/.mozilla/
++// UNIX   : ~/.mozilla/ or ${XDG_DATA_HOME:-~/.local/share}/mozilla
+ // WIN    : <Application Data folder on user's machine>\Mozilla\Profiles
+ // Mac    : :Documents:Mozilla:Profiles:
+ //----------------------------------------------------------------------------------------
diff --git a/overlays/patches/firefox/esr/D6995.diff b/overlays/patches/firefox/esr/D6995.diff
new file mode 100644
index 000000000000..e6425af02ca6
--- /dev/null
+++ b/overlays/patches/firefox/esr/D6995.diff
@@ -0,0 +1,282 @@
+diff --git a/toolkit/moz.build b/toolkit/moz.build
+index f01b128b2493a..ae0e19ec9c509 100644
+--- a/toolkit/moz.build
++++ b/toolkit/moz.build
+@@ -84,3 +84,6 @@ with Files('pluginproblem/**'):
+ 
+ with Files('l10n-registry.manifest'):
+     BUG_COMPONENT = ('Core', 'Localization')
++
++if CONFIG['ENABLE_TESTS']:
++    DIRS += ['tests/gtest']
+diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
+index 1d6ffb748e4e4..8708279b964a2 100644
+--- a/toolkit/xre/nsXREDirProvider.cpp
++++ b/toolkit/xre/nsXREDirProvider.cpp
+@@ -390,13 +390,6 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
+     nsCOMPtr<nsIFile> localDir;
+     rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
+     if (NS_SUCCEEDED(rv)) {
+-#  if defined(XP_MACOSX)
+-      rv = localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla"));
+-#  else
+-      rv = localDir->AppendNative(NS_LITERAL_CSTRING(".mozilla"));
+-#  endif
+-    }
+-    if (NS_SUCCEEDED(rv)) {
+       localDir.swap(file);
+     }
+   }
+@@ -1302,7 +1295,8 @@ nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile** aResult,
+             nsDependentCString(hasVendor ? GetAppVendor() : GetAppName())))) {
+       return NS_ERROR_FAILURE;
+     }
+-  } else if (NS_FAILED(localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla")))) {
++  }
++  else if (NS_FAILED(localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla")))) {
+     return NS_ERROR_FAILURE;
+   }
+ 
+@@ -1443,6 +1437,9 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   localDir = dirFileMac;
++
++  rv = localDir->AppendRelativeNativePath(nsDependentCString("Mozilla"));
++  NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_IOS)
+   nsAutoCString userDir;
+   if (GetUIKitDirectory(aLocal, userDir)) {
+@@ -1466,6 +1463,9 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
++  NS_ENSURE_SUCCESS(rv, rv);
++  rv = localDir->AppendRelativeNativePath(nsDependentCString("Mozilla"));
++  NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_UNIX)
+   const char* homeDir = getenv("HOME");
+   if (!homeDir || !*homeDir) return NS_ERROR_FAILURE;
+@@ -1487,8 +1487,51 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+         rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache"));
+     }
+   } else {
++    bool exists;
++    // check old config ~/.mozilla
+     rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+                                getter_AddRefs(localDir));
++    NS_ENSURE_SUCCESS(rv, rv);
++    rv = localDir->AppendRelativeNativePath(nsDependentCString(".mozilla"));
++    NS_ENSURE_SUCCESS(rv, rv);
++    rv = localDir->Exists(&exists);
++    NS_ENSURE_SUCCESS(rv, rv);
++    // otherwise, use new config
++    if (!exists) {
++      const char* xdghomedir = getenv("XDG_DATA_HOME");
++      if (!xdghomedir || !*xdghomedir) {
++        rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
++                                   getter_AddRefs(localDir));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->AppendRelativeNativePath(nsDependentCString(".local"));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->Exists(&exists);
++        if (NS_SUCCEEDED(rv) && !exists) {
++          rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++          NS_ENSURE_SUCCESS(rv, rv);
++        }
++        rv = localDir->AppendRelativeNativePath(nsDependentCString("share"));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->Exists(&exists);
++        if (NS_SUCCEEDED(rv) && !exists) {
++          rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++        }
++      }
++      else {
++        rv = NS_NewNativeLocalFile(nsDependentCString(xdghomedir), true,
++                               getter_AddRefs(localDir));
++      }
++      NS_ENSURE_SUCCESS(rv, rv);
++
++      rv = localDir->AppendRelativeNativePath(nsDependentCString("mozilla"));
++      NS_ENSURE_SUCCESS(rv, rv);
++      rv = localDir->Exists(&exists);
++      NS_ENSURE_SUCCESS(rv, rv);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
++        NS_ENSURE_SUCCESS(rv, rv);
++      }
++    }
+   }
+ #else
+ #  error "Don't know how to get product dir on your platform"
+@@ -1609,20 +1652,12 @@ nsresult nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile) {
+ 
+ #if defined(XP_MACOSX) || defined(XP_WIN)
+ 
+-  static const char* const sXR = "Mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "Extensions";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+ #elif defined(XP_UNIX)
+ 
+-  static const char* const sXR = ".mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "extensions";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+@@ -1640,20 +1675,12 @@ nsresult nsXREDirProvider::AppendSysUserExtensionsDevPath(nsIFile* aFile) {
+ 
+ #if defined(XP_MACOSX) || defined(XP_WIN)
+ 
+-  static const char* const sXR = "Mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "SystemExtensionsDev";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+ #elif defined(XP_UNIX)
+ 
+-  static const char* const sXR = ".mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "systemextensionsdev";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+@@ -1718,9 +1745,6 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
+   NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_UNIX)
+   nsAutoCString folder;
+-  // Make it hidden (by starting with "."), except when local (the
+-  // profile is already under ~/.cache or XDG_CACHE_HOME).
+-  if (!aLocal) folder.Assign('.');
+ 
+   if (!profile.IsEmpty()) {
+     // Skip any leading path characters
+@@ -1740,8 +1764,12 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
+       folder.Append(vendor);
+       ToLowerCase(folder);
+ 
+-      rv = aFile->AppendNative(folder);
+-      NS_ENSURE_SUCCESS(rv, rv);
++      // Keep the 'mozilla' path for cache:
++      // Use ${XDG_DATA_HOME:-$HOME/.cache}/mozilla/firefox
++      if (aLocal) {
++        rv = aFile->AppendNative(folder);
++        NS_ENSURE_SUCCESS(rv, rv);
++      }
+ 
+       folder.Truncate();
+     }
+diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp
+index e79c8303fe129..53c550db18c05 100644
+--- a/xpcom/io/nsAppFileLocationProvider.cpp
++++ b/xpcom/io/nsAppFileLocationProvider.cpp
+@@ -247,7 +247,7 @@ nsresult nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile** aLocalFile) {
+ // GetProductDirectory - Gets the directory which contains the application data
+ // folder
+ //
+-// UNIX   : ~/.mozilla/
++// UNIX   : ~/.mozilla/ or ${XDG_DATA_HOME:-~/.local/share}/mozilla
+ // WIN    : <Application Data folder on user's machine>\Mozilla
+ // Mac    : :Documents:Mozilla:
+ //----------------------------------------------------------------------------------------
+@@ -291,19 +291,80 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
+     return rv;
+   }
+ #elif defined(XP_UNIX)
+-  rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), true,
++  const char* homeDir = PR_GetEnv("HOME");
++  /* check old config ~/.mozilla */
++  rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+                              getter_AddRefs(localDir));
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
++  rv = localDir->AppendRelativeNativePath(nsDependentCString(".mozilla"));
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++  rv = localDir->Exists(&exists);
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++  /* otherwise, use new config */
++  if (!exists) {
++    const char* xdghomedir = PR_GetEnv("XDG_DATA_HOME");
++    if (!xdghomedir || !*xdghomedir) {
++      /* XDG_DATA_HOME=$HOME/.local/share */
++      rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
++                                 getter_AddRefs(localDir));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->AppendRelativeNativePath(nsDependentCString(".local"));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->Exists(&exists);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++        if (NS_FAILED(rv)) {
++          return rv;
++        }
++      }
++      rv = localDir->AppendRelativeNativePath(nsDependentCString("share"));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->Exists(&exists);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++      }
++    }
++    else {
++      rv = NS_NewNativeLocalFile(nsDependentCString(xdghomedir), true,
++                                 getter_AddRefs(localDir));
++    }
++    if (NS_FAILED(rv)) {
++      return rv;
++    }
++    rv = localDir->AppendRelativeNativePath(nsDependentCString("mozilla"));
++    if (NS_FAILED(rv)) {
++      return rv;
++    }
++  }
+ #else
+ #  error dont_know_how_to_get_product_dir_on_your_platform
+ #endif
+ 
++#if !defined(XP_UNIX) || defined(XP_MACOSX)
++  // Since we have to check for legacy configuration, we have
++  // the complete path for Linux already, so this is not
++  // needed. If we stop checking for legacy at some point,
++  // then we can change this to not be protected by
++  // this clause.
+   rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR);
++
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
++#endif
++
+   rv = localDir->Exists(&exists);
+ 
+   if (NS_SUCCEEDED(rv) && !exists) {
+@@ -323,7 +384,7 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
+ // GetDefaultUserProfileRoot - Gets the directory which contains each user
+ // profile dir
+ //
+-// UNIX   : ~/.mozilla/
++// UNIX   : ~/.mozilla/ or ${XDG_DATA_HOME:-~/.local/share}/mozilla
+ // WIN    : <Application Data folder on user's machine>\Mozilla\Profiles
+ // Mac    : :Documents:Mozilla:Profiles:
+ //----------------------------------------------------------------------------------------
diff --git a/overlays/patches/firefox/packages.nix b/overlays/patches/firefox/packages.nix
new file mode 100644
index 000000000000..c214e9810a80
--- /dev/null
+++ b/overlays/patches/firefox/packages.nix
@@ -0,0 +1,27 @@
+{ firefoxPackages, llvmPackages }:
+
+with firefoxPackages;
+
+firefoxPackages // {
+  # Use clangStdenv to work around
+  # <https://github.com/NixOS/nixpkgs/issues/84283>
+  # (Firefox fails to build with GCC on AMD EPYC 7401P.)
+
+  firefox = (firefox.override {
+    inherit (llvmPackages) stdenv;
+  }).overrideAttrs ({ patches ? [], ... }: {
+    patches = patches ++ [ release/D6995.diff ];
+  });
+
+  firefox-esr-78 = (firefox-esr-78.override {
+    inherit (llvmPackages) stdenv;
+  }).overrideAttrs ({ patches ? [], ... }: {
+    patches = patches ++ [ esr/D6995.diff ];
+  });
+
+  firefox-beta = (firefox-beta.override {
+    inherit (llvmPackages) stdenv;
+  }).overrideAttrs ({ patches ? [], ... }: {
+    patches = patches ++ [ beta/D6995.diff ];
+  });
+}
diff --git a/overlays/patches/firefox/profiles.ini b/overlays/patches/firefox/profiles.ini
new file mode 100644
index 000000000000..becf53354e76
--- /dev/null
+++ b/overlays/patches/firefox/profiles.ini
@@ -0,0 +1,8 @@
+[General]
+StartWithLastProfile=1
+
+[Profile0]
+Name=default
+IsRelative=1
+Path=default
+Default=1
diff --git a/overlays/patches/firefox/release/D6995.diff b/overlays/patches/firefox/release/D6995.diff
new file mode 100644
index 000000000000..011173813974
--- /dev/null
+++ b/overlays/patches/firefox/release/D6995.diff
@@ -0,0 +1,249 @@
+diff --git a/toolkit/moz.build b/toolkit/moz.build
+index fd2295bd9f6d3..827c29aba408d 100644
+--- a/toolkit/moz.build
++++ b/toolkit/moz.build
+@@ -96,3 +96,6 @@ GeneratedFile(
+     script="content/neterror/gen_aboutneterror_codes.py",
+     inputs=["/toolkit/locales/en-US/toolkit/neterror/nsserrors.ftl"],
+ )
++
++if CONFIG["ENABLE_TESTS"]:
++    DIRS += ["tests/gtest"]
+diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
+index ea1e5a80613ef..7575ef4cf6718 100644
+--- a/toolkit/xre/nsXREDirProvider.cpp
++++ b/toolkit/xre/nsXREDirProvider.cpp
+@@ -367,11 +367,6 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
+   } else if (!strcmp(aProperty, XRE_USER_NATIVE_MANIFESTS)) {
+     rv = GetUserDataDirectoryHome(getter_AddRefs(file), false);
+     NS_ENSURE_SUCCESS(rv, rv);
+-#  if defined(XP_MACOSX)
+-    rv = file->AppendNative("Mozilla"_ns);
+-#  else   // defined(XP_MACOSX)
+-    rv = file->AppendNative(".mozilla"_ns);
+-#  endif  // defined(XP_MACOSX)
+   }
+ #endif  // defined(XP_UNIX) || defined(XP_MACOSX)
+   else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
+@@ -1223,6 +1218,9 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   localDir = dirFileMac;
++
++  rv = localDir->AppendRelativeNativePath(nsDependentCString("Mozilla"));
++  NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_IOS)
+   nsAutoCString userDir;
+   if (GetUIKitDirectory(aLocal, userDir)) {
+@@ -1246,6 +1244,9 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
++  NS_ENSURE_SUCCESS(rv, rv);
++  rv = localDir->AppendRelativeNativePath(nsDependentCString("Mozilla"));
++  NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_UNIX)
+   const char* homeDir = getenv("HOME");
+   if (!homeDir || !*homeDir) return NS_ERROR_FAILURE;
+@@ -1266,8 +1267,51 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+       if (NS_SUCCEEDED(rv)) rv = localDir->AppendNative(".cache"_ns);
+     }
+   } else {
++    bool exists;
++    // check old config ~/.mozilla
+     rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+                                getter_AddRefs(localDir));
++    NS_ENSURE_SUCCESS(rv, rv);
++    rv = localDir->AppendRelativeNativePath(nsDependentCString(".mozilla"));
++    NS_ENSURE_SUCCESS(rv, rv);
++    rv = localDir->Exists(&exists);
++    NS_ENSURE_SUCCESS(rv, rv);
++    // otherwise, use new config
++    if (!exists) {
++      const char* xdghomedir = getenv("XDG_DATA_HOME");
++      if (!xdghomedir || !*xdghomedir) {
++        rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
++                                   getter_AddRefs(localDir));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->AppendRelativeNativePath(nsDependentCString(".local"));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->Exists(&exists);
++        if (NS_SUCCEEDED(rv) && !exists) {
++          rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++          NS_ENSURE_SUCCESS(rv, rv);
++        }
++        rv = localDir->AppendRelativeNativePath(nsDependentCString("share"));
++        NS_ENSURE_SUCCESS(rv, rv);
++        rv = localDir->Exists(&exists);
++        if (NS_SUCCEEDED(rv) && !exists) {
++          rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++        }
++      }
++      else {
++        rv = NS_NewNativeLocalFile(nsDependentCString(xdghomedir), true,
++                               getter_AddRefs(localDir));
++      }
++      NS_ENSURE_SUCCESS(rv, rv);
++
++      rv = localDir->AppendRelativeNativePath(nsDependentCString("mozilla"));
++      NS_ENSURE_SUCCESS(rv, rv);
++      rv = localDir->Exists(&exists);
++      NS_ENSURE_SUCCESS(rv, rv);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
++        NS_ENSURE_SUCCESS(rv, rv);
++      }
++    }
+   }
+ #else
+ #  error "Don't know how to get product dir on your platform"
+@@ -1357,20 +1401,12 @@ nsresult nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile) {
+ 
+ #if defined(XP_MACOSX) || defined(XP_WIN)
+ 
+-  static const char* const sXR = "Mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "Extensions";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+ #elif defined(XP_UNIX)
+ 
+-  static const char* const sXR = ".mozilla";
+-  rv = aFile->AppendNative(nsDependentCString(sXR));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+   static const char* const sExtensions = "extensions";
+   rv = aFile->AppendNative(nsDependentCString(sExtensions));
+   NS_ENSURE_SUCCESS(rv, rv);
+@@ -1435,9 +1471,6 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
+   NS_ENSURE_SUCCESS(rv, rv);
+ #elif defined(XP_UNIX)
+   nsAutoCString folder;
+-  // Make it hidden (by starting with "."), except when local (the
+-  // profile is already under ~/.cache or XDG_CACHE_HOME).
+-  if (!aLocal) folder.Assign('.');
+ 
+   if (!profile.IsEmpty()) {
+     // Skip any leading path characters
+@@ -1457,8 +1490,12 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
+       folder.Append(vendor);
+       ToLowerCase(folder);
+ 
+-      rv = aFile->AppendNative(folder);
+-      NS_ENSURE_SUCCESS(rv, rv);
++      // Keep the 'mozilla' path for cache:
++      // Use ${XDG_DATA_HOME:-$HOME/.cache}/mozilla/firefox
++      if (aLocal) {
++        rv = aFile->AppendNative(folder);
++        NS_ENSURE_SUCCESS(rv, rv);
++      }
+ 
+       folder.Truncate();
+     }
+diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp
+index aedaad1b4ff91..40ee7ee00f596 100644
+--- a/xpcom/io/nsAppFileLocationProvider.cpp
++++ b/xpcom/io/nsAppFileLocationProvider.cpp
+@@ -168,7 +168,7 @@ nsresult nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile** aLocalFile) {
+ // GetProductDirectory - Gets the directory which contains the application data
+ // folder
+ //
+-// UNIX   : ~/.mozilla/
++// UNIX   : ~/.mozilla/ or ${XDG_DATA_HOME:-~/.local/share}/mozilla
+ // WIN    : <Application Data folder on user's machine>\Mozilla
+ // Mac    : :Documents:Mozilla:
+ //----------------------------------------------------------------------------------------
+@@ -207,19 +207,80 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
+     return rv;
+   }
+ #elif defined(XP_UNIX)
+-  rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), true,
++  const char* homeDir = PR_GetEnv("HOME");
++  /* check old config ~/.mozilla */
++  rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+                              getter_AddRefs(localDir));
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
++  rv = localDir->AppendRelativeNativePath(nsDependentCString(".mozilla"));
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++  rv = localDir->Exists(&exists);
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++  /* otherwise, use new config */
++  if (!exists) {
++    const char* xdghomedir = PR_GetEnv("XDG_DATA_HOME");
++    if (!xdghomedir || !*xdghomedir) {
++      /* XDG_DATA_HOME=$HOME/.local/share */
++      rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
++                                 getter_AddRefs(localDir));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->AppendRelativeNativePath(nsDependentCString(".local"));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->Exists(&exists);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++        if (NS_FAILED(rv)) {
++          return rv;
++        }
++      }
++      rv = localDir->AppendRelativeNativePath(nsDependentCString("share"));
++      if (NS_FAILED(rv)) {
++        return rv;
++      }
++      rv = localDir->Exists(&exists);
++      if (NS_SUCCEEDED(rv) && !exists) {
++        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
++      }
++    }
++    else {
++      rv = NS_NewNativeLocalFile(nsDependentCString(xdghomedir), true,
++                                 getter_AddRefs(localDir));
++    }
++    if (NS_FAILED(rv)) {
++      return rv;
++    }
++    rv = localDir->AppendRelativeNativePath(nsDependentCString("mozilla"));
++    if (NS_FAILED(rv)) {
++      return rv;
++    }
++  }
+ #else
+ #  error dont_know_how_to_get_product_dir_on_your_platform
+ #endif
+ 
++#if !defined(XP_UNIX) || defined(XP_MACOSX)
++  // Since we have to check for legacy configuration, we have
++  // the complete path for Linux already, so this is not
++  // needed. If we stop checking for legacy at some point,
++  // then we can change this to not be protected by
++  // this clause.
+   rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR);
++
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
++#endif
++
+   rv = localDir->Exists(&exists);
+ 
+   if (NS_SUCCEEDED(rv) && !exists) {
+@@ -239,7 +300,7 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
+ // GetDefaultUserProfileRoot - Gets the directory which contains each user
+ // profile dir
+ //
+-// UNIX   : ~/.mozilla/
++// UNIX   : ~/.mozilla/ or ${XDG_DATA_HOME:-~/.local/share}/mozilla
+ // WIN    : <Application Data folder on user's machine>\Mozilla\Profiles
+ // Mac    : :Documents:Mozilla:Profiles:
+ //----------------------------------------------------------------------------------------
diff --git a/overlays/patches/firefox/user.js b/overlays/patches/firefox/user.js
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/overlays/patches/firefox/user.js
@@ -0,0 +1 @@
+
diff --git a/overlays/patches/mailman/web.nix b/overlays/patches/mailman/web.nix
new file mode 100644
index 000000000000..fe9ce51d6ffe
--- /dev/null
+++ b/overlays/patches/mailman/web.nix
@@ -0,0 +1,7 @@
+{ web, ... } @ args:
+
+(web.overrideAttrs ({ postPatch ? "", ... }: {
+  postPatch = postPatch + ''
+    substituteInPlace mailman_web/urls.py --replace "'archives/" "'hyperkitty/"
+  '';
+})).override (builtins.removeAttrs args [ "web" ])
diff --git a/overlays/patches/public-inbox/0001-wwwtext-make-source-info-configurable.patch b/overlays/patches/public-inbox/0001-wwwtext-make-source-info-configurable.patch
new file mode 100644
index 000000000000..401e3f8a72cc
--- /dev/null
+++ b/overlays/patches/public-inbox/0001-wwwtext-make-source-info-configurable.patch
@@ -0,0 +1,69 @@
+From 1fadaba96bd64ef113bfe37e14925b627ec2940e Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Fri, 17 Jan 2020 15:21:42 +0000
+Subject: [PATCH] wwwtext: make source info configurable
+
+---
+ Documentation/public-inbox-config.pod |  6 ++++++
+ lib/PublicInbox/WwwText.pm            | 19 ++++++++++++++++++-
+ 2 files changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/public-inbox-config.pod b/Documentation/public-inbox-config.pod
+index d8504e61..420b5c01 100644
+--- a/Documentation/public-inbox-config.pod
++++ b/Documentation/public-inbox-config.pod
+@@ -196,6 +196,12 @@ and the path may be "/dev/null" or any empty file.
+ Multiple files may be specified and will be included in the
+ order specified.
+ 
++=item publicinbox.sourceinfo
++
++Path to a file containing HTML instructions for downloading the
++public-inbox source code.  Useful for AGPL compliance.  If not
++specified, default git clone instructions are used.
++
+ =item publicinboxmda.spamcheck
+ 
+ This may be set to C<none> to disable the use of SpamAssassin
+diff --git a/lib/PublicInbox/WwwText.pm b/lib/PublicInbox/WwwText.pm
+index c6957e81..fa22ab94 100644
+--- a/lib/PublicInbox/WwwText.pm
++++ b/lib/PublicInbox/WwwText.pm
+@@ -309,6 +309,21 @@ note: .onion URLs require Tor: https://www.torproject.org/
+ EOM
+ }
+ 
++sub _get_user_source_info ($) {
++	my ($pi_cfg) = @_;
++
++	local $/;
++	my $path = $pi_cfg->{'publicinbox.sourceinfo'};
++	if (!defined($path)) {
++		return;
++	}
++	open my $fh, '<', $path or do {
++		warn "Failed to open publicinbox.sourceinfo=$path: $!\n";
++		return;
++	};
++	<$fh>;
++}
++
+ sub _mirror_help ($$) {
+ 	my ($ctx, $txt) = @_;
+ 	my $ibx = $ctx->{ibx};
+@@ -390,9 +405,11 @@ EOF
+ 	_add_onion_note($txt);
+ 
+ 	my $code_url = prurl($ctx->{env}, $PublicInbox::WwwStream::CODE_URL);
++	my $default_info = "git clone $code_url";
++	my $info = _get_user_source_info($ctx->{www}->{pi_cfg}) || $default_info;
+ 	$$txt .= join("\n\n",
+ 		coderepos_raw($ctx, $top_url), # may be empty
+-		"AGPL code for this site:\n  git clone $code_url");
++		"AGPL code for this site:\n  $info");
+ 	1;
+ }
+ 
+-- 
+2.40.1
+
diff --git a/overlays/patches/public-inbox/default.nix b/overlays/patches/public-inbox/default.nix
new file mode 100644
index 000000000000..e2d53933132a
--- /dev/null
+++ b/overlays/patches/public-inbox/default.nix
@@ -0,0 +1,7 @@
+{ public-inbox, fetchpatch }:
+
+public-inbox.overrideAttrs ({ patches ? [], ... }: {
+  patches = patches ++ [
+    ./0001-wwwtext-make-source-info-configurable.patch
+  ];
+})
diff --git a/overlays/patches/python/default.nix b/overlays/patches/python/default.nix
new file mode 100644
index 000000000000..7018ccb8f01d
--- /dev/null
+++ b/overlays/patches/python/default.nix
@@ -0,0 +1,18 @@
+{ python, lib, packageOverrides ? (_: _: {}), ... } @ args:
+
+let
+  inherit (builtins) removeAttrs;
+  inherit (lib) composeExtensions fold;
+in
+
+python.override ((removeAttrs args [ "lib" "python" ]) // {
+  packageOverrides = fold composeExtensions python.packageOverrides
+    [
+      (final: super: with final; {
+        hyperkitty = callPackage ./packages/hyperkitty {
+          inherit (super) hyperkitty;
+        };
+      })
+      packageOverrides
+    ];
+})
diff --git a/overlays/patches/python/packages/hyperkitty/0001-Improve-look-of-fixed-width-messages.patch b/overlays/patches/python/packages/hyperkitty/0001-Improve-look-of-fixed-width-messages.patch
new file mode 100644
index 000000000000..cbf9083ed5e9
--- /dev/null
+++ b/overlays/patches/python/packages/hyperkitty/0001-Improve-look-of-fixed-width-messages.patch
@@ -0,0 +1,29 @@
+From bd62e0ac83b46d763bb6d083e2979032d75c7587 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Sat, 4 Apr 2020 11:11:45 +0000
+Subject: [PATCH] Improve look of fixed-width messages
+
+Use the system monospace font, which can be set to whatever the user
+wants, and decrease the font size a bit, because monospace fonts
+usually feel a bit bigger than their variable-width counterparts.
+---
+ hyperkitty/static/hyperkitty/sass/_hyperkitty-message.scss | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/hyperkitty/static/hyperkitty/sass/_hyperkitty-message.scss b/hyperkitty/static/hyperkitty/sass/_hyperkitty-message.scss
+index 25f7f1e..f035d69 100644
+--- a/hyperkitty/static/hyperkitty/sass/_hyperkitty-message.scss
++++ b/hyperkitty/static/hyperkitty/sass/_hyperkitty-message.scss
+@@ -127,7 +127,8 @@ $oddEmailColor: rgb(238, 238, 238);
+     }
+ }
+ .email-body.fixed {
+-    font-family: 'Droid Sans Mono', monospace;
++    font-family: monospace;
++    font-size: 0.9em;
+     white-space: pre;
+ }
+ 
+-- 
+2.24.1
+
diff --git a/overlays/patches/python/packages/hyperkitty/default.nix b/overlays/patches/python/packages/hyperkitty/default.nix
new file mode 100644
index 000000000000..e8a4315e2be4
--- /dev/null
+++ b/overlays/patches/python/packages/hyperkitty/default.nix
@@ -0,0 +1,7 @@
+{ hyperkitty, fetchpatch }:
+
+hyperkitty.overridePythonAttrs ({ patches ? [], ... }: {
+  patches = patches ++ [
+    ./0001-Improve-look-of-fixed-width-messages.patch
+  ];
+})
diff --git a/overlays/patches/thunderbird/default.nix b/overlays/patches/thunderbird/default.nix
new file mode 100644
index 000000000000..f6dd6ac0326f
--- /dev/null
+++ b/overlays/patches/thunderbird/default.nix
@@ -0,0 +1,5 @@
+{ thunderbird, llvmPackages, ... } @ args:
+
+thunderbird.override ({
+  inherit (llvmPackages) stdenv;
+} // (builtins.removeAttrs args [ "llvmPackages" "thunderbird" ]))
diff --git a/overlays/patches/tmux/default.nix b/overlays/patches/tmux/default.nix
new file mode 100644
index 000000000000..cc13ac2a86c2
--- /dev/null
+++ b/overlays/patches/tmux/default.nix
@@ -0,0 +1,7 @@
+{ tmux }:
+
+tmux.overrideAttrs ({ CPPFLAGS ? [], ... }: {
+  CPPFLAGS = CPPFLAGS ++ [
+    ''-DTMUX_CONF="\"\$$XDG_CONFIG_HOME/tmux/tmux.conf"\"''
+  ];
+})
diff --git a/overlays/patches/youtube-dl/default.nix b/overlays/patches/youtube-dl/default.nix
new file mode 100644
index 000000000000..c2014726b623
--- /dev/null
+++ b/overlays/patches/youtube-dl/default.nix
@@ -0,0 +1,8 @@
+{ youtube-dl, ... } @ args:
+
+(youtube-dl.override (builtins.removeAttrs args [ "youtube-dl" ])).overrideAttrs (
+  { patches ? [], ... }:
+  {
+    patches = patches ++ [ ./fix-youtube-bitrate.diff ];
+  }
+)
diff --git a/overlays/patches/youtube-dl/fix-youtube-bitrate.diff b/overlays/patches/youtube-dl/fix-youtube-bitrate.diff
new file mode 100644
index 000000000000..b633d6410160
--- /dev/null
+++ b/overlays/patches/youtube-dl/fix-youtube-bitrate.diff
@@ -0,0 +1,15 @@
+--- a/youtube_dl/extractor/common.py
++++ b/youtube_dl/extractor/common.py
+@@ -1367,10 +1367,8 @@
+             raise ExtractorError('No video formats found')
+ 
+         for f in formats:
+-            # Automatically determine tbr when missing based on abr and vbr (improves
+-            # formats sorting in some cases)
+-            if 'tbr' not in f and f.get('abr') is not None and f.get('vbr') is not None:
+-                f['tbr'] = f['abr'] + f['vbr']
++            if f.get('vcodec') != 'none':
++                f['tbr'] = None
+ 
+         def _formats_key(f):
+             # TODO remove the following workaround
diff --git a/overlays/personal/choose/choose.in b/overlays/personal/choose/choose.in
new file mode 100644
index 000000000000..1fc2b7f91c2a
--- /dev/null
+++ b/overlays/personal/choose/choose.in
@@ -0,0 +1,20 @@
+#! @execline@/bin/execlineb -S0
+
+define -s fzf_opts "--reverse"
+
+ifelse { importas -i _ DISPLAY }
+{
+  foot -a float
+  getpid my_pid
+  importas -i -u my_pid my_pid
+  backtick -i -n term_pid { awk "{print $4}" /proc/${my_pid}/stat }
+  importas -i -u term_pid term_pid
+  redirfd -r 0 /proc/${term_pid}/fd/0
+  redirfd -w 1 /proc/${term_pid}/fd/1
+  @fzf@/bin/fzf $fzf_opts $@
+}
+
+ifelse { importas -i _ TMUX }
+{ @fzf@/bin/fzf-tmux $fzf_opts $@ }
+
+@fzf@/bin/fzf $fzf_opts $@
diff --git a/overlays/personal/choose/choosebin.in b/overlays/personal/choose/choosebin.in
new file mode 100644
index 000000000000..7f8ea520c994
--- /dev/null
+++ b/overlays/personal/choose/choosebin.in
@@ -0,0 +1,17 @@
+#! @execline@/bin/execlineb -S0
+
+backtick -i entry_points {
+  importas PATH PATH
+  heredoc 0 $PATH
+  tr : " "
+}
+importas -s -i -u entry_points entry_points
+
+pipeline {
+  redirfd -w 2 /dev/null
+  find -L $entry_points -mindepth 1 -maxdepth 1 -executable -type f
+}
+
+pipeline { awk -F / "{print $NF}" }
+
+@out@/bin/choose --prompt "$ " $@
diff --git a/overlays/personal/choose/default.nix b/overlays/personal/choose/default.nix
new file mode 100644
index 000000000000..d4e845f8b967
--- /dev/null
+++ b/overlays/personal/choose/default.nix
@@ -0,0 +1,8 @@
+{ runCommand, makeWrapper, execline, fzf }:
+
+runCommand "choose" { inherit execline fzf; } ''
+  install -d $out/bin
+  substituteAll ${./choose.in} $out/bin/choose
+  substituteAll ${./choosebin.in} $out/bin/choosebin
+  chmod +x $out/bin/*
+''
diff --git a/overlays/personal/declarative-git-repository/default.nix b/overlays/personal/declarative-git-repository/default.nix
new file mode 100644
index 000000000000..e1b2693dff4f
--- /dev/null
+++ b/overlays/personal/declarative-git-repository/default.nix
@@ -0,0 +1,55 @@
+# SPDX-FileCopyrightText: V <v@unfathomable.blue>
+# SPDX-FileCopyrightText: 2022 Alyssa Ross <hi@alyssa.is>
+# SPDX-License-Identifier: OSL-3.0
+
+# Adapted from https://src.unfathomable.blue/nixos-config/tree/pkgs/declarative-git-repository/default.nix
+
+{ lib, buildEnv, runtimeShell, writeTextDir, writeText, writeTextFile
+, writeScript
+}:
+
+{ path
+, branch ? "main"
+, description
+, config ? {}
+, hooks ? {}
+, owner ? "-", group ? "-"
+}:
+
+with lib;
+
+let
+  # As generated by an initial `git init --bare`
+  defaultConfig = {
+    core = {
+      repositoryformatversion = 0;
+      filemode = true;
+      bare = true;
+    };
+  };
+
+  hooksDir = buildEnv {
+    name = "git-repository-hooks";
+    paths = mapAttrsToList (hook: scripts: writeTextFile {
+      name = hook;
+      text = ''
+        #!${runtimeShell}
+      '' + concatMapStrings (script: ''
+        ${script} "$@"
+      '') scripts;
+      destination = "/${hook}";
+      executable = true;
+    }) hooks;
+  };
+in writeTextDir "lib/tmpfiles.d/git-repository${replaceStrings [ "/" ] [ "-" ] path}.conf" ''
+  d ${path} 2775 ${owner} ${group}
+
+  f+ ${path}/HEAD - root root - ref: refs/heads/${branch}
+  d ${path}/refs 2775 ${owner} ${group}
+  d ${path}/objects 2775 ${owner} ${group}
+  d ${path}/objects/pack 2775 ${owner} ${group}
+
+  L+ ${path}/config - - - -  ${writeText "git-repository-config" (generators.toGitINI (recursiveUpdate defaultConfig config))}
+  L+ ${path}/description - - - - ${builtins.toFile "git-repository-description" description}
+  L+ ${path}/hooks - - - - ${hooksDir}
+''
diff --git a/overlays/personal/default.nix b/overlays/personal/default.nix
new file mode 100644
index 000000000000..643129f0feec
--- /dev/null
+++ b/overlays/personal/default.nix
@@ -0,0 +1,6 @@
+self: super: {
+  choose = self.callPackage ./choose { };
+
+  declarative-git-repository =
+    self.callPackage ./declarative-git-repository { };
+}