about summary refs log tree commit diff
path: root/pkgs/applications/version-management
diff options
context:
space:
mode:
authorEdmund Wu <fangkazuto@gmail.com>2019-01-21 21:01:52 -0500
committerEdmund Wu <fangkazuto@gmail.com>2019-08-13 11:25:52 -0400
commita2ca6ef26f31c806652ea36b04f95ae01eb701eb (patch)
tree814756908e18131952ce4bf382522366728e13ee /pkgs/applications/version-management
parentf006c88d82267952b745cca94c55c94f8970c75d (diff)
downloadnixlib-a2ca6ef26f31c806652ea36b04f95ae01eb701eb.tar
nixlib-a2ca6ef26f31c806652ea36b04f95ae01eb701eb.tar.gz
nixlib-a2ca6ef26f31c806652ea36b04f95ae01eb701eb.tar.bz2
nixlib-a2ca6ef26f31c806652ea36b04f95ae01eb701eb.tar.lz
nixlib-a2ca6ef26f31c806652ea36b04f95ae01eb701eb.tar.xz
nixlib-a2ca6ef26f31c806652ea36b04f95ae01eb701eb.tar.zst
nixlib-a2ca6ef26f31c806652ea36b04f95ae01eb701eb.zip
sourcehut: init
builds-sr-ht: init at 0.45.13
dispatch-sr-ht: init at 0.11.0
git-sr-ht: init at 0.32.3
hg-sr-ht: init at 0.13.0
lists-sr-ht: init at 0.36.3
man-sr-ht: init at 0.12.4
meta-sr-ht: init at 0.34.3
paste-sr-ht: init at 0.5.1
todo-sr-ht: init at 0.46.8
Diffstat (limited to 'pkgs/applications/version-management')
-rw-r--r--pkgs/applications/version-management/sourcehut/builds.nix60
-rw-r--r--pkgs/applications/version-management/sourcehut/core.nix80
-rw-r--r--pkgs/applications/version-management/sourcehut/default.nix49
-rw-r--r--pkgs/applications/version-management/sourcehut/disable-npm-install.patch14
-rw-r--r--pkgs/applications/version-management/sourcehut/dispatch.nix39
-rw-r--r--pkgs/applications/version-management/sourcehut/git.nix55
-rw-r--r--pkgs/applications/version-management/sourcehut/hg.nix39
-rw-r--r--pkgs/applications/version-management/sourcehut/lists.nix40
-rw-r--r--pkgs/applications/version-management/sourcehut/man.nix37
-rw-r--r--pkgs/applications/version-management/sourcehut/meta.nix48
-rw-r--r--pkgs/applications/version-management/sourcehut/paste.nix37
-rw-r--r--pkgs/applications/version-management/sourcehut/scm.nix55
-rw-r--r--pkgs/applications/version-management/sourcehut/todo.nix42
-rwxr-xr-xpkgs/applications/version-management/sourcehut/update.sh54
-rw-r--r--pkgs/applications/version-management/sourcehut/use-srht-path.patch43
15 files changed, 692 insertions, 0 deletions
diff --git a/pkgs/applications/version-management/sourcehut/builds.nix b/pkgs/applications/version-management/sourcehut/builds.nix
new file mode 100644
index 000000000000..e554afe4a92e
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/builds.nix
@@ -0,0 +1,60 @@
+{ stdenv, fetchgit, buildPythonPackage
+, python
+, buildGoModule
+, srht, redis, celery, pyyaml, markdown }:
+
+let
+  version = "0.45.13";
+
+  buildWorker = src: buildGoModule {
+    inherit src version;
+    pname = "builds-sr-ht-worker";
+    goPackagePath = "git.sr.ht/~sircmpwn/builds.sr.ht/worker";
+
+    modSha256 = "1jm259ncw8dgqp0fqbjn30c4y3v3vwqj41gfh99jx30bwlmpgfax";
+  };
+in buildPythonPackage rec {
+  inherit version;
+  pname = "buildsrht";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/builds.sr.ht";
+    rev = version;
+    sha256 = "002pcj2a98gbmv77a10449w1q6iqhqjz4fim8hm4qm7vn6bwp0hz";
+  };
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    redis
+    celery
+    pyyaml
+    markdown
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  postInstall = ''
+    mkdir -p $out/lib
+    mkdir -p $out/bin/builds.sr.ht
+
+    cp -r images $out/lib
+    cp contrib/submit_image_build $out/bin/builds.sr.ht
+    cp ${buildWorker "${src}/worker"}/bin/worker $out/bin/builds.sr.ht-worker
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/builds.sr.ht;
+    description = "Continuous integration service for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/core.nix b/pkgs/applications/version-management/sourcehut/core.nix
new file mode 100644
index 000000000000..ca054c5cfde9
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/core.nix
@@ -0,0 +1,80 @@
+{ stdenv, fetchgit, fetchNodeModules, buildPythonPackage
+, pgpy, flask, bleach, misaka, humanize, markdown, psycopg2, pygments, requests
+, sqlalchemy, flask_login, beautifulsoup4, sqlalchemy-utils, celery, alembic
+, sassc, nodejs-11_x
+, writeText }:
+
+buildPythonPackage rec {
+  pname = "srht";
+  version = "0.52.13";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/core.sr.ht";
+    rev = version;
+    sha256 = "0i7gd2rkq4y4lffxsgb3mql9ddmk3vqckan29w266imrqs6p8c0z";
+  };
+
+  node_modules = fetchNodeModules {
+    src = "${src}/srht";
+    nodejs = nodejs-11_x;
+    sha256 = "0axl50swhcw8llq8z2icwr4nkr5qsw2riih0a040f9wx4xiw4p6p";
+  };
+
+  patches = [
+    ./disable-npm-install.patch
+  ];
+
+  nativeBuildInputs = [
+    sassc
+    nodejs-11_x
+  ];
+
+  propagatedBuildInputs = [
+    pgpy
+    flask
+    bleach
+    misaka
+    humanize
+    markdown
+    psycopg2
+    pygments
+    requests
+    sqlalchemy
+    flask_login
+    beautifulsoup4
+    sqlalchemy-utils
+
+    # Unofficial runtime dependencies?
+    celery
+    alembic
+  ];
+
+  PKGVER = version;
+
+  preBuild = ''
+    cp -r ${node_modules} srht/node_modules
+  '';
+
+  # No actual? tests but seems like it needs this anyway
+  preCheck = let
+    config = writeText "config.ini" ''
+      [webhooks]
+      private-key=K6JupPpnr0HnBjelKTQUSm3Ro9SgzEA2T2Zv472OvzI=
+
+      [meta.sr.ht]
+      origin=http://meta.sr.ht.local
+    '';
+  in ''
+    # Validation needs config option(s)
+    # webhooks <- ( private-key )
+    # meta.sr.ht <- ( origin )
+    cp ${config} config.ini
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/srht;
+    description = "Core modules for sr.ht";
+    license = licenses.bsd3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/default.nix b/pkgs/applications/version-management/sourcehut/default.nix
new file mode 100644
index 000000000000..b7c8eaf3820f
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/default.nix
@@ -0,0 +1,49 @@
+{ python37, openssl_1_1
+, callPackage }:
+
+# To expose the *srht modules, they have to be a python module so we use `buildPythonModule`
+# Then we expose them through all-packages.nix as an application through `toPythonApplication`
+# https://github.com/NixOS/nixpkgs/pull/54425#discussion_r250688781
+
+let
+  fetchNodeModules = callPackage ../../networking/instant-messengers/rambox/fetchNodeModules.nix { };
+
+  python = python37.override {
+    packageOverrides = self: super: {
+      srht = self.callPackage ./core.nix { inherit fetchNodeModules; };
+
+      buildsrht = self.callPackage ./builds.nix { };
+      dispatchsrht = self.callPackage ./dispatch.nix { };
+      gitsrht = self.callPackage ./git.nix { };
+      hgsrht = self.callPackage ./hg.nix { };
+      listssrht = self.callPackage ./lists.nix { };
+      mansrht = self.callPackage ./man.nix { };
+      metasrht = self.callPackage ./meta.nix { };
+      pastesrht = self.callPackage ./paste.nix { };
+      todosrht = self.callPackage ./todo.nix { };
+
+      scmsrht = self.callPackage ./scm.nix { };
+
+      # OVERRIDES
+
+      cryptography = super.cryptography.override {
+        openssl = openssl_1_1;
+      };
+
+      pyopenssl = super.pyopenssl.override {
+        openssl = openssl_1_1;
+      };
+    };
+  };
+in with python.pkgs; {
+  inherit python;
+  buildsrht = toPythonApplication buildsrht;
+  dispatchsrht = toPythonApplication dispatchsrht;
+  gitsrht = toPythonApplication gitsrht;
+  hgsrht = toPythonApplication hgsrht;
+  listssrht = toPythonApplication listssrht;
+  mansrht = toPythonApplication mansrht;
+  metasrht = toPythonApplication metasrht;
+  pastesrht = toPythonApplication pastesrht;
+  todosrht = toPythonApplication todosrht;
+}
diff --git a/pkgs/applications/version-management/sourcehut/disable-npm-install.patch b/pkgs/applications/version-management/sourcehut/disable-npm-install.patch
new file mode 100644
index 000000000000..3a8d1c82b341
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/disable-npm-install.patch
@@ -0,0 +1,14 @@
+diff --git a/setup.py b/setup.py
+index d63bac8..e1d0c35 100755
+--- a/setup.py
++++ b/setup.py
+@@ -5,9 +5,6 @@ import glob
+ import os
+ import sys
+ 
+-if subprocess.call(["npm", "i"], cwd="srht") != 0:
+-    sys.exit(1)
+-
+ ver = os.environ.get("PKGVER") or subprocess.run(['git', 'describe', '--tags'],
+       stdout=subprocess.PIPE).stdout.decode().strip()
+ 
diff --git a/pkgs/applications/version-management/sourcehut/dispatch.nix b/pkgs/applications/version-management/sourcehut/dispatch.nix
new file mode 100644
index 000000000000..c77fc9022771
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/dispatch.nix
@@ -0,0 +1,39 @@
+{ stdenv, fetchgit, buildPythonPackage
+, python
+, srht, pyyaml, PyGithub, cryptography }:
+
+buildPythonPackage rec {
+  pname = "dispatchsrht";
+  version = "0.11.0";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/dispatch.sr.ht";
+    rev = version;
+    sha256 = "1kahl2gy5a5li79djwkzkglkw2s7pl4d29bzqp8c53r0xvx4sqkz";
+  };
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    pyyaml
+    PyGithub
+    cryptography
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://dispatch.sr.ht/~sircmpwn/dispatch.sr.ht;
+    description = "Task dispatcher and service integration tool for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/git.nix b/pkgs/applications/version-management/sourcehut/git.nix
new file mode 100644
index 000000000000..996663761a7d
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/git.nix
@@ -0,0 +1,55 @@
+{ stdenv, fetchgit, buildPythonPackage
+, python
+, buildGoModule
+, srht, pygit2, scmsrht }:
+
+let
+  version = "0.32.3";
+
+  buildDispatcher = src: buildGoModule {
+    inherit src version;
+    pname = "git-sr-ht-dispatcher";
+    goPackagePath = "git.sr.ht/~sircmpwn/git.sr.ht/gitsrht-dispatch";
+
+    modSha256 = "1lmgmlin460g09dph2hw6yz25d4agqwjhrjv0qqsis7df9qpf3i1";
+  };
+in buildPythonPackage rec {
+  inherit version;
+  pname = "gitsrht";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/git.sr.ht";
+    rev = version;
+    sha256 = "0grycmblhm9dnhcf1kcmn6bclgb9znahk2026dan58m9j9pja5vw";
+  };
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    pygit2
+    scmsrht
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  # TODO: Remove redundant mkdir?
+  postInstall = ''
+    mkdir -p $out/bin
+    cp ${buildDispatcher "${src}/gitsrht-dispatch"}/bin/gitsrht-dispatch $out/bin/gitsrht-dispatch
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/git.sr.ht;
+    description = "Git repository hosting service for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/hg.nix b/pkgs/applications/version-management/sourcehut/hg.nix
new file mode 100644
index 000000000000..938176484686
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/hg.nix
@@ -0,0 +1,39 @@
+{ stdenv, fetchhg, buildPythonPackage
+, python
+, srht, hglib, scmsrht, unidiff }:
+
+buildPythonPackage rec {
+  pname = "hgsrht";
+  version = "0.13.0";
+
+  src = fetchhg {
+    url = "https://hg.sr.ht/~sircmpwn/hg.sr.ht";
+    rev = version;
+    sha256 = "0qkknvja0pyk69fvzqafj3x8hi5miw22nmksvifbrjcqph8jknqg";
+  };
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    hglib
+    scmsrht
+    unidiff
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/hg.sr.ht;
+    description = "Mercurial repository hosting service for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/lists.nix b/pkgs/applications/version-management/sourcehut/lists.nix
new file mode 100644
index 000000000000..ac36a219a912
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/lists.nix
@@ -0,0 +1,40 @@
+{ stdenv, fetchgit, buildPythonPackage
+, python
+, srht, asyncpg, unidiff, aiosmtpd, emailthreads }:
+
+buildPythonPackage rec {
+  pname = "listssrht";
+  version = "0.36.3";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/lists.sr.ht";
+    rev = version;
+    sha256 = "1q2z2pjwz4zifsrkxab9b9jh1vzayjqych1cx3i4859f1swl2gwa";
+  };
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    asyncpg
+    unidiff
+    aiosmtpd
+    emailthreads
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/lists.sr.ht;
+    description = "Mailing list service for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/man.nix b/pkgs/applications/version-management/sourcehut/man.nix
new file mode 100644
index 000000000000..a0198cb52cf5
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/man.nix
@@ -0,0 +1,37 @@
+{ stdenv, fetchgit, buildPythonPackage
+, python
+, srht, pygit2 }:
+
+buildPythonPackage rec {
+  pname = "mansrht";
+  version = "0.12.4";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/man.sr.ht";
+    rev = version;
+    sha256 = "1csnw71yh5zw7l17xmmxyskwiqbls0ynbbjrg45y5k1i3622mhiy";
+  };
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    pygit2
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/man.sr.ht;
+    description = "Wiki service for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/meta.nix b/pkgs/applications/version-management/sourcehut/meta.nix
new file mode 100644
index 000000000000..af3685c472cf
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/meta.nix
@@ -0,0 +1,48 @@
+{ stdenv, fetchgit, buildPythonPackage
+, python
+, pgpy, srht, redis, bcrypt, qrcode, stripe, zxcvbn, alembic, pystache
+, sshpubkeys, weasyprint, prometheus_client }:
+
+buildPythonPackage rec {
+  pname = "metasrht";
+  version = "0.34.3";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/meta.sr.ht";
+    rev = version;
+    sha256 = "1yj3npw1vlqawzj6q1mh6qryx009dg5prja9fn6rasfmxjn2gr7v";
+  };
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    pgpy
+    srht
+    redis
+    bcrypt
+    qrcode
+    stripe
+    zxcvbn
+    alembic
+    pystache
+    sshpubkeys
+    weasyprint
+    prometheus_client
+  ];
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/meta.sr.ht;
+    description = "Account management service for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/paste.nix b/pkgs/applications/version-management/sourcehut/paste.nix
new file mode 100644
index 000000000000..47153d9f204e
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/paste.nix
@@ -0,0 +1,37 @@
+{ stdenv, fetchgit, buildPythonPackage
+, python
+, srht, pyyaml }:
+
+buildPythonPackage rec {
+  pname = "pastesrht";
+  version = "0.5.1";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/paste.sr.ht";
+    rev = version;
+    sha256 = "0bzw03hcwi1pw16kliqjsr7kphqq3qw0pbpdjqkcs7jdr0a59vny";
+  };
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    pyyaml
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/paste.sr.ht;
+    description = "Ad-hoc text file hosting service for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/scm.nix b/pkgs/applications/version-management/sourcehut/scm.nix
new file mode 100644
index 000000000000..ef6ed3a744b6
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/scm.nix
@@ -0,0 +1,55 @@
+{ stdenv, fetchgit, buildPythonPackage
+, srht, redis, pyyaml, buildsrht
+, writeText }:
+
+buildPythonPackage rec {
+  pname = "scmsrht";
+  version = "0.13.3";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/scm.sr.ht";
+    rev = version;
+    sha256 = "0bapddgfqrs27y6prd6kwpz6jdlr33zdqr6ci6ixi584a7z8z7d6";
+  };
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    redis
+    pyyaml
+    buildsrht
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+  '';
+
+  # No actual? tests but seems like it needs this anyway
+  preCheck = let
+    config = writeText "config.ini" ''
+      [webhooks]
+      private-key=K6JupPpnr0HnBjelKTQUSm3Ro9SgzEA2T2Zv472OvzI=
+
+      [builds.sr.ht]
+      origin=http://builds.sr.ht.local
+      oauth-client-id=
+
+      [meta.sr.ht]
+      origin=http://meta.sr.ht.local
+    '';
+  in ''
+    # Validation needs config option(s)
+    # webhooks <- ( private-key )
+    # meta.sr.ht <- ( origin )
+    # builds.sr.ht <- ( origin, oauth-client-id )
+    cp ${config} config.ini
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://git.sr.ht/~sircmpwn/git.sr.ht;
+    description = "Shared support code for sr.ht source control services.";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/todo.nix b/pkgs/applications/version-management/sourcehut/todo.nix
new file mode 100644
index 000000000000..6b67478aa674
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/todo.nix
@@ -0,0 +1,42 @@
+{ stdenv, fetchgit, buildPythonPackage
+, python
+, srht, redis, alembic, pystache }:
+
+buildPythonPackage rec {
+  pname = "todosrht";
+  version = "0.46.8";
+
+  src = fetchgit {
+    url = "https://git.sr.ht/~sircmpwn/todo.sr.ht";
+    rev = version;
+    sha256 = "17nqqy81535jnkidjiqv8v2301w5wzbbvx4czib69aagw1l85gnn";
+  };
+
+  patches = [
+    ./use-srht-path.patch
+  ];
+
+  nativeBuildInputs = srht.nativeBuildInputs;
+
+  propagatedBuildInputs = [
+    srht
+    redis
+    alembic
+    pystache
+  ];
+
+  preBuild = ''
+    export PKGVER=${version}
+    export SRHT_PATH=${srht}/${python.sitePackages}/srht
+  '';
+
+  # Tests require a network connection
+  doCheck = false;
+
+  meta = with stdenv.lib; {
+    homepage = https://todo.sr.ht/~sircmpwn/todo.sr.ht;
+    description = "Ticket tracking service for the sr.ht network";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ eadwu ];
+  };
+}
diff --git a/pkgs/applications/version-management/sourcehut/update.sh b/pkgs/applications/version-management/sourcehut/update.sh
new file mode 100755
index 000000000000..fdc0639c4c6e
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/update.sh
@@ -0,0 +1,54 @@
+#! /usr/bin/env nix-shell
+#! nix-shell -i bash -p git mercurial common-updater-scripts
+
+cd "$(dirname "${BASH_SOURCE[0]}")"
+root=../../../..
+
+default() {
+  (cd "$root" && nix-instantiate --eval --strict -A "sourcehut.python.pkgs.$1.meta.position" | sed -re 's/^"(.*):[0-9]+"$/\1/')
+}
+
+version() {
+  (cd "$root" && nix-instantiate --eval --strict -A "sourcehut.python.pkgs.$1.version" | tr -d '"')
+}
+
+src_url() {
+  (cd "$root" && nix-instantiate --eval --strict -A "sourcehut.python.pkgs.$1.src.drvAttrs.url" | tr -d '"')
+}
+
+get_latest_version() {
+  src="$(src_url "$1")"
+  tmp=$(mktemp -d)
+
+  if [ "$1" = "hgsrht" ]; then
+    hg clone "$src" "$tmp" &> /dev/null
+    printf "%s" "$(cd "$tmp" && hg log --limit 1 --template '{latesttag}')"
+  else
+    git clone "$src" "$tmp"
+    printf "%s" "$(cd "$tmp" && git describe $(git rev-list --tags --max-count=1))"
+  fi
+}
+
+update_version() {
+  default_nix="$(default "$1")"
+  version_old="$(version "$1")"
+  version="$(get_latest_version "$1")"
+
+  (cd "$root" && update-source-version "sourcehut.python.pkgs.$1" "$version")
+
+  git add "$default_nix"
+  git commit -m "$1: $version_old -> $version"
+}
+
+services=( "srht" "buildsrht" "dispatchsrht" "gitsrht" "hgsrht" "listssrht" "mansrht" "metasrht"
+           "pastesrht" "todosrht" "scmsrht" )
+
+# Whether or not a specific service is requested
+if [ -n "$1" ]; then
+  version="$(get_latest_version "$1")"
+  (cd "$root" && update-source-version "sourcehut.python.pkgs.$1" "$version")
+else
+  for service in "${services[@]}"; do
+    update_version "$service"
+  done
+fi
diff --git a/pkgs/applications/version-management/sourcehut/use-srht-path.patch b/pkgs/applications/version-management/sourcehut/use-srht-path.patch
new file mode 100644
index 000000000000..43b494bf9d21
--- /dev/null
+++ b/pkgs/applications/version-management/sourcehut/use-srht-path.patch
@@ -0,0 +1,43 @@
+diff --git a/setup.py b/setup.py
+index e6ecfb6..89fa92a 100755
+--- a/setup.py
++++ b/setup.py
+@@ -5,28 +5,16 @@ import os
+ import site
+ import sys
+ 
+-if hasattr(site, 'getsitepackages'):
+-    pkg_dirs = site.getsitepackages()
+-    if site.getusersitepackages():
+-        pkg_dirs.append(site.getusersitepackages())
+-    for pkg_dir in pkg_dirs:
+-        srht_path = os.path.join(pkg_dir, "srht")
+-        if os.path.isdir(srht_path):
+-            break
+-    else:
+-        raise Exception("Can't find core srht module in your site packages "
+-            "directories. Please install it first.")
+-else:
+-    srht_path = os.getenv("SRHT_PATH")
+-    if not srht_path:
+-        raise Exception("You're running inside a virtual environment. "
+-            "Due to virtualenv limitations, you need to set the "
+-            "$SRHT_PATH environment variable to the path of the "
+-            "core srht module.")
+-    elif not os.path.isdir(srht_path):
+-        raise Exception(
+-            "The $SRHT_PATH environment variable points to an invalid "
+-            "directory: {}".format(srht_path))
++srht_path = os.getenv("SRHT_PATH")
++if not srht_path:
++    raise Exception("You're running inside a virtual environment. "
++        "Due to virtualenv limitations, you need to set the "
++        "$SRHT_PATH environment variable to the path of the "
++        "core srht module.")
++elif not os.path.isdir(srht_path):
++    raise Exception(
++        "The $SRHT_PATH environment variable points to an invalid "
++        "directory: {}".format(srht_path))
+ 
+ subp = subprocess.run(["make", "SRHT_PATH=" + srht_path])
+ if subp.returncode != 0: