push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
{
lib,
stdenv,
fetchurl,
jdk17_headless,
makeWrapper,
bash,
coreutils,
gnugrep,
gnused,
ps,
nixosTests,
}:
let
versionMap = {
"4_1" = {
kafkaVersion = "4.1.0";
scalaVersion = "2.13";
sha256 = "sha256-hbRThHDR3LmNAnMoa/q4cXBlUi5Zfs//zU24OjAhdY4=";
jre = jdk17_headless;
nixosTest = nixosTests.kafka.base.kafka_4_1;
};
"4_0" = {
kafkaVersion = "4.0.0";
scalaVersion = "2.13";
sha256 = "sha256-e4Uuk4vAneEM2W7KN1UljH0l+4nb3XYwVxdgfhg14qo=";
jre = jdk17_headless;
nixosTest = nixosTests.kafka.base.kafka_4_0;
};
"3_9" = {
kafkaVersion = "3.9.1";
scalaVersion = "2.13";
sha256 = "sha256-3UOZgW5niUbKt2470WhhA1VeabyPKrhobNpxqhW8MaM=";
jre = jdk17_headless;
nixosTest = nixosTests.kafka.base.kafka_3_9;
};
};
build =
versionInfo:
stdenv.mkDerivation rec {
version = "${versionInfo.scalaVersion}-${versionInfo.kafkaVersion}";
pname = "apache-kafka";
src = fetchurl {
url = "mirror://apache/kafka/${versionInfo.kafkaVersion}/kafka_${version}.tgz";
inherit (versionInfo) sha256;
};
nativeBuildInputs = [ makeWrapper ];
buildInputs = [
versionInfo.jre
bash
gnugrep
gnused
coreutils
ps
];
installPhase = ''
mkdir -p $out
cp -R config libs $out
mkdir -p $out/bin
cp bin/kafka* $out/bin
cp bin/connect* $out/bin
# allow us the specify logging directory using env
substituteInPlace $out/bin/kafka-run-class.sh \
--replace 'LOG_DIR="$base_dir/logs"' 'LOG_DIR="$KAFKA_LOG_DIR"'
substituteInPlace $out/bin/kafka-server-stop.sh \
--replace 'ps' '${ps}/bin/ps'
for p in $out/bin\/*.sh; do
wrapProgram $p \
--set JAVA_HOME "${versionInfo.jre}" \
--set KAFKA_LOG_DIR "/tmp/apache-kafka-logs" \
--prefix PATH : "${bash}/bin:${coreutils}/bin:${gnugrep}/bin:${gnused}/bin"
done
chmod +x $out/bin\/*
'';
passthru = {
inherit (versionInfo) jre; # Used by the NixOS module to select the supported JRE
tests.nixos = versionInfo.nixosTest;
};
meta = {
homepage = "https://kafka.apache.org";
description = "High-throughput distributed messaging system";
license = lib.licenses.asl20;
sourceProvenance = [ lib.sourceTypes.binaryBytecode ];
maintainers = [ lib.maintainers.ragge ];
platforms = lib.platforms.unix;
};
};
in
lib.mapAttrs' (
majorVersion: versionInfo: lib.nameValuePair "apacheKafka_${majorVersion}" (build versionInfo)
) versionMap

View File

@@ -0,0 +1,232 @@
{
stdenv,
lib,
fetchurl,
fetchsvn,
fetchFromGitHub,
jansson,
libedit,
libxml2,
libxslt,
ncurses,
openssl,
sqlite,
util-linux,
dmidecode,
libuuid,
newt,
lua,
speex,
libopus,
opusfile,
libogg,
srtp,
wget,
curl,
iksemel,
pkg-config,
autoconf,
libtool,
automake,
python3,
writeScript,
withOpus ? true,
ldapSupport ? false,
openldap,
}:
let
common =
{
version,
sha256,
externals,
pjsip_patches ? [ ],
}:
stdenv.mkDerivation {
inherit version;
pname = "asterisk" + lib.optionalString ldapSupport "-ldap";
buildInputs = [
jansson
libedit
libxml2
libxslt
ncurses
openssl
sqlite
dmidecode
libuuid
newt
lua
speex
srtp
wget
curl
iksemel
]
++ lib.optionals withOpus [
libopus
opusfile
libogg
]
++ lib.optionals ldapSupport [ openldap ];
nativeBuildInputs = [
util-linux
pkg-config
autoconf
libtool
automake
];
patches = [
# We want the Makefile to install the default /var skeleton
# under ${out}/var but we also want to use /var at runtime.
# This patch changes the runtime behavior to look for state
# directories in /var rather than ${out}/var.
./runtime-vardirs.patch
]
++ lib.optional withOpus "${asterisk-opus}/asterisk.patch";
postPatch = ''
echo "PJPROJECT_CONFIG_OPTS += --prefix=$out" >> third-party/pjproject/Makefile.rules
'';
src = fetchurl {
url = "https://downloads.asterisk.org/pub/telephony/asterisk/old-releases/asterisk-${version}.tar.gz";
inherit sha256;
};
# The default libdir is $PREFIX/usr/lib, which causes problems when paths
# compiled into Asterisk expect ${out}/usr/lib rather than ${out}/lib.
# Copy in externals to avoid them being downloaded;
# they have to be copied, because the modification date is checked.
# If you are getting a permission denied error on this dir,
# you're likely missing an automatically downloaded dependency
preConfigure = ''
mkdir externals_cache
${lib.concatStringsSep "\n" (
lib.mapAttrsToList (dst: src: "cp -r --no-preserve=mode ${src} ${dst}") externals
)}
${lib.optionalString (externals ? "addons/mp3") "bash contrib/scripts/get_mp3_source.sh || true"}
chmod -w externals_cache
${lib.optionalString withOpus ''
cp ${asterisk-opus}/include/asterisk/* ./include/asterisk
cp ${asterisk-opus}/codecs/* ./codecs
cp ${asterisk-opus}/formats/* ./formats
''}
${lib.concatMapStringsSep "\n" (patch: ''
cp ${patch} ./third-party/pjproject/patches/${patch.name}
'') pjsip_patches}
./bootstrap.sh
'';
configureFlags = [
"--libdir=\${out}/lib"
"--with-lua=${lua}/lib"
"--with-pjproject-bundled"
"--with-externals-cache=$(PWD)/externals_cache"
];
preBuild = ''
cat third-party/pjproject/source/pjlib-util/src/pjlib-util/scanner.c
make menuselect.makeopts
${lib.optionalString (externals ? "addons/mp3") ''
substituteInPlace menuselect.makeopts --replace 'format_mp3 ' ""
''}
${lib.optionalString withOpus ''
substituteInPlace menuselect.makeopts --replace 'codec_opus_open_source ' ""
substituteInPlace menuselect.makeopts --replace 'format_ogg_opus_open_source ' ""
''}
'';
postInstall = ''
# Install sample configuration files for this version of Asterisk
make samples
make install-headers
'';
meta = with lib; {
description = "Software implementation of a telephone private branch exchange (PBX)";
homepage = "https://www.asterisk.org/";
license = licenses.gpl2Only;
mainProgram = "asterisk";
maintainers = with maintainers; [
auntie
DerTim1
yorickvp
];
};
};
pjproject = fetchurl {
url = "https://raw.githubusercontent.com/asterisk/third-party/master/pjproject/2.15.1/pjproject-2.15.1.tar.bz2";
hash = "sha256-WLuDzsTUMfSNAG5FXYIWaEUPjPa2yV8JDe9HBi+jpgw=";
};
mp3-204 = fetchsvn {
url = "http://svn.digium.com/svn/thirdparty/mp3/trunk";
rev = "204";
hash = "sha256-Viec0LwFPfR7ewy+2hc/LIUR1LiDZfYos3RUbc+tyNk=";
};
asterisk-opus = fetchFromGitHub {
owner = "traud";
repo = "asterisk-opus";
# No releases, points to master as of 2022-04-06
rev = "a959f072d3f364be983dd27e6e250b038aaef747";
hash = "sha256-CASlTvTahOg9D5jccF/IN10LP/U8rRy9BFCSaHGQfCw=";
};
# auto-generated by update.py
versions = lib.mapAttrs (
_:
{ version, sha256 }:
common {
inherit version sha256;
externals = {
"externals_cache/${pjproject.name}" = pjproject;
"addons/mp3" = mp3-204;
};
}
) (lib.importJSON ./versions.json);
updateScript_python = python3.withPackages (
p: with p; [
packaging
beautifulsoup4
requests
]
);
updateScript = writeScript "asterisk-update" ''
#!/usr/bin/env bash
exec ${updateScript_python}/bin/python ${toString ./update.py}
'';
in
{
# Supported releases (as of 2023-04-19).
# v16 and v19 have been dropped because they go EOL before the NixOS 23.11 release.
# Source: https://wiki.asterisk.org/wiki/display/AST/Asterisk+Versions
# Exact version can be found at https://www.asterisk.org/downloads/asterisk/all-asterisk-versions/
#
# Series Type Rel. Date Sec. Fixes EOL
# 16.x LTS 2018-10-09 2022-10-09 2023-10-09 (dropped)
# 18.x LTS 2020-10-20 2024-10-20 2025-10-20
# 19.x Standard 2021-11-02 2022-11-02 2023-11-02 (dropped)
# 20.x LTS 2022-11-02 2026-10-19 2027-10-19
# 21.x Standard 2023-10-18 2025-10-18 2026-10-18 (unreleased)
asterisk-lts = versions.asterisk_18;
asterisk-stable = versions.asterisk_20;
asterisk = versions.asterisk_20.overrideAttrs (o: {
passthru = (o.passthru or { }) // {
inherit updateScript;
};
});
}
// versions

View File

@@ -0,0 +1,50 @@
diff -rupN asterisk-14.1.2/build_tools/make_defaults_h asterisk-14.1.2-patched/build_tools/make_defaults_h
--- asterisk-14.1.2/build_tools/make_defaults_h 2016-11-10 20:43:02.000000000 +0100
+++ asterisk-14.1.2-patched/build_tools/make_defaults_h 2016-11-16 10:09:04.189625495 +0100
@@ -1,4 +1,13 @@
#!/bin/sh
+
+ASTLOGDIR=/var/log/asterisk
+ASTVARRUNDIR=/run/asterisk
+ASTVARLIBDIR=/var/lib/asterisk
+ASTDBDIR=${ASTVARLIBDIR}
+ASTDATADIR=${ASTVARLIBDIR}
+AGI_DIR=${ASTDATADIR}/agi-bin
+ASTSPOOLDIR=/var/spool/asterisk
+
cat << END
/*
* defaults.h
@@ -9,21 +18,21 @@ cat << END
#define DEFAULT_CONFIG_DIR "${INSTALL_PATH}${ASTETCDIR}"
#define DEFAULT_MODULE_DIR "${INSTALL_PATH}${ASTMODDIR}"
-#define DEFAULT_AGI_DIR "${INSTALL_PATH}${AGI_DIR}"
-#define DEFAULT_LOG_DIR "${INSTALL_PATH}${ASTLOGDIR}"
+#define DEFAULT_AGI_DIR "${AGI_DIR}"
+#define DEFAULT_LOG_DIR "${ASTLOGDIR}"
-#define DEFAULT_RUN_DIR "${INSTALL_PATH}${ASTVARRUNDIR}"
-#define DEFAULT_SOCKET "${INSTALL_PATH}${ASTVARRUNDIR}/asterisk.ctl"
-#define DEFAULT_PID "${INSTALL_PATH}${ASTVARRUNDIR}/asterisk.pid"
+#define DEFAULT_RUN_DIR "${ASTVARRUNDIR}"
+#define DEFAULT_SOCKET "${ASTVARRUNDIR}/asterisk.ctl"
+#define DEFAULT_PID "${ASTVARRUNDIR}/asterisk.pid"
-#define DEFAULT_VAR_DIR "${INSTALL_PATH}${ASTVARLIBDIR}"
-#define DEFAULT_DB "${INSTALL_PATH}${ASTDBDIR}/astdb"
+#define DEFAULT_VAR_DIR "${ASTVARLIBDIR}"
+#define DEFAULT_DB "${ASTDBDIR}/astdb"
-#define DEFAULT_DATA_DIR "${INSTALL_PATH}${ASTDATADIR}"
-#define DEFAULT_KEY_DIR "${INSTALL_PATH}${ASTDATADIR}/keys"
+#define DEFAULT_DATA_DIR "${ASTDATADIR}"
+#define DEFAULT_KEY_DIR "${ASTDATADIR}/keys"
-#define DEFAULT_SPOOL_DIR "${INSTALL_PATH}${ASTSPOOLDIR}"
-#define DEFAULT_TMP_DIR "${INSTALL_PATH}${ASTSPOOLDIR}/tmp"
+#define DEFAULT_SPOOL_DIR "${ASTSPOOLDIR}"
+#define DEFAULT_TMP_DIR "${ASTSPOOLDIR}/tmp"
#define DEFAULT_SBIN_DIR "${INSTALL_PATH}${ASTSBINDIR}"
END

41
pkgs/servers/asterisk/update.py Executable file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p python3 python3.pkgs.packaging python3.pkgs.beautifulsoup4 python3.pkgs.requests
# mirrored in ./default.nix
from packaging import version
from bs4 import BeautifulSoup
import re, requests, json
import os, sys
from pathlib import Path
URL = "https://downloads.asterisk.org/pub/telephony/asterisk/"
page = requests.get(URL)
changelog = re.compile(r"^ChangeLog-\d+\.\d+\.\d+\.md$")
changelogs = [a.get_text() for a in BeautifulSoup(page.text, 'html.parser').find_all('a') if changelog.match(a.get_text())]
major_versions = {}
for changelog in changelogs:
v = version.parse(changelog.removeprefix("ChangeLog-").removesuffix(".md"))
major_versions.setdefault(v.major, []).append(v)
out = {}
for mv in major_versions.keys():
v = max(major_versions[mv])
sha = requests.get(f"{URL}/asterisk-{v}.sha256").text.split()[0]
out["asterisk_" + str(mv)] = {
"version": str(v),
"sha256": sha
}
versions_path = Path(sys.argv[0]).parent / "versions.json"
try:
with open(versions_path, "r") as in_file:
in_data = json.loads(in_file.read())
for v in in_data.keys():
print(v + ":", in_data[v]["version"], "->", out[v]["version"])
except:
# nice to have for the PR, not a requirement
pass
with open(versions_path, "w") as out_file:
out_file.write(json.dumps(out, sort_keys=True, indent=2) + "\n")

View File

@@ -0,0 +1,18 @@
{
"asterisk_18": {
"sha256": "a17f511bfa092c8fa9eccd3a5ecf5f728ccdcf2b1a04d2c06e7177d96c3c9ee1",
"version": "18.26.4"
},
"asterisk_20": {
"sha256": "4bbe0aaecc0e7294780269a5dc7ff78a85c58cf26ffc63dd63be5406eef0b687",
"version": "20.15.2"
},
"asterisk_21": {
"sha256": "9624e807a1138cabed14431a326c9870e53fc132738dbbd61314abc027785d94",
"version": "21.10.2"
},
"asterisk_22": {
"sha256": "5061c852fd850b17e6be9d866c8e73298471883fc5e3ccd5a24b3e1364e24218",
"version": "22.5.2"
}
}

View File

@@ -0,0 +1,112 @@
{
lib,
stdenv,
nodejs,
pnpm,
fetchFromGitHub,
buildGoModule,
installShellFiles,
callPackage,
nixosTests,
authelia-web ? callPackage ./web.nix { inherit nodejs pnpm fetchFromGitHub; },
}:
let
inherit (import ./sources.nix { inherit fetchFromGitHub; })
pname
version
src
vendorHash
;
web = authelia-web;
in
buildGoModule rec {
inherit
pname
version
src
vendorHash
;
nativeBuildInputs = [ installShellFiles ];
## FIXME: add swagger-ui https://github.com/authelia/authelia/blob/master/cmd/authelia-scripts/cmd/build.go#L148
postPatch = ''
cp -r api internal/server/public_html
cp -r ${web}/share/authelia-web/* internal/server/public_html
'';
subPackages = [ "cmd/authelia" ];
ldflags =
let
p = "github.com/authelia/authelia/v${lib.versions.major version}/internal/utils";
in
[
"-s"
"-w"
"-X ${p}.BuildTag=v${version}"
"-X '${p}.BuildState=tagged clean'"
"-X ${p}.BuildBranch=v${version}"
"-X ${p}.BuildExtra=nixpkgs"
];
# It is required to set this to avoid a change in the
# handling of sync map in go 1.24+
# Upstream issue: https://github.com/authelia/authelia/issues/8980
env.GOEXPERIMENT = "nosynchashtriemap";
# several tests with networking and several that want chromium
doCheck = false;
postInstall = ''
mkdir -p $out/etc/authelia
cp config.template.yml $out/etc/authelia
''
+ lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
installShellCompletion --cmd authelia \
--bash <($out/bin/authelia completion bash) \
--fish <($out/bin/authelia completion fish) \
--zsh <($out/bin/authelia completion zsh)
'';
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
$out/bin/authelia --help
$out/bin/authelia --version | grep "v${version}"
$out/bin/authelia build-info | grep 'v${version}\|nixpkgs'
runHook postInstallCheck
'';
passthru = {
# if overriding replace the postPatch to put your web UI output in internal/server/public_html
inherit web;
updateScript = ./update.sh;
tests = { inherit (nixosTests) authelia; };
};
meta = with lib; {
homepage = "https://www.authelia.com/";
changelog = "https://github.com/authelia/authelia/releases/tag/v${version}";
description = "Single Sign-On Multi-Factor portal for web apps";
longDescription = ''
Authelia is an open-source authentication and authorization server
providing two-factor authentication and single sign-on (SSO) for your
applications via a web portal. It acts as a companion for reverse proxies
like nginx, Traefik, caddy or HAProxy to let them know whether requests
should either be allowed or redirected to Authelia's portal for
authentication.
'';
license = licenses.asl20;
maintainers = with maintainers; [
jk
dit7ya
nicomem
];
mainProgram = "authelia";
};
}

View File

@@ -0,0 +1,14 @@
{ fetchFromGitHub }:
rec {
pname = "authelia";
version = "4.39.10";
src = fetchFromGitHub {
owner = "authelia";
repo = "authelia";
rev = "v${version}";
hash = "sha256-v6KxDfl/dG4FEC/6V2io5jYlS6FY/WemnZJ7tpikpyM=";
};
vendorHash = "sha256-Gvk5AX0kyIYyFmgvb/TGCIEycTjtdxNLHk9sbrU5Ybw=";
pnpmDepsHash = "sha256-0evGB5UYphBCrVN3/hJfNXJvDGSz77Cm/s7XW7JNU/o=";
}

70
pkgs/servers/authelia/update.sh Executable file
View File

@@ -0,0 +1,70 @@
#! /usr/bin/env nix-shell
#! nix-shell -I nixpkgs=./. -i bash -p coreutils gnused curl nix jq nodejs
set -euo pipefail
DRV_DIR="$(dirname "${BASH_SOURCE[0]}")"
DRV_DIR=$(realpath "$DRV_DIR")
NIXPKGS_ROOT="$DRV_DIR/../../.."
NIXPKGS_ROOT=$(realpath "$NIXPKGS_ROOT")
instantiateClean() {
nix-instantiate --eval --strict -E "with import ./. {}; $1" | cut -d\" -f2
}
fetchNewHash() {
set +eo pipefail
HASH="$(nix-build -A "$1" 2>&1 >/dev/null | grep "got:" | cut -d':' -f2 | sed 's| ||g')"
set -eo pipefail
if [ -z "$HASH" ]; then
echo "Could not generate hash" >&2
exit 1
else
echo "$HASH"
fi
}
replace() {
sed -i "s@$1@$2@g" "$3"
}
# provide a github token so you don't get rate limited
# if you use gh cli you can use:
# `export GITHUB_TOKEN="$(cat ~/.config/gh/config.yml | yq '.hosts."github.com".oauth_token' -r)"`
# or just set your token by hand:
# `read -s -p "Enter your token: " GITHUB_TOKEN; export GITHUB_TOKEN`
# (we use read so it doesn't show in our shell history and in secret mode so the token you paste isn't visible)
if [ -z "${GITHUB_TOKEN:-}" ]; then
echo "no GITHUB_TOKEN provided - you could meet API request limiting" >&2
fi
OLD_VERSION=$(instantiateClean "authelia.version")
LATEST_TAG=$(curl ${GITHUB_TOKEN:+" -u \":$GITHUB_TOKEN\""} --silent https://api.github.com/repos/authelia/authelia/releases/latest | jq -r '.tag_name')
NEW_VERSION=$(echo ${LATEST_TAG} | sed 's/^v//')
if [[ "$OLD_VERSION" == "$NEW_VERSION" ]]; then
echo "already up to date"
exit
fi
TMP_HASH="sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
echo "New version $NEW_VERSION"
replace "$OLD_VERSION" "$NEW_VERSION" "$DRV_DIR/sources.nix"
OLD_SRC_HASH="$(instantiateClean authelia.src.outputHash)"
echo "Old src hash $OLD_SRC_HASH"
replace "$OLD_SRC_HASH" "$TMP_HASH" "$DRV_DIR/sources.nix"
NEW_SRC_HASH="$(fetchNewHash authelia.src)"
echo "New src hash $NEW_SRC_HASH"
replace "$TMP_HASH" "$NEW_SRC_HASH" "$DRV_DIR/sources.nix"
OLD_PNPM_DEPS_HASH="$(instantiateClean authelia.web.pnpmDeps.outputHash)"
echo "Old pnpm deps hash $OLD_PNPM_DEPS_HASH"
replace "$OLD_PNPM_DEPS_HASH" "$TMP_HASH" "$DRV_DIR/sources.nix"
NEW_PNPM_DEPS_HASH="$(fetchNewHash authelia.web)"
echo "New pnpm deps hash $NEW_PNPM_DEPS_HASH"
replace "$TMP_HASH" "$NEW_PNPM_DEPS_HASH" "$DRV_DIR/sources.nix"
OLD_GO_VENDOR_HASH="$(instantiateClean authelia.vendorHash)"
echo "Old go vendor hash $OLD_GO_VENDOR_HASH"
replace "$OLD_GO_VENDOR_HASH" "$TMP_HASH" "$DRV_DIR/sources.nix"
NEW_GO_VENDOR_HASH="$(fetchNewHash authelia.goModules)"
echo "New go vendor hash $NEW_GO_VENDOR_HASH"
replace "$TMP_HASH" "$NEW_GO_VENDOR_HASH" "$DRV_DIR/sources.nix"

View File

@@ -0,0 +1,55 @@
{
stdenv,
nodejs,
pnpm,
fetchFromGitHub,
}:
let
inherit (import ./sources.nix { inherit fetchFromGitHub; })
pname
version
src
pnpmDepsHash
;
in
stdenv.mkDerivation (finalAttrs: {
pname = "${pname}-web";
inherit src version;
sourceRoot = "${finalAttrs.src.name}/web";
nativeBuildInputs = [
nodejs
pnpm.configHook
];
pnpmDeps = pnpm.fetchDeps {
inherit (finalAttrs)
pname
version
src
sourceRoot
;
fetcherVersion = 1;
hash = pnpmDepsHash;
};
postPatch = ''
substituteInPlace ./vite.config.ts \
--replace 'outDir: "../internal/server/public_html"' 'outDir: "dist"'
'';
postBuild = ''
pnpm run build
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share
mv dist $out/share/authelia-web
runHook postInstall
'';
})

View File

@@ -0,0 +1,20 @@
diff --git a/ci/build/build-vscode.sh b/ci/build/build-vscode.sh
index a72549fb..3aed1ad5 100755
--- a/ci/build/build-vscode.sh
+++ b/ci/build/build-vscode.sh
@@ -58,7 +58,6 @@ main() {
# telemetry available; telemetry can still be disabled by flag or setting).
# This needs to be done before building as Code will read this file and embed
# it into the client-side code.
- git checkout product.json # Reset in case the script exited early.
cp product.json product.original.json # Since jq has no inline edit.
jq --slurp '.[0] * .[1]' product.original.json <(
cat << EOF
@@ -105,7 +104,6 @@ EOF
# Reset so if you develop after building you will not be stuck with the wrong
# commit (the dev client will use `oss-dev` but the dev server will still use
# product.json which will have `stable-$commit`).
- git checkout product.json
popd

View File

@@ -0,0 +1,340 @@
{
lib,
stdenv,
fetchFromGitHub,
buildGoModule,
makeWrapper,
cacert,
moreutils,
jq,
git,
rsync,
pkg-config,
yarn,
python3,
esbuild,
nodejs,
node-gyp,
libsecret,
xorg,
ripgrep,
cctools,
xcbuild,
quilt,
nixosTests,
}:
let
system = stdenv.hostPlatform.system;
python = python3;
yarn' = yarn.override { inherit nodejs; };
defaultYarnOpts = [ ];
esbuild' = esbuild.override {
buildGoModule =
args:
buildGoModule (
args
// rec {
version = "0.16.17";
src = fetchFromGitHub {
owner = "evanw";
repo = "esbuild";
rev = "v${version}";
hash = "sha256-8L8h0FaexNsb3Mj6/ohA37nYLFogo5wXkAhGztGUUsQ=";
};
vendorHash = "sha256-+BfxCyg0KkDQpHt/wycy/8CTG6YBA/VJvJFhhzUnSiQ=";
}
);
};
# replaces esbuild's download script with a binary from nixpkgs
patchEsbuild = path: version: ''
mkdir -p ${path}/node_modules/esbuild/bin
jq "del(.scripts.postinstall)" ${path}/node_modules/esbuild/package.json | sponge ${path}/node_modules/esbuild/package.json
sed -i 's/${version}/${esbuild'.version}/g' ${path}/node_modules/esbuild/lib/main.js
ln -s -f ${esbuild'}/bin/esbuild ${path}/node_modules/esbuild/bin/esbuild
'';
# Comment from @code-asher, the code-server maintainer
# See https://github.com/NixOS/nixpkgs/pull/240001#discussion_r1244303617
#
# If the commit is missing it will break display languages (Japanese, Spanish,
# etc). For some reason VS Code has a hard dependency on the commit being set
# for that functionality.
# The commit is also used in cache busting. Without the commit you could run
# into issues where the browser is loading old versions of assets from the
# cache.
# Lastly, it can be helpful for the commit to be accurate in bug reports
# especially when they are built outside of our CI as sometimes the version
# numbers can be unreliable (since they are arbitrarily provided).
#
# To compute the commit when upgrading this derivation, do:
# `$ git rev-parse <git-rev>` where <git-rev> is the git revision of the `src`
# Example: `$ git rev-parse v4.16.1`
commit = "1962f48b7f71772dc2c060dbaa5a6b4c0792a549";
in
stdenv.mkDerivation (finalAttrs: {
pname = "code-server";
version = "4.91.1";
src = fetchFromGitHub {
owner = "coder";
repo = "code-server";
rev = "v${finalAttrs.version}";
fetchSubmodules = true;
hash = "sha256-w0+lg/DcxKLrAz6DQGQ9+yPn42LrQ95Yn16IKNfqPvE=";
};
yarnCache = stdenv.mkDerivation {
name = "${finalAttrs.pname}-${finalAttrs.version}-${system}-yarn-cache";
inherit (finalAttrs) src;
nativeBuildInputs = [
yarn'
git
cacert
];
buildPhase = ''
runHook preBuild
export HOME=$PWD
export GIT_SSL_CAINFO="${cacert}/etc/ssl/certs/ca-bundle.crt"
yarn --cwd "./vendor" install --modules-folder modules --ignore-scripts --frozen-lockfile
yarn config set yarn-offline-mirror $out
find "$PWD" -name "yarn.lock" -printf "%h\n" | \
xargs -I {} yarn --cwd {} \
--frozen-lockfile --ignore-scripts --ignore-platform \
--ignore-engines --no-progress --non-interactive
find ./lib/vscode -name "yarn.lock" -printf "%h\n" | \
xargs -I {} yarn --cwd {} \
--ignore-scripts --ignore-engines
runHook postBuild
'';
outputHashMode = "recursive";
outputHashAlgo = "sha256";
outputHash = "sha256-LCmygPid6VJqR1PCOMk/Hc6bo4nwsLwYr7O1p3FQVvQ=";
};
nativeBuildInputs = [
nodejs
yarn'
python
pkg-config
makeWrapper
git
rsync
jq
moreutils
quilt
];
buildInputs = [
xorg.libX11
xorg.libxkbfile
]
++ lib.optionals (!stdenv.hostPlatform.isDarwin) [
libsecret
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
cctools
xcbuild
];
patches = [
# Remove all git calls from the VS Code build script except `git rev-parse
# HEAD` which is replaced in postPatch with the commit.
./build-vscode-nogit.patch
];
postPatch = ''
export HOME=$PWD
patchShebangs ./ci
# inject git commit
substituteInPlace ./ci/build/build-vscode.sh \
--replace-fail '$(git rev-parse HEAD)' "${commit}"
substituteInPlace ./ci/build/build-release.sh \
--replace-fail '$(git rev-parse HEAD)' "${commit}"
'';
configurePhase = ''
runHook preConfigure
# run yarn offline by default
echo '--install.offline true' >> .yarnrc
# set default yarn opts
${lib.concatMapStrings (option: ''
yarn --offline config set ${option}
'') defaultYarnOpts}
# set offline mirror to yarn cache we created in previous steps
yarn --offline config set yarn-offline-mirror "${finalAttrs.yarnCache}"
# skip unnecessary electron download
export ELECTRON_SKIP_BINARY_DOWNLOAD=1
# set nodedir to prevent node-gyp from downloading headers
# taken from https://nixos.org/manual/nixpkgs/stable/#javascript-tool-specific
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}
# use updated node-gyp. fixes the following error on Darwin:
# PermissionError: [Errno 1] Operation not permitted: '/usr/sbin/pkgutil'
export npm_config_node_gyp=${node-gyp}/lib/node_modules/node-gyp/bin/node-gyp.js
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
# Apply patches.
quilt push -a
export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
export SKIP_SUBMODULE_DEPS=1
export NODE_OPTIONS="--openssl-legacy-provider --max-old-space-size=4096"
# Remove all built-in extensions, as these are 3rd party extensions that
# get downloaded from the VS Code marketplace.
jq --slurp '.[0] * .[1]' "./lib/vscode/product.json" <(
cat << EOF
{
"builtInExtensions": []
}
EOF
) | sponge ./lib/vscode/product.json
# Disable automatic updates.
sed -i '/update.mode/,/\}/{s/default:.*/default: "none",/g}' \
lib/vscode/src/vs/platform/update/common/update.config.contribution.ts
# Patch out remote download of nodejs from build script.
patch -p1 -i ${./remove-node-download.patch}
# Install dependencies.
patchShebangs .
find . -name "yarn.lock" -printf "%h\n" | \
xargs -I {} yarn --cwd {} \
--offline --frozen-lockfile --ignore-scripts --ignore-engines
patchShebangs .
# Use esbuild from nixpkgs.
${patchEsbuild "./lib/vscode/build" "0.12.6"}
${patchEsbuild "./lib/vscode/extensions" "0.11.23"}
# Kerberos errors while building, so remove it for now as it is not
# required.
yarn remove kerberos --cwd lib/vscode/remote --offline --frozen-lockfile --ignore-scripts --ignore-engines
# Put ripgrep binary into bin, so post-install does not try to download it.
find -name ripgrep -type d \
-execdir mkdir -p {}/bin \; \
-execdir ln -s ${ripgrep}/bin/rg {}/bin/rg \;
# Run post-install scripts after patching.
find ./lib/vscode \( -path "*/node_modules/*" -or -path "*/extensions/*" \) \
-and -type f -name "yarn.lock" -printf "%h\n" | \
xargs -I {} sh -c 'jq -e ".scripts.postinstall" {}/package.json >/dev/null && yarn --cwd {} postinstall --frozen-lockfile --offline || true'
patchShebangs .
''
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
# Use prebuilt binary for @parcel/watcher, which requires macOS SDK 10.13+
# (see issue #101229).
pushd ./lib/vscode/remote/node_modules/@parcel/watcher
mkdir -p ./build/Release
mv ./prebuilds/darwin-x64/node.napi.glibc.node ./build/Release/watcher.node
jq "del(.scripts) | .gypfile = false" ./package.json | sponge ./package.json
popd
''
+ ''
# Build binary packages (argon2, node-pty, etc).
npm rebuild --offline
npm rebuild --offline --prefix lib/vscode/remote
# Build code-server and VS Code.
yarn build
VERSION=${finalAttrs.version} yarn build:vscode
# Inject version into package.json.
jq --slurp '.[0] * .[1]' ./package.json <(
cat << EOF
{
"version": "${finalAttrs.version}"
}
EOF
) | sponge ./package.json
# Create release, keeping all dependencies.
KEEP_MODULES=1 yarn release
# Prune development dependencies. We only need to do this for the root as
# the VS Code build process already does this for VS Code.
npm prune --omit=dev --prefix release
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/libexec/code-server $out/bin
# copy release to libexec path
cp -R -T release "$out/libexec/code-server"
# create wrapper
makeWrapper "${nodejs}/bin/node" "$out/bin/code-server" \
--add-flags "$out/libexec/code-server/out/node/entry.js"
runHook postInstall
'';
passthru = {
prefetchYarnCache = lib.overrideDerivation finalAttrs.yarnCache (d: {
outputHash = lib.fakeSha256;
});
tests = {
inherit (nixosTests) code-server;
};
# vscode-with-extensions compatibility
executableName = "code-server";
longName = "Visual Studio Code Server";
};
meta = {
changelog = "https://github.com/coder/code-server/blob/${finalAttrs.src.rev}/CHANGELOG.md";
description = "Run VS Code on a remote server";
longDescription = ''
code-server is VS Code running on a remote server, accessible through the
browser.
'';
homepage = "https://github.com/coder/code-server";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [
offline
henkery
code-asher
];
platforms = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
];
mainProgram = "code-server";
};
})

