Start NUR rewrite

This commit is contained in:
Charlotte 🦝 Delenk 2022-09-25 14:06:44 +01:00
parent 2afcb8b5ba
commit 3bbfeb2422
Signed by: darkkirb
GPG key ID: AB2BD8DAF2E37122
28 changed files with 29579 additions and 1928 deletions

22
LICENSE Normal file
View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2022 Charlotte 🦝 Delenk
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,83 @@
{
lib,
mkYarnPackage,
fetchFromGitea,
fetchYarnDeps,
fixup_yarn_lock,
yarn,
nodejs,
jpegoptim,
oxipng,
nodePackages,
writeScript,
applyPatches,
python3,
libsass,
pkg-config,
}: let
source = builtins.fromJSON (builtins.readFile ./source.json);
src = applyPatches {
src = fetchFromGitea {
domain = "akkoma.dev";
owner = "AkkomaGang";
repo = "admin-fe";
inherit (source) rev sha256;
};
patches = [./admin-fe.patch];
};
in
mkYarnPackage rec {
pname = "admin-fe";
version = source.date;
inherit src;
yarnNix = ./yarn.nix;
nativeBuildInputs = [
jpegoptim
oxipng
nodePackages.svgo
];
configurePhase = "cp -r $node_modules node_modules";
buildPhase = ''
export NODE_OPTIONS="--openssl-legacy-provider"
yarn build:prod --offline
'';
installPhase = "cp -rv dist $out";
distPhase = ''
# (Losslessly) optimise compression of image artifacts
find $out -type f -name '*.jpg' -execdir ${jpegoptim}/bin/jpegoptim -w$NIX_BUILD_CORES {} \;
find $out -type f -name '*.png' -execdir ${oxipng}/bin/oxipng -o max -t $NIX_BUILD_CORES {} \;
find $out -type f -name '*.svg' -execdir ${nodePackages.svgo}/bin/svgo {} \;
'';
yarnPreBuild = ''
mkdir -p $HOME/.node-gyp/${nodejs.version}
echo 9 > $HOME/.node-gyp/${nodejs.version}/installVersion
ln -sfv ${nodejs}/include $HOME/.node-gyp/${nodejs.version}
export npm_config_nodedir=${nodejs}
'';
pkgConfig = {
node-sass = {
buildInputs = [python3 libsass pkg-config];
postInstall = ''
LIBSASS_EXT=auto yarn --offline run build
rm build/config.gypi
'';
};
};
passthru = {
updateScript = writeScript "update-pleroma-fe" ''
${../../scripts/update-git.sh} https://akkoma.dev/AkkomaGang/admin-fe.git akkoma/admin-fe/source.json
SRC_PATH=$(nix-build -E '(import ./. {}).${pname}.src')
${../../scripts/update-yarn.sh} $SRC_PATH akkoma/admin-fe/yarn.nix
'';
};
meta = with lib; {
description = "Administration Frontend for Akkoma and Pleroma";
homepage = "https://akkoma.dev/AkkomaGang/admin-fe/";
license = licenses.mit;
};
}

View file

@ -0,0 +1,11 @@
{
"url": "https://akkoma.dev/AkkomaGang/admin-fe.git",
"rev": "6b131e0779b16f8f3c1021b2a0e72b4e7a271c4c",
"date": "2022-08-29T19:36:36+00:00",
"path": "/nix/store/mzsirdh6cd5q3aqj15hvf37lp21ypg4c-admin-fe",
"sha256": "1280fmdbwv9wbh7mr99cq6dhnfzqg32sf86z3psrryrikvr1dabn",
"fetchLFS": false,
"fetchSubmodules": false,
"deepClone": false,
"leaveDotGit": false
}

View file

@ -0,0 +1 @@
sha256-h+QUBT2VwPWu2l05Zkcp+0vHN/x40uXxw2KYjq7l/Xk=

13163
akkoma/admin-fe/yarn.nix Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -889,24 +889,3 @@ index 000000000..eaa3fe695
+ {:ok, %{mrf_sample: %{content: "<br/><emph>This post contained media without content description. Offending media has been removed from this post.</emph>"}}}
+ end
+end
diff --git a/mix.exs b/mix.exs
index ef038ce74..a28d98917 100644
--- a/mix.exs
+++ b/mix.exs
@@ -78,7 +78,7 @@ def application do
:comeonin,
:quack,
:fast_sanitize,
- :os_mon,
+# :os_mon,
:ssl
],
included_applications: [:ex_syslogger]
@@ -197,6 +197,7 @@ defp deps do
# indirect dependency version override
{:plug, "~> 1.10.4", override: true},
+ {:temple, git: "https://akkoma.dev/AkkomaGang/temple.git", ref: "066a699ade472d8fa42a9d730b29a61af9bc8b59"},
## dev & test
{:ex_doc, "~> 0.22", only: :dev, runtime: false},

View file

