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.nix5
-rw-r--r--overlays/patches/cgit/ui-commit-use-Git-raw-note-format.patch195
-rw-r--r--overlays/patches/default.nix17
-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.nix16
-rw-r--r--overlays/patches/firefox/beta/D6695.diff281
-rw-r--r--overlays/patches/firefox/nightly/D6695.diff159
-rw-r--r--overlays/patches/firefox/packages.nix27
-rw-r--r--overlays/patches/firefox/profiles.ini8
-rw-r--r--overlays/patches/firefox/release/D6695.diff282
-rw-r--r--overlays/patches/firefox/user.js1
-rw-r--r--overlays/patches/public-inbox/0003-view-don-t-show-page-if-no-links-follow-it.patch27
-rw-r--r--overlays/patches/public-inbox/0004-view-don-t-500-if-no-mail-received-yet.patch25
-rw-r--r--overlays/patches/public-inbox/0005-wwwstream-make-source-info-configurable.patch112
-rw-r--r--overlays/patches/public-inbox/default.nix9
-rw-r--r--overlays/patches/python/default.nix11
-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/tmux/default.nix7
-rw-r--r--overlays/scripts/choose/choose.in20
-rw-r--r--overlays/scripts/choose/choosebin.in17
-rw-r--r--overlays/scripts/choose/default.nix8
-rw-r--r--overlays/scripts/default.nix3
23 files changed, 1381 insertions, 0 deletions
diff --git a/overlays/patches/cgit/default.nix b/overlays/patches/cgit/default.nix
new file mode 100644
index 000000000000..fa63bf5f14ed
--- /dev/null
+++ b/overlays/patches/cgit/default.nix
@@ -0,0 +1,5 @@
+{ cgit }:
+
+cgit.overrideAttrs ({ patches ? [], ... }: {
+  patches = patches ++ [ ./ui-commit-use-Git-raw-note-format.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/default.nix b/overlays/patches/default.nix
new file mode 100644
index 000000000000..4c664ba3ab11
--- /dev/null
+++ b/overlays/patches/default.nix
@@ -0,0 +1,17 @@
+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;
+  };
+
+  public-inbox = self.callPackage ./public-inbox {
+    inherit (super) public-inbox;
+  };
+
+  python3 = self.callPackage ./python { python = super.python3; };
+
+  tmux = self.callPackage ./tmux { inherit (super) tmux; };
+}
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..2a23ee5e0cc9
--- /dev/null
+++ b/overlays/patches/dino/default.nix
@@ -0,0 +1,16 @@
+{ dino, fetchpatch }:
+
+dino.overrideAttrs ({ patches ? [], ... }: {
+  patches = patches ++ [
+    ./0001-add-an-option-to-enable-omemo-by-default-in-new-conv.patch
+    (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/D6695.diff b/overlays/patches/firefox/beta/D6695.diff
new file mode 100644
index 000000000000..f8a8deeb8581
--- /dev/null
+++ b/overlays/patches/firefox/beta/D6695.diff
@@ -0,0 +1,281 @@
+diff --git a/toolkit/moz.build b/toolkit/moz.build
+index 109fb2c..0b871d9 100644
+--- a/toolkit/moz.build
++++ b/toolkit/moz.build
+@@ -72,3 +72,5 @@ with Files('mozapps/preferences/**'):
+ with Files('pluginproblem/**'):
+     BUG_COMPONENT = ('Core', 'Plug-ins')
+ 
++if CONFIG['ENABLE_TESTS']:
++    DIRS += ['tests/gtest']
+diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
+index aafe82e..2d850fe 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);
+     }
+   }
+@@ -1238,7 +1231,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;
+   }
+ 
+@@ -1367,6 +1361,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)) {
+@@ -1390,6 +1387,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;
+@@ -1411,8 +1411,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"
+@@ -1523,20 +1566,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);
+@@ -1554,20 +1589,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);
+@@ -1625,9 +1652,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
+@@ -1647,8 +1671,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 90e4ec9..8b838ec 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/nightly/D6695.diff b/overlays/patches/firefox/nightly/D6695.diff
new file mode 100644
index 000000000000..31a08471a8cc
--- /dev/null
+++ b/overlays/patches/firefox/nightly/D6695.diff
@@ -0,0 +1,159 @@
+--- 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);
+     }
+   }
+@@ -1249,8 +1242,6 @@ nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile** aResult,
+             nsDependentCString(hasVendor ? GetAppVendor() : GetAppName())))) {
+       return NS_ERROR_FAILURE;
+     }
+-  } else if (NS_FAILED(localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla")))) {
+-    return NS_ERROR_FAILURE;
+   }
+
+   if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("updates"))) ||
+@@ -1378,6 +1369,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)) {
+@@ -1401,6 +1395,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;
+@@ -1422,8 +1419,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"
+@@ -1534,20 +1574,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);
+@@ -1565,20 +1597,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);
+@@ -1636,9 +1660,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
+@@ -1658,9 +1679,6 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
+       folder.Append(vendor);
+       ToLowerCase(folder);
+
+-      rv = aFile->AppendNative(folder);
+-      NS_ENSURE_SUCCESS(rv, rv);
+-
+       folder.Truncate();
+     }
+
diff --git a/overlays/patches/firefox/packages.nix b/overlays/patches/firefox/packages.nix
new file mode 100644
index 000000000000..ec4fdcc5336e
--- /dev/null
+++ b/overlays/patches/firefox/packages.nix
@@ -0,0 +1,27 @@
+{ firefoxPackages, clangStdenv }:
+
+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 {
+    stdenv = clangStdenv;
+  }).overrideAttrs ({ patches ? [], ... }: {
+    patches = patches ++ [ release/D6695.diff ];
+  });
+
+  firefox-beta = (firefox-beta.override {
+    stdenv = clangStdenv;
+  }).overrideAttrs ({ patches ? [], ... }: {
+    patches = patches ++ [ beta/D6695.diff ];
+  });
+
+  firefox-nightly = (firefox-nightly.override {
+    stdenv = clangStdenv;
+  }).overrideAttrs ({ patches ? [], ... }: {
+    patches = patches ++ [ nightly/D6695.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/D6695.diff b/overlays/patches/firefox/release/D6695.diff
new file mode 100644
index 000000000000..e6425af02ca6
--- /dev/null
+++ b/overlays/patches/firefox/release/D6695.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/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/public-inbox/0003-view-don-t-show-page-if-no-links-follow-it.patch b/overlays/patches/public-inbox/0003-view-don-t-show-page-if-no-links-follow-it.patch
new file mode 100644
index 000000000000..811d6149d994
--- /dev/null
+++ b/overlays/patches/public-inbox/0003-view-don-t-show-page-if-no-links-follow-it.patch
@@ -0,0 +1,27 @@
+From 054697a5129725f900a84bbdfee356a4f5373376 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Thu, 16 Jan 2020 18:08:33 +0000
+Subject: [PATCH 3/5] view: don't show `page:' if no links follow it
+
+---
+ lib/PublicInbox/View.pm | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm
+index 39b04174..aebf7fe9 100644
+--- a/lib/PublicInbox/View.pm
++++ b/lib/PublicInbox/View.pm
+@@ -1157,7 +1157,9 @@ sub pagination_footer ($$) {
+ 		$next = $next ? "$next " : '     ';
+ 		$prev .= qq! <a\nhref='$latest'>latest</a>!;
+ 	}
+-	"<hr><pre>page: $next$prev</pre>";
++	if ($prev || $next) {
++		"<hr><pre>page: $next$prev</pre>";
++	}
+ }
+ 
+ sub index_nav { # callback for WwwStream
+-- 
+2.26.1
+
diff --git a/overlays/patches/public-inbox/0004-view-don-t-500-if-no-mail-received-yet.patch b/overlays/patches/public-inbox/0004-view-don-t-500-if-no-mail-received-yet.patch
new file mode 100644
index 000000000000..eb33468e1992
--- /dev/null
+++ b/overlays/patches/public-inbox/0004-view-don-t-500-if-no-mail-received-yet.patch
@@ -0,0 +1,25 @@
+From 2712913f07d83a6a33bbdc55a1edee0a008e5b2e Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Thu, 16 Jan 2020 18:09:12 +0000
+Subject: [PATCH 4/5] view: don't 500 if no mail received yet
+
+---
+ lib/PublicInbox/View.pm | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm
+index aebf7fe9..b40108bc 100644
+--- a/lib/PublicInbox/View.pm
++++ b/lib/PublicInbox/View.pm
+@@ -1083,7 +1083,7 @@ sub acc_topic {
+ sub dump_topics {
+ 	my ($ctx) = @_;
+ 	my $order = delete $ctx->{order}; # [ ds, subj1, subj2, subj3, ... ]
+-	if (!@$order) {
++	if (!defined $order || !@$order) {
+ 		$ctx->{-html_tip} = '<pre>[No topics in range]</pre>';
+ 		return 404;
+ 	}
+-- 
+2.26.1
+
diff --git a/overlays/patches/public-inbox/0005-wwwstream-make-source-info-configurable.patch b/overlays/patches/public-inbox/0005-wwwstream-make-source-info-configurable.patch
new file mode 100644
index 000000000000..605100cd38ae
--- /dev/null
+++ b/overlays/patches/public-inbox/0005-wwwstream-make-source-info-configurable.patch
@@ -0,0 +1,112 @@
+From f119d4315be998de65d5a1b56fa643fb9084410b Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Fri, 17 Jan 2020 15:21:42 +0000
+Subject: [PATCH 5/5] wwwstream: make source info configurable
+
+---
+ Documentation/public-inbox-config.pod |  6 ++++++
+ lib/PublicInbox/WwwListing.pm         |  9 +++++----
+ lib/PublicInbox/WwwStream.pm          | 28 +++++++++++++++++++++++----
+ 3 files changed, 35 insertions(+), 8 deletions(-)
+
+diff --git a/Documentation/public-inbox-config.pod b/Documentation/public-inbox-config.pod
+index 1c5ba015..5ae23924 100644
+--- a/Documentation/public-inbox-config.pod
++++ b/Documentation/public-inbox-config.pod
+@@ -186,6 +186,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/WwwListing.pm b/lib/PublicInbox/WwwListing.pm
+index 03534f03..f1a1fd81 100644
+--- a/lib/PublicInbox/WwwListing.pm
++++ b/lib/PublicInbox/WwwListing.pm
+@@ -87,8 +87,8 @@ sub ibx_entry {
+ 	$tmp;
+ }
+ 
+-sub html ($$) {
+-	my ($env, $list) = @_;
++sub html ($$$) {
++	my ($pi_config, $env, $list) = @_;
+ 	my $title = 'public-inbox';
+ 	my $out = '';
+ 	my $code = 404;
+@@ -107,7 +107,8 @@ sub html ($$) {
+ 		$out = '<pre>'.$l->linkify_2(ascii_html($tmp)).'</pre><hr>';
+ 	}
+ 	$out = "<html><head><title>$title</title></head><body>" . $out;
+-	$out .= '<pre>'. PublicInbox::WwwStream::code_footer($env) .
++	$out .= '<pre>' .
++	        PublicInbox::WwwStream::code_footer($pi_config, $env) .
+ 		'</pre></body></html>';
+ 
+ 	my $h = [ 'Content-Type', 'text/html; charset=UTF-8' ];
+@@ -231,7 +232,7 @@ sub call {
+ 		js($env, $list);
+ 	} else { # /
+ 		my $list = $self->{www_cb}->($self, $env, 'www');
+-		html($env, $list);
++		html($self->{pi_config}, $env, $list);
+ 	}
+ }
+ 
+diff --git a/lib/PublicInbox/WwwStream.pm b/lib/PublicInbox/WwwStream.pm
+index 0f4f55d0..09473c9f 100644
+--- a/lib/PublicInbox/WwwStream.pm
++++ b/lib/PublicInbox/WwwStream.pm
+@@ -76,10 +76,30 @@ sub _html_top ($) {
+ 		"</head><body>". $top . $tip;
+ }
+ 
+-sub code_footer ($) {
+-	my ($env) = @_;
++sub get_user_source_info ($) {
++	my ($pi_config) = @_;
++
++	local $/;
++	my $path = $pi_config->{'publicinbox.sourceinfo'};
++	if (!defined($path)) {
++		return;
++	}
++	open my $fh, '<', $path or do {
++		warn "Failed to open publicinbox.sourceinfo=$path: $!\n";
++		return;
++	};
++	<$fh>;
++}
++
++sub code_footer {
++	my ($pi_config, $env) = @_;
++
+ 	my $u = PublicInbox::Hval::prurl($env, $CODE_URL);
+-	qq(AGPL code for this site: git clone <a\nhref="$u">$u</a>)
++	my $default_info = qq(git clone <a\n href="$u">$u</a>);
++
++	my $info = get_user_source_info($pi_config) || $default_info;
++
++	"AGPL code for this site: $info"
+ }
+ 
+ sub _html_end {
+@@ -153,7 +173,7 @@ EOF
+ 	'<hr><pre>'.join("\n\n",
+ 		$desc,
+ 		$urls,
+-		code_footer($ctx->{env})
++		code_footer($ctx->{www}->{pi_config}, $ctx->{env})
+ 	).'</pre></body></html>';
+ }
+ 
+-- 
+2.26.1
+
diff --git a/overlays/patches/public-inbox/default.nix b/overlays/patches/public-inbox/default.nix
new file mode 100644
index 000000000000..f9f573787c1c
--- /dev/null
+++ b/overlays/patches/public-inbox/default.nix
@@ -0,0 +1,9 @@
+{ public-inbox }:
+
+public-inbox.overrideAttrs ({ patches ? [], ... }: {
+  patches = patches ++ [
+    ./0003-view-don-t-show-page-if-no-links-follow-it.patch
+    ./0004-view-don-t-500-if-no-mail-received-yet.patch
+    ./0005-wwwstream-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..332cebfcb3fc
--- /dev/null
+++ b/overlays/patches/python/default.nix
@@ -0,0 +1,11 @@
+{ python, lib }:
+
+python.override {
+  packageOverrides = lib.composeExtensions python.packageOverrides (
+    final: super: with final; {
+      hyperkitty = callPackage ./packages/hyperkitty {
+        inherit (super) hyperkitty;
+      };
+    }
+  );
+}
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/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/scripts/choose/choose.in b/overlays/scripts/choose/choose.in
new file mode 100644
index 000000000000..7f60b47386a3
--- /dev/null
+++ b/overlays/scripts/choose/choose.in
@@ -0,0 +1,20 @@
+#! @execline@/bin/execlineb -S0
+
+define -s fzf_opts "--reverse"
+
+ifelse { importas -i _ DISPLAY }
+{
+  alacritty --class float -e
+  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/scripts/choose/choosebin.in b/overlays/scripts/choose/choosebin.in
new file mode 100644
index 000000000000..7f8ea520c994
--- /dev/null
+++ b/overlays/scripts/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/scripts/choose/default.nix b/overlays/scripts/choose/default.nix
new file mode 100644
index 000000000000..d4e845f8b967
--- /dev/null
+++ b/overlays/scripts/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/scripts/default.nix b/overlays/scripts/default.nix
new file mode 100644
index 000000000000..983d32d867a4
--- /dev/null
+++ b/overlays/scripts/default.nix
@@ -0,0 +1,3 @@
+self: super: {
+  choose = self.callPackage ./choose { };
+}