View File

@@ -0,0 +1,28 @@
--- ./lib/vscode/build/gulpfile.reh.js
+++ ./lib/vscode/build/gulpfile.reh.js
@@ -268,9 +268,6 @@
.pipe(util.stripSourceMappingURL())
.pipe(jsFilter.restore);
- const nodePath = `.build/node/v${nodeVersion}/${platform}-${arch}`;
- const node = gulp.src(`${nodePath}/**`, { base: nodePath, dot: true });
-
let web = [];
if (type === 'reh-web') {
web = [
@@ -287,7 +284,6 @@
license,
sources,
deps,
- node,
...web
);
@@ -385,7 +381,6 @@
const destinationFolderName = `vscode-${type}${dashed(platform)}${dashed(arch)}`;
const serverTaskCI = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series(
- gulp.task(`node-${platform}-${arch}`),
util.rimraf(path.join(BUILD_ROOT, destinationFolderName)),
packageTask(type, platform, arch, sourceFolderName, destinationFolderName)
));

View File

@@ -0,0 +1,33 @@
{
buildPythonApplication,
fetchPypi,
lib,
pycryptodome,
}:
buildPythonApplication rec {
pname = "dcnnt";
version = "0.10.0";
format = "setuptools";
src = fetchPypi {
inherit pname version;
hash = "sha256-73ZLgb5YcXlAOjbKLVv8oqgS6pstBdJxa7LFUgIHpUE=";
};
propagatedBuildInputs = [
pycryptodome
];
meta = with lib; {
homepage = "https://github.com/cyanomiko/dcnnt-py";
description = "UI-less tool to connect Android phone with desktop";
longDescription = ''
Yet another tool to connect Android phone with desktop similar to
KDE Connect.
'';
license = licenses.mit;
maintainers = with maintainers; [ arnoutkroeze ];
mainProgram = "dcnnt";
};
}

View File

@@ -0,0 +1,98 @@
{
stdenv,
lib,
fetchurl,
wrapQtAppsHook,
dpkg,
autoPatchelfHook,
qtserialport,
qtwebsockets,
openssl,
libredirect,
makeWrapper,
gzip,
gnutar,
nixosTests,
}:
stdenv.mkDerivation rec {
pname = "deconz";
version = "2.30.2";
src = fetchurl {
url = "https://deconz.dresden-elektronik.de/ubuntu/beta/deconz-${version}-qt5.deb";
sha256 = "sha256-exkelou1xgFEtW3vUqMZFc4AqXruzMRD9n23WmUFr3k=";
};
nativeBuildInputs = [
dpkg
autoPatchelfHook
makeWrapper
wrapQtAppsHook
];
buildInputs = [
qtserialport
qtwebsockets
openssl
];
unpackPhase = ''
runHook preUnpack
dpkg -x $src ./deconz-src
runHook postUnpack
'';
installPhase = ''
runHook preInstall
mkdir -p "$out"
cp -r deconz-src/* "$out"
# Flatten /usr and manually merge lib/ and usr/lib/, since mv refuses to.
mv "$out/lib" "$out/orig_lib"
mv "$out/usr/"* "$out/"
mkdir -p "$out/lib/systemd/system/"
mv "$out/orig_lib/systemd/system/"* "$out/lib/systemd/system/"
rmdir "$out/orig_lib/systemd/system"
rmdir "$out/orig_lib/systemd"
rmdir "$out/orig_lib"
rmdir "$out/usr"
for f in "$out/lib/systemd/system/"*.service \
"$out/share/applications/"*.desktop; do
substituteInPlace "$f" \
--replace "/usr/" "$out/"
done
for p in "$out/bin/deCONZ" "$out/bin/GCFFlasher_internal.bin"; do
wrapProgram "$p" \
--set LD_PRELOAD "${libredirect}/lib/libredirect.so" \
--set NIX_REDIRECTS "/usr/share=$out/share:/usr/bin=$out/bin" \
--prefix PATH : "${
lib.makeBinPath [
gzip
gnutar
]
}"
done
runHook postInstall
'';
passthru = {
tests = { inherit (nixosTests) deconz; };
};
meta = with lib; {
description = "Manage Zigbee network with ConBee, ConBee II or RaspBee hardware";
homepage = "https://www.dresden-elektronik.com/wireless/software/deconz.html";
license = licenses.unfree;
platforms = [ "x86_64-linux" ];
sourceProvenance = with sourceTypes; [ binaryNativeCode ];
maintainers = with maintainers; [ bjornfor ];
mainProgram = "deCONZ";
};
}

View File

@@ -0,0 +1,2 @@
[wordnet_structures.py]
trim_trailing_whitespace = unset

View File

@@ -0,0 +1,11 @@
--- a/Makefile.in~ 2011-03-06 18:52:54.000000000 +0100
+++ a/Makefile.in 2014-01-29 19:04:51.384844897 +0100
@@ -123,7 +123,7 @@
%: %.o
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ -static \
- $^ $(OBJS) $(LDFLAGS) -lz ${LIBS}
+ $(^:.o=.lo) $(OBJS) $(LDFLAGS) -lz ${LIBS}
include $(srcdir)/deps

View File

@@ -0,0 +1,57 @@
{
lib,
stdenv,
fetchurl,
which,
bison,
flex,
libmaa,
zlib,
libtool,
}:
stdenv.mkDerivation rec {
pname = "dictd";
version = "1.13.3";
src = fetchurl {
url = "mirror://sourceforge/dict/dictd-${version}.tar.gz";
hash = "sha256-GSEp37OPpyP0ipWGx5xRmPxJBP7BdXF2kXMU3Qc/EXE=";
};
patches = [
./buildfix.diff
];
buildInputs = [
libmaa
zlib
];
nativeBuildInputs = [
bison
flex
libtool
which
];
# In earlier versions, parallel building was not supported but it's OK with 1.13
enableParallelBuilding = true;
configureFlags = [
"--datadir=/run/current-system/sw/share/dictd"
"--sysconfdir=/etc"
];
postInstall = ''
install -Dm444 -t $out/share/doc/${pname} NEWS README
'';
meta = {
description = "Dict protocol server and client";
homepage = "http://www.dict.org";
license = lib.licenses.gpl2Plus;
maintainers = with lib.maintainers; [ sikmir ];
platforms = lib.platforms.unix;
};
}

View File

@@ -0,0 +1,91 @@
{
stdenv,
lib,
dict,
libfaketime,
}:
(
{
dictlist,
allowList ? [ "127.0.0.1" ],
denyList ? [ ],
}:
/*
dictlist is a list of form
[ { filename = /path/to/files/basename;
name = "name"; } ]
basename.dict.dz and basename.index should be
dict files. Or look below for other options.
allowList is a list of IP/domain *-wildcarded strings
denyList is the same..
*/
let
link_arguments = map (x: ''"${x.filename}" '') dictlist;
databases = lib.concatStrings (map (x: "${x.name} ${x.filename}\n") dictlist);
allow = lib.concatStrings (map (x: "allow ${x}\n") allowList);
deny = lib.concatStrings (map (x: "deny ${x}\n") denyList);
accessSection = "
access {
${allow}
${deny}
}
";
installPhase = ''
mkdir -p $out/share/dictd
cd $out/share/dictd
echo "${databases}" >databases.names
echo "${accessSection}" > dictd.conf
for j in ${toString link_arguments}; do
name="$(egrep ' '"$j"\$ databases.names)"
name=''${name% $j}
if test -d "$j"; then
if test -d "$j"/share/dictd ; then
echo "Got store path $j"
j="$j"/share/dictd
fi
echo "Directory reference: $j"
i=$(ls "$j""/"*.index)
i="''${i%.index}";
else
i="$j";
fi
echo "Basename is $i"
locale=$(cat "$(dirname "$i")"/locale)
base="$(basename "$i")"
echo "Locale is $locale"
export LC_ALL=$locale
export LANG=$locale
if test -e "$i".dict.dz; then
ln -s "$i".dict.dz
else
cp "$i".dict .
source_date=$(date --utc --date=@$SOURCE_DATE_EPOCH "+%F %T")
faketime -f "$source_date" dictzip "$base".dict
fi
ln -s "$i".index .
dictfmt_index2word --locale $locale < "$base".index > "$base".word || true
dictfmt_index2suffix --locale $locale < "$base".index > "$base".suffix || true
echo "database $name {" >> dictd.conf
echo " data $out/share/dictd/$base.dict.dz" >> dictd.conf
echo " index $out/share/dictd/$base.index" >> dictd.conf
echo " index_word $out/share/dictd/$base.word" >> dictd.conf
echo " index_suffix $out/share/dictd/$base.suffix" >> dictd.conf
echo "}" >> dictd.conf
done
'';
in
stdenv.mkDerivation {
name = "dictd-dbs";
nativeBuildInputs = [ libfaketime ];
buildInputs = [ dict ];
dontUnpack = true;
inherit installPhase;
}
)