@ -1,22 +1,42 @@
{
pkgs,
inputs,
}:
with pkgs; let
mkYarnPackage =
(yarn2nix-moretea.override (super: {
nodejs = pkgs.nodejs-16_x;
}))
.mkYarnPackage;
in rec {
akkoma = beamPackages.mixRelease rec {
lib,
beamPackages,
fetchFromGitea,
fetchFromGitHub,
fetchFromGitLab,
cmake,
file,
writeText,
writeScript,
applyPatches,
...
}: let
source = builtins.fromJSON (builtins.readFile ./source.json);
src = applyPatches {
src = fetchFromGitea {
domain = "akkoma.dev";
owner = "AkkomaGang";
repo = "akkoma";
inherit (source) rev sha256;
};
patches = [./akkoma.patch];
};
in
beamPackages.mixRelease rec {
pname = "akkoma";
version = inputs.akkoma.lastModifiedDate;
version = source.date;
src = inputs.akkoma;
patches = [
./akkoma.patch
];
inherit src;
# Correct version number and remove dependency on OS_Mon
postPatch = ''
sed -E -i \
-e 's/(version\(")\d+\.\d+\.\d+("\))/\1${version}\2/' \
-e 's/(^|\s):os_mon,//' \
mix.exs
'';
# cf. https://github.com/whitfin/cachex/issues/205
stripDebug = false;
mixNixDeps = import ./mix.nix {
@ -38,68 +58,75 @@ in rec {
};
beamDeps = with final; [];
};
crypt = beamPackages.buildRebar3 rec {
name = "crypt";
version = "0.4.3";
src = fetchFromGitHub {
owner = "msantos";
repo = "crypt";
rev = "f75cd55325e33cbea198fb41fe41871392f8fb76";
sha256 = "sha256-ZYhZTe7cTITkl8DZ4z2IOlxTX5gnbJImu/lVJ2ZjR1o=";
};
postInstall = "mv $out/lib/erlang/lib/crypt-${version}/priv/{source,crypt}.so";
beamDeps = with final; [elixir_make];
};
elasticsearch = beamPackages.buildMix rec {
name = "elasticsearch";
version = "1.0.1";
src = fetchFromGitea {
domain = "akkoma.dev";
owner = "AkkomaGang";
repo = "elasticsearch-elixir";
rev = "6cd946f75f6ab9042521a009d1d32d29a90113ca";
sha256 = "0pf8m5a91nqkcivyp8q2p2p08rv0whb9zgkpk9g3lmbyb4fr1n8a";
hash = "sha256-CtmQHVl+VTpemne+nxbkYGcErrgCo+t3ZBPbkFSpyF0=";
};
beamDeps = with final; [];
};
gettext = beamPackages.buildMix {
name = "gettext";
version = "0.19.1";
src = fetchFromGitHub {
owner = "tusooa";
repo = "gettext";
rev = "72fb2496b6c5280ed911bdc3756890e7f38a4808";
hash = "sha256-V0qmE+LcAbVoWsJmWE4fwrduYFIZ5BzK/sGzgLY3eH0=";
};
beamDeps = with final; [];
};
linkify = beamPackages.buildMix rec {
name = "linkify";
version = "0.5.2";
src = fetchFromGitea {
domain = "akkoma.dev";
owner = "AkkomaGang";
repo = "linkify";
rev = "2567e2c1073fa371fd26fd66dfa5bc77b6919c16";
sha256 = "1y7n48clwfgs1gyif85c7zar3xaz6f5frnwl0za0zjvfnjak6z3v";
hash = "sha256-e3wzlbRuyw/UB5Tb7IozX/WR1T+sIBf9C/o5Thki9vg=";
};
beamDeps = with final; [];
};
mfm_parser = beamPackages.buildMix rec {
name = "mfm_parser";
version = "0.1.1";
src = fetchFromGitea {
domain = "akkoma.dev";
owner = "AkkomaGang";
repo = "mfm-parser";
rev = "912fba81152d4d572e457fd5427f9875b2bc3dbe";
sha256 = "0frkklrnxmiq0avsi3pkpx7insg8s81h8j1iy96caasa3h8scxcz";
hash = "sha256-n3WmERxKK8VM8jFIBAPS6GkbT7/zjqi3AjjWbjOdMzs=";
};
beamDeps = with final; [temple];
};
temple = beamPackages.buildMix rec {
name = "temple";
version = "0.9.0-rc.1";
src = fetchFromGitea {
domain = "akkoma.dev";
owner = "AkkomaGang";
repo = "temple";
rev = "066a699ade472d8fa42a9d730b29a61af9bc8b59";
sha256 = "05sqxlzqxlnrcxq6nb1pgdbyxdpwcw20868pif7fv36cckqk63d8";
};
beamDeps = with final; [];
patchPhase = ''
cp config/dev.exs config/prod.exs
'';
};
gettext = beamPackages.buildMix rec {
name = "gettext";
version = "0.19.1";
src = fetchFromGitHub {
owner = "tusooa";
repo = "gettext";
rev = "72fb2496b6c5280ed911bdc3756890e7f38a4808";
sha256 = "0zbq6yv81cy1zv51rr0ra9h6xdy23x75hrn2b9lba0fww89scjjp";
};
beamDeps = with final; [];
beamDeps = with final; [phoenix_view temple];
};
remote_ip = beamPackages.buildMix rec {
name = "remote_ip";
@ -118,48 +145,49 @@ in rec {
search_parser = beamPackages.buildMix rec {
name = "search_parser";
version = "0.1.0";
src = fetchFromGitHub {
owner = "FloatingGhost";
repo = "pleroma-contrib-search-parser";
rev = "08971a81e68686f9ac465cfb6661d51c5e4e1e7f";
sha256 = "0xl3mbcwlhn02igh0nm4c1icy8nf43i1g031lcwkv8bnr8lkvfmi";
hash = "sha256-sbo9Kcp2oT05o2GAF+IgziLPYmCkWgBfFMBCytmqg3Y=";
};
beamDeps = with final; [nimble_parsec];
};
crypt = beamPackages.buildRebar3 rec {
name = "crypt";
version = "0.4.3";
temple = beamPackages.buildMix rec {
name = "temple";
version = "0.9.0-rc.0";
src = fetchFromGitHub {
owner = "msantos";
repo = "crypt";
rev = "f75cd55325e33cbea198fb41fe41871392f8fb76";
sha256 = "sha256-ZYhZTe7cTITkl8DZ4z2IOlxTX5gnbJImu/lVJ2ZjR1o=";
src = fetchFromGitea {
domain = "akkoma.dev";
owner = "AkkomaGang";
repo = "temple";
rev = "066a699ade472d8fa42a9d730b29a61af9bc8b59";
hash = "sha256-qA0z8WTMjO2OixcZBARn/LbuV3s3LGtwZ9nSjj/tWBc=";
};
postInstall = "mv $out/lib/erlang/lib/crypt-${version}/priv/{source,crypt}.so";
beamDeps = with final; [elixir_make];
mixEnv = "dev";
beamDeps = with final; [earmark_parser ex_doc makeup makeup_elixir makeup_erlang nimble_parsec];
};
# Some additional build inputs and build fixes
fast_html = prev.fast_html.override {
nativeBuildInputs = [cmake];
dontUseCmakeConfigure = true;
};
http_signatures = prev.http_signatures.override {
patchPhase = ''
substituteInPlace mix.exs --replace ":logger" ":logger, :public_key"
'';
};
fast_html = prev.fast_html.override {
nativeBuildInputs = [cmake];
dontUseCmakeConfigure = true;
majic = prev.majic.override {
buildInputs = [file];
};
syslog = prev.syslog.override {
buildPlugins = with beamPackages; [pc];
};
majic = prev.majic.override {
buildInputs = [file];
};
mime = prev.mime.override {
patchPhase = let
cfgFile = writeText "config.exs" ''
@ -179,63 +207,20 @@ in rec {
};
};
};
};
akkoma-fe-src = applyPatches {
name = "akkoma-fe-src-${inputs.akkoma-fe.lastModifiedDate}";
src = inputs.akkoma-fe;
patches = [
./akkoma-fe.patch
];
};
akkoma-fe = mkYarnPackage rec {
pname = "akkoma-fe";
version = inputs.akkoma-fe.lastModifiedDate;
src = akkoma-fe-src;
patchPhase = ''
sed -i 's/let commitHash = .*/let commitHash = "${inputs.akkoma-fe.rev}"/' build/webpack.prod.conf.js
sed -i 's/.*git rev-parse.*//' build/webpack.prod.conf.js
'';
configurePhase = "cp -r $node_modules node_modules";
buildPhase = ''
export NODE_OPTIONS="--openssl-legacy-provider"
yarn build --offline
'';
installPhase = "cp -rv dist $out";
distPhase = "true";
};
akkoma-admin-src = applyPatches {
name = "akkoma-admin-fe-src-${inputs.akkoma-admin-fe.lastModifiedDate}";
src = inputs.akkoma-admin-fe;
patches = [
./akkoma-admin.patch
];
};
akkoma-admin-fe = mkYarnPackage rec {
pname = "akkoma-admin-fe";
version = inputs.akkoma-admin-fe.lastModifiedDate;
src = akkoma-admin-src;
configurePhase = "cp -r $node_modules node_modules";
buildPhase = ''
export NODE_OPTIONS="--openssl-legacy-provider"
yarn build:prod --offline
'';
installPhase = "cp -rv dist $out";
distPhase = "true";
yarnPreBuild = ''
mkdir -p $HOME/.node-gyp/${nodejs.version}
echo 9 > $HOME/.node-gyp/${nodejs.version}/installVersion
ln -sfv ${nodejs}/include $HOME/.node-gyp/${nodejs.version}
export npm_config_nodedir=${nodejs}
'';
pkgConfig = {
node-sass = {
buildInputs = [python3 libsass pkg-config];
postInstall = ''
LIBSASS_EXT=auto yarn --offline run build
rm build/config.gypi
'';
};
passthru = {
inherit mixNixDeps;
updateScript = writeScript "update-akkoma" ''
${../scripts/update-git.sh} https://akkoma.dev/AkkomaGang/akkoma.git akkoma/source.json
SRC_PATH=$(nix-build -E '(import ./. {}).${pname}.src')
${../scripts/update-mix.sh} $SRC_PATH akkoma/mix.nix
'';
};
};
}
meta = with lib; {
description = "ActivityPub microblogging server";
homepage = "https://akkoma.dev";
license = licenses.agpl3;
platforms = platforms.unix;
};
}

View file

@ -0,0 +1,68 @@
{
lib,
mkYarnPackage,
fetchFromGitea,
fetchYarnDeps,
fixup_yarn_lock,
yarn,
nodejs,
jpegoptim,
oxipng,
nodePackages,
writeScript,
applyPatches,
}: let
source = builtins.fromJSON (builtins.readFile ./source.json);
src = applyPatches {
src = fetchFromGitea {
domain = "akkoma.dev";
owner = "AkkomaGang";
repo = "pleroma-fe";
inherit (source) rev sha256;
};
patches = [./pleroma-fe.patch];
};
in
mkYarnPackage rec {
pname = "pleroma-fe";
version = source.date;
inherit src;
yarnNix = ./yarn.nix;
nativeBuildInputs = [
jpegoptim
oxipng
nodePackages.svgo
];
# Build scripts assume to be used within a Git repository checkout
patchPhase = ''
sed -E -i \
-e '/^let commitHash =/,/;$/clet commitHash = "${builtins.substring 0 7 source.rev}";' \
build/webpack.prod.conf.js
'';
configurePhase = "cp -r $node_modules node_modules";
buildPhase = ''
export NODE_OPTIONS="--openssl-legacy-provider"
yarn build --offline
'';
installPhase = "cp -rv dist $out";
distPhase = ''
# (Losslessly) optimise compression of image artifacts
find $out -type f -name '*.jpg' -execdir ${jpegoptim}/bin/jpegoptim -w$NIX_BUILD_CORES {} \;
find $out -type f -name '*.png' -execdir ${oxipng}/bin/oxipng -o max -t $NIX_BUILD_CORES {} \;
find $out -type f -name '*.svg' -execdir ${nodePackages.svgo}/bin/svgo {} \;
'';
passthru = {
updateScript = writeScript "update-pleroma-fe" ''
${../../scripts/update-git.sh} https://akkoma.dev/AkkomaGang/pleroma-fe.git akkoma/pleroma-fe/source.json
SRC_PATH=$(nix-build -E '(import ./. {}).${pname}.src')
${../../scripts/update-yarn.sh} $SRC_PATH akkoma/pleroma-fe/yarn.nix
'';
};
meta = with lib; {
description = "Frontend for Akkoma and Pleroma";
homepage = "https://akkoma.dev/AkkomaGang/pleroma-fe/";
license = licenses.agpl3;
};
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
{
"url": "https://akkoma.dev/AkkomaGang/pleroma-fe.git",
"rev": "468eb12573325111fe8405cfbc43407ac9fe2686",
"date": "2022-09-23T10:27:14+00:00",
"path": "/nix/store/m6nbbdapc8d581fam2vrrg98vcfm59pd-pleroma-fe",
"sha256": "0kcmkgzbc9vjilsymkdz8vb60l66haf1cpnzcpqmvr6767v078ha",
"fetchLFS": false,
"fetchSubmodules": false,
"deepClone": false,
"leaveDotGit": false
}

12483
akkoma/pleroma-fe/yarn.nix Normal file

File diff suppressed because it is too large Load diff

11
akkoma/source.json Normal file
View file

@ -0,0 +1,11 @@
{
"url": "https://akkoma.dev/AkkomaGang/akkoma.git",
"rev": "07295f7c8ce8109f1a2df23b0d7c62d230319c82",
"date": "2022-09-20T13:43:14+00:00",
"path": "/nix/store/zdrz6r9pvjpwb04bhai8w6vd5s0ml398-akkoma",
"sha256": "1kf04khili9myxg3034jm2x502ydrzk4076syh84mnny5mmf7cvn",
"fetchLFS": false,
"fetchSubmodules": false,
"deepClone": false,
"leaveDotGit": false
}

View file

@ -1,24 +0,0 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p nix-prefetch-git jq mix2nix
set -e
WORK_DIR=$(mktemp -d)
URL=https://akkoma.dev/AkkomaGang/akkoma
REVISION=$(jq -r '.nodes."akkoma".locked.rev' ../flake.lock)
TARGET_DIR="$PWD"
function cleanup {
grep "fatal" $WORK_DIR/nix-prefetch-git.out >/dev/stderr || true
rm -rf "$WORK_DIR"
}
trap cleanup EXIT
echo "Fetching source code $REVISION from $URL"
JSON=$(nix-prefetch-git --url "$URL" --rev "$REVISION" --leave-dotGit 2> $WORK_DIR/nix-prefetch-git.out)
SHA=$(echo $JSON | jq -r .sha256)
SOURCE_DIR=$(grep '^path is' $WORK_DIR/nix-prefetch-git.out | sed 's/^path is //')
echo "creating mix.nix"
mix2nix $SOURCE_DIR/mix.lock > mix.nix

52
ci.nix Normal file
View file

@ -0,0 +1,52 @@
# This file provides all the buildable and cacheable packages and
# package outputs in your package set. These are what gets built by CI,
# so if you correctly mark packages as
#
# - broken (using `meta.broken`),
# - unfree (using `meta.license.free`), and
# - locally built (using `preferLocalBuild`)
#
# then your CI will be able to build and cache only those packages for
# which this is possible.
{pkgs ? import <nixpkgs> {}}:
with builtins; let
isReserved = n: n == "lib" || n == "overlays" || n == "modules";
isDerivation = p: isAttrs p && p ? type && p.type == "derivation";
isBuildable = p: !(p.meta.broken or false) && p.meta.license.free or true;
isCacheable = p: !(p.preferLocalBuild or false);
shouldRecurseForDerivations = p: isAttrs p && p.recurseForDerivations or false;
nameValuePair = n: v: {
name = n;
value = v;
};
concatMap = builtins.concatMap or (f: xs: concatLists (map f xs));
flattenPkgs = s: let
f = p:
if shouldRecurseForDerivations p
then flattenPkgs p
else if isDerivation p
then [p]
else [];
in
concatMap f (attrValues s);
outputsOf = p: map (o: p.${o}) p.outputs;
nurAttrs = import ./default.nix {inherit pkgs;};
nurPkgs =
flattenPkgs
(listToAttrs
(map (n: nameValuePair n nurAttrs.${n})
(filter (n: !isReserved n)
(attrNames nurAttrs))));
in rec {
buildPkgs = filter isBuildable nurPkgs;
cachePkgs = filter isCacheable buildPkgs;
buildOutputs = concatMap outputsOf buildPkgs;
cacheOutputs = concatMap outputsOf cachePkgs;
}

17
default.nix Normal file
View file

@ -0,0 +1,17 @@
# This file describes your repository contents.
# It should return a set of nix derivations
# and optionally the special attributes `lib`, `modules` and `overlays`.
# It should NOT import <nixpkgs>. Instead, you should take pkgs as an argument.
# Having pkgs default to <nixpkgs> is fine though, and it lets you use short
# commands such as:
# nix-build -A mypackage
{pkgs ? import <nixpkgs> {}}: {
# The `lib`, `modules`, and `overlay` names are special
lib = import ./lib {inherit pkgs;}; # functions
modules = import ./modules; # NixOS modules
overlays = import ./overlays; # nixpkgs overlays
akkoma = pkgs.callPackage ./akkoma {};
pleroma-fe = pkgs.callPackage ./akkoma/pleroma-fe {};
admin-fe = pkgs.callPackage ./akkoma/admin-fe {};
}

View file

@ -1,138 +1,6 @@
{
"nodes": {
"akkoma": {
"flake": false,
"locked": {
"lastModified": 1663681394,
"narHash": "sha256-drPjai3e2koQ9NocQObPzQtQuqiSDDBe9zVFGuEkwM0=",
"ref": "refs/heads/develop",
"rev": "07295f7c8ce8109f1a2df23b0d7c62d230319c82",
"revCount": 14734,
"type": "git",
"url": "https://akkoma.dev/AkkomaGang/akkoma"
},
"original": {
"type": "git",
"url": "https://akkoma.dev/AkkomaGang/akkoma"
}
},
"akkoma-admin-fe": {
"flake": false,
"locked": {
"lastModified": 1661801796,
"narHash": "sha256-dqkW8p4x+5z1Hd8gp8V4+DsLm8EspVwPXDxtvlp1AIk=",
"ref": "refs/heads/develop",
"rev": "6b131e0779b16f8f3c1021b2a0e72b4e7a271c4c",
"revCount": 1961,
"type": "git",
"url": "https://akkoma.dev/AkkomaGang/admin-fe"
},
"original": {
"type": "git",
"url": "https://akkoma.dev/AkkomaGang/admin-fe"
}
},
"akkoma-fe": {
"flake": false,
"locked": {
"lastModified": 1663928834,
"narHash": "sha256-CqID9jHH5F3xZd9eFpyCxlBg1ka/zeo1jXIntv6blU0=",
"ref": "refs/heads/develop",
"rev": "468eb12573325111fe8405cfbc43407ac9fe2686",
"revCount": 6751,
"type": "git",
"url": "https://akkoma.dev/AkkomaGang/pleroma-fe"
},
"original": {
"type": "git",
"url": "https://akkoma.dev/AkkomaGang/pleroma-fe"
}
},
"cargo2nix": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1655189312,
"narHash": "sha256-gpJ57OgIebUpO+7F00VltxSEy6dz2x6HeJ5BcRM8rDA=",
"owner": "cargo2nix",
"repo": "cargo2nix",
"rev": "c149357cc3d17f2849c73eb7a09d07a307cdcfe8",
"type": "github"
},
"original": {
"owner": "cargo2nix",
"repo": "cargo2nix",
"type": "github"
}
},
"clean-s3-cache": {
"flake": false,
"locked": {
"lastModified": 1654955107,
"narHash": "sha256-eOT9UWpp75gchFDhgnwj1UpVBAZZG5nJUl6N+JAIkT8=",
"ref": "refs/heads/main",
"rev": "1a4dc9cc727b1f824507f28d35cbc93008d7de76",
"revCount": 2,
"type": "git",
"url": "https://gist.github.com/DarkKirb/533e9e8b9b6dd1badf9b103b4285dc4e"
},
"original": {
"type": "git",
"url": "https://gist.github.com/DarkKirb/533e9e8b9b6dd1badf9b103b4285dc4e"
}
},
"drone-runner-docker": {
"flake": false,
"locked": {
"lastModified": 1655209621,
"narHash": "sha256-ZpkVfzqeltZSYrKYB6dXtlVjl1uFpQdl2fa+c5ApiW4=",
"owner": "drone-runners",
"repo": "drone-runner-docker",
"rev": "47ee73d829ac4796415b8ccb6c96bbbf43da8d18",
"type": "github"
},
"original": {
"owner": "drone-runners",
"repo": "drone-runner-docker",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
@ -147,310 +15,7 @@
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"nixpkgs": "nixpkgs_2",
"utils": "utils"
},
"locked": {
"lastModified": 1660809738,
"narHash": "sha256-/yM36JkONdmYsQAW3F2YAXse2cgEb3QffOjBn8sqEXw=",
"ref": "refs/heads/master",
"rev": "10983293d08a6e3d6fa277eba417b8e399e361a5",
"revCount": 171,
"type": "git",
"url": "https://git.chir.rs/darkkirb/gomod2nix"
},
"original": {
"type": "git",
"url": "https://git.chir.rs/darkkirb/gomod2nix"
}
},
"hydra": {
"inputs": {
"newNixpkgs": "newNixpkgs",
"nix": "nix",
"nixpkgs": [
"hydra",
"nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1662719678,
"narHash": "sha256-39yAqCjLaDT5rZqXGwEYKcmOEC+WrW/XQWSI+SdUlOw=",
"ref": "hack",
"rev": "01d3598243ac9d07dce5a82ca4789713c2c4994f",
"revCount": 4015,
"type": "git",
"url": "https://git.chir.rs/darkkirb/hydra"
},
"original": {
"ref": "hack",
"type": "git",
"url": "https://git.chir.rs/darkkirb/hydra"
}
},
"kreative-open-relay": {
"flake": false,
"locked": {
"lastModified": 1662351068,
"narHash": "sha256-gV/1CnIPrFeTBHU0WyBBc9SdbnExai2RnRfhceCvvsw=",
"owner": "kreativekorp",
"repo": "open-relay",
"rev": "cbaca8d9d6d65bddbc05dd3e20b7063639f6664a",
"type": "github"
},
"original": {
"owner": "kreativekorp",
"repo": "open-relay",
"type": "github"
}
},
"lowdown-src": {
"flake": false,
"locked": {
"lastModified": 1633514407,
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
"owner": "kristapsdz",
"repo": "lowdown",
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
"type": "github"
},
"original": {
"owner": "kristapsdz",
"repo": "lowdown",
"type": "github"
}
},
"matrix-media-repo": {
"flake": false,
"locked": {
"lastModified": 1660710533,
"narHash": "sha256-6brtTyWmkYhHiaT/sRIKy6L1LHH27BZBQBWk+o1j42E=",
"owner": "turt2live",
"repo": "matrix-media-repo",
"rev": "b821ac0a9e2bb152fc3f572e6d502c3266e99ea5",
"type": "github"
},
"original": {
"owner": "turt2live",
"repo": "matrix-media-repo",
"type": "github"
}
},
"mautrix-discord": {
"flake": false,
"locked": {
"lastModified": 1663622286,
"narHash": "sha256-j/LjX41ajTzUTrwsvLO8fjPCJXwHkSe8P9ClYOj51I4=",
"owner": "mautrix",
"repo": "discord",
"rev": "6be531685f308f081675034904d89c9e920be996",
"type": "github"
},
"original": {
"owner": "mautrix",
"repo": "discord",
"type": "github"
}
},
"mautrix-signal": {
"flake": false,
"locked": {
"lastModified": 1663955309,
"narHash": "sha256-VewfTmPikRxYyc9rYXJIPem6NfBf0n0/qlLFgckVBes=",
"owner": "mautrix",
"repo": "signal",
"rev": "2798e463ca6774d8199944aa9dbc588d61b310bf",
"type": "github"
},
"original": {
"owner": "mautrix",
"repo": "signal",
"type": "github"
}
},
"mautrix-telegram": {
"flake": false,
"locked": {
"lastModified": 1664017093,
"narHash": "sha256-B+XUrdcDbT4mM8iisUITvY6YLOKfmAllj+C7SilZfFA=",
"owner": "mautrix",
"repo": "telegram",
"rev": "282ad431802966e8e5280d674f5c6e7eeea37876",
"type": "github"
},
"original": {
"owner": "mautrix",
"repo": "telegram",
"type": "github"
}
},
"mautrix-whatsapp": {
"flake": false,
"locked": {
"lastModified": 1663684272,
"narHash": "sha256-eEHB+VtXFdUroiC437E9FzcHHU6VyEwaupC2nthx3Rc=",
"owner": "mautrix",
"repo": "whatsapp",
"rev": "f0401ee81e2e71262498d4e34e25c141b5b92acd",
"type": "github"
},
"original": {
"owner": "mautrix",
"repo": "whatsapp",
"type": "github"
}
},
"miifox-net": {
"flake": false,
"locked": {
"lastModified": 1648216492,
"narHash": "sha256-OKGPwQZjZXbXziJLSOE8K/0fCWCnvU/I2Lm3Vc8KD/o=",
"ref": "refs/heads/master",
"rev": "7826b9a3bec5dddd4b8a879c3396a1406fc37370",
"revCount": 5,
"type": "git",
"url": "https://git.chir.rs/CarolineHusky/MiiFox.net"
},
"original": {
"type": "git",
"url": "https://git.chir.rs/CarolineHusky/MiiFox.net"
}
},
"nasin-nanpa": {
"flake": false,
"locked": {
"lastModified": 1653261911,
"narHash": "sha256-f92PUd4pIS7wK5W0vJ79Qvtw1d8VVW0gquBWW1XWSpw=",
"owner": "ETBCOR",
"repo": "nasin-nanpa",
"rev": "4cf4a762576d8ca2818683139ab1d04d149c9bec",
"type": "github"
},
"original": {
"owner": "ETBCOR",
"repo": "nasin-nanpa",
"type": "github"
}
},
"newNixpkgs": {
"locked": {
"lastModified": 1647380550,
"narHash": "sha256-909TI9poX7CIUiFx203WL29YON6m/I6k0ExbZvR7bLM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6e3ee8957637a60f5072e33d78e05c0f65c54366",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable-small",
"repo": "nixpkgs",
"type": "github"
}
},
"nix": {
"inputs": {
"lowdown-src": "lowdown-src",
"nixpkgs": "nixpkgs_3",
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1654014617,
"narHash": "sha256-qNL3lQPBsnStkru3j1ajN/H+knXI+X3dku8/dBfSw3g=",
"owner": "NixOS",
"repo": "nix",
"rev": "624e38aa43f304fbb78b4779172809add042b513",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "2.9.1",
"repo": "nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1654275867,
"narHash": "sha256-pt14ZE4jVPGvfB2NynGsl34pgXfOqum5YJNpDK4+b9E=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "7a20c208aacf4964c19186dcad51f89165dc7ed0",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "release-22.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"id": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "indirect"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1664029467,
"narHash": "sha256-ir7JbsLp2mqseCs3qI+Z/pkt+Gh+GfANbYcI5I+Gvnk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "893b6b9f6c4ed0c7efdb84bd300a499a2da9fa51",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-22.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1658285632,
"narHash": "sha256-zRS5S/hoeDGUbO+L95wXG9vJNwsSYcl93XiD0HQBXLk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5342fc6fb59d0595d26883c3cadff16ce58e44f3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1645296114,
"narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-21.05-small",
"type": "indirect"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1664093517,
"narHash": "sha256-Ov7I8Ty4GuEuheXJpTDJbeVNlBmDwadhqqd6WtKFqSg=",
@ -465,136 +30,10 @@
"type": "github"
}
},
"nvim-telescope-file-browser": {
"flake": false,
"locked": {
"lastModified": 1663933278,
"narHash": "sha256-kYnvQjGAn2enz1tSCTM/9QfrkT01ZVV+iEr8n+kJk5U=",
"owner": "nvim-telescope",
"repo": "telescope-file-browser.nvim",
"rev": "b1bc53e0da3d26f0003ffb9602115ce258411aa5",
"type": "github"
},
"original": {
"owner": "nvim-telescope",
"repo": "telescope-file-browser.nvim",
"type": "github"
}
},
"plover": {
"flake": false,
"locked": {
"lastModified": 1648942277,
"narHash": "sha256-SiGt8tgB3haT+NsU7BOZZRSZ6FkrkHlabDPOoiCPoNw=",
"owner": "benoit-pierre",
"repo": "plover",
"rev": "9aa7c562ba8c6cf8fdd56b0a8304865cc58bc322",
"type": "github"
},
"original": {
"owner": "benoit-pierre",
"ref": "wayland-sway",
"repo": "plover",
"type": "github"
}
},
"plover-machine-hid": {
"flake": false,
"locked": {
"lastModified": 1658954470,
"narHash": "sha256-iuu32Q5pdgyRybaBv8NQajgziicdwWwqvZV7DwIO64s=",
"ref": "refs/heads/main",
"rev": "f11d7586a993522832efed78cfa5e3654bb48258",
"revCount": 16,
"type": "git",
"url": "https://git.chir.rs/darkkirb/plover-machine-hid"
},
"original": {
"type": "git",
"url": "https://git.chir.rs/darkkirb/plover-machine-hid"
}
},
"root": {
"inputs": {
"akkoma": "akkoma",
"akkoma-admin-fe": "akkoma-admin-fe",
"akkoma-fe": "akkoma-fe",
"cargo2nix": "cargo2nix",
"clean-s3-cache": "clean-s3-cache",
"drone-runner-docker": "drone-runner-docker",
"flake-utils": "flake-utils_2",
"gomod2nix": "gomod2nix",
"hydra": "hydra",
"kreative-open-relay": "kreative-open-relay",
"matrix-media-repo": "matrix-media-repo",
"mautrix-discord": "mautrix-discord",
"mautrix-signal": "mautrix-signal",
"mautrix-telegram": "mautrix-telegram",
"mautrix-whatsapp": "mautrix-whatsapp",
"miifox-net": "miifox-net",
"nasin-nanpa": "nasin-nanpa",
"nixpkgs": "nixpkgs_4",
"nixpkgs-stable": "nixpkgs-stable",
"nvim-telescope-file-browser": "nvim-telescope-file-browser",
"plover": "plover",
"plover-machine-hid": "plover-machine-hid",
"steno-dictionaries": "steno-dictionaries"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": [
"cargo2nix",
"flake-utils"
],
"nixpkgs": [
"cargo2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1653878966,
"narHash": "sha256-T51Gck/vrJZi1m+uTbhEFTRgZmE59sydVONadADv358=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "8526d618af012a923ca116be9603e818b502a8db",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"steno-dictionaries": {
"flake": false,
"locked": {
"lastModified": 1661648632,
"narHash": "sha256-tt/2uR9Nw0d7Imz6aPXj6YDqg1p8MAbNq7m4+Pou/j0=",
"owner": "didoesdigital",
"repo": "steno-dictionaries",
"rev": "f706309c530d0d52f5ace3175834d29c7b1ba8fd",
"type": "github"
},
"original": {
"owner": "didoesdigital",
"repo": "steno-dictionaries",
"type": "github"
}
},
"utils": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},

View file

@ -3,47 +3,7 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-22.05";
flake-utils.url = "github:numtide/flake-utils";
# Source files for packages
clean-s3-cache.url = "git+https://gist.github.com/DarkKirb/533e9e8b9b6dd1badf9b103b4285dc4e";
clean-s3-cache.flake = false;
miifox-net.url = "git+https://git.chir.rs/CarolineHusky/MiiFox.net";
miifox-net.flake = false;
akkoma.url = "git+https://akkoma.dev/AkkomaGang/akkoma";
akkoma.flake = false;
akkoma-fe.url = "git+https://akkoma.dev/AkkomaGang/pleroma-fe";
akkoma-fe.flake = false;
akkoma-admin-fe.url = "git+https://akkoma.dev/AkkomaGang/admin-fe";
akkoma-admin-fe.flake = false;
matrix-media-repo.url = "github:turt2live/matrix-media-repo";
matrix-media-repo.flake = false;
mautrix-whatsapp.url = "github:mautrix/whatsapp";
mautrix-whatsapp.flake = false;
mautrix-discord.url = "github:mautrix/discord";
mautrix-discord.flake = false;
mautrix-telegram.url = "github:mautrix/telegram";
mautrix-telegram.flake = false;
mautrix-signal.url = "github:mautrix/signal";
mautrix-signal.flake = false;
gomod2nix.url = "git+https://git.chir.rs/darkkirb/gomod2nix";
kreative-open-relay.url = "github:kreativekorp/open-relay";
kreative-open-relay.flake = false;
nasin-nanpa.url = "github:ETBCOR/nasin-nanpa";
nasin-nanpa.flake = false;
plover.url = "github:benoit-pierre/plover/wayland-sway";
plover.flake = false;
cargo2nix.url = "github:cargo2nix/cargo2nix";
drone-runner-docker.url = "github:drone-runners/drone-runner-docker";
drone-runner-docker.flake = false;
hydra.url = "git+https://git.chir.rs/darkkirb/hydra?ref=hack";
steno-dictionaries.url = "github:didoesdigital/steno-dictionaries";
steno-dictionaries.flake = false;
plover-machine-hid.url = "git+https://git.chir.rs/darkkirb/plover-machine-hid";
plover-machine-hid.flake = false;
nvim-telescope-file-browser.url = "github:nvim-telescope/telescope-file-browser.nvim";
nvim-telescope-file-browser.flake = false;
};
outputs = {
@ -57,6 +17,9 @@
pkgs = import nixpkgs {
inherit system;
};
inherit (pkgs) lib;
nur = import ./default.nix {inherit pkgs;};
packages = lib.filterAttrs (n: _: n != "overlays" && n != "modules" && n != "lib") nur;
in rec {
formatter = pkgs.alejandra;
@ -67,43 +30,13 @@
];
};
packages = pkgs.lib.lists.foldl (a: b: a // b) {} (map (f: import f {inherit pkgs inputs;}) ([
./scripts/clean-s3-cache.nix
./web/old-homepage.nix
./web/miifox-net.nix
./akkoma
./matrix/matrix-media-repo
./matrix/mautrix-whatsapp
./matrix/mautrix-discord
./matrix/mautrix-telegram.nix
./matrix/mautrix-signal.nix
./fonts/kreative.nix
./fonts/nasin-nanpa.nix
./plover
./plover/dicts.nix
./art
./ci/drone-runner-docker
./vim
./python/tarballs.nix
./python/packages.nix
]
++ (
if system == "x86_64-linux"
then [./hydra]
else []
)
++ (
if system != "i686-linux"
then [./minecraft/paper.nix]
else []
)));
inherit packages;
inherit (nur) overlays modules lib;
hydraJobs =
if (system == "x86_64-linux") || (system == "aarch64-linux")
then {
inherit packages devShells formatter;
inherit (inputs.cargo2nix.packages.${system}) cargo2nix;
gomod2nix = inputs.gomod2nix.packages.${system}.default;
}
else {};
}

1
lib/default.nix Normal file
View file

@ -0,0 +1 @@
_: {}

2
modules/default.nix Normal file
View file

@ -0,0 +1,2 @@
{
}

15
overlay.nix Normal file
View file

@ -0,0 +1,15 @@
# You can use this file as a nixpkgs overlay. This is useful in the
# case where you don't want to add the whole NUR namespace to your
# configuration.
self: super: let
isReserved = n: n == "lib" || n == "overlays" || n == "modules";
nameValuePair = n: v: {
name = n;
value = v;
};
nurAttrs = import ./default.nix {pkgs = super;};
in
builtins.listToAttrs
(map (n: nameValuePair n nurAttrs.${n})
(builtins.filter (n: !isReserved n)
(builtins.attrNames nurAttrs)))

3
overlays/default.nix Normal file
View file

@ -0,0 +1,3 @@
{
default = import ../overlay.nix;
}

6
scripts/update-git.sh Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p nix-prefetch-git
URL=$1
WRITE_PATH=$2
nix-prefetch-git $URL > $WRITE_PATH

6
scripts/update-mix.sh Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p mix2nix
SOURCE_DIR=$1
MIX2NIX_OUT=$2
mix2nix $SOURCE_DIR/mix.lock > $MIX2NIX_OUT

6
scripts/update-yarn.sh Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p yarn2nix
SOURCE=$1
WRITE_PATH=$2
yarn2nix --lockfile $1/yarn.lock > $WRITE_PATH

185
scripts/update.nix Normal file
View file

@ -0,0 +1,185 @@
{
package ? null,
maintainer ? null,
predicate ? null,
path ? null,
max-workers ? null,
include-overlays ? false,
keep-going ? null,
commit ? null,
}:
# TODO: add assert statements
let
nixpkgs = import <nixpkgs> (
if !include-overlays
then {overlays = [];}
else if include-overlays
then {} # Let Nixpkgs include overlays impurely.
else {overlays = include-overlays;}
);
pkgs = import ../default.nix {pkgs = nixpkgs;};
inherit (nixpkgs) lib;
/*
Remove duplicate elements from the list based on some extracted value. O(n^2) complexity.
*/
nubOn = f: list:
if list == []
then []
else let
x = lib.head list;
xs = lib.filter (p: f x != f p) (lib.drop 1 list);
in
[x] ++ nubOn f xs;
/*
Recursively find all packages (derivations) in `pkgs` matching `cond` predicate.
Type: packagesWithPath :: AttrPath (AttrPath derivation bool) AttrSet List<AttrSet{attrPath :: str; package :: derivation; }>
AttrPath :: [str]
The packages will be returned as a list of named pairs comprising of:
- attrPath: stringified attribute path (based on `rootPath`)
- package: corresponding derivation
*/
packagesWithPath = rootPath: cond: pkgs: let
packagesWithPathInner = path: pathContent: let
result = builtins.tryEval pathContent;
dedupResults = lst:
nubOn ({
package,
attrPath,
}:
package.updateScript) (lib.concatLists lst);
in
if result.success
then let
evaluatedPathContent = result.value;
in
if lib.isDerivation evaluatedPathContent
then
lib.optional (cond path evaluatedPathContent) {
attrPath = lib.concatStringsSep "." path;
package = evaluatedPathContent;
}
else if lib.isAttrs evaluatedPathContent
then
# If user explicitly points to an attrSet or it is marked for recursion, we recur.
if path == rootPath || evaluatedPathContent.recurseForDerivations or false || evaluatedPathContent.recurseForRelease or false
then dedupResults (lib.mapAttrsToList (name: packagesWithPathInner (path ++ [name])) evaluatedPathContent)
else []
else []
else [];
in
packagesWithPathInner rootPath pkgs;
/*
Recursively find all packages (derivations) in `pkgs` matching `cond` predicate.
*/
packagesWith = packagesWithPath [];
allPackagesWithUpdateScript = packagesWith (_: builtins.hasAttr "updateScript");
/*
Recursively find all packages under `path` in `pkgs` with updateScript.
*/
packagesWithUpdateScript = path: pkgs: let
prefix = lib.splitString "." path;
pathContent = lib.attrByPath prefix null pkgs;
in
if pathContent == null
then builtins.throw "Attribute path `${path}` does not exist."
else
packagesWithPath prefix (path: builtins.hasAttr "updateScript")
pathContent;
/*
List of packages matched based on the CLI arguments.
*/
packages =
if path != null
then packagesWithUpdateScript path pkgs
else allPackagesWithUpdateScript pkgs;
helpText = ''
Please run:
% nix-shell maintainers/scripts/update.nix --argstr maintainer garbas
to run all update scripts for all packages that lists \`garbas\` as a maintainer
and have \`updateScript\` defined, or:
% nix-shell maintainers/scripts/update.nix --argstr package gnome.nautilus
to run update script for specific package, or
% nix-shell maintainers/scripts/update.nix --arg predicate '(path: pkg: pkg.updateScript.name or null == "gnome-update-script")'
to run update script for all packages matching given predicate, or
% nix-shell maintainers/scripts/update.nix --argstr path gnome
to run update script for all package under an attribute path.
You can also add
--argstr max-workers 8
to increase the number of jobs in parallel, or
--argstr keep-going true
to continue running when a single update fails.
You can also make the updater automatically commit on your behalf from updateScripts
that support it by adding
--argstr commit true
'';
/*
Transform a matched package into an object for update.py.
*/
packageData = {
package,
attrPath,
}: {
inherit (package) name;
pname = lib.getName package;
oldVersion = lib.getVersion package;
updateScript = map builtins.toString (lib.toList (package.updateScript.command or package.updateScript));
supportedFeatures = package.updateScript.supportedFeatures or [];
attrPath = package.updateScript.attrPath or attrPath;
};
/*
JSON file with data for update.py.
*/
packagesJson = nixpkgs.writeText "packages.json" (builtins.toJSON (map packageData packages));
optionalArgs =
lib.optional (max-workers != null) "--max-workers=${max-workers}"
++ lib.optional (keep-going == "true") "--keep-going"
++ lib.optional (commit == "true") "--commit";
args = [packagesJson] ++ optionalArgs;
in
nixpkgs.stdenv.mkDerivation {
name = "nixpkgs-update-script";
buildCommand = ''
echo ""
echo "----------------------------------------------------------------"
echo ""
echo "Not possible to update packages using \`nix-build\`"
echo ""
echo "${helpText}"
echo "----------------------------------------------------------------"
exit 1
'';
shellHook = ''
unset shellHook # do not contaminate nested shells
exec ${nixpkgs.python3.interpreter} ${./update.py} ${builtins.concatStringsSep " " args}
'';
}

262
scripts/update.py Normal file
View file

@ -0,0 +1,262 @@
from __future__ import annotations
from typing import Dict, Generator, List, Optional, Tuple
import argparse
import asyncio
import contextlib
import json
import os
import re
import subprocess
import sys
import tempfile
class CalledProcessError(Exception):
process: asyncio.subprocess.Process
class UpdateFailedException(Exception):
pass
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
async def check_subprocess(*args, **kwargs):
"""
Emulate check argument of subprocess.run function.
"""
process = await asyncio.create_subprocess_exec(*args, **kwargs)
returncode = await process.wait()
if returncode != 0:
error = CalledProcessError()
error.process = process
raise error
return process
async def run_update_script(nixpkgs_root: str, merge_lock: asyncio.Lock, temp_dir: Optional[Tuple[str, str]], package: Dict, keep_going: bool):
worktree: Optional[str] = None
update_script_command = package['updateScript']
if temp_dir is not None:
worktree, _branch = temp_dir
# Ensure the worktree is clean before update.
await check_subprocess('git', 'reset', '--hard', '--quiet', 'HEAD', cwd=worktree)
# Update scripts can use $(dirname $0) to get their location but we want to run
# their clones in the git worktree, not in the main nixpkgs repo.
update_script_command = map(lambda arg: re.sub(r'^{0}'.format(
re.escape(nixpkgs_root)), worktree, arg), update_script_command)
eprint(f" - {package['name']}: UPDATING ...")
try:
update_process = await check_subprocess('env', f"UPDATE_NIX_ATTR_PATH={package['attrPath']}", *update_script_command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, cwd=worktree)
update_info = await update_process.stdout.read()
await merge_changes(merge_lock, package, update_info, temp_dir)
except KeyboardInterrupt as e:
eprint('Cancelling…')
raise asyncio.exceptions.CancelledError()
except CalledProcessError as e:
eprint(f" - {package['name']}: ERROR")
eprint()
eprint(
f"--- SHOWING ERROR LOG FOR {package['name']} ----------------------")
eprint()
stderr = await e.process.stderr.read()
eprint(stderr.decode('utf-8'))
with open(f"{package['pname']}.log", 'wb') as logfile:
logfile.write(stderr)
eprint()
eprint(
f"--- SHOWING ERROR LOG FOR {package['name']} ----------------------")
if not keep_going:
raise UpdateFailedException(
f"The update script for {package['name']} failed with exit code {e.process.returncode}")
@contextlib.contextmanager
def make_worktree() -> Generator[Tuple[str, str], None, None]:
with tempfile.TemporaryDirectory() as wt:
branch_name = f'update-{os.path.basename(wt)}'
target_directory = f'{wt}/nixpkgs'
subprocess.run(['git', 'worktree', 'add', '-b',
branch_name, target_directory])
yield (target_directory, branch_name)
subprocess.run(['git', 'worktree', 'remove',
'--force', target_directory])
subprocess.run(['git', 'branch', '-D', branch_name])
async def commit_changes(name: str, merge_lock: asyncio.Lock, worktree: str, branch: str, changes: List[Dict]) -> None:
for change in changes:
# Git can only handle a single index operation at a time
async with merge_lock:
await check_subprocess('git', 'add', *change['files'], cwd=worktree)
commit_message = '{attrPath}: {oldVersion}{newVersion}'.format(
**change)
if 'commitMessage' in change:
commit_message = change['commitMessage']
elif 'commitBody' in change:
commit_message = commit_message + '\n\n' + change['commitBody']
await check_subprocess('git', 'commit', '--quiet', '-m', commit_message, cwd=worktree)
await check_subprocess('git', 'cherry-pick', branch)
async def check_changes(package: Dict, worktree: str, update_info: str):
if 'commit' in package['supportedFeatures']:
changes = json.loads(update_info)
else:
changes = [{}]
# Try to fill in missing attributes when there is just a single change.
if len(changes) == 1:
# Dynamic data from updater take precedence over static data from passthru.updateScript.
if 'attrPath' not in changes[0]:
# update.nix is always passing attrPath
changes[0]['attrPath'] = package['attrPath']
if 'oldVersion' not in changes[0]:
# update.nix is always passing oldVersion
changes[0]['oldVersion'] = package['oldVersion']
if 'newVersion' not in changes[0]:
attr_path = changes[0]['attrPath']
obtain_new_version_process = await check_subprocess('nix-instantiate', '--expr', f'with import ./. {{}}; lib.getVersion {attr_path}', '--eval', '--strict', '--json', stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, cwd=worktree)
changes[0]['newVersion'] = json.loads((await obtain_new_version_process.stdout.read()).decode('utf-8'))
if 'files' not in changes[0]:
changed_files_process = await check_subprocess('git', 'diff', '--name-only', 'HEAD', stdout=asyncio.subprocess.PIPE, cwd=worktree)
changed_files = (await changed_files_process.stdout.read()).splitlines()
changes[0]['files'] = changed_files
if len(changed_files) == 0:
return []
return changes
async def merge_changes(merge_lock: asyncio.Lock, package: Dict, update_info: str, temp_dir: Optional[Tuple[str, str]]) -> None:
if temp_dir is not None:
worktree, branch = temp_dir
changes = await check_changes(package, worktree, update_info)
if len(changes) > 0:
await commit_changes(package['name'], merge_lock, worktree, branch, changes)
else:
eprint(f" - {package['name']}: DONE, no changes.")
else:
eprint(f" - {package['name']}: DONE.")
async def updater(nixpkgs_root: str, temp_dir: Optional[Tuple[str, str]], merge_lock: asyncio.Lock, packages_to_update: asyncio.Queue[Optional[Dict]], keep_going: bool, commit: bool):
while True:
package = await packages_to_update.get()
if package is None:
# A sentinel received, we are done.
return
if not ('commit' in package['supportedFeatures'] or 'attrPath' in package):
temp_dir = None
await run_update_script(nixpkgs_root, merge_lock, temp_dir, package, keep_going)
async def start_updates(max_workers: int, keep_going: bool, commit: bool, packages: List[Dict]):
merge_lock = asyncio.Lock()
packages_to_update: asyncio.Queue[Optional[Dict]] = asyncio.Queue()
with contextlib.ExitStack() as stack:
temp_dirs: List[Optional[Tuple[str, str]]] = []
# Do not create more workers than there are packages.
num_workers = min(max_workers, len(packages))
nixpkgs_root_process = await check_subprocess('git', 'rev-parse', '--show-toplevel', stdout=asyncio.subprocess.PIPE)
nixpkgs_root = (await nixpkgs_root_process.stdout.read()).decode('utf-8').strip()
# Set up temporary directories when using auto-commit.
for i in range(num_workers):
temp_dir = stack.enter_context(make_worktree()) if commit else None
temp_dirs.append(temp_dir)
# Fill up an update queue,
for package in packages:
await packages_to_update.put(package)
# Add sentinels, one for each worker.
# A workers will terminate when it gets sentinel from the queue.
for i in range(num_workers):
await packages_to_update.put(None)
# Prepare updater workers for each temp_dir directory.
# At most `num_workers` instances of `run_update_script` will be running at one time.
updaters = asyncio.gather(*[updater(nixpkgs_root, temp_dir, merge_lock,
packages_to_update, keep_going, commit) for temp_dir in temp_dirs])
try:
# Start updater workers.
await updaters
except asyncio.exceptions.CancelledError:
# When one worker is cancelled, cancel the others too.
updaters.cancel()
except UpdateFailedException as e:
# When one worker fails, cancel the others, as this exception is only thrown when keep_going is false.
updaters.cancel()
eprint(e)
sys.exit(1)
def main(max_workers: int, keep_going: bool, commit: bool, packages_path: str) -> None:
with open(packages_path) as f:
packages = json.load(f)
eprint()
eprint('Going to be running update for following packages:')
for package in packages:
eprint(f" - {package['name']}")
eprint()
confirm = input('Press Enter key to continue...')
if confirm == '':
eprint()
eprint('Running update for:')
asyncio.run(start_updates(max_workers, keep_going, commit, packages))
eprint()
eprint('Packages updated!')
sys.exit()
else:
eprint('Aborting!')
sys.exit(130)
parser = argparse.ArgumentParser(description='Update packages')
parser.add_argument('--max-workers', '-j', dest='max_workers', type=int,
help='Number of updates to run concurrently', nargs='?', default=4)
parser.add_argument('--keep-going', '-k', dest='keep_going',
action='store_true', help='Do not stop after first failure')
parser.add_argument('--commit', '-c', dest='commit',
action='store_true', help='Commit the changes')
parser.add_argument(
'packages', help='JSON file containing the list of package names and their update scripts')
if __name__ == '__main__':
args = parser.parse_args()
try:
main(args.max_workers, args.keep_going, args.commit, args.packages)
except KeyboardInterrupt as e:
# Lets cancel outside of the main loop too.
sys.exit(130)