View File

@@ -0,0 +1,123 @@
{
lib,
stdenv,
fetchurl,
callPackage,
}:
let
# Probably a bug in some FreeDict release files, but easier to trivially
# work around than report. Not that it can cause any other problems..
makeDictdDBFreedict =
src: name: locale:
makeDictdDB src name "{.,bin}" locale;
makeDictdDB =
src: _name: _subdir: _locale:
stdenv.mkDerivation {
name = "dictd-db-${_name}";
inherit src;
locale = _locale;
dbName = _name;
dontBuild = true;
unpackPhase = ''
tar xf ${src}
'';
installPhase = ''
mkdir -p $out/share/dictd
cp $(ls ./${_subdir}/*.{dict*,index} || true) $out/share/dictd
echo "${_locale}" >$out/share/dictd/locale
'';
meta = {
description = "Dictd-db dictionary for dictd";
platforms = lib.platforms.linux;
};
};
in
rec {
deu2eng = makeDictdDBFreedict (fetchurl {
url = "mirror://sourceforge/freedict/deu-eng.tar.gz";
sha256 = "0dqrhv04g4f5s84nbgisgcfwk5x0rpincif0yfhfh4sc1bsvzsrb";
}) "deu-eng" "de_DE";
eng2deu = makeDictdDBFreedict (fetchurl {
url = "mirror://sourceforge/freedict/eng-deu.tar.gz";
sha256 = "01x12p72sa3071iff3jhzga8588440f07zr56r3x98bspvdlz73r";
}) "eng-deu" "en_EN";
nld2eng = makeDictdDBFreedict (fetchurl {
url = "mirror://sourceforge/freedict/nld-eng.tar.gz";
sha256 = "1vhw81pphb64fzsjvpzsnnyr34ka2fxizfwilnxyjcmpn9360h07";
}) "nld-eng" "nl_NL";
eng2nld = makeDictdDBFreedict (fetchurl {
url = "mirror://sourceforge/freedict/eng-nld.tar.gz";
sha256 = "0rcg28ldykv0w2mpxc6g4rqmfs33q7pbvf68ssy1q9gpf6mz7vcl";
}) "eng-nld" "en_UK";
eng2rus = makeDictdDBFreedict (fetchurl {
url = "mirror://sourceforge/freedict/eng-rus.tar.gz";
sha256 = "15409ivhww1wsfjr05083pv6mg10bak8v5pg1wkiqybk7ck61rry";
}) "eng-rus" "en_UK";
fra2eng = makeDictdDBFreedict (fetchurl {
url = "mirror://sourceforge/freedict/fra-eng.tar.gz";
sha256 = "0sdd88s2zs5whiwdf3hd0s4pzzv75sdsccsrm1wxc87l3hjm85z3";
}) "fra-eng" "fr_FR";
eng2fra = makeDictdDBFreedict (fetchurl {
url = "mirror://sourceforge/freedict/eng-fra.tar.gz";
sha256 = "0fi6rrnbqnhc6lq8d0nmn30zdqkibrah0mxfg27hsn9z7alwbj3m";
}) "eng-fra" "en_UK";
epo2eng = makeDictdDB (fetchurl {
url = "https://download.freedict.org/dictionaries/epo-eng/1.0.1/freedict-epo-eng-1.0.1.dictd.tar.xz";
sha256 = "095xwqfc43dnm0g74i83lg03542f064jy2xbn3qnjxiwysz9ksnz";
}) "epo-eng" "epo-eng" "eo";
jpn2eng = makeDictdDB (fetchurl {
url =
let
version = "0.1";
in
"mirror://sourceforge/freedict/jpn-eng/${version}/freedict-jpn-eng-${version}.dictd.tar.xz";
sha256 = "sha256-juJBoEq7EztLZzOomc7uoZhXVaQPKoUvIxxPLB0xByc=";
}) "jpn-eng" "jpn-eng" "ja_JP";
eng2jpn = makeDictdDB (fetchurl {
url =
let
version = "2022.04.06";
in
"https://download.freedict.org/dictionaries/eng-jpn/${version}/freedict-eng-jpn-${version}.dictd.tar.xz";
sha256 = "sha256-kfRT2kgbV3XKarCr4mqDRT5A1jR8M8APky5M5MFYatE=";
}) "eng-jpn" "eng-jpn" "en_UK";
mueller_eng2rus_pkg = makeDictdDB (fetchurl {
url = "mirror://sourceforge/mueller-dict/mueller-dict-3.1.tar.gz";
sha256 = "04r5xxznvmcb8hkxqbjgfh2gxvbdd87jnhqn5gmgvxxw53zpwfmq";
}) "mueller-eng-rus" "mueller-dict-*/dict" "en_UK";
mueller_enru_abbr = {
outPath = "${mueller_eng2rus_pkg}/share/dictd/mueller-abbrev";
name = "mueller-abbr";
dbName = "mueller-abbr";
locale = "en_UK";
};
mueller_enru_base = {
outPath = "${mueller_eng2rus_pkg}/share/dictd/mueller-base";
name = "mueller-base";
dbName = "mueller-base";
locale = "en_UK";
};
mueller_enru_dict = {
outPath = "${mueller_eng2rus_pkg}/share/dictd/mueller-dict";
name = "mueller-dict";
dbName = "mueller-dict";
locale = "en_UK";
};
mueller_enru_geo = {
outPath = "${mueller_eng2rus_pkg}/share/dictd/mueller-geo";
name = "mueller-geo";
dbName = "mueller-geo";
locale = "en_UK";
};
mueller_enru_names = {
outPath = "${mueller_eng2rus_pkg}/share/dictd/mueller-names";
name = "mueller-names";
dbName = "mueller-names";
locale = "en_UK";
};
wordnet = callPackage ./dictd-wordnet.nix { };
wiktionary = callPackage ./wiktionary { };
}

View File

@@ -0,0 +1,49 @@
{
lib,
stdenv,
python3,
wordnet,
writeScript,
libfaketime,
}:
stdenv.mkDerivation rec {
version = "542";
pname = "dict-db-wordnet";
buildInputs = [
python3
wordnet
libfaketime
];
convert = ./wordnet_structures.py;
builder = writeScript "builder.sh" ''
. ${stdenv}/setup
mkdir -p $out/share/dictd/
cd $out/share/dictd
for i in ${wordnet}/dict/data.*; do
DATA="$DATA `echo $i | sed -e s,data,index,` $i";
done
source_date=$(date --utc --date=@$SOURCE_DATE_EPOCH "+%F %T")
faketime -f "$source_date" python ${convert} $DATA
echo en_US.UTF-8 > locale
'';
meta = {
description = "Dictd-compatible version of WordNet";
longDescription = ''
WordNet® is a large lexical database of English. This package makes
the wordnet data available to dictd and by extension for lookup with
the dict command.
'';
homepage = "https://wordnet.princeton.edu/";
maintainers = [ ];
platforms = lib.platforms.all;
};
}

View File

@@ -0,0 +1,28 @@
{
lib,
stdenv,
fetchurl,
libtool,
}:
stdenv.mkDerivation rec {
version = "1.3.2";
pname = "libmaa";
src = fetchurl {
url = "mirror://sourceforge/dict/libmaa-${version}.tar.gz";
sha256 = "1idi4c30pi79g5qfl7rr9s17krbjbg93bi8f2qrbsdlh78ga19ar";
};
buildInputs = [ libtool ];
# configureFlags = [ "--datadir=/run/current-system/share/dictd" ];
env.NIX_CFLAGS_COMPILE = "-Wno-error=format-truncation";
meta = with lib; {
description = "Provides many low-level data structures which are helpful for writing compilers";
license = licenses.gpl2Plus;
maintainers = with maintainers; [ sikmir ];
platforms = platforms.unix;
};
}

View File

@@ -0,0 +1,51 @@
{
lib,
stdenv,
fetchurl,
python3,
dict,
glibcLocales,
libfaketime,
}:
stdenv.mkDerivation rec {
pname = "dict-db-wiktionary";
version = "20240901";
src = fetchurl {
url = "https://dumps.wikimedia.org/enwiktionary/${version}/enwiktionary-${version}-pages-articles.xml.bz2";
sha256 = "f37e899a9091a1b01137c7b0f3d58813edf3039e9e94ae656694c88859bbe756";
};
nativeBuildInputs = [
python3
dict
glibcLocales
libfaketime
];
dontUnpack = true;
installPhase = ''
mkdir -p $out/share/dictd/
cd $out/share/dictd
source_date=$(date --utc --date=@$SOURCE_DATE_EPOCH "+%F %T")
faketime -f "$source_date" ${python3.interpreter} -O ${./wiktionary2dict.py} "${src}"
faketime -f "$source_date" dictzip wiktionary-en.dict
echo en_US.UTF-8 > locale
'';
passthru.updateScript = ./update.sh;
meta = with lib; {
description = "DICT version of English Wiktionary";
homepage = "https://en.wiktionary.org/";
maintainers = with maintainers; [ qyliss ];
platforms = platforms.all;
license = with licenses; [
cc-by-sa-30
fdl11Plus
];
};
}

View File

@@ -0,0 +1,42 @@
import subprocess
from html.parser import HTMLParser
from os.path import abspath, dirname
from urllib.request import urlopen
class WiktionaryLatestVersionParser(HTMLParser):
def __init__(self, current_version, *args, **kwargs):
self.latest_version = current_version
super().__init__(*args, **kwargs)
def handle_starttag(self, tag, attrs):
if tag != 'a':
return
href = dict(attrs)['href'][0:-1]
if href == 'latest':
return
self.latest_version = max(self.latest_version, href)
def nix_prefetch_url(url, algo='sha256'):
"""Prefetches the content of the given URL."""
print(f'nix-prefetch-url {url}')
out = subprocess.check_output(['nix-prefetch-url', '--type', algo, url])
return out.rstrip()
current_version = subprocess.check_output([
'nix', 'eval', '--raw',
'-f', dirname(abspath(__file__)) + '/../../../..',
'dictdDBs.wiktionary.version',
])
parser = WiktionaryLatestVersionParser(current_version)
with urlopen('https://dumps.wikimedia.org/enwiktionary/') as resp:
parser.feed(resp.read())
print(parser.latest_version)

View File

@@ -0,0 +1,7 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p common-updater-scripts python3
set -ueo pipefail
version="$(python "$(dirname "${BASH_SOURCE[0]}")"/latest_version.py)"
update-source-version dictdDBs.wiktionary "$version"

View File

@@ -0,0 +1,775 @@
# Adapted to produce DICT-compatible files by Petr Rockai in 2012
# Based on code from wiktiondict by Greg Hewgill
import re
import sys
import os
import textwrap
import time
import xml.sax
class Text:
def __init__(self, s):
self.s = s
def process(self):
return s
class TemplateCall:
def __init__(self):
pass
def process(self):
pass
class Template:
def __init__(self):
self.parts = []
def append(self, part):
self.parts.append(part)
def process(self):
return ''.join(x.process() for x in self.parts)
class Whitespace:
def __init__(self, s):
self.s = s
class OpenDouble: pass
class OpenTriple: pass
class CloseDouble: pass
class CloseTriple: pass
class Equals:
def __str__(self):
return "="
class Delimiter:
def __init__(self, c):
self.c = c
def __str__(self):
return self.c
def Tokenise(s):
s = str(s)
stack = []
last = 0
i = 0
while i < len(s):
if s[i] == '{' and i+1 < len(s) and s[i+1] == '{':
if i > last:
yield s[last:i]
if i+2 < len(s) and s[i+2] == '{':
yield OpenTriple()
stack.append(3)
i += 3
else:
yield OpenDouble()
stack.append(2)
i += 2
last = i
elif s[i] == '}' and i+1 < len(s) and s[i+1] == '}':
if i > last:
yield s[last:i]
if len(stack) == 0:
yield "}}"
i += 2
elif stack[-1] == 2:
yield CloseDouble()
i += 2
stack.pop()
elif i+2 < len(s) and s[i+2] == '}':
yield CloseTriple()
i += 3
stack.pop()
else:
raise SyntaxError()
last = i
elif s[i] == ':' or s[i] == '|':
if i > last:
yield s[last:i]
yield Delimiter(s[i])
i += 1
last = i
elif s[i] == '=':
if i > last:
yield s[last:i]
yield Equals()
i += 1
last = i
#elif s[i] == ' ' or s[i] == '\t' or s[i] == '\n':
# if i > last:
# yield s[last:i]
# last = i
# m = re.match(r"\s+", s[i:])
# assert m
# yield Whitespace(m.group(0))
# i += len(m.group(0))
# last = i
else:
i += 1
if i > last:
yield s[last:i]
def processSub(templates, tokens, args):
t = next(tokens)
if not isinstance(t, str):
raise SyntaxError
name = t
t = next(tokens)
default = None
if isinstance(t, Delimiter) and t.c == '|':
default = ""
while True:
t = next(tokens)
if isinstance(t, str):
default += t
elif isinstance(t, OpenDouble):
default += processTemplateCall(templates, tokens, args)
elif isinstance(t, OpenTriple):
default += processSub(templates, tokens, args)
elif isinstance(t, CloseTriple):
break
else:
print("Unexpected:", t)
raise SyntaxError()
if name in args:
return args[name]
if default is not None:
return default
if name == "lang":
return "en"
return "{{{%s}}}" % name
def processTemplateCall(templates, tokens, args):
template = tokens.next().strip().lower()
args = {}
a = 1
t = next(tokens)
while True:
if isinstance(t, Delimiter):
name = str(a)
arg = ""
while True:
t = next(tokens)
if isinstance(t, str):
arg += t
elif isinstance(t, OpenDouble):
arg += processTemplateCall(templates, tokens, args)
elif isinstance(t, OpenTriple):
arg += processSub(templates, tokens, args)
elif isinstance(t, Delimiter) and t.c != '|':
arg += str(t)
else:
break
if isinstance(t, Equals):
name = arg.strip()
arg = ""
while True:
t = next(tokens)
if isinstance(t, (str, Equals)):
arg += str(t)
elif isinstance(t, OpenDouble):
arg += processTemplateCall(templates, tokens, args)
elif isinstance(t, OpenTriple):
arg += processSub(templates, tokens, args)
elif isinstance(t, Delimiter) and t.c != '|':
arg += str(t)
else:
break
arg = arg.strip()
else:
a += 1
args[name] = arg
elif isinstance(t, CloseDouble):
break
else:
print("Unexpected:", t)
raise SyntaxError
#print template, args
if template[0] == '#':
if template == "#if":
if args['1'].strip():
return args['2']
elif '3' in args:
return args['3']
else:
return ""
elif template == "#ifeq":
if args['1'].strip() == args['2'].strip():
return args['3']
elif '4' in args:
return args['4']
else:
return ""
elif template == "#ifexist":
return ""
elif template == "#switch":
sw = args['1'].strip()
if sw in args:
return args[sw]
else:
return ""
else:
print("Unknown ParserFunction:", template)
sys.exit(1)
if template not in templates:
return "{{%s}}" % template
return process(templates, templates[template], args)
def process(templates, s, args = {}):
s = re.compile(r"<!--.*?-->", re.DOTALL).sub("", s)
s = re.compile(r"<noinclude>.*?</noinclude>", re.DOTALL).sub("", s)
assert "<onlyinclude>" not in s
#s = re.sub(r"(.*?)<onlyinclude>(.*?)</onlyinclude>(.*)", r"\1", s)
s = re.compile(r"<includeonly>(.*?)</includeonly>", re.DOTALL).sub(r"\1", s)
r = ""
#print list(Tokenise(s))
tokens = Tokenise(s)
try:
while True:
t = next(tokens)
if isinstance(t, OpenDouble):
r += processTemplateCall(templates, tokens, args)
elif isinstance(t, OpenTriple):
r += processSub(templates, tokens, args)
else:
r += str(t)
except StopIteration:
pass
return r
def test():
templates = {
'lb': "{{",
'name-example': "I am a template example, my first name is '''{{{firstName}}}''' and my last name is '''{{{lastName}}}'''. You can reference my page at [[{{{lastName}}}, {{{firstName}}}]].",
't': "start-{{{1|pqr}}}-end",
't0': "start-{{{1}}}-end",
't1': "start{{{1}}}end<noinclude>moo</noinclude>",
't2a1': "{{t2demo|a|{{{1}}}}}",
't2a2': "{{t2demo|a|2={{{1}}}}}",
't2demo': "start-{{{1}}}-middle-{{{2}}}-end",
't5': "{{t2demo|{{{a}}}=b}}",
't6': "t2demo|a",
}
def t(text, expected):
print("text:", text)
s = process(templates, text)
if s != expected:
print("got:", s)
print("expected:", expected)
sys.exit(1)
t("{{Name-example}}", "I am a template example, my first name is '''{{{firstName}}}''' and my last name is '''{{{lastName}}}'''. You can reference my page at [[{{{lastName}}}, {{{firstName}}}]].")
t("{{Name-example | firstName=John | lastName=Smith }}", "I am a template example, my first name is '''John''' and my last name is '''Smith'''. You can reference my page at [[Smith, John]].")
t("{{t0|a}}", "start-a-end")
t("{{t0| }}", "start- -end")
t("{{t0|}}", "start--end")
t("{{t0}}", "start-{{{1}}}-end")
t("{{t0| }}", "start- -end")
t("{{t0|\n}}", "start-\n-end")
t("{{t0|1= }}", "start--end")
t("{{t0|1=\n}}", "start--end")
t("{{T}}", "start-pqr-end")
t("{{T|}}", "start--end")
t("{{T|abc}}", "start-abc-end")
t("{{T|abc|def}}", "start-abc-end")
t("{{T|1=abc|1=def}}", "start-def-end")
t("{{T|abc|1=def}}", "start-def-end")
t("{{T|1=abc|def}}", "start-def-end")
t("{{T|{{T}}}}", "start-start-pqr-end-end")
t("{{T|{{T|{{T}}}}}}", "start-start-start-pqr-end-end-end")
t("{{T|{{T|{{T|{{T}}}}}}}}", "start-start-start-start-pqr-end-end-end-end")
t("{{T|a{{t|b}}}}", "start-astart-b-end-end")
t("{{T|{{T|a=b}}}}", "start-start-pqr-end-end")
t("{{T|a=b}}", "start-pqr-end")
t("{{T|1=a=b}}", "start-a=b-end")
#t("{{t1|{{lb}}tc}}}}", "start{{tcend}}")
#t("{{t2a1|1=x=y}}", "start-a-middle-{{{2}}}-end")
#t("{{t2a2|1=x=y}}", "start-a-middle-x=y-end")
#t("{{t5|a=2=d}}", "start-{{{1}}}-middle-d=b-end")
#t("{{ {{t6}} }}", "{{ t2demo|a }}")
t("{{t|[[a|b]]}}", "start-b-end")
t("{{t|[[a|b]] }}", "start-b -end")
Parts = {
# Standard POS headers
'noun': "n.",
'Noun': "n.",
'Noun 1': "n.",
'Noun 2': "n.",
'Verb': "v.",
'Adjective': "adj.",
'Adverb': "adv.",
'Pronoun': "pron.",
'Conjunction': "conj.",
'Interjection': "interj.",
'Preposition': "prep.",
'Proper noun': "n.p.",
'Proper Noun': "n.p.",
'Article': "art.",
# Standard non-POS level 3 headers
'{{acronym}}': "acr.",
'Acronym': "acr.",
'{{abbreviation}}': "abbr.",
'[[Abbreviation]]': "abbr.",
'Abbreviation': "abbr.",
'[[initialism]]': "init.",
'{{initialism}}': "init.",
'Initialism': "init.",
'Contraction': "cont.",
'Prefix': "prefix",
'Suffix': "suffix",
'Symbol': "sym.",
'Letter': "letter",
'Idiom': "idiom",
'Idioms': "idiom",
'Phrase': "phrase",
# Debated POS level 3 headers
'Number': "num.",
'Numeral': "num.",
'Cardinal number': "num.",
'Ordinal number': "num.",
'Cardinal numeral': "num.",
'Ordinal numeral': "num.",
# Other headers in use
'Personal pronoun': "pers.pron.",
'Adjective/Adverb': "adj./adv.",
'Proper adjective': "prop.adj.",
'Determiner': "det.",
'Demonstrative determiner': "dem.det.",
'Clitic': "clitic",
'Infix': "infix",
'Counter': "counter",
'Kanji': None,
'Kanji reading': None,
'Hiragana letter': None,
'Katakana letter': None,
'Pinyin': None,
'Han character': None,
'Hanzi': None,
'Hanja': None,
'Proverb': "prov.",
'Expression': None,
'Adjectival noun': None,
'Quasi-adjective': None,
'Particle': "part.",
'Infinitive particle': "part.",
'Possessive adjective': "poss.adj.",
'Verbal prefix': "v.p.",
'Postposition': "post.",
'Prepositional article': "prep.art.",
'Phrasal verb': "phr.v.",
'Participle': "participle",
'Interrogative auxiliary verb': "int.aux.v.",
'Pronominal adverb': "pron.adv.",
'Adnominal': "adn.",
'Abstract pronoun': "abs.pron.",
'Conjunction particle': None,
'Root': "root",
# Non-standard, deprecated headers
'Noun form': "n.",
'Verb form': "v.",
'Adjective form': "adj.form.",
'Nominal phrase': "nom.phr.",
'Noun phrase': "n. phrase",
'Verb phrase': "v. phrase",
'Transitive verb': "v.t.",
'Intransitive verb': "v.i.",
'Reflexive verb': "v.r.",
'Cmavo': None,
'Romaji': "rom.",
'Hiragana': None,
'Furigana': None,
'Compounds': None,
# Other headers seen
'Alternative forms': None,
'Alternative spellings': None,
'Anagrams': None,
'Antonym': None,
'Antonyms': None,
'Conjugation': None,
'Declension': None,
'Declension and pronunciations': None,
'Definite Article': "def.art.",
'Definite article': "def.art.",
'Demonstrative pronoun': "dem.pron.",
'Derivation': None,
'Derived expression': None,
'Derived expressions': None,
'Derived forms': None,
'Derived phrases': None,
'Derived terms': None,
'Derived, Related terms': None,
'Descendants': None,
#'Etymology': None,
#'Etymology 1': None,
#'Etymology 2': None,
#'Etymology 3': None,
#'Etymology 4': None,
#'Etymology 5': None,
'Examples': None,
'External links': None,
'[[Gismu]]': None,
'Gismu': None,
'Homonyms': None,
'Homophones': None,
'Hyphenation': None,
'Indefinite article': "art.",
'Indefinite pronoun': "ind.pron.",
'Indefinite Pronoun': "ind.pron.",
'Indetermined pronoun': "ind.pron.",
'Interrogative conjunction': "int.conj.",
'Interrogative determiner': "int.det.",
'Interrogative particle': "int.part.",
'Interrogative pronoun': "int.pron.",
'Legal expression': "legal",
'Mass noun': "n.",
'Miscellaneous': None,
'Mutations': None,
'Noun and verb': "n/v.",
'Other language': None,
'Pinyin syllable': None,
'Possessive determiner': "poss.det.",
'Possessive pronoun': "poss.pron.",
'Prepositional phrase': "prep.phr.",
'Prepositional Pronoun': "prep.pron.",
'Pronunciation': None,
'Pronunciation 1': None,
'Pronunciation 2': None,
'Quotations': None,
'References': None,
'Reflexive pronoun': "refl.pron.",
'Related expressions': None,
'Related terms': None,
'Related words': None,
'Relative pronoun': "rel.pron.",
'Saying': "saying",
'See also': None,
'Shorthand': None,
'[http://en.wikipedia.org/wiki/Shorthand Shorthand]': None,
'Sister projects': None,
'Spelling note': None,
'Synonyms': None,
'Translation': None,
'Translations': None,
'Translations to be checked': None,
'Transliteration': None,
'Trivia': None,
'Usage': None,
'Usage in English': None,
'Usage notes': None,
'Verbal noun': "v.n.",
}
PartsUsed = {}
for p in list(Parts.keys()):
PartsUsed[p] = 0
def encode(s):
r = e(s)
assert r[1] == len(s)
return r[0]
def dowikilink(m):
a = m.group(1).split("|")
if len(a) > 1:
link = a[1]
else:
link = a[0]
if ':' in link:
link = ""
return link
seentemplates = {}
def dotemplate(m):
aa = m.group(1).split("|")
args = {}
n = 0
for a in aa:
am = re.match(r"(.*?)(=(.*))?", a)
if am:
args[am.group(1)] = am.group(3)
else:
n += 1
args[n] = am.group(1)
#if aa[0] in seentemplates:
# seentemplates[aa[0]] += 1
#else:
# seentemplates[aa[0]] = 1
# print len(seentemplates), aa[0]
#print aa[0]
#if aa[0] not in Templates:
# return "(unknown template %s)" % aa[0]
#body = Templates[aa[0]]
#body = re.sub(r"<noinclude>.*?</noinclude>", "", body)
#assert "<onlyinclude>" not in body
##body = re.sub(r"(.*?)<onlyinclude>(.*?)</onlyinclude>(.*)", r"\1", body)
#body = re.sub(r"<includeonly>(.*?)</includeonly>", r"\1", body)
#def dotemplatearg(m):
# ta = m.group(1).split("|")
# if ta[0] in args:
# return args[ta[0]]
# elif len(ta) > 1:
# return ta[1]
# else:
# return "{{{%s}}}" % ta[0]
#body = re.sub(r"{{{(.*?)}}}", dotemplatearg, body)
#return dewiki(body)
def doparserfunction(m):
a = m.group(2).split("|")
if m.group(1) == "ifeq":
if a[0] == a[1]:
return a[2]
elif len(a) >= 4:
return a[3]
return ""
def dewiki(body, indent = 0):
# process in this order:
# {{{ }}}
# <> <>
# [[ ]]
# {{ }}
# ''' '''
# '' ''
#body = wikimediatemplate.process(Templates, body)
body = re.sub(r"\[\[(.*?)\]\]", dowikilink, body)
#body = re.sub(r"{{(.*?)}}", dotemplate, body)
#body = re.sub(r"{{#(.*?):(.*?)}}", doparserfunction, body)
body = re.sub(r"'''(.*?)'''", r"\1", body)
body = re.sub(r"''(.*?)''", r"\1", body)
lines = body.split("\n")
n = 0
i = 0
while i < len(lines):
if len(lines[i]) > 0 and lines[i][0] == "#":
if len(lines[i]) > 1 and lines[i][1] == '*':
wlines = textwrap.wrap(lines[i][2:].strip(),
initial_indent = " * ",
subsequent_indent = " ")
elif len(lines[i]) > 1 and lines[i][1] == ':':
wlines = textwrap.wrap(lines[i][2:].strip(),
initial_indent = " ",
subsequent_indent = " ")
else:
n += 1
wlines = textwrap.wrap(str(n) + ". " + lines[i][1:].strip(),
subsequent_indent = " ")
elif len(lines[i]) > 0 and lines[i][0] == "*":
n = 0
wlines = textwrap.wrap(lines[i][1:].strip(),
initial_indent = "* ",
subsequent_indent = " ")
else:
n = 0
wlines = textwrap.wrap(lines[i].strip())
if len(wlines) == 0:
wlines = ['']
lines[i:i+1] = wlines
i += len(wlines)
return ''.join(" "*(indent-1)+x+"\n" for x in lines)
class WikiSection:
def __init__(self, heading, body):
self.heading = heading
self.body = body
#self.lines = re.split("\n+", body.strip())
#if len(self.lines) == 1 and len(self.lines[0]) == 0:
# self.lines = []
self.children = []
def __str__(self):
return "<%s:%i:%s>" % (self.heading, len(self.body or ""), ','.join([str(x) for x in self.children]))
def add(self, section):
self.children.append(section)
def parse(word, text):
headings = list(re.finditer("^(=+)\s*(.*?)\s*=+\n", text, re.MULTILINE))
#print [x.group(1) for x in headings]
doc = WikiSection(word, "")
stack = [doc]
for i, m in enumerate(headings):
depth = len(m.group(1))
if depth < len(stack):
stack = stack[:depth]
else:
while depth > len(stack):
s = WikiSection(None, "")
stack[-1].add(s)
stack.append(s)
if i+1 < len(headings):
s = WikiSection(m.group(2), text[m.end(0):headings[i+1].start(0)].strip())
else:
s = WikiSection(m.group(2), text[m.end(0):].strip())
assert len(stack) == depth
stack[-1].add(s)
stack.append(s)
#while doc.heading is None and len(doc.lines) == 0 and len(doc.children) == 1:
# doc = doc.children[0]
return doc
def formatFull(word, doc):
def f(depth, section):
if section.heading:
r = " "*(depth-1) + section.heading + "\n\n"
else:
r = ""
if section.body:
r += dewiki(section.body, depth+1)+"\n"
#r += "".join(" "*depth + x + "\n" for x in dewiki(section.body))
#if len(section.lines) > 0:
# r += "\n"
for c in section.children:
r += f(depth+1, c)
return r
s = f(0, doc)
s += "Ref: http://en.wiktionary.org/wiki/%s\n" % word
return s
def formatNormal(word, doc):
def f(depth, posdepth, section):
r = ""
if depth == posdepth:
if not section.heading or section.heading.startswith("Etymology"):
posdepth += 1
elif section.heading in Parts:
#p = Parts[section.heading]
#if p:
# r += " "*(depth-1) + word + " (" + p + ")\n\n"
r += " "*(depth-1) + section.heading + "\n\n"
else:
print("Unknown part: (%s) %s" % (word, section.heading), file=errors)
return ""
elif depth > posdepth:
return ""
elif section.heading:
r += " "*(depth-1) + section.heading + "\n\n"
if section.body:
r += dewiki(section.body, depth+1)+"\n"
#r += "".join(" "*depth + x + "\n" for x in dewiki(section.lines))
#if len(section.lines) > 0:
# r += "\n"
for c in section.children:
r += f(depth+1, posdepth, c)
return r
s = f(0, 3, doc)
s += "Ref: http://en.wiktionary.org/wiki/%s\n" % word
return s
def formatBrief(word, doc):
def f(depth, posdepth, section):
if depth == posdepth:
h = section.heading
if not section.heading or section.heading.startswith("Etymology"):
posdepth += 1
elif section.heading in Parts:
#h = Parts[section.heading]
#if h:
# h = "%s (%s)" % (word, h)
pass
stack.append([h, False])
elif depth > 0:
stack.append([section.heading, False])
else:
stack.append(["%h " + section.heading, False])
r = ""
#if section.heading:
# r += " "*(depth-1) + section.heading + "\n"
body = ''.join(x+"\n" for x in section.body.split("\n") if len(x) > 0 and x[0] == '#')
if len(body) > 0:
for i in range(len(stack)):
if not stack[i][1]:
if stack[i][0]:
r += " "*(i-1) + stack[i][0] + "\n"
stack[i][1] = True
r += dewiki(body, depth+1)
for c in section.children:
r += f(depth+1, posdepth, c)
stack.pop()
return r
stack = []
s = f(0, 3, doc)
s += "Ref: http://en.wiktionary.org/wiki/%s\n" % word
return s
class WikiHandler(xml.sax.ContentHandler):
def __init__(self):
self.element = None
self.page = None
self.text = ""
self.long = {}
def startElement(self, name, attrs):
#print "start", name, attrs
self.element = name
def endElement(self, name):
#print "end", name
if self.element == "text":
if self.page:
if self.page in self.long:
print(self.page, len(self.text))
print()
self.doPage(self.page, self.text)
self.page = None
self.text = ""
self.element = None
def characters(self, content):
#print "characters", content
if self.element == "title":
if self.checkPage(content):
self.page = content
elif self.element == "text":
if self.page:
self.text += content
if len(self.text) > 100000 and self.page not in self.long:
self.long[self.page] = 1
def checkPage(self, page):
return False
def doPage(self, page, text):
pass
class TemplateHandler(WikiHandler):
def checkPage(self, page):
return page.startswith("Template:")
def doPage(self, page, text):
Templates[page[page.find(':')+1:].lower()] = text
class WordHandler(WikiHandler):
def checkPage(self, page):
return ':' not in page
def doPage(self, page, text):
m = re.match(r"#redirect\s*\[\[(.*?)\]\]", text, re.IGNORECASE)
if m:
out.write(" See <%s>" % page)
return
doc = parse(page, text)
out.write(formatBrief(page, doc))
#print formatBrief(page, doc)
fn = sys.argv[1]
info = """ This file was converted from the original database on:
%s
The original data is available from:
http://en.wiktionary.org
The version from which this file was generated was:
%s
Wiktionary is available under the GNU Free Documentation License.
""" % (time.ctime(), os.path.basename(fn))
errors = open("mkdict.err", "w")
Templates = {}
f = os.popen("bunzip2 -c %s" % fn, "r")
xml.sax.parse(f, TemplateHandler())
f.close()
f = os.popen("bunzip2 -c %s" % fn, "r")
out = os.popen("dictfmt -p wiktionary-en --utf8 --columns 0 -u http://en.wiktionary.org", "w")
out.write("%%h English Wiktionary\n%s" % info)
xml.sax.parse(f, WordHandler())
f.close()
out.close()

View File

@@ -0,0 +1,320 @@
#!/usr/bin/env python3
#Copyright 2007 Sebastian Hagen
# This file is part of wordnet_tools.
# wordnet_tools is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation
# wordnet_tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with wordnet_tools; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This program requires python >= 2.4.
# This program converts wordnet index/data file pairs into dict index/data
# files usable by dictd.
# This is basically a reimplementation of the wnfilter program by Rik Faith,
# which unfortunately doesn't work correctly for wordnet files in the newer
# formats. This version of wordnet_structures whould parse wordnet 2.1 files
# correctly, and create output very similar to what wnfilter would have
# written.
import datetime
import math
from textwrap import TextWrapper
CAT_ADJECTIVE = 0
CAT_ADVERB = 1
CAT_NOUN = 2
CAT_VERB = 3
category_map = {
'n': CAT_NOUN,
'v': CAT_VERB,
'a': CAT_ADJECTIVE,
's': CAT_ADJECTIVE,
'r': CAT_ADVERB
}
class WordIndex:
def __init__(self, lemma, category, ptrs, synsets, tagsense_count):
self.lemma = lemma
self.category = category
self.ptrs = ptrs
self.synsets = synsets
self.tagsense_count = tagsense_count
@classmethod
def build_from_line(cls, line_data, synset_map):
line_split = line_data.split()
lemma = line_split[0]
category = category_map[line_split[1]]
synset_count = int(line_split[2],10)
ptr_count = int(line_split[3],10)
ptrs = [line_split[i] for i in range(3, 3+ptr_count)]
tagsense_count = int(line_split[5 + ptr_count],10)
synsets = [synset_map[int(line_split[i],10)] for i in range(6 + ptr_count, 6 + ptr_count + synset_count)]
return cls(lemma, category, ptrs, synsets, tagsense_count)
@classmethod
def build_from_file(cls, f, synset_map, rv_base=None):
if (rv_base is None):
rv = {}
else:
rv = rv_base
for line in f:
if (line.startswith(' ')):
continue
wi = cls.build_from_line(line, synset_map)
word = wi.lemma.lower()
if not (word in rv):
rv[word] = []
rv[word].append(wi)
return rv
def __repr__(self):
return '%s%s' % (self.__class__.__name__, (self.lemma, self.category, self.ptrs, self.synsets, self.tagsense_count))
class WordIndexDictFormatter(WordIndex):
category_map_rev = {
CAT_NOUN: 'n',
CAT_VERB: 'v',
CAT_ADJECTIVE: 'adj',
CAT_ADVERB: 'adv'
}
linesep = '\n'
LINE_WIDTH_MAX = 68
prefix_fmtf_line_first = '%5s 1: '
prefix_fmtn_line_first = ' '
prefix_fmtf_line_nonfirst = '%5d: '
prefix_fmtn_line_nonfirst = ' '
def dict_str(self):
tw = TextWrapper(width=self.LINE_WIDTH_MAX,
initial_indent=(self.prefix_fmtf_line_first % self.category_map_rev[self.category]),
subsequent_indent=self.prefix_fmtn_line_first)
lines = (tw.wrap(self.synsets[0].dict_str()))
i = 2
for synset in self.synsets[1:]:
tw = TextWrapper(width=self.LINE_WIDTH_MAX,
initial_indent=(self.prefix_fmtf_line_nonfirst % i),
subsequent_indent=self.prefix_fmtn_line_nonfirst)
lines.extend(tw.wrap(synset.dict_str()))
i += 1
return self.linesep.join(lines)
class Synset:
def __init__(self, offset, ss_type, words, ptrs, gloss, frames=()):
self.offset = offset
self.type = ss_type
self.words = words
self.ptrs = ptrs
self.gloss = gloss
self.frames = frames
self.comments = []
@classmethod
def build_from_line(cls, line_data):
line_split = line_data.split()
synset_offset = int(line_split[0],10)
ss_type = category_map[line_split[2]]
word_count = int(line_split[3],16)
words = [line_split[i] for i in range(4, 4 + word_count*2,2)]
ptr_count = int(line_split[4 + word_count*2],10)
ptrs = [(line_split[i], line_split[i+1], line_split[i+2], line_split[i+3]) for i in range(5 + word_count*2,4 + word_count*2 + ptr_count*4,4)]
tok = line_split[5 + word_count*2 + ptr_count*4]
base = 6 + word_count*2 + ptr_count*4
if (tok != '|'):
frame_count = int(tok, 10)
frames = [(int(line_split[i+1],10), int(line_split[i+2],16)) for i in range(base, base + frame_count*3, 3)]
base += frame_count*3 + 1
else:
frames = []
line_split2 = line_data.split(None, base)
if (len(line_split2) < base):
gloss = None
else:
gloss = line_split2[-1]
return cls(synset_offset, ss_type, words, ptrs, gloss, frames)
@classmethod
def build_from_file(cls, f):
rv = {}
comments = []
for line in f:
if (line.startswith(' ')):
line_s = line.lstrip().rstrip('\n')
line_elements = line_s.split(None,1)
try:
int(line_elements[0])
except ValueError:
continue
if (len(line_elements) == 1):
line_elements.append('')
comments.append(line_elements[1])
continue
synset = cls.build_from_line(line.rstrip())
rv[synset.offset] = synset
return (rv, comments)
def dict_str(self):
rv = self.gloss
if (len(self.words) > 1):
rv += ' [syn: %s]' % (', '.join([('{%s}' % word) for word in self.words]))
return rv
def __repr__(self):
return '%s%s' % (self.__class__.__name__, (self.offset, self.type, self.words, self.ptrs, self.gloss, self.frames))
class WordnetDict:
db_info_fmt = '''This file was converted from the original database on:
%(conversion_datetime)s
The original data is available from:
%(wn_url)s
The original data was distributed with the notice shown below. No
additional restrictions are claimed. Please redistribute this changed
version under the same conditions and restriction that apply to the
original version.\n\n
%(wn_license)s'''
datetime_fmt = '%Y-%m-%dT%H:%M:%S'
base64_map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
def __init__(self, wn_url, desc_short, desc_long):
self.word_data = {}
self.wn_url = wn_url
self.desc_short = desc_short
self.desc_long = desc_long
self.wn_license = None
def wn_dict_add(self, file_index, file_data):
file_data.seek(0)
file_index.seek(0)
(synsets, license_lines) = Synset.build_from_file(file_data)
WordIndexDictFormatter.build_from_file(file_index, synsets, self.word_data)
if (license_lines):
self.wn_license = '\n'.join(license_lines) + '\n'
@classmethod
def base64_encode(cls, i):
"""Encode a non-negative integer into a dictd compatible base64 string"""
if (i < 0):
raise ValueError('Value %r for i is negative' % (i,))
r = 63
e = 1
while (r < i):
e += 1
r = 64**e - 1
rv = ''
while (e > 0):
e -= 1
d = math.floor(i / 64**e)
rv += cls.base64_map[d]
i = i % (64**e)
return rv
@classmethod
def dict_entry_write(cls, file_index, file_data, key, entry, linesep='\n'):
"""Write a single dict entry for <key> to index and data files"""
entry_start = file_data.tell()
file_data.write(entry)
entry_len = len(entry)
file_index.write('%s\t%s\t%s%s' % (key, cls.base64_encode(entry_start),
cls.base64_encode(entry_len), linesep))
def dict_generate(self, file_index, file_data):
file_index.seek(0)
file_data.seek(0)
# The dictd file format is fairly iffy on the subject of special
# headwords: either dictd is buggy, or the manpage doesn't tell the whole
# story about the format.
# The upshot is that order of these entries in the index *matters*.
# Putting them at the beginning and in alphabetic order is afaict ok.
# Some other orders completely and quietly break the ability to look
# those headwords up.
# -- problem encountered with 1.10.2, at 2007-08-05.
file_data.write('\n')
wn_url = self.wn_url
conversion_datetime = datetime.datetime.now().strftime(self.datetime_fmt)
wn_license = self.wn_license
self.dict_entry_write(file_index, file_data, '00-database-info', '00-database-info\n%s\n' % (self.db_info_fmt % vars()))
self.dict_entry_write(file_index, file_data, '00-database-long', '00-database-long\n%s\n' % self.desc_long)
self.dict_entry_write(file_index, file_data, '00-database-short', '00-database-short\n%s\n' % self.desc_short)
self.dict_entry_write(file_index, file_data, '00-database-url', '00-database-url\n%s\n' % self.wn_url)
words = list(self.word_data.keys())
words.sort()
for word in words:
for wi in self.word_data[word]:
word_cs = word
# Use case-sensitivity information of first entry of first synset that
# matches this word case-insensitively
for synset in wi.synsets:
for ss_word in synset.words:
if (ss_word.lower() == word_cs.lower()):
word_cs = ss_word
break
else:
continue
break
else:
continue
break
outstr = ''
for wi in self.word_data[word]:
outstr += wi.dict_str() + '\n'
outstr = '%s%s%s' % (word_cs, wi.linesep, outstr)
self.dict_entry_write(file_index, file_data, word_cs, outstr, wi.linesep)
file_index.truncate()
file_data.truncate()
if (__name__ == '__main__'):
import optparse
op = optparse.OptionParser(usage='usage: %prog [options] (<wn_index_file> <wn_data_file>)+')
op.add_option('-i', '--outindex', dest='oi', default='wn.index', help='filename of index file to write to')
op.add_option('-d', '--outdata', dest='od', default='wn.dict', help='filename of data file to write to')
op.add_option('--wn_url', dest='wn_url', default='ftp://ftp.cogsci.princeton.edu/pub/wordnet/2.0', help='URL for wordnet sources')
op.add_option('--db_desc_short', dest='desc_short', default=' WordNet (r) 2.1 (2005)', help='short dict DB description')
op.add_option('--db_desc_long', dest='desc_long', default=' WordNet (r): A Lexical Database for English from the\n Cognitive Science Laboratory at Princeton University', help='long dict DB description')
(options, args) = op.parse_args()
wnd = WordnetDict(wn_url=options.wn_url, desc_short=options.desc_short, desc_long=options.desc_long)
for i in range(0,len(args),2):
print('Opening index file %r...' % args[i])
file_index = open(args[i])
print('Opening data file %r...' % args[i+1])
file_data = open(args[i+1])
print('Parsing index file and data file...')
wnd.wn_dict_add(file_index, file_data)
print('All input files parsed. Writing output to index file %r and data file %r.' % (options.oi, options.od))
wnd.dict_generate(open(options.oi, 'w'),open(options.od, 'w'))
print('All done.')

View File

@@ -0,0 +1,40 @@
{
lib,
stdenv,
fetchurl,
munge,
lua,
libcap,
perl,
ncurses,
}:
stdenv.mkDerivation rec {
pname = "diod";
version = "1.0.24";
src = fetchurl {
url = "https://github.com/chaos/diod/releases/download/${version}/${pname}-${version}.tar.gz";
sha256 = "17wckwfsqj61yixz53nwkc35z66arb1x3napahpi64m7q68jn7gl";
};
postPatch = ''
substituteInPlace diod/xattr.c --replace attr/xattr.h sys/xattr.h
sed -i -e '/sys\/types\.h>/a #include <sys/sysmacros.h>' diod/ops.c
'';
buildInputs = [
munge
lua
libcap
perl
ncurses
];
meta = with lib; {
description = "I/O forwarding server that implements a variant of the 9P protocol";
maintainers = with maintainers; [ rnhmjoj ];
platforms = platforms.linux;
license = licenses.gpl2Plus;
};
}

View File

@@ -0,0 +1,192 @@
{
lib,
stdenv,
fetchurl,
# native deps.
runCommand,
pkg-config,
meson,
ninja,
makeWrapper,
# build+runtime deps.
knot-dns,
luajitPackages,
libuv,
gnutls,
lmdb,
jemalloc,
systemd,
libcap_ng,
dns-root-data,
nghttp2, # optionals, in principle
fstrm,
protobufc, # more optionals
# test-only deps.
cmocka,
which,
cacert,
extraFeatures ? false, # catch-all if defaults aren't enough
}:
let
result = if extraFeatures then wrapped-full else unwrapped;
inherit (lib) optional optionals optionalString;
lua = luajitPackages;
unwrapped = stdenv.mkDerivation rec {
pname = "knot-resolver";
version = "5.7.6";
src = fetchurl {
url = "https://secure.nic.cz/files/knot-resolver/${pname}-${version}.tar.xz";
sha256 = "500ccd3a560300e547b8dc5aaff322f7c8e2e7d6f0d7ef5f36e59cb60504d674";
};
outputs = [
"out"
"dev"
];
# Path fixups for the NixOS service.
postPatch = ''
patch meson.build <<EOF
@@ -50,2 +50,2 @@
-systemd_work_dir = prefix / get_option('localstatedir') / 'lib' / 'knot-resolver'
-systemd_cache_dir = prefix / get_option('localstatedir') / 'cache' / 'knot-resolver'
+systemd_work_dir = '/var/lib/knot-resolver'
+systemd_cache_dir = '/var/cache/knot-resolver'
EOF
# ExecStart can't be overwritten in overrides.
# We need that to use wrapped executable and correct config file.
sed '/^ExecStart=/d' -i systemd/kresd@.service.in
# On x86_64-darwin loading by soname fails to find the libs, surprisingly.
# Even though they should already be loaded and they're in RPATH, too.
for f in daemon/lua/{kres,zonefile}.lua; do
substituteInPlace "$f" \
--replace-fail "ffi.load(" "ffi.load('${lib.getLib knot-dns}/lib/' .. "
done
''
# some tests have issues with network sandboxing, apparently
+ optionalString doInstallCheck ''
echo 'os.exit(77)' > daemon/lua/trust_anchors.test/bootstrap.test.lua
sed -E '/^[[:blank:]]*test_(dstaddr|headers),?$/d' -i \
tests/config/doh2.test.lua modules/http/http_doh.test.lua
'';
preConfigure = ''
patchShebangs scripts/
'';
nativeBuildInputs = [
pkg-config
meson
ninja
];
# http://knot-resolver.readthedocs.io/en/latest/build.html#requirements
buildInputs = [
knot-dns
lua.lua
libuv
gnutls
lmdb
]
## the rest are optional dependencies
++ optionals stdenv.hostPlatform.isLinux [
# lib
systemd
libcap_ng
]
++ [
jemalloc
nghttp2
]
++ [
fstrm
protobufc
] # dnstap support
;
mesonFlags = [
"-Dkeyfile_default=${dns-root-data}/root.ds"
"-Droot_hints=${dns-root-data}/root.hints"
"-Dinstall_kresd_conf=disabled" # not really useful; examples are inside share/doc/
"-Dmalloc=jemalloc"
"--default-library=static" # not used by anyone
]
++ optional doInstallCheck "-Dunit_tests=enabled"
++ optional doInstallCheck "-Dconfig_tests=enabled"
++ optional stdenv.hostPlatform.isLinux "-Dsystemd_files=enabled" # used by NixOS service
#"-Dextra_tests=enabled" # not suitable as in-distro tests; many deps, too.
;
postInstall = ''
rm "$out"/lib/libkres.a
rm "$out"/lib/knot-resolver/upgrade-4-to-5.lua # not meaningful on NixOS
''
+ optionalString stdenv.hostPlatform.isLinux ''
rm -r "$out"/lib/sysusers.d/ # ATM more likely to harm than help
'';
doInstallCheck = with stdenv; hostPlatform == buildPlatform;
nativeInstallCheckInputs = [
cmocka
which
cacert
lua.cqueues
lua.basexx
lua.http
];
installCheckPhase = ''
meson test --print-errorlogs --no-suite snowflake
'';
meta = with lib; {
description = "Caching validating DNS resolver, from .cz domain registry";
homepage = "https://knot-resolver.cz";
license = licenses.gpl3Plus;
platforms = platforms.unix;
maintainers = [
maintainers.vcunat # upstream developer
];
mainProgram = "kresd";
};
};
wrapped-full =
runCommand unwrapped.name
{
nativeBuildInputs = [ makeWrapper ];
buildInputs = with luajitPackages; [
# For http module, prefill module, trust anchor bootstrap.
# It brings lots of deps; some are useful elsewhere (e.g. cqueues).
http
# used by policy.slice_randomize_psl()
psl
];
preferLocalBuild = true;
allowSubstitutes = false;
inherit (unwrapped) meta;
}
(
''
mkdir -p "$out"/bin
makeWrapper '${unwrapped}/bin/kresd' "$out"/bin/kresd \
--set LUA_PATH "$LUA_PATH" \
--set LUA_CPATH "$LUA_CPATH"
ln -sr '${unwrapped}/share' "$out"/
ln -sr '${unwrapped}/lib' "$out"/ # useful in NixOS service
ln -sr "$out"/{bin,sbin}
''
+ lib.optionalString unwrapped.doInstallCheck ''
echo "Checking that 'http' module loads, i.e. lua search paths work:"
echo "modules.load('http')" > test-http.lua
echo -e 'quit()' | env -i "$out"/bin/kresd -a 127.0.0.1#53535 -c test-http.lua
''
);
in
result

View File

@@ -0,0 +1,88 @@
{
lib,
stdenv,
fetchurl,
libevent,
openssl,
pkg-config,
systemdMinimal,
nixosTests,
bind8Stats ? false,
checking ? false,
ipv6 ? true,
mmap ? false,
minimalResponses ? true,
nsec3 ? true,
ratelimit ? false,
recvmmsg ? false,
rootServer ? false,
rrtypes ? false,
zoneStats ? false,
withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemdMinimal,
configFile ? "/etc/nsd/nsd.conf",
}:
stdenv.mkDerivation rec {
pname = "nsd";
version = "4.12.0";
src = fetchurl {
url = "https://www.nlnetlabs.nl/downloads/${pname}/${pname}-${version}.tar.gz";
sha256 = "sha256-+ezCz3m6UFgPLfYpGO/EQAhMW/EQV9tEwZqpZDzUteg=";
};
prePatch = ''
substituteInPlace nsd-control-setup.sh.in --replace openssl ${openssl}/bin/openssl
'';
buildInputs = [
libevent
openssl
]
++ lib.optionals withSystemd [
systemdMinimal
pkg-config
];
enableParallelBuilding = true;
configureFlags =
let
edf = c: o: if c then [ "--enable-${o}" ] else [ "--disable-${o}" ];
in
edf bind8Stats "bind8-stats"
++ edf checking "checking"
++ edf ipv6 "ipv6"
++ edf mmap "mmap"
++ edf minimalResponses "minimal-responses"
++ edf nsec3 "nsec3"
++ edf ratelimit "ratelimit"
++ edf recvmmsg "recvmmsg"
++ edf rootServer "root-server"
++ edf rrtypes "draft-rrtypes"
++ edf zoneStats "zone-stats"
++ edf withSystemd "systemd"
++ [
"--with-ssl=${openssl.dev}"
"--with-libevent=${libevent.dev}"
"--with-nsd_conf_file=${configFile}"
"--with-configdir=etc/nsd"
];
patchPhase = ''
sed 's@$(INSTALL_DATA) nsd.conf.sample $(DESTDIR)$(nsdconfigfile).sample@@g' -i Makefile.in
'';
passthru.tests = {
inherit (nixosTests) nsd;
};
meta = with lib; {
homepage = "https://www.nlnetlabs.nl";
description = "Authoritative only, high performance, simple and open source name server";
license = licenses.bsd3;
platforms = platforms.unix;
maintainers = [ maintainers.hrdinka ];
};
}

View File

@@ -0,0 +1,127 @@
{
applyPatches,
buildGoModule,
fetchFromGitHub,
fetchpatch,
k3s,
lib,
nixosTests,
symlinkJoin,
}:
let
version = "3.5.22";
etcdSrcHash = "sha256-tS1IFMxfb8Vk9HJTAK+BGPZiVE3ls4Q2DQSerALOQCc=";
etcdServerVendorHash = "sha256-ul3R0c6RoCqLvlD2dfso1KwfHjsHfzQiUVJZJmz28ks=";
etcdUtlVendorHash = "sha256-S2pje2fTDaZwf6jnyE2YXWcs/fgqF51nxCVfEwg0Gsw=";
etcdCtlVendorHash = "sha256-lZ6o0oWUsc3WiCa87ynm7UAG6VxTf81a301QMSPOvW0=";
src = applyPatches {
src = fetchFromGitHub {
owner = "etcd-io";
repo = "etcd";
tag = "v${version}";
hash = etcdSrcHash;
};
patches = [
(fetchpatch {
url = "https://github.com/etcd-io/etcd/commit/31650ab0c8df43af05fc4c13b48ffee59271eec7.patch";
hash = "sha256-Q94HOLFx2fnb61wMQsAUT4sIBXfxXqW9YEayukQXX18=";
})
];
};
env = {
CGO_ENABLED = 0;
};
meta = with lib; {
description = "Distributed reliable key-value store for the most critical data of a distributed system";
license = licenses.asl20;
homepage = "https://etcd.io/";
maintainers = with maintainers; [
dtomvan
];
platforms = platforms.darwin ++ platforms.linux;
};
etcdserver = buildGoModule {
pname = "etcdserver";
inherit
env
meta
src
version
;
__darwinAllowLocalNetworking = true;
vendorHash = etcdServerVendorHash;
modRoot = "./server";
preInstall = ''
mv $GOPATH/bin/{server,etcd}
'';
# We set the GitSHA to `GitNotFound` to match official build scripts when
# git is unavailable. This is to avoid doing a full Git Checkout of etcd.
# User facing version numbers are still available in the binary, just not
# the sha it was built from.
ldflags = [ "-X go.etcd.io/etcd/api/v3/version.GitSHA=GitNotFound" ];
};
etcdutl = buildGoModule {
pname = "etcdutl";
inherit
env
meta
src
version
;
vendorHash = etcdUtlVendorHash;
modRoot = "./etcdutl";
};
etcdctl = buildGoModule {
pname = "etcdctl";
inherit
env
meta
src
version
;
vendorHash = etcdCtlVendorHash;
modRoot = "./etcdctl";
};
in
symlinkJoin {
name = "etcd-${version}";
inherit meta version;
passthru = {
deps = {
inherit etcdserver etcdutl etcdctl;
};
tests = {
inherit (nixosTests) etcd etcd-cluster;
k3s = k3s.passthru.tests.etcd;
};
updateScript = ./update.sh;
};
paths = [
etcdserver
etcdutl
etcdctl
];
}

74
pkgs/servers/etcd/3_5/update.sh Executable file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p curl gnugrep gnused jq nurl
set -x -eu -o pipefail
MAJOR_VERSION=3
MINOR_VERSION=5
ETCD_PATH="$(dirname "$0")"
ETCD_VERSION_MAJOR_MINOR=${MAJOR_VERSION}.${MINOR_VERSION}
ETCD_PKG_NAME=etcd_${MAJOR_VERSION}_${MINOR_VERSION}
NIXPKGS_PATH="$(git rev-parse --show-toplevel)"
LATEST_TAG=$(curl ${GITHUB_TOKEN:+" -u \":$GITHUB_TOKEN\""} \
--silent https://api.github.com/repos/etcd-io/etcd/releases \
| jq -r 'map(select(.prerelease == false))' \
| jq -r 'map(.tag_name)' \
| grep "v${ETCD_VERSION_MAJOR_MINOR}." \
| sed 's|[", ]||g' \
| sort -rV | head -n1 )
LATEST_VERSION=$(echo ${LATEST_TAG} | sed 's/^v//')
OLD_VERSION="$(nix-instantiate --eval -E "with import $NIXPKGS_PATH {}; \
$ETCD_PKG_NAME.version or (builtins.parseDrvName $ETCD_PKG_NAME.name).version" | tr -d '"')"
if [ ! "$OLD_VERSION" = "$LATEST_VERSION" ]; then
echo "Attempting to update etcd from $OLD_VERSION to $LATEST_VERSION"
ETCD_SRC_HASH=$(nix-prefetch-url --quiet --unpack https://github.com/etcd-io/etcd/archive/refs/tags/${LATEST_TAG}.tar.gz)
ETCD_SRC_HASH=$(nix --extra-experimental-features nix-command hash to-sri --type sha256 $ETCD_SRC_HASH)
setKV () {
sed -i "s|$1 = \".*\"|$1 = \"${2:-}\"|" "$ETCD_PATH/default.nix"
}
setKV version $LATEST_VERSION
setKV etcdSrcHash $ETCD_SRC_HASH
getAndSetVendorHash () {
local EMPTY_HASH="sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" # Hash from lib.fakeHash
local VENDOR_HASH=$EMPTY_HASH
local PKG_KEY=$1
local INNER_PKG=$2
setKV $PKG_KEY $EMPTY_HASH
set +e
VENDOR_HASH=$(nurl -e "(import ${NIXPKGS_PATH}/. {}).$ETCD_PKG_NAME.passthru.deps.$INNER_PKG.goModules")
set -e
if [ -n "${VENDOR_HASH:-}" ]; then
setKV $PKG_KEY $VENDOR_HASH
else
echo "Update failed. $PKG_KEY is empty."
exit 1
fi
}
getAndSetVendorHash etcdServerVendorHash etcdserver
getAndSetVendorHash etcdUtlVendorHash etcdutl
getAndSetVendorHash etcdCtlVendorHash etcdctl
# `git` flag here is to be used by local maintainers to speed up the bump process
if [ $# -eq 1 ] && [ "$1" = "git" ]; then
git switch -c "package-$ETCD_PKG_NAME-$LATEST_VERSION"
git add "$ETCD_PATH"/default.nix
git commit -m "$ETCD_PKG_NAME: $OLD_VERSION -> $LATEST_VERSION
Release: https://github.com/etcd-io/etcd/releases/tag/$LATEST_TAG"
fi
else
echo "etcd is already up-to-date at $OLD_VERSION"
fi

View File

@@ -0,0 +1,26 @@
# etcd
## Upstream release cadence and support
The etcd project maintains release branches for the current version and previous release.
For example, when v3.5 is the current version, v3.4 is supported. When v3.6 is released, v3.4 goes out of support.
Reference: https://etcd.io/docs/v3.5/op-guide/versioning/
## NixOS release and etcd version upkeep
Every major/minor version bump of `etcd` top-level alias in nixpkgs requires a notification in the next NixOS release notes scheduling the removal of the now unsupported etcd version.
After every NixOS release, the unsupported etcd versions should be removed by etcd maintainers.
## User guidelines on etcd upgrades
Before upgrading a NixOS release, certify to upgrade etcd to the latest version in the current used release.
Manual steps might be required for the upgrade.
NixOS release notes might have instructions on how to proceed on upgrades.

View File

@@ -0,0 +1,28 @@
{
lib,
stdenv,
fetchurl,
}:
stdenv.mkDerivation rec {
pname = "apache-felix";
version = "7.0.5";
src = fetchurl {
url = "mirror://apache/felix/org.apache.felix.main.distribution-${version}.tar.gz";
sha256 = "sha256-N9mbkIzMkMV2RLONv15EiosJxMU9iEJvwPWEauPIEe8=";
};
buildCommand = ''
tar xfvz $src
cd felix-framework-*
mkdir -p $out
cp -av * $out
'';
meta = with lib; {
description = "OSGi gateway";
homepage = "https://felix.apache.org";
sourceProvenance = with sourceTypes; [ binaryBytecode ];
license = licenses.asl20;
maintainers = [ maintainers.sander ];
mainProgram = "felix.jar";
};
}

View File

@@ -0,0 +1,14 @@
{ stdenv, fetchurl }:
stdenv.mkDerivation rec {
version = "1.1.2";
pname = "apache-felix-remoteshell-bundle";
src = fetchurl {
url = "http://apache.proserve.nl/felix/org.apache.felix.shell.remote-${version}.jar";
sha256 = "147zw5ppn98wfl3pr32isyb267xm3gwsvdfdvjr33m9g2v1z69aq";
};
buildCommand = ''
mkdir -p $out/bundle
cp ${src} $out/bundle/org.apache.felix.shell.remote-${version}.jar
'';
}

View File

@@ -0,0 +1,118 @@
{
lib,
stdenv,
fetchFromGitHub,
fetchDebianPatch,
libedit,
autoreconfHook,
zlib,
unzip,
libtommath,
libtomcrypt,
icu73,
superServer ? false,
}:
let
base = {
pname = "firebird";
meta = with lib; {
description = "SQL relational database management system";
downloadPage = "https://github.com/FirebirdSQL/firebird/";
homepage = "https://firebirdsql.org/";
changelog = "https://github.com/FirebirdSQL/firebird/blob/master/CHANGELOG.md";
license = with lib.licenses; [
mpl11
interbase
];
platforms = platforms.linux;
maintainers = with maintainers; [
bbenno
marcweber
];
};
nativeBuildInputs = [ autoreconfHook ];
buildInputs = [
libedit
icu73
];
LD_LIBRARY_PATH = lib.makeLibraryPath [ icu73 ];
configureFlags = [
"--with-system-editline"
]
++ (lib.optional superServer "--enable-superserver");
enableParallelBuilding = true;
installPhase = ''
runHook preInstall
mkdir -p $out
cp -r gen/Release/firebird/* $out
rm -f $out/lib/*.a # they were just symlinks to /build/source/...
runHook postInstall
'';
};
in
rec {
firebird_3 = stdenv.mkDerivation (
base
// rec {
version = "3.0.13";
src = fetchFromGitHub {
owner = "FirebirdSQL";
repo = "firebird";
rev = "v${version}";
hash = "sha256-ti3cFfByM2wxOLkAebwtFe25B5W7jOwi3f7MPYo/yUA=";
};
patches = [
(fetchDebianPatch {
pname = "firebird3.0";
version = "3.0.13.ds7";
debianRevision = "2";
patch = "no-binary-gbaks.patch";
hash = "sha256-LXUMM38PBYeLPdgaxLPau4HWB4ItJBBnx7oGwalL6Pg=";
})
];
buildInputs = base.buildInputs ++ [
zlib
libtommath
];
meta = base.meta // {
platforms = [ "x86_64-linux" ];
};
}
);
firebird_4 = stdenv.mkDerivation (
base
// rec {
version = "4.0.6";
src = fetchFromGitHub {
owner = "FirebirdSQL";
repo = "firebird";
rev = "v${version}";
hash = "sha256-65wfG6huDzvG/tEVllA58OfZqoL4U/ilw5YIDqQywTs=";
};
nativeBuildInputs = base.nativeBuildInputs ++ [ unzip ];
buildInputs = base.buildInputs ++ [
zlib
libtommath
libtomcrypt
];
}
);
firebird = firebird_4;
}

View File

@@ -0,0 +1,92 @@
{
lib,
stdenv,
fetchFromGitHub,
automake,
autoconf,
libtool,
flex,
bison,
texinfo,
fetchpatch,
pkgsStatic,
withNcurses ? true,
ncurses,
}:
stdenv.mkDerivation {
pname = "gpm";
version = "unstable-2020-06-17";
src = fetchFromGitHub {
owner = "telmich";
repo = "gpm";
rev = "e82d1a653ca94aa4ed12441424da6ce780b1e530";
sha256 = "0ndn6dwc87slvyqp2cnbb02a6hkjwb6zjhs6viysykv06hq7ihy6";
};
postPatch = ''
substituteInPlace src/prog/gpm-root.y --replace __sigemptyset sigemptyset
'';
nativeBuildInputs = [
automake
autoconf
libtool
flex
bison
texinfo
];
buildInputs = [ ncurses ];
hardeningDisable = [ "format" ];
patches = [
(fetchpatch {
# pull request telmich/gpm#42
url = "https://github.com/kaction/gpm/commit/217b4fe4c9b62298a4e9a54c1f07e3b52b013a09.patch";
sha256 = "1f74h12iph4z1dldbxk9imcq11805c3ai2xhbsqvx8jpjrcfp19q";
})
# Pull fix pending upstream inclusion to fix parallel installation:
# https://github.com/telmich/gpm/pull/43
(fetchpatch {
name = "parallel-install.patch";
url = "https://github.com/telmich/gpm/commit/a88fb82a7afe96e872bb31c554e9ad5888f5a451.patch";
sha256 = "0g1jhz9bjw7vqjv922xkhs8xkjxdqh11nj38jj3c8nv5lcil76nx";
})
];
preConfigure = ''
./autogen.sh
'';
configureFlags = [
"--sysconfdir=/etc"
"--localstatedir=/var"
(if withNcurses then "--with-curses" else "--without-curses")
# The code won't compile in c23 mode.
# https://gcc.gnu.org/gcc-15/porting_to.html#c23-fn-decls-without-parameters
"CFLAGS=-std=gnu17"
];
enableParallelBuilding = true;
# Provide libgpm.so for compatibility
postInstall = ''
if test -e "$out/lib/libgpm.so.2"; then
ln -sv "$out/lib/libgpm.so.2" "$out/lib/libgpm.so"
else
rm -f "$out/lib/libgpm.so.2"
fi
'';
passthru.tests.static = pkgsStatic.gpm;
meta = with lib; {
homepage = "https://www.nico.schottelius.org/software/gpm/";
description = "Daemon that provides mouse support on the Linux console";
license = licenses.gpl2Plus;
platforms = platforms.linux ++ platforms.cygwin;
maintainers = [ ];
};
}

View File

@@ -0,0 +1,68 @@
{
lib,
stdenv,
fetchurl,
makeWrapper,
jdk11_headless,
nixosTests,
}:
let
common =
{
version,
hash,
jdk ? jdk11_headless,
tests,
}:
stdenv.mkDerivation rec {
pname = "hbase";
inherit version;
src = fetchurl {
url = "mirror://apache/hbase/${version}/hbase-${version}-bin.tar.gz";
inherit hash;
};
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
mkdir -p $out
cp -R * $out
wrapProgram $out/bin/hbase --set-default JAVA_HOME ${jdk.home} \
--run "test -d /etc/hadoop-conf && export HBASE_CONF_DIR=\''${HBASE_CONF_DIR-'/etc/hadoop-conf/'}" \
--set-default HBASE_CONF_DIR "$out/conf/"
'';
passthru = { inherit tests; };
meta = with lib; {
description = "Distributed, scalable, big data store";
homepage = "https://hbase.apache.org";
license = licenses.asl20;
maintainers = with lib.maintainers; [ illustris ];
platforms = lib.platforms.linux;
};
};
in
{
hbase_2_4 = common {
version = "2.4.18";
hash = "sha256-zYrHAxzlPRrRchHGVp3fhQT0BD0+wavZ4cAWncrv+MQ=";
tests.standalone = nixosTests.hbase_2_4;
};
hbase_2_5 = common {
version = "2.5.11";
hash = "sha256-W3o8J+aY2bQoiu1Lr1n5EQWDVoS1OwWTNIUAU03a5Es=";
tests.standalone = nixosTests.hbase_2_5;
};
hbase_2_6 = common {
version = "2.6.2";
hash = "sha256-X/mjmTAx9anh2U/Xlfuf+O4AO5BXDkdsY69tPddEpYM=";
tests.standalone = nixosTests.hbase2;
};
hbase_3_0 = common {
version = "3.0.0-beta-1";
hash = "sha256-lmeaH2gDP6sBwZpzROKhR2Je7dcrwnq7qlMUh0B5fZs=";
tests.standalone = nixosTests.hbase3;
};
}

View File

@@ -0,0 +1,26 @@
{
lib,
buildGoModule,
fetchFromGitHub,
nixosTests,
}:
let
sources = (import ./sources.nix) { inherit fetchFromGitHub; };
in
buildGoModule {
inherit (sources) pname version src;
modRoot = "src/hockeypuck/";
vendorHash = null;
doCheck = false; # Uses networking for tests
passthru.tests = nixosTests.hockeypuck;
meta = with lib; {
description = "OpenPGP Key Server";
homepage = "https://github.com/hockeypuck/hockeypuck";
license = licenses.agpl3Plus;
maintainers = [ ];
};
}

View File

@@ -0,0 +1,16 @@
{ fetchFromGitHub }:
let
pname = "hockeypuck";
version = "2.1.0";
in
{
inherit version pname;
src = fetchFromGitHub {
owner = pname;
repo = pname;
rev = version;
sha256 = "0da3ffbqck0dr7d89gy2yillp7g9a4ziyjlvrm8vgkkg2fs8dlb1";
};
}

View File

@@ -0,0 +1,33 @@
{
stdenv,
lib,
fetchFromGitHub,
nixosTests,
}:
let
sources = (import ./sources.nix) { inherit fetchFromGitHub; };
in
stdenv.mkDerivation {
pname = "${sources.pname}-web";
inherit (sources) version src;
dontBuild = true; # We should just copy the web templates
installPhase = ''
mkdir -p $out/share/
cp -vr contrib/webroot $out/share/
cp -vr contrib/templates $out/share/
'';
passthru.tests = nixosTests.hockeypuck;
meta = with lib; {
description = "OpenPGP Key Server web resources";
homepage = "https://github.com/hockeypuck/hockeypuck";
license = licenses.gpl3Plus;
maintainers = [ ];
};
}

View File

@@ -0,0 +1,58 @@
{
lib,
python3Packages,
fetchFromGitHub,
}:
python3Packages.buildPythonApplication rec {
pname = "appdaemon";
version = "4.5.11";
pyproject = true;
src = fetchFromGitHub {
owner = "AppDaemon";
repo = "appdaemon";
rev = "refs/tags/${version}";
hash = "sha256-1wnAniw7fdyfH6QeFjdIAxX5mU92ZZxLLJ/QkKge1eY=";
};
pythonRelaxDeps = true;
build-system = [ python3Packages.setuptools ];
dependencies = with python3Packages; [
aiohttp
aiohttp-jinja2
astral
bcrypt
deepdiff
feedparser
iso8601
paho-mqtt
pid
pydantic
python-dateutil
python-socketio
pytz
pyyaml
requests
sockjs
uvloop
tomli
tomli-w
];
# no tests implemented
checkPhase = ''
$out/bin/appdaemon -v | grep -q "${version}"
'';
meta = with lib; {
description = "Sandboxed Python execution environment for writing automation apps for Home Assistant";
mainProgram = "appdaemon";
homepage = "https://github.com/AppDaemon/appdaemon";
changelog = "https://github.com/AppDaemon/appdaemon/blob/${version}/docs/HISTORY.md";
license = licenses.mit;
teams = [ teams.home-assistant ];
};
}

View File

@@ -0,0 +1,87 @@
#!/usr/bin/env python3
import argparse
import json
import os
import sys
import importlib.metadata
from typing import Dict, List
from packaging.requirements import InvalidRequirement, Requirement
def error(msg: str, ret: bool = False) -> bool:
print(f" - {msg}", file=sys.stderr)
return ret
def check_derivation_name(manifest: Dict) -> bool:
derivation_domain = os.environ.get("domain")
manifest_domain = manifest["domain"]
if derivation_domain != manifest_domain:
return error(
f"Derivation attribute domain ({derivation_domain}) should match manifest domain ({manifest_domain})"
)
return True
def test_requirement(req: str, ignore_version_requirement: List[str]) -> bool:
# https://packaging.pypa.io/en/stable/requirements.html
try:
requirement = Requirement(req)
except InvalidRequirement:
return error(f"{req} could not be parsed", ret=True)
try:
version = importlib.metadata.distribution(requirement.name).version
except importlib.metadata.PackageNotFoundError:
return error(f"{requirement.name}{requirement.specifier} not installed")
# https://packaging.pypa.io/en/stable/specifiers.html
if (
requirement.name not in ignore_version_requirement
and version not in requirement.specifier
):
return error(
f"{requirement.name}{requirement.specifier} not satisfied by version {version}"
)
return True
def check_requirements(manifest: Dict, ignore_version_requirement: List[str]):
ok = True
for requirement in manifest.get("requirements", []):
ok &= test_requirement(requirement, ignore_version_requirement)
return ok
def main(args):
ok = True
manifests = []
for fd in args.manifests:
manifests.append(json.load(fd))
# At least one manifest should match the component name
ok &= any(check_derivation_name(manifest) for manifest in manifests)
# All requirements need to match, use `ignoreRequirementVersion` to ignore too strict version constraints
ok &= all(
check_requirements(manifest, args.ignore_version_requirement)
for manifest in manifests
)
if not ok:
sys.exit(1)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("manifests", type=argparse.FileType("r"), nargs="+")
parser.add_argument("--ignore-version-requirement", action="append", default=[])
args = parser.parse_args()
main(args)

View File

@@ -0,0 +1,72 @@
{
home-assistant,
makeSetupHook,
}:
{
owner,
domain,
version,
format ? "other",
...
}@args:
let
manifestRequirementsCheckHook = import ./manifest-requirements-check-hook.nix {
inherit makeSetupHook;
inherit (home-assistant) python;
};
in
home-assistant.python.pkgs.buildPythonPackage (
{
pname = "${owner}/${domain}";
inherit version format;
buildPhase = ''
true
'';
installPhase = ''
runHook preInstall
mkdir $out
if [[ -f ./manifest.json ]]; then
mkdir $out/custom_components
cp -R "$(realpath .)" "$out/custom_components/${domain}"
else
cp -r ./custom_components/ $out/
fi
# optionally copy sentences, if they exist
if [[ -d ./custom_sentences ]]; then
cp -r ./custom_sentences/ $out/
fi
runHook postInstall
'';
nativeCheckInputs =
with home-assistant.python.pkgs;
[
manifestRequirementsCheckHook
packaging
]
++ (args.nativeCheckInputs or [ ]);
passthru = {
isHomeAssistantComponent = true;
}
// args.passthru or { };
meta = {
inherit (home-assistant.meta) platforms;
}
// args.meta or { };
}
// removeAttrs args [
"meta"
"nativeCheckInputs"
"passthru"
]
)

View File

@@ -0,0 +1,12 @@
{
python,
makeSetupHook,
}:
makeSetupHook {
name = "manifest-check-hook";
substitutions = {
pythonCheckInterpreter = python.interpreter;
checkManifest = ./check_manifest.py;
};
} ./manifest-requirements-check-hook.sh

View File

@@ -0,0 +1,42 @@
# shellcheck shell=bash
# Setup hook to check HA manifest requirements
echo "Sourcing manifest-check-hook"
function manifestCheckPhase() {
echo "Executing manifestCheckPhase"
runHook preCheck
args=""
# shellcheck disable=SC2154
for package in "${ignoreVersionRequirement[@]}"; do
args+=" --ignore-version-requirement ${package}"
done
readarray -d '' manifests < <(
find . -type f \( \
-path ./manifest.json \
-o -path './custom_components/*/manifest.json' \
-o -path './custom_components/*/integrations/*/manifest.json' \
\) -print0
)
if [ "${#manifests[@]}" -gt 0 ]; then
# shellcheck disable=SC2068
echo Checking manifests ${manifests[@]}
# shellcheck disable=SC2068,SC2086
@pythonCheckInterpreter@ @checkManifest@ ${manifests[@]} $args
else
# shellcheck disable=SC2154
echo "No component manifests found in $out" >&2
exit 1
fi
runHook postCheck
echo "Finished executing manifestCheckPhase"
}
if [ -z "${dontCheckManifest-}" ] && [ -z "${installCheckPhase-}" ]; then
echo "Using manifestCheckPhase"
appendToVar preDistPhases manifestCheckPhase
fi

View File

@@ -0,0 +1,64 @@
{
lib,
stdenv,
fetchFromGitHub,
python3,
installShellFiles,
}:
python3.pkgs.buildPythonApplication rec {
pname = "homeassistant-cli";
version = "0.9.6";
format = "setuptools";
src = fetchFromGitHub {
owner = "home-assistant-ecosystem";
repo = "home-assistant-cli";
rev = version;
hash = "sha256-4OeHJ7icDZUOC5K4L0F0Nd9lbJPgdW4LCU0wniLvJ1Q=";
};
postPatch = ''
# Ignore pinned versions
sed -i "s/'\(.*\)\(==\|>=\).*'/'\1'/g" setup.py
'';
propagatedBuildInputs = with python3.pkgs; [
aiohttp
click
click-log
dateparser
jinja2
jsonpath-ng
netdisco
regex
requests
ruamel-yaml
tabulate
];
postInstall = lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
installShellCompletion --cmd hass-cli \
--bash <(_HASS_CLI_COMPLETE=bash_source $out/bin/hass-cli) \
--fish <(_HASS_CLI_COMPLETE=fish_source $out/bin/hass-cli) \
--zsh <(_HASS_CLI_COMPLETE=zsh_source $out/bin/hass-cli)
'';
nativeBuildInputs = [ installShellFiles ];
nativeCheckInputs = with python3.pkgs; [
pytestCheckHook
requests-mock
];
pythonImportsCheck = [ "homeassistant_cli" ];
meta = {
description = "Command-line tool for Home Assistant";
mainProgram = "hass-cli";
homepage = "https://github.com/home-assistant-ecosystem/home-assistant-cli";
changelog = "https://github.com/home-assistant-ecosystem/home-assistant-cli/releases/tag/${version}";
license = lib.licenses.asl20;
teams = [ lib.teams.home-assistant ];
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
# Packaging guidelines
## buildHomeAssistantComponent
Custom components should be packaged using the
`buildHomeAssistantComponent` function, that is provided at top-level.
It builds upon `buildPythonPackage` but uses a custom install and check
phase.
Python runtime dependencies can be directly consumed as unqualified
function arguments. Pass them into `dependencies`, for them to
be available to Home Assistant.
Out-of-tree components need to use Python packages from
`home-assistant.python.pkgs` as to not introduce conflicting package
versions into the Python environment.
**Example Boilerplate:**
```nix
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
}:
buildHomeAssistantComponent {
# owner, domain, version
src = fetchFromGithub {
# owner, repo, rev, hash
};
dependencies = [
# python requirements, as specified in manifest.json
];
meta = with lib; {
# changelog, description, homepage, license, maintainers
};
}
```
## Package attribute
The attribute name must reflect the domain as seen in the
`manifest.json`, which in turn will match the python module name below
in the `custom_components/` directory.
**Example:**
The project [mweinelt/ha-prometheus-sensor](https://github.com/mweinelt/ha-prometheus-sensor/blob/1.0.0/custom_components/prometheus_sensor/manifest.json#L2)
would receive the attribute name `"prometheus_sensor"`, because both
domain in the `manifest.json` as well as the module name are
`prometheus_sensor`.
## Package name
The `pname` attribute is a composition of both `owner` and `domain`.
Don't set `pname`, set `owner` and `domain` instead.
Exposing the `domain` attribute separately allows checking for
conflicting components at eval time.
## Manifest check
The `buildHomeAssistantComponent` builder uses a hook to check whether
the dependencies specified in the `manifest.json` are present and
inside the specified version range. It also makes sure derivation
and manifest agree about the domain name.
There shouldn't be a need to disable this hook, but you can set
`dontCheckManifest` to `true` in the derivation to achieve that.
### Too narrow version constraints
Every once in a while a dependency constraint is more narrow than it
needs to be. Instead of applying brittle substitutions the version constraint
can be ignored on a per requirement basis.
```nix
{
dependencies = [ pyemvue ];
# don't check the version constraint of pyemvue
ignoreVersionRequirement = [ "pyemvue" ];
}
```

View File

@@ -0,0 +1,31 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
ulid-transform,
}:
buildHomeAssistantComponent rec {
owner = "basnijholt";
domain = "adaptive_lighting";
version = "1.26.0";
src = fetchFromGitHub {
owner = "basnijholt";
repo = "adaptive-lighting";
tag = "v${version}";
hash = "sha256-I8pay2cWj604PQxOBLkaWjcj56dtbaAiBCv6LQQM6XI=";
};
dependencies = [
ulid-transform
];
meta = with lib; {
changelog = "https://github.com/basnijholt/adaptive-lighting/releases/tag/${version}";
description = "Home Assistant Adaptive Lighting Plugin - Sun Synchronized Lighting";
homepage = "https://github.com/basnijholt/adaptive-lighting";
maintainers = with maintainers; [ mindstorms6 ];
license = licenses.asl20;
};
}

View File

@@ -0,0 +1,30 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
}:
buildHomeAssistantComponent rec {
owner = "nielsfaber";
domain = "alarmo";
version = "1.10.11";
src = fetchFromGitHub {
owner = "nielsfaber";
repo = "alarmo";
tag = "v${version}";
hash = "sha256-OASgIudnxPtWiBLpkiOioCRhIqlr2B5E2/XGlhs16sQ=";
};
postPatch = ''
find ./custom_components/alarmo/frontend -mindepth 1 -maxdepth 1 ! -name "dist" -exec rm -rf {} \;
'';
meta = with lib; {
changelog = "https://github.com/nielsfaber/alarmo/releases/tag/v${version}";
description = "Alarm System for Home Assistant";
homepage = "https://github.com/nielsfaber/alarmo";
maintainers = with maintainers; [ mindstorms6 ];
license = licenses.asl20;
};
}

View File

@@ -0,0 +1,34 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
amshan,
}:
buildHomeAssistantComponent rec {
owner = "toreamun";
domain = "amshan";
version = "2024.12.0";
src = fetchFromGitHub {
owner = "toreamun";
repo = "amshan-homeassistant";
tag = version;
hash = "sha256-L7TGdUjDvIRP9dHIkng9GYwilmRzhGbUK6ivx8PVtQ4=";
};
dependencies = [
amshan
];
meta = {
description = "Home Assistant integration for electricity meters (AMS/HAN/P1)";
longDescription = ''
The integration supports both streaming (serial port / TCP/IP) and MQTT
(Tibber Pulse, energyintelligence.se etc.).
'';
homepage = "https://github.com/toreamun/amshan-homeassistant";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ bjornfor ];
};
}

View File

@@ -0,0 +1,26 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
}:
buildHomeAssistantComponent rec {
owner = "BeryJu";
domain = "auth_header";
version = "1.12";
src = fetchFromGitHub {
inherit owner;
repo = "hass-auth-header";
tag = "v${version}";
hash = "sha256-BPG/G6IM95g9ip2OsPmcAebi2ZvKHUpFzV4oquOFLPM=";
};
meta = with lib; {
changelog = "https://github.com/BeryJu/hass-auth-header/releases/tag/v${version}";
description = "Home Assistant custom component which allows you to delegate authentication to a reverse proxy";
homepage = "https://github.com/BeryJu/hass-auth-header";
maintainers = with maintainers; [ mjm ];
license = licenses.gpl3;
};
}

View File

@@ -0,0 +1,37 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
aiofiles,
bcrypt,
jinja2,
python-jose,
}:
buildHomeAssistantComponent rec {
owner = "christaangoossens";
domain = "auth_oidc";
version = "0.6.3-alpha";
src = fetchFromGitHub {
owner = "christiaangoossens";
repo = "hass-oidc-auth";
tag = "v${version}";
hash = "sha256-+R2IIs9MixR8epVpk4QycN8PjOfRITlZ+oUbdPEk2eA=";
};
dependencies = [
aiofiles
bcrypt
jinja2
python-jose
];
meta = {
changelog = "https://github.com/christiaangoossens/hass-oidc-auth/releases/tag/v${version}";
description = "OpenID Connect authentication provider for Home Assistant";
homepage = "https://github.com/christiaangoossens/hass-oidc-auth";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ hexa ];
};
}

View File

@@ -0,0 +1,30 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
}:
buildHomeAssistantComponent rec {
owner = "Limych";
domain = "average";
version = "2.4.0";
src = fetchFromGitHub {
inherit owner;
repo = "ha-average";
tag = version;
hash = "sha256-LISGpgfoVxdOeJ9LHzxf7zt49pbIJrLiPkNg/Mf1lxM=";
};
postPatch = ''
sed -i "/pip>=/d" custom_components/average/manifest.json
'';
meta = with lib; {
changelog = "https://github.com/Limych/ha-average/releases/tag/${version}";
description = "Average Sensor for Home Assistant";
homepage = "https://github.com/Limych/ha-average";
maintainers = with maintainers; [ matthiasbeyer ];
license = licenses.cc-by-nc-40;
};
}

View File

@@ -0,0 +1,31 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
requests,
}:
buildHomeAssistantComponent rec {
owner = "10der";
domain = "awtrix";
version = "0.3.21";
src = fetchFromGitHub {
inherit owner;
repo = "homeassistant-custom_components-awtrix";
# https://github.com/10der/homeassistant-custom_components-awtrix/issues/9
rev = "8180cef7b1837e85115ef7ece553e39b0f94ff4d";
hash = "sha256-D/RXi7nX+xqFs5Dvu1pwomQWCJ8PJhc1H3wsAgBhRMQ=";
};
dependencies = [
requests
];
meta = with lib; {
description = "Home-assistant integration for awtrix";
homepage = "https://github.com/10der/homeassistant-custom_components-awtrix";
maintainers = with maintainers; [ pinpox ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,29 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
benqprojector,
}:
buildHomeAssistantComponent rec {
owner = "rrooggiieerr";
domain = "benqprojector";
version = "0.1.3";
src = fetchFromGitHub {
inherit owner;
repo = "homeassistant-benqprojector";
tag = version;
hash = "sha256-iAFmXL10QqudECsS9u9w7KBETzu9aWCg1EBbFR1ff+o=";
};
dependencies = [ benqprojector ];
meta = rec {
description = "Home Assistant integration for BenQ projectors";
homepage = "https://github.com/rrooggiieerr/homeassistant-benqprojector";
changelog = "${homepage}/releases/tag/${version}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ sephalon ];
};
}

View File

@@ -0,0 +1,31 @@
{
buildHomeAssistantComponent,
fetchFromGitHub,
lib,
gitUpdater,
}:
buildHomeAssistantComponent rec {
owner = "KartoffelToby";
domain = "better_thermostat";
version = "1.7.0";
src = fetchFromGitHub {
owner = "KartoffelToby";
repo = "better_thermostat";
tag = version;
hash = "sha256-rE14iKAXo3hecK3bQ9MLcOtnZviwjOpYKGlIc4+uCfw=";
};
passthru.updateScript = gitUpdater {
ignoredVersions = "(Alpha|Beta|alpha|beta).*";
};
meta = {
changelog = "https://github.com/KartoffelToby/better_thermostat/releases/tag/${version}";
description = "Smart TRV control integrates room-temp sensors, window/door sensors, weather forecasts, and ambient probes for efficient heating and calibration, enhancing energy savings and comfort";
homepage = "https://better-thermostat.org/";
maintainers = with lib.maintainers; [ mguentner ];
license = lib.licenses.agpl3Only;
};
}

View File

@@ -0,0 +1,35 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
cachetools,
}:
buildHomeAssistantComponent rec {
owner = "dckiller51";
domain = "bodymiscale";
version = "2024.6.0";
src = fetchFromGitHub {
inherit owner;
repo = domain;
rev = version;
hash = "sha256-6bYKqU9yucISjTrmCUx1bNn9kqvT9jW1OBrqAa4ayEQ=";
};
dependencies = [
cachetools
];
ignoreVersionRequirement = [
"cachetools"
];
meta = {
description = "Home Assistant custom component providing body metrics for Xiaomi Mi Scale 1 and 2";
homepage = "https://github.com/dckiller51/bodymiscale";
license = with lib.licenses; [ asl20 ];
maintainers = with lib.maintainers; [ justinas ];
};
}

View File

@@ -0,0 +1,30 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
icalendar,
}:
buildHomeAssistantComponent rec {
owner = "JosephAbbey";
domain = "calendar_export";
version = "0.1.0";
src = fetchFromGitHub {
owner = "JosephAbbey";
repo = "ha_calendar_export";
tag = "v${version}";
hash = "sha256-ULnkjnBc0oR1CwA+Mz1RnVamEXOKpgd60xryZMkCQwg=";
};
dependencies = [ icalendar ];
ignoreVersionRequirement = [ "icalendar" ];
meta = {
description = "Export calendar events in the iCalendar format";
homepage = "https://github.com/JosephAbbey/ha_calendar_export";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ hexa ];
};
}

View File

@@ -0,0 +1,25 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
}:
buildHomeAssistantComponent rec {
owner = "bjrnptrsn";
domain = "climate_group";
version = "1.0.8";
src = fetchFromGitHub {
inherit owner;
repo = "climate_group";
tag = version;
hash = "sha256-HwMHhrmQ+fbdLHQAM+ka/1oNCIBFaLTqOlPMzCEEeQ0=";
};
meta = {
changelog = "https://github.com/bjrnptrsn/climate_group/blob/${src.rev}/README.md#changelog";
description = "Group multiple climate devices to a single entity";
homepage = "https://github.com/bjrnptrsn/climate_group";
maintainers = builtins.attrValues { inherit (lib.maintainers) jamiemagee; };
license = lib.licenses.mit;
};
}

View File

@@ -0,0 +1,26 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
}:
buildHomeAssistantComponent rec {
owner = "jwillemsen";
domain = "daikin_onecta";
version = "4.2.8";
src = fetchFromGitHub {
owner = "jwillemsen";
repo = "daikin_onecta";
tag = "v${version}";
hash = "sha256-ozOJQDoE/t2FhnsVCnP+WCrFr/l19+onr488JN2fSE0=";
};
meta = {
changelog = "https://github.com/jwillemsen/daikin_onecta/tag/v${version}";
description = "Home Assistant Integration for devices supported by the Daikin Onecta App";
homepage = "https://github.com/jwillemsen/daikin_onecta";
maintainers = with lib.maintainers; [ dandellion ];
license = lib.licenses.gpl3Only;
};
}

View File

@@ -0,0 +1,35 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
dirigera,
}:
buildHomeAssistantComponent rec {
owner = "sanjoyg";
domain = "dirigera_platform";
version = "2.6.8";
src = fetchFromGitHub {
owner = "sanjoyg";
repo = "dirigera_platform";
rev = version;
hash = "sha256-FNcGl6INQlVP+P3qmExWLI1ALh9ZacjJAbNKRtgM3ms=";
};
postPatch = ''
substituteInPlace custom_components/dirigera_platform/manifest.json \
--replace-fail "0.0.1" "${version}"
'';
dependencies = [ dirigera ];
ignoreVersionRequirement = [ "dirigera" ];
meta = with lib; {
description = "Home-assistant integration for IKEA Dirigera hub";
homepage = "https://github.com/sanjoyg/dirigera_platform";
maintainers = with maintainers; [ rhoriguchi ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,40 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
nix-update-script,
websockets,
# Test dependencies
pytestCheckHook,
pytest-homeassistant-custom-component,
}:
buildHomeAssistantComponent rec {
owner = "JeffSteinbok";
domain = "dreo";
version = "1.3.3";
src = fetchFromGitHub {
inherit owner;
repo = "hass-dreo";
tag = "v${version}";
hash = "sha256-eAgqjAXNAY8kr7+49q+tikW3bDBJ0N0Rh5WJwzLYr8I=";
};
dependencies = [ websockets ];
nativeCheckInputs = [
pytest-homeassistant-custom-component
pytestCheckHook
];
passthru.updateScript = nix-update-script { };
meta = {
changelog = "https://github.com/JeffSteinbok/hass-dreo/releases/tag/${src.tag}";
description = "Dreo Smart Device Integration for Home Assistant";
homepage = "https://github.com/JeffSteinbok/hass-dreo";
maintainers = with lib.maintainers; [ CodedNil ];
license = lib.licenses.mit;
};
}

View File

@@ -0,0 +1,34 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
defusedxml,
}:
buildHomeAssistantComponent rec {
owner = "hg1337";
domain = "dwd";
version = "2025.5.0";
src = fetchFromGitHub {
owner = "hg1337";
repo = "homeassistant-dwd";
rev = version;
hash = "sha256-CuoHVgk4jWDEe3OkzFCok8YqVkWLJF6Rl7i/SDeSU50=";
};
dependencies = [ defusedxml ];
# defusedxml version mismatch
dontCheckManifest = true;
meta = with lib; {
description = "Custom component for Home Assistant that integrates weather data (measurements and forecasts) of Deutscher Wetterdienst";
homepage = "https://github.com/hg1337/homeassistant-dwd";
license = licenses.asl20;
maintainers = with maintainers; [
hexa
emilylange
];
};
}

View File

@@ -0,0 +1,26 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
}:
buildHomeAssistantComponent rec {
owner = "carleeno";
domain = "elevenlabs_tts";
version = "2.4.0";
src = fetchFromGitHub {
owner = "carleeno";
repo = "elevenlabs_tts";
tag = version;
hash = "sha256-/hszK5J1iGB46WfmCCK9/F0JOR405gplMwVC4niAqig=";
};
meta = with lib; {
changelog = "https://github.com/carleeno/elevenlabs_tts/releases/tag/${version}";
description = "Home Assistant Eleven Labs TTS Integration";
homepage = "https://github.com/carleeno/elevenlabs_tts";
maintainers = with maintainers; [ mindstorms6 ];
license = licenses.asl20;
};
}

View File

@@ -0,0 +1,35 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
pyemvue,
}:
buildHomeAssistantComponent rec {
owner = "magico13";
domain = "emporia_vue";
version = "0.11.2";
src = fetchFromGitHub {
owner = "magico13";
repo = "ha-emporia-vue";
rev = "v${version}";
hash = "sha256-p8rBO+Z64n87NE7BXNSsTT5IA7ba5RzCZjqX05LqD0A=";
};
dependencies = [
pyemvue
];
ignoreVersionRequirement = [
"pyemvue"
];
meta = with lib; {
description = "Reads data from the Emporia Vue energy monitor into Home Assistant";
homepage = "https://github.com/magico13/ha-emporia-vue";
changelog = "https://github.com/magico13/ha-emporia-vue/releases/tag/v${version}";
maintainers = with maintainers; [ presto8 ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,35 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
beautifulsoup4,
}:
buildHomeAssistantComponent rec {
owner = "mampfes";
domain = "epex_spot";
version = "3.0.0";
src = fetchFromGitHub {
owner = "mampfes";
repo = "ha_epex_spot";
tag = version;
hash = "sha256-UaPgf0861TaSgawjJCyNjs8hRE5L5vWnyoXENrzCfb4=";
};
dependencies = [
beautifulsoup4
];
#skip phases without activity
dontConfigure = true;
doCheck = false;
meta = with lib; {
changelog = "https://github.com/mampfes/ha_epex_spot/releases/tag/${version}";
description = "This component adds electricity prices from stock exchange EPEX Spot to Home Assistant";
homepage = "https://github.com/mampfes/ha_epex_spot";
maintainers = with maintainers; [ _9R ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,35 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
unstableGitUpdater,
requests,
pydantic,
}:
buildHomeAssistantComponent {
owner = "NewsGuyTor";
domain = "fellow";
version = "0-unstable-2025-10-06";
src = fetchFromGitHub {
owner = "NewsGuyTor";
repo = "FellowAiden-HomeAssistant";
rev = "c0b724e2ac3174b99fcb7d05a9c63a3ac6ce03b4";
hash = "sha256-gK9lVFehqRWq7HQd+VPJB/iaIvLdHu51XxyfM14aY0s=";
};
passthru.updateScript = unstableGitUpdater { };
dependencies = [
requests
pydantic
];
meta = {
description = "Home Assistant integration for Fellow Aiden coffee brewer";
homepage = "https://github.com/NewsGuyTor/FellowAiden-HomeAssistant";
license = lib.licenses.gpl3Only;
maintainers = [ lib.maintainers.jamiemagee ];
};
}

View File

@@ -0,0 +1,63 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
# dependencies
hass-web-proxy-lib,
# tests
homeassistant,
pytest-aiohttp,
pytest-cov-stub,
pytest-homeassistant-custom-component,
pytest-timeout,
pytestCheckHook,
}:
buildHomeAssistantComponent rec {
owner = "blakeblackshear";
domain = "frigate";
version = "5.9.4";
src = fetchFromGitHub {
owner = "blakeblackshear";
repo = "frigate-hass-integration";
tag = "v${version}";
hash = "sha256-LzrIvHJMB6mFAEfKoMIs0wL+xbEjoBIx48pSEcCHmg4=";
};
dependencies = [ hass-web-proxy-lib ];
nativeCheckInputs = [
homeassistant
pytest-aiohttp
pytest-cov-stub
pytest-homeassistant-custom-component
pytest-timeout
pytestCheckHook
]
++ (homeassistant.getPackages "mqtt" homeassistant.python.pkgs)
++ (homeassistant.getPackages "stream" homeassistant.python.pkgs);
disabledTests = [
# https://github.com/blakeblackshear/frigate-hass-integration/issues/922
"test_frigate_camera_setup"
"test_frigate_camera_setup_birdseye"
"test_frigate_camera_setup_webrtc"
"test_frigate_camera_setup_birdseye_webrtc"
];
disabledTestPaths = [
# https://github.com/blakeblackshear/frigate-hass-integration/issues/907
"tests/test_media_source.py"
];
meta = with lib; {
description = "Provides Home Assistant integration to interface with a separately running Frigate service";
homepage = "https://github.com/blakeblackshear/frigate-hass-integration";
changelog = "https://github.com/blakeblackshear/frigate-hass-integration/releases/tag/v${version}";
maintainers = with maintainers; [ presto8 ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,31 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
frigidaire,
}:
buildHomeAssistantComponent rec {
owner = "bm1549";
domain = "frigidaire";
version = "0.1.2";
src = fetchFromGitHub {
inherit owner;
repo = "home-assistant-frigidaire";
tag = version;
hash = "sha256-7SyOsB16P0O0RHEUXy79cqil+QFO2PilyWWlpv428g0=";
};
dependencies = [ frigidaire ];
# NOTE: The manifest.json specifies an exact version requirement for the
# frigidaire dependency
ignoreVersionRequirement = [ "frigidaire" ];
meta = {
description = "Custom component for the Frigidaire integration";
homepage = "https://github.com/bm1549/home-assistant-frigidaire";
maintainers = with lib.maintainers; [ nullcube ];
license = lib.licenses.mit;
};
}

View File

@@ -0,0 +1,35 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
garminconnect,
tzlocal,
}:
buildHomeAssistantComponent rec {
owner = "cyberjunky";
domain = "garmin_connect";
version = "0.2.30";
src = fetchFromGitHub {
owner = "cyberjunky";
repo = "home-assistant-garmin_connect";
tag = version;
hash = "sha256-Gxz0mKVgs2o7IlhGJkz4JlKRb448IRFqK87Kn+Gebkk=";
};
dependencies = [
garminconnect
tzlocal
];
meta = with lib; {
description = "Garmin Connect integration allows you to expose data from Garmin Connect to Home Assistant";
homepage = "https://github.com/cyberjunky/home-assistant-garmin_connect";
maintainers = with maintainers; [
matthiasbeyer
dmadisetti
];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,50 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
fetchpatch2,
govee-led-wez,
pytest-cov-stub,
pytest-homeassistant-custom-component,
pytestCheckHook,
}:
buildHomeAssistantComponent {
owner = "wez";
domain = "govee_lan";
version = "unstable-2023-06-10";
src = fetchFromGitHub {
owner = "wez";
repo = "govee-lan-hass";
rev = "18d8455510d158496f7e5d4f0286f58bd61042bb";
hash = "sha256-ZhrxEPBEi+Z+2ZOAQ1amhO0tqvhM6tyFQgoRIVNDtXY=";
};
patches = [
(fetchpatch2 {
url = "https://github.com/wez/govee-lan-hass/commit/b4cecac5ae00d95c49fcfe3bbfc405cbfc5dd84c.patch";
hash = "sha256-+MPO4kxxE1nZ/+sIY7v8WukHMrVowgMMBVfRDw2uv8o=";
})
];
dependencies = [
govee-led-wez
];
# AttributeError: 'async_generator' object has no attribute 'config'
doCheck = false;
nativeCheckInputs = [
pytest-cov-stub
pytest-homeassistant-custom-component
pytestCheckHook
];
meta = with lib; {
description = "Control Govee lights via the LAN API from Home Assistant";
homepage = "https://github.com/wez/govee-lan-hass";
maintainers = with maintainers; [ SuperSandro2000 ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,29 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitea,
libgpiod,
}:
buildHomeAssistantComponent rec {
owner = "raboof";
domain = "gpio";
version = "0.0.4";
src = fetchFromGitea {
domain = "codeberg.org";
owner = "raboof";
repo = "ha-gpio";
rev = "v${version}";
hash = "sha256-JyyJPI0lbZLJj+016WgS1KXU5rnxUmRMafel4/wKsYk=";
};
dependencies = [ libgpiod ];
meta = with lib; {
description = "Home Assistant GPIO custom integration";
homepage = "https://codeberg.org/raboof/ha-gpio";
maintainers = with maintainers; [ raboof ];
license = licenses.asl20;
};
}

View File

@@ -0,0 +1,31 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
pyopensprinkler,
}:
buildHomeAssistantComponent rec {
owner = "vinteo";
domain = "opensprinkler";
version = "1.5.1";
src = fetchFromGitHub {
owner = "vinteo";
repo = "hass-opensprinkler";
tag = "v${version}";
hash = "sha256-cq9BCN/lvEZ5xPt4cLOFwNP36S+u0hQr4o2gGFz0IGo=";
};
dependencies = [
pyopensprinkler
];
meta = {
changelog = "https://github.com/vinteo/hass-opensprinkler/releases/tag/${src.tag}";
description = "OpenSprinkler Integration for Home Assistant";
homepage = "https://github.com/vinteo/hass-opensprinkler";
maintainers = with lib.maintainers; [ jfly ];
license = lib.licenses.mit;
};
}

View File

@@ -0,0 +1,57 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
fetchpatch,
hass-web-proxy-lib,
urlmatch,
pytestCheckHook,
pytest-aiohttp,
pytest-cov-stub,
pytest-freezer,
pytest-homeassistant-custom-component,
pytest-timeout,
}:
buildHomeAssistantComponent rec {
owner = "dermotduffy";
domain = "hass_web_proxy";
version = "0.0.3";
src = fetchFromGitHub {
owner = "dermotduffy";
repo = "hass-web-proxy-integration";
tag = "v${version}";
hash = "sha256-qtiea0L0Zw0CtrUpuPjS/DuBzlV61v6K4SARzHGGgUY=";
};
patches = [
(fetchpatch {
# https://github.com/dermotduffy/hass-web-proxy-integration/pull/106
url = "https://github.com/dermotduffy/hass-web-proxy-integration/commit/77964d49fd6e9d7aefe0cd9c19226a80477dc909.patch";
hash = "sha256-PZBRHVoHXMiELHitmj+YmgVSQiOqEmyP4o3MBc1Yjsg=";
})
];
dependencies = [
hass-web-proxy-lib
urlmatch
];
nativeCheckInputs = [
pytestCheckHook
pytest-aiohttp
pytest-cov-stub
pytest-freezer
pytest-homeassistant-custom-component
pytest-timeout
];
meta = {
changelog = "https://github.com/dermotduffy/hass-web-proxy-integration/releases/tag/${src.tag}";
description = "Home Assistant Web Proxy";
homepage = "https://github.com/dermotduffy/hass-web-proxy-integration";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ hexa ];
};
}

View File

@@ -0,0 +1,38 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
jsonpath-ng,
paho-mqtt,
protobuf,
nix-update-script,
}:
buildHomeAssistantComponent rec {
owner = "tolwi";
domain = "ecoflow_cloud";
version = "1.3.0";
src = fetchFromGitHub {
owner = "tolwi";
repo = "hassio-ecoflow-cloud";
tag = "v${version}";
hash = "sha256-CVm5+zLWN/ayhHRNFUr4PLwedwf4GJXvLOFgrh2qxAc=";
};
dependencies = [
jsonpath-ng
paho-mqtt
protobuf
];
passthru.updateScript = nix-update-script { };
meta = {
changelog = "https://github.com/tolwi/hassio-ecoflow-cloud/releases/tag/v${version}";
description = "Home Assistant component for EcoFlow Cloud";
homepage = "https://github.com/tolwi/hassio-ecoflow-cloud";
maintainers = with lib.maintainers; [ ananthb ];
# license = lib.licenses.asl20;
};
}

View File

@@ -0,0 +1,28 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
nix-update-script,
}:
buildHomeAssistantComponent rec {
owner = "megakid";
domain = "hildebrand_glow_ihd";
version = "1.8.0";
src = fetchFromGitHub {
inherit owner;
repo = "ha_hildebrand_glow_ihd_mqtt";
tag = "v${version}";
hash = "sha256-13NmNHaCYDZkWK5uqKeTZlB84UuThNLOAYaPS4QfTKY=";
};
passthru.updateScript = nix-update-script { };
meta = {
changelog = "https://github.com/megakid/ha_hildebrand_glow_ihd_mqtt/releases/tag/${src.tag}";
description = "Home Assistant integration for local MQTT Hildebrand Glow IHD";
homepage = "https://github.com/megakid/ha_hildebrand_glow_ihd_mqtt";
maintainers = with lib.maintainers; [ CodedNil ];
};
}

View File

@@ -0,0 +1,28 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
home-connect-async,
}:
buildHomeAssistantComponent rec {
owner = "ekutner";
domain = "home_connect_alt";
version = "1.3.0-b1";
src = fetchFromGitHub {
owner = "ekutner";
repo = "home-connect-hass";
tag = version;
hash = "sha256-jWrVHwMdzjG0gHWl1NS6WAzdmlmS20BUmh6HzplsGgw=";
};
dependencies = [ home-connect-async ];
meta = with lib; {
description = "Alternative (and improved) Home Connect integration for Home Assistant";
homepage = "https://github.com/ekutner/home-connect-hass";
maintainers = with maintainers; [ kranzes ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,39 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
aiohomematic,
home-assistant,
}:
buildHomeAssistantComponent rec {
owner = "SukramJ";
domain = "homematicip_local";
version = "1.88.1";
src = fetchFromGitHub {
owner = "SukramJ";
repo = "custom_homematic";
tag = version;
hash = "sha256-SAjASZgcpEx/8kiBb8JGifYXnIx2cMbt6c2JNk/n/QU=";
};
postPatch = ''
min_ha_version="$(sed -nr 's/^HMIP_LOCAL_MIN_HA_VERSION.*= "([0-9.]+)"$/\1/p' custom_components/homematicip_local/const.py)"
test \
"$(printf '%s\n' "$min_ha_version" "${home-assistant.version}" | sort -V | head -n1)" = "$min_ha_version" \
|| (echo "error: only Home Assistant >= $min_ha_version is supported" && exit 1)
'';
dependencies = [
aiohomematic
];
meta = {
changelog = "https://github.com/SukramJ/custom_homematic/blob/${src.tag}/changelog.md";
description = "Custom Home Assistant Component for HomeMatic";
homepage = "https://github.com/SukramJ/custom_homematic";
maintainers = with lib.maintainers; [ dotlambda ];
license = lib.licenses.mit;
};
}

View File

@@ -0,0 +1,29 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
pyindego,
}:
buildHomeAssistantComponent rec {
owner = "sander1988";
domain = "indego";
version = "5.7.8";
src = fetchFromGitHub {
owner = "sander1988";
repo = "Indego";
tag = version;
hash = "sha256-7PQUsSPS+o5Vt4Do4/TXyGXAqyHJg96w8n7UMpZ0uFo=";
};
dependencies = [ pyindego ];
meta = with lib; {
description = "Bosch Indego lawn mower component";
changelog = "https://github.com/sander1988/Indego/releases/tag/${version}";
homepage = "https://github.com/sander1988/Indego";
license = licenses.asl20;
maintainers = with maintainers; [ hexa ];
};
}

View File

@@ -0,0 +1,43 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
bluetooth-sensor-state-data,
bleak-retry-connector,
bleak,
nix-update-script,
}:
let
version = "0.0.15.1";
in
buildHomeAssistantComponent {
owner = "8none1";
domain = "lednetwf_ble";
inherit version;
src = fetchFromGitHub {
owner = "8none1";
repo = "lednetwf_ble";
tag = "v${version}";
hash = "sha256-LSVvwJZFtBC+iwxfZ3R8msPvrvimPw2Tjzqw6Dx7ZsM=";
};
dependencies = [
bluetooth-sensor-state-data
bleak-retry-connector
bleak
];
# Currently there are no tests run, so we skip
doCheck = false;
passthru.updateScript = nix-update-script { };
meta = {
description = "Home Assistant custom integration for LEDnetWF devices";
homepage = "https://github.com/8none1/lednetwf_ble";
changelog = "https://github.com/8none1/lednetwf_ble/releases/tag/v${version}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ blenderfreaky ];
};
}

View File

@@ -0,0 +1,26 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
}:
buildHomeAssistantComponent rec {
owner = "lichtteil";
domain = "local_luftdaten";
version = "2.3.1";
src = fetchFromGitHub {
owner = "lichtteil";
repo = "local_luftdaten";
rev = version;
hash = "sha256-68clZgS7Qo62srcZWD3Un9BnNSwQUBr4Z5oBMTC9m8o=";
};
meta = with lib; {
changelog = "https://github.com/lichtteil/local_luftdaten/releases/tag/${version}";
description = "Custom component for Home Assistant that integrates your (own) local Luftdaten sensor (air quality/particle sensor) without using the cloud";
homepage = "https://github.com/lichtteil/local_luftdaten";
license = licenses.mit;
maintainers = with maintainers; [ hexa ];
};
}

View File

@@ -0,0 +1,26 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
}:
buildHomeAssistantComponent rec {
owner = "xZetsubou";
domain = "localtuya";
version = "2025.10.0";
src = fetchFromGitHub {
owner = "xZetsubou";
repo = "hass-localtuya";
tag = version;
hash = "sha256-PjxDPZK/T4meafMFX3WFoA5ur0NPJsbPOxaOuL0+NWg=";
};
meta = with lib; {
changelog = "https://github.com/xZetsubou/hass-localtuya/releases/tag/${version}";
description = "Home Assistant custom Integration for local handling of Tuya-based devices, fork from local-tuya";
homepage = "https://github.com/xZetsubou/hass-localtuya";
maintainers = with maintainers; [ rhoriguchi ];
license = licenses.gpl3Only;
};
}

View File

@@ -0,0 +1,26 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
ruff,
}:
buildHomeAssistantComponent {
owner = "tjhorner";
domain = "luxer";
version = "0-unstable-2023-03-27";
src = fetchFromGitHub {
owner = "tjhorner";
repo = "home-assistant-luxer-one";
rev = "f6a810034ab76e6a8635de755c4a1750e86b1674";
hash = "sha256-WmsL0NLe2ICqNGbEQ4vg1EzcZgIGi++G9aDyKjnmJMs=";
};
meta = {
description = "Home Assistant integration for Luxer One";
homepage = "https://github.com/tjhorner/home-assistant-luxer-one";
license = lib.licenses.mit;
maintainers = [ lib.maintainers.haylin ];
};
}

View File

@@ -0,0 +1,29 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
midea-beautiful-air,
}:
buildHomeAssistantComponent rec {
owner = "nbogojevic";
domain = "midea_dehumidifier_lan";
version = "0.9.6";
src = fetchFromGitHub {
inherit owner;
repo = "homeassistant-midea-air-appliances-lan";
rev = "v${version}";
hash = "sha256-61LAecJRHQi9/Wf4L25HwAMOV5Yzsr8irAnh5xuWJ7c=";
};
dependencies = [ midea-beautiful-air ];
meta = with lib; {
description = "Home Assistant custom component adding support for controlling Midea air conditioners and dehumidifiers on local network";
homepage = "https://github.com/nbogojevic/homeassistant-midea-air-appliances-lan";
changelog = "https://github.com/nbogojevic/homeassistant-midea-air-appliances-lan/releases/tag/v${version}";
maintainers = with maintainers; [ k900 ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,39 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
msmart-ng,
pytestCheckHook,
pytest-homeassistant-custom-component,
}:
buildHomeAssistantComponent rec {
owner = "mill1000";
domain = "midea_ac";
version = "2025.9.1";
src = fetchFromGitHub {
owner = "mill1000";
repo = "midea-ac-py";
tag = version;
hash = "sha256-fmVX+b7x4+172+mcJ8+LFhljQEQrhLFXwXn6eI1f36Y=";
};
dependencies = [ msmart-ng ];
nativeCheckInputs = [
pytest-homeassistant-custom-component
pytestCheckHook
];
meta = with lib; {
changelog = "https://github.com/mill1000/midea-ac-py/releases/tag/${src.tag}";
description = "Home Assistant custom integration to control Midea (and associated brands) air conditioners via LAN";
homepage = "https://github.com/mill1000/midea-ac-py";
license = licenses.mit;
maintainers = with maintainers; [
hexa
emilylange
];
};
}

View File

@@ -0,0 +1,29 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
midea-local,
}:
buildHomeAssistantComponent rec {
owner = "wuwentao";
domain = "midea_ac_lan";
version = "0.6.9";
src = fetchFromGitHub {
inherit owner;
repo = domain;
tag = "v${version}";
hash = "sha256-pPPJFs4earRbh6ovR57k9xgZtrYN0L26eupOoFuBVz8=";
};
dependencies = [ midea-local ];
meta = with lib; {
description = "Auto-configure and then control your Midea M-Smart devices (Air conditioner, Fan, Water heater, Washer, etc) via local area network";
homepage = "https://github.com/wuwentao/midea_ac_lan/";
changelog = "https://github.com/wuwentao/midea_ac_lan/releases/tag/v${version}";
maintainers = with maintainers; [ k900 ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,36 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
miraie-ac,
aiomqtt,
nix-update-script,
}:
buildHomeAssistantComponent rec {
owner = "rkzofficial";
domain = "miraie";
version = "1.1.6";
src = fetchFromGitHub {
owner = "rkzofficial";
repo = "ha-miraie-ac";
tag = "v${version}";
hash = "sha256-5VpLfTKOLdx8P693jaW4o79CH2NKkgkgl7ai+I6JRQs=";
};
dependencies = [
miraie-ac
aiomqtt
];
passthru.updateScript = nix-update-script { };
meta = {
changelog = "https://github.com/rkzofficial/ha-miraie-ac/releases/tag/v${version}";
description = "Home Assistant component for Miraie ACs";
homepage = "https://github.com/rkzofficial/ha-miraie-ac";
maintainers = with lib.maintainers; [ ananthb ];
license = lib.licenses.asl20;
};
}

View File

@@ -0,0 +1,40 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
pymitsubishi,
pytest-cov-stub,
pytestCheckHook,
pytest-homeassistant-custom-component,
}:
buildHomeAssistantComponent rec {
owner = "pymitsubishi";
domain = "mitsubishi";
version = "0.2.0";
src = fetchFromGitHub {
owner = "pymitsubishi";
repo = "homeassistant-mitsubishi";
tag = "v${version}";
hash = "sha256-V8fT/w7a/uUN4yKJ+jB6UUQDP6dif80MvlqV9n4KENc=";
};
dependencies = [
pymitsubishi
];
nativeCheckInputs = [
pytest-cov-stub
pytestCheckHook
pytest-homeassistant-custom-component
];
meta = with lib; {
description = "Home Assistant Mitsubishi Air Conditioner Integration";
changelog = "https://github.com/pymitsubishi/homeassistant-mitsubishi/releases/tag/v${version}";
homepage = "https://github.com/pymitsubishi/homeassistant-mitsubishi";
maintainers = with maintainers; [ uvnikita ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,45 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
pytestCheckHook,
pytest-cov-stub,
pytest-homeassistant-custom-component,
# dependency
moonraker-api,
}:
buildHomeAssistantComponent rec {
owner = "marcolivierarsenault";
domain = "moonraker";
version = "1.10.0";
src = fetchFromGitHub {
owner = "marcolivierarsenault";
repo = "moonraker-home-assistant";
tag = version;
hash = "sha256-U4vjWFUZlxRPIrK9YXuYzPCMAjdQGoPXewmDessWh+c=";
};
dependencies = [
moonraker-api
];
nativeCheckInputs = [
pytest-homeassistant-custom-component
pytest-cov-stub
pytestCheckHook
];
#skip phases with nothing to do
dontConfigure = true;
meta = with lib; {
changelog = "https://github.com/marcolivierarsenault/moonraker-home-assistant/releases/tag/${version}";
description = "Custom integration for Moonraker and Klipper in Home Assistant";
homepage = "https://github.com/marcolivierarsenault/moonraker-home-assistant";
maintainers = with maintainers; [ _9R ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,28 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
}:
buildHomeAssistantComponent rec {
owner = "iMicknl";
domain = "nest_protect";
version = "0.4.2b0";
src = fetchFromGitHub {
inherit owner;
repo = "ha-nest-protect";
tag = "v${version}";
hash = "sha256-CQVAvx7iRCRHw8YXDmsWaF6fhddx3OfSLjq218+ob6I=";
};
# AttributeError: 'async_generator' object has no attribute 'data'
doCheck = false;
meta = with lib; {
changelog = "https://github.com/iMicknl/ha-nest-protect/releases/tag/v${version}";
description = "Nest Protect integration for Home Assistant";
homepage = "https://github.com/iMicknl/ha-nest-protect";
maintainers = with maintainers; [ jamiemagee ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,33 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
requests,
}:
buildHomeAssistantComponent rec {
owner = "hbrennhaeuser";
domain = "ntfy";
version = "1.2.0";
src = fetchFromGitHub {
inherit owner;
repo = "homeassistant_integration_ntfy";
rev = "v${version}";
hash = "sha256-cy4aHrUdFlMGQt9we0pA8TEGffQEGptZoaSKxwXD4kM=";
};
dependencies = [
requests
];
meta = with lib; {
description = "Send notifications with ntfy.sh and selfhosted ntfy-servers";
homepage = "https://github.com/hbrennhaeuser/homeassistant_integration_ntfy";
maintainers = with maintainers; [
koral
baksa
];
license = licenses.gpl3;
};
}

View File

@@ -0,0 +1,59 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
pytestCheckHook,
pytest-homeassistant-custom-component,
pydantic,
mock,
nix-update-script,
}:
buildHomeAssistantComponent rec {
owner = "BottlecapDave";
domain = "octopus_energy";
version = "16.3.1";
src = fetchFromGitHub {
inherit owner;
repo = "HomeAssistant-OctopusEnergy";
tag = "v${version}";
hash = "sha256-rn8wCGUYisLgr61Cd2qaQGfSiAtjKMo2wG/AotEXknE=";
};
dependencies = [ pydantic ];
nativeCheckInputs = [
pytestCheckHook
pytest-homeassistant-custom-component
mock
];
disabledTestPaths = [
# Integration tests require a valid Octopus Energy API Key
# https://github.com/BottlecapDave/HomeAssistant-OctopusEnergy/blob/develop/CONTRIBUTING.md#integration-tests
"tests/integration"
"tests/local_integration"
# These unit tests change Home Assistant's default time zone to Europe/London
# without restoring it, which fails pytest-homeassistant-custom-component's
# teardown
"tests/unit/utils/test_get_off_peak_cost.py::test_when_rates_available_and_bst_then_off_peak_cost_returned"
"tests/unit/utils/test_dict_to_typed_dict.py::test_when_utc_datetime_is_present_during_bst_then_converted_to_correct_datetime"
];
passthru.updateScript = nix-update-script {
extraArgs = [
# Ignore pre-release versions ("beta")
"--version-regex=^v([0-9]+\\.[0-9]+\\.[0-9])$"
];
};
meta = {
changelog = "https://github.com/BottlecapDave/HomeAssistant-OctopusEnergy/releases/tag/v${version}";
description = "Unofficial Home Assistant integration for interacting with Octopus Energy";
homepage = "https://github.com/BottlecapDave/HomeAssistant-OctopusEnergy";
maintainers = [ lib.maintainers.matteopacini ];
license = lib.licenses.mit;
};
}

View File

@@ -0,0 +1,33 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
omnikinverter,
}:
buildHomeAssistantComponent rec {
owner = "robbinjanssen";
domain = "omnik_inverter";
version = "2.6.4";
src = fetchFromGitHub {
owner = "robbinjanssen";
repo = "home-assistant-omnik-inverter";
tag = "v${version}";
hash = "sha256-O1NxT7u27xLydPqEqH72laU0tlYVrMPo0TwWIVNJ+0Q=";
};
dependencies = [
omnikinverter
];
doCheck = false; # no tests
meta = with lib; {
changelog = "https://github.com/robbinjanssen/home-assistant-omnik-inverter/releases/tag/v${version}";
description = "Omnik Inverter integration will scrape data from an Omnik inverter connected to your local network";
homepage = "https://github.com/robbinjanssen/home-assistant-omnik-inverter";
maintainers = with maintainers; [ _9R ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,46 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
aiofiles,
shapely,
paho-mqtt,
pytestCheckHook,
pytest-homeassistant-custom-component,
pytest-freezer,
}:
buildHomeAssistantComponent rec {
owner = "amitfin";
domain = "oref_alert";
version = "3.2.4";
src = fetchFromGitHub {
owner = "amitfin";
repo = "oref_alert";
tag = "v${version}";
hash = "sha256-+kZOwepyfehETfRDeA4w0eTaGSvkXNzG5rL2wdAKOy8=";
};
dependencies = [
aiofiles
shapely
paho-mqtt
];
ignoreVersionRequirement = [ "shapely" ];
nativeCheckInputs = [
pytestCheckHook
pytest-homeassistant-custom-component
pytest-freezer
];
meta = {
changelog = "https://github.com/amitfin/oref_alert/releases/tag/v${version}";
description = "Israeli Oref Alerts";
homepage = "https://github.com/amitfin/oref_alert";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ kranzes ];
};
}

View File

@@ -0,0 +1,37 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
aioairctrl,
getmac,
}:
buildHomeAssistantComponent rec {
owner = "kongo09";
domain = "philips_airpurifier_coap";
version = "0.34.3";
src = fetchFromGitHub {
inherit owner;
repo = "philips-airpurifier-coap";
rev = "v${version}";
hash = "sha256-jZmFvozkmmCCeKmdOV/FKXj0V8iGP3tnAqED/PBZrrY=";
};
dependencies = [
aioairctrl
getmac
];
ignoreVersionRequirement = [
"getmac"
];
meta = {
description = "Philips AirPurifier custom component for Home Assistant";
homepage = "https://github.com/kongo09/philips-airpurifier-coap";
license = lib.licenses.unfree; # See https://github.com/kongo09/philips-airpurifier-coap/issues/209
maintainers = with lib.maintainers; [ justinas ];
};
}

View File

@@ -0,0 +1,25 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
}:
buildHomeAssistantComponent rec {
owner = "samoswall";
domain = "polaris";
version = "1.0.10";
src = fetchFromGitHub {
owner = "samoswall";
repo = "polaris-mqtt";
tag = "v${version}";
hash = "sha256-GxNGZISV/YjMLH2hpoyuyKGvRDiZ3ejI2eJ7o00dqK8=";
};
meta = {
description = "Polaris IQ Home devices integration to Home Assistant";
homepage = "https://github.com/samoswall/polaris-mqtt";
license = lib.licenses.gpl3Only;
maintainers = [ lib.maintainers.k900 ];
};
}

View File

@@ -0,0 +1,26 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
}:
buildHomeAssistantComponent rec {
owner = "mweinelt";
domain = "prometheus_sensor";
version = "1.1.3";
src = fetchFromGitHub {
owner = "mweinelt";
repo = "ha-prometheus-sensor";
tag = version;
hash = "sha256-d13KJXgRPWrR2ilpEgZbVS/a6/y7DBRdEiGLpBaBsPc=";
};
meta = with lib; {
changelog = "https://github.com/mweinelt/ha-prometheus-sensor/blob/${version}/CHANGELOG.md";
description = "Import prometheus query results into Home Assistant";
homepage = "https://github.com/mweinelt/ha-prometheus-sensor";
maintainers = with maintainers; [ hexa ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,33 @@
{
lib,
fetchFromGitHub,
buildHomeAssistantComponent,
rctclient,
}:
buildHomeAssistantComponent rec {
owner = "weltenwort";
domain = "rct_power";
version = "v0.14.1";
src = fetchFromGitHub {
owner = "weltenwort";
repo = "home-assistant-rct-power-integration";
tag = version;
hash = "sha256-wM66MyRhBsMfUr+KlqV4jSuXcnKfW0fkbDAyuU2crsc=";
};
dependencies = [
rctclient
];
doCheck = false; # no tests
meta = with lib; {
changelog = "https://github.com/weltenwort/home-assistant-rct-power-integration/releases/tag/${src.tag}";
description = "Custom integration for RCT Power Inverters";
homepage = "https://github.com/weltenwort/home-assistant-rct-power-integration";
maintainers = with maintainers; [ _9R ];
license = licenses.mit;
};
}

View File

@@ -0,0 +1,25 @@
{
lib,
buildHomeAssistantComponent,
fetchFromGitHub,
}:
buildHomeAssistantComponent rec {
owner = "Lash-L";
domain = "roborock_custom_map";
version = "0.1.1";
src = fetchFromGitHub {
owner = "Lash-L";
repo = "RoborockCustomMap";
tag = version;
hash = "sha256-ZKaUTUTN0tTW8bks0TYixfmbEa7A7ERdJ+xZ365HEbU=";
};
meta = {
description = "This allows you to use the core Roborock integration with the Xiaomi Map Card";
homepage = "https://github.com/Lash-L/RoborockCustomMap";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ kranzes ];
};
}

Some files were not shown because too many files have changed in this diff Show More