Merge master into staging-next

This commit is contained in:
github-actions[bot]
2025-01-13 12:06:21 +00:00
committed by GitHub
88 changed files with 2607 additions and 599 deletions
+6
View File
@@ -15768,6 +15768,12 @@
githubId = 110892040;
name = "Mykyta Polchanov";
};
mzabani = {
email = "mzabani@gmail.com";
github = "mzabani";
githubId = 4662691;
name = "Marcelo Zabani";
};
mzacho = {
email = "nixpkgs@martinzacho.net";
github = "mzacho";
@@ -95,6 +95,8 @@
- [InputPlumber](https://github.com/ShadowBlip/InputPlumber/), an open source input router and remapper daemon for Linux. Available as [services.inputplumber](#opt-services.inputplumber.enable).
- [echoip](https://github.com/mpolden/echoip), a simple service for looking up your IP address. Available as [services.echoip](#opt-services.echoip.enable).
- [Buffyboard](https://gitlab.postmarketos.org/postmarketOS/buffybox/-/tree/master/buffyboard), a framebuffer on-screen keyboard. Available as [services.buffyboard](option.html#opt-services.buffyboard).
- [KanBoard](https://github.com/kanboard/kanboard), a project management tool that focuses on the Kanban methodology. Available as [services.kanboard](#opt-services.kanboard.enable).
+7
View File
@@ -571,7 +571,13 @@
./services/editors/emacs.nix
./services/editors/haste.nix
./services/editors/infinoted.nix
./services/finance/libeufin/bank.nix
./services/finance/libeufin/module.nix
./services/finance/libeufin/nexus.nix
./services/finance/odoo.nix
./services/finance/taler/exchange.nix
./services/finance/taler/merchant.nix
./services/finance/taler/module.nix
./services/games/archisteamfarm.nix
./services/games/armagetronad.nix
./services/games/crossfire-server.nix
@@ -1459,6 +1465,7 @@
./services/web-apps/documize.nix
./services/web-apps/dokuwiki.nix
./services/web-apps/dolibarr.nix
./services/web-apps/echoip.nix
./services/web-apps/eintopf.nix
./services/web-apps/engelsystem.nix
./services/web-apps/ethercalc.nix
@@ -0,0 +1,92 @@
{
lib,
config,
options,
...
}:
{
imports = [ (import ./common.nix "bank") ];
options.services.libeufin.bank = {
initialAccounts = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
description = ''
Accounts to enable before the bank service starts.
This is mainly needed for the nexus currency conversion
since the exchange's bank account is expected to be already
registered.
Don't forget to change the account passwords afterwards.
'';
default = [ ];
};
settings = lib.mkOption {
description = ''
Configuration options for the libeufin bank system config file.
For a list of all possible options, please see the man page [`libeufin-bank.conf(5)`](https://docs.taler.net/manpages/libeufin-bank.conf.5.html)
'';
type = lib.types.submodule {
inherit (options.services.libeufin.settings.type.nestedTypes) freeformType;
options = {
libeufin-bank = {
CURRENCY = lib.mkOption {
type = lib.types.str;
description = ''
The currency under which the libeufin-bank should operate.
This defaults to the GNU taler module's currency for convenience
but if you run libeufin-bank separately from taler, you must set
this yourself.
'';
};
PORT = lib.mkOption {
type = lib.types.port;
default = 8082;
description = ''
The port on which libeufin-bank should listen.
'';
};
SUGGESTED_WITHDRAWAL_EXCHANGE = lib.mkOption {
type = lib.types.str;
default = "https://exchange.demo.taler.net/";
description = ''
Exchange that is suggested to wallets when withdrawing.
Note that, in order for withdrawals to work, your libeufin-bank
must be able to communicate with and send money etc. to the bank
at which the exchange used for withdrawals has its bank account.
If you also have your own bank and taler exchange network, you
probably want to set one of your exchange's url here instead of
the demo exchange.
This setting must always be set in order for the Android app to
not crash during the withdrawal process but the exchange to be
used can always be changed in the app.
'';
};
};
libeufin-bankdb-postgres = {
CONFIG = lib.mkOption {
type = lib.types.str;
description = ''
The database connection string for the libeufin-bank database.
'';
};
};
};
};
};
};
config = {
services.libeufin.bank.settings.libeufin-bank.CURRENCY = lib.mkIf (
config.services.taler.enable && (config.services.taler.settings.taler ? CURRENCY)
) config.services.taler.settings.taler.CURRENCY;
services.libeufin.bank.settings.libeufin-bankdb-postgres.CONFIG = lib.mkIf config.services.libeufin.bank.createLocalDatabase "postgresql:///libeufin-bank";
};
}
@@ -0,0 +1,157 @@
# TODO: create a common module generator for Taler and Libeufin?
libeufinComponent:
{
lib,
pkgs,
config,
...
}:
{
options.services.libeufin.${libeufinComponent} = {
enable = lib.mkEnableOption "libeufin core banking system and web interface";
package = lib.mkPackageOption pkgs "libeufin" { };
debug = lib.mkEnableOption "debug logging";
createLocalDatabase = lib.mkEnableOption "automatic creation of a local postgres database";
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to open ports in the firewall";
};
};
config =
let
cfg = cfgMain.${libeufinComponent};
cfgMain = config.services.libeufin;
configFile = config.environment.etc."libeufin/libeufin.conf".source;
serviceName = "libeufin-${libeufinComponent}";
isNexus = libeufinComponent == "nexus";
# get database name from config
# TODO: should this always be the same db? In which case, should this be an option directly under `services.libeufin`?
dbName =
lib.removePrefix "postgresql:///"
cfg.settings."libeufin-${libeufinComponent}db-postgres".CONFIG;
bankPort = cfg.settings."${if isNexus then "nexus-httpd" else "libeufin-bank"}".PORT;
in
lib.mkIf cfg.enable {
services.libeufin.settings = cfg.settings;
# TODO add system-libeufin.slice?
systemd.services = {
# Main service
"${serviceName}" = {
serviceConfig = {
DynamicUser = true;
ExecStart =
let
args = lib.cli.toGNUCommandLineShell { } {
c = configFile;
L = if cfg.debug then "debug" else null;
};
in
"${lib.getExe' cfg.package "libeufin-${libeufinComponent}"} serve ${args}";
Restart = "on-failure";
RestartSec = "10s";
};
requires = [ "libeufin-dbinit.service" ];
after = [ "libeufin-dbinit.service" ];
wantedBy = [ "multi-user.target" ];
};
# Database Initialisation
libeufin-dbinit =
let
dbScript = pkgs.writers.writeText "libeufin-db-permissions.sql" ''
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA libeufin_bank TO "${serviceName}";
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA libeufin_nexus TO "${serviceName}";
GRANT USAGE ON SCHEMA libeufin_bank TO "${serviceName}";
GRANT USAGE ON SCHEMA libeufin_nexus TO "${serviceName}";
'';
# Accounts to be created after the bank database initialization.
#
# For example, if the bank's currency conversion is enabled, it's
# required that the exchange account is registered before the
# service starts.
initialAccountRegistration = lib.concatMapStringsSep "\n" (
account:
let
args = lib.cli.toGNUCommandLineShell { } {
c = configFile;
inherit (account) username password name;
payto_uri = "payto://x-taler-bank/bank:${toString bankPort}/${account.username}?receiver-name=${account.name}";
exchange = lib.toLower account.username == "exchange";
};
in
"${lib.getExe' cfg.package "libeufin-bank"} create-account ${args}"
) cfg.initialAccounts;
args = lib.cli.toGNUCommandLineShell { } {
c = configFile;
L = if cfg.debug then "debug" else null;
};
in
{
path = [ config.services.postgresql.package ];
serviceConfig = {
Type = "oneshot";
DynamicUser = true;
StateDirectory = "libeufin-dbinit";
StateDirectoryMode = "0750";
User = dbName;
};
script = lib.optionalString cfg.enable ''
${lib.getExe' cfg.package "libeufin-${libeufinComponent}"} dbinit ${args}
'';
# Grant DB permissions after schemas have been created
postStart =
''
psql -U "${dbName}" -f "${dbScript}"
''
+ lib.optionalString ((!isNexus) && (cfg.initialAccounts != [ ])) ''
# only register initial accounts once
if [ ! -e /var/lib/libeufin-dbinit/init ]; then
${initialAccountRegistration}
touch /var/lib/libeufin-dbinit/init
echo "Bank initialisation complete"
fi
'';
requires = lib.optionals cfg.createLocalDatabase [ "postgresql.service" ];
after = [ "network.target" ] ++ lib.optionals cfg.createLocalDatabase [ "postgresql.service" ];
};
};
networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [
bankPort
];
};
environment.systemPackages = [ cfg.package ];
services.postgresql = lib.mkIf cfg.createLocalDatabase {
enable = true;
ensureDatabases = [ dbName ];
ensureUsers = [
{ name = serviceName; }
{
name = dbName;
ensureDBOwnership = true;
}
];
};
assertions = [
{
assertion =
cfg.createLocalDatabase || (cfg.settings."libeufin-${libeufinComponent}db-postgres" ? CONFIG);
message = "Libeufin ${libeufinComponent} database is not configured.";
}
];
};
}
@@ -0,0 +1,26 @@
{
lib,
pkgs,
config,
...
}:
let
cfg = config.services.libeufin;
settingsFormat = pkgs.formats.ini { };
configFile = settingsFormat.generate "generated-libeufin.conf" cfg.settings;
in
{
options.services.libeufin = {
settings = lib.mkOption {
description = "Global configuration options for the libeufin bank system config file.";
type = lib.types.submodule { freeformType = settingsFormat.type; };
default = { };
};
};
config = lib.mkIf (cfg.bank.enable || cfg.nexus.enable) {
environment.etc."libeufin/libeufin.conf".source = configFile;
};
}
@@ -0,0 +1,131 @@
{
lib,
config,
options,
...
}:
{
imports = [ (import ./common.nix "nexus") ];
options.services.libeufin.nexus.settings = lib.mkOption {
description = ''
Configuration options for the libeufin nexus config file.
For a list of all possible options, please see the man page [`libeufin-nexus.conf(5)`](https://docs.taler.net/manpages/libeufin-nexus.conf.5.html)
'';
type = lib.types.submodule {
inherit (options.services.libeufin.settings.type.nestedTypes) freeformType;
options = {
nexus-ebics = {
# Mandatory configuration values
# https://docs.taler.net/libeufin/nexus-manual.html#setting-up-the-ebics-subscriber
# https://docs.taler.net/libeufin/setup-ebics-at-postfinance.html
CURRENCY = lib.mkOption {
description = "Name of the fiat currency.";
type = lib.types.nonEmptyStr;
example = "CHF";
};
HOST_BASE_URL = lib.mkOption {
description = "URL of the EBICS server.";
type = lib.types.nonEmptyStr;
example = "https://ebics.postfinance.ch/ebics/ebics.aspx";
};
BANK_DIALECT = lib.mkOption {
description = ''
Name of the following combination: EBICS version and ISO20022
recommendations that Nexus would honor in the communication with the
bank.
Currently only the "postfinance" or "gls" value is supported.
'';
type = lib.types.enum [
"postfinance"
"gls"
];
example = "postfinance";
};
HOST_ID = lib.mkOption {
description = "Name of the EBICS host.";
type = lib.types.nonEmptyStr;
example = "PFEBICS";
};
USER_ID = lib.mkOption {
description = ''
User ID of the EBICS subscriber.
This value must be assigned by the bank after having activated a new EBICS subscriber.
'';
type = lib.types.nonEmptyStr;
example = "PFC00563";
};
PARTNER_ID = lib.mkOption {
description = ''
Partner ID of the EBICS subscriber.
This value must be assigned by the bank after having activated a new EBICS subscriber.
'';
type = lib.types.nonEmptyStr;
example = "PFC00563";
};
IBAN = lib.mkOption {
description = "IBAN of the bank account that is associated with the EBICS subscriber.";
type = lib.types.nonEmptyStr;
example = "CH7789144474425692816";
};
BIC = lib.mkOption {
description = "BIC of the bank account that is associated with the EBICS subscriber.";
type = lib.types.nonEmptyStr;
example = "POFICHBEXXX";
};
NAME = lib.mkOption {
description = "Legal entity that is associated with the EBICS subscriber.";
type = lib.types.nonEmptyStr;
example = "John Smith S.A.";
};
BANK_PUBLIC_KEYS_FILE = lib.mkOption {
type = lib.types.path;
default = "/var/lib/libeufin-nexus/bank-ebics-keys.json";
description = ''
Filesystem location where Nexus should store the bank public keys.
'';
};
CLIENT_PRIVATE_KEYS_FILE = lib.mkOption {
type = lib.types.path;
default = "/var/lib/libeufin-nexus/client-ebics-keys.json";
description = ''
Filesystem location where Nexus should store the subscriber private keys.
'';
};
};
nexus-httpd = {
PORT = lib.mkOption {
type = lib.types.port;
default = 8084;
description = ''
The port on which libeufin-bank should listen.
'';
};
};
libeufin-nexusdb-postgres = {
CONFIG = lib.mkOption {
type = lib.types.str;
description = ''
The database connection string for the libeufin-nexus database.
'';
};
};
};
};
};
config =
let
cfgMain = config.services.libeufin;
cfg = config.services.libeufin.nexus;
in
lib.mkIf cfg.enable {
services.libeufin.nexus.settings.libeufin-nexusdb-postgres.CONFIG = lib.mkIf (
cfgMain.bank.enable && cfgMain.bank.createLocalDatabase
) "postgresql:///libeufin-bank";
};
}
@@ -0,0 +1,119 @@
# TODO: create a common module generator for Taler and Libeufin?
{
talerComponent ? "",
servicesDB ? [ ],
servicesNoDB ? [ ],
...
}:
{
lib,
pkgs,
config,
...
}:
let
cfg = cfgTaler.${talerComponent};
cfgTaler = config.services.taler;
settingsFormat = pkgs.formats.ini { };
configFile = config.environment.etc."taler/taler.conf".source;
componentConfigFile = settingsFormat.generate "generated-taler-${talerComponent}.conf" cfg.settings;
services = servicesDB ++ servicesNoDB;
dbName = "taler-${talerComponent}-httpd";
groupName = "taler-${talerComponent}-services";
inherit (cfgTaler) runtimeDir;
in
{
options = {
services.taler.${talerComponent} = {
enable = lib.mkEnableOption "the GNU Taler ${talerComponent}";
package = lib.mkPackageOption pkgs "taler-${talerComponent}" { };
# TODO: make option accept multiple debugging levels?
debug = lib.mkEnableOption "debug logging";
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to open ports in the firewall";
};
};
};
config = lib.mkIf cfg.enable {
services.taler.enable = cfg.enable;
services.taler.includes = [ componentConfigFile ];
systemd.services = lib.mergeAttrsList [
# Main services
(lib.genAttrs (map (n: "taler-${talerComponent}-${n}") services) (name: {
serviceConfig = {
DynamicUser = true;
User = name;
Group = groupName;
ExecStart = toString [
(lib.getExe' cfg.package name)
"-c ${configFile}"
(lib.optionalString cfg.debug " -L debug")
];
RuntimeDirectory = name;
StateDirectory = name;
CacheDirectory = name;
ReadWritePaths = [ runtimeDir ];
Restart = "always";
RestartSec = "10s";
};
requires = [ "taler-${talerComponent}-dbinit.service" ];
after = [ "taler-${talerComponent}-dbinit.service" ];
wantedBy = [ "multi-user.target" ]; # TODO slice?
}))
# Database Initialisation
{
"taler-${talerComponent}-dbinit" = {
path = [ config.services.postgresql.package ];
serviceConfig = {
Type = "oneshot";
DynamicUser = true;
User = dbName;
Restart = "on-failure";
RestartSec = "5s";
};
requires = [ "postgresql.service" ];
after = [ "postgresql.service" ];
};
}
];
users.groups.${groupName} = { };
systemd.tmpfiles.settings = {
"10-taler-${talerComponent}" = {
"${runtimeDir}" = {
d = {
group = groupName;
user = "nobody";
mode = "070";
};
};
};
};
networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.settings."${talerComponent}".PORT ];
};
environment.systemPackages = [ cfg.package ];
services.postgresql = {
enable = true;
ensureDatabases = [ dbName ];
ensureUsers = map (service: { name = "taler-${talerComponent}-${service}"; }) servicesDB ++ [
{
name = dbName;
ensureDBOwnership = true;
}
];
};
};
}
@@ -0,0 +1,154 @@
{
lib,
config,
options,
pkgs,
...
}:
let
cfg = cfgTaler.exchange;
cfgTaler = config.services.taler;
talerComponent = "exchange";
# https://docs.taler.net/taler-exchange-manual.html#services-users-groups-and-file-system-hierarchy
servicesDB = [
"httpd"
"aggregator"
"closer"
"wirewatch"
];
servicesNoDB = [
"secmod-cs"
"secmod-eddsa"
"secmod-rsa"
];
in
{
imports = [
(import ./common.nix { inherit talerComponent servicesDB servicesNoDB; })
];
options.services.taler.exchange = {
settings = lib.mkOption {
description = ''
Configuration options for the taler exchange config file.
For a list of all possible options, please see the man page [`taler-exchange.conf(5)`](https://docs.taler.net/manpages/taler-exchange.conf.5.html)
'';
type = lib.types.submodule {
inherit (options.services.taler.settings.type.nestedTypes) freeformType;
options = {
# TODO: do we want this to be a sub-attribute or only define the exchange set of options here
exchange = {
AML_THRESHOLD = lib.mkOption {
type = lib.types.str;
default = "${cfgTaler.settings.taler.CURRENCY}:1000000";
defaultText = "1000000 in {option}`CURRENCY`";
description = "Monthly transaction volume until an account is considered suspicious and flagged for AML review.";
};
DB = lib.mkOption {
type = lib.types.enum [ "postgres" ];
default = "postgres";
description = "Plugin to use for the database.";
};
MASTER_PUBLIC_KEY = lib.mkOption {
type = lib.types.str;
default = "";
description = "Used by the exchange to verify information signed by the offline system.";
};
PORT = lib.mkOption {
type = lib.types.port;
default = 8081;
description = "Port on which the HTTP server listens.";
};
};
exchangedb-postgres = {
CONFIG = lib.mkOption {
type = lib.types.nonEmptyStr;
default = "postgres:///taler-exchange-httpd";
description = "Database connection URI.";
};
};
};
};
default = { };
};
denominationConfig = lib.mkOption {
type = lib.types.lines;
defaultText = "None, you must set this yourself.";
example = ''
[COIN-KUDOS-n1-t1718140083]
VALUE = KUDOS:0.1
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0.1
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
'';
description = ''
This option configures the cash denomination for the coins that the exchange offers.
For more information, consult the [upstream docs](https://docs.taler.net/taler-exchange-manual.html#coins-denomination-keys).
You can either write these manually or you can use the `taler-harness deployment gen-coin-config`
command to generate it.
Warning: Do not modify existing denominations after deployment.
Please see the upstream docs for how to safely do that.
'';
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.settings.exchange.MASTER_PUBLIC_KEY != "";
message = ''
You must provide `config.services.taler.exchange.settings.exchange.MASTER_PUBLIC_KEY` with the
public part of your master key.
This will be used by the auditor service to get information about the exchange.
For more information, see https://docs.taler.net/taler-auditor-manual.html#initial-configuration
To generate this key, you must run `taler-exchange-offline setup`, which will print the public key.
'';
}
];
services.taler.includes = [
(pkgs.writers.writeText "exchange-denominations.conf" cfg.denominationConfig)
];
systemd.services.taler-exchange-wirewatch = {
requires = [ "taler-exchange-httpd.service" ];
after = [ "taler-exchange-httpd.service" ];
};
# Taken from https://docs.taler.net/taler-exchange-manual.html#exchange-database-setup
# TODO: Why does aggregator need DELETE?
systemd.services."taler-${talerComponent}-dbinit".script =
let
deletePerm = name: lib.optionalString (name == "aggregator") ",DELETE";
dbScript = pkgs.writers.writeText "taler-exchange-db-permissions.sql" (
lib.pipe servicesDB [
(map (name: ''
GRANT SELECT,INSERT,UPDATE${deletePerm name} ON ALL TABLES IN SCHEMA exchange TO "taler-exchange-${name}";
GRANT USAGE ON SCHEMA exchange TO "taler-exchange-${name}";
''))
lib.concatStrings
]
);
in
''
${lib.getExe' cfg.package "taler-exchange-dbinit"}
psql -U taler-exchange-httpd -f ${dbScript}
'';
};
}
@@ -0,0 +1,108 @@
{
lib,
config,
options,
pkgs,
...
}:
let
cfg = cfgTaler.merchant;
cfgTaler = config.services.taler;
talerComponent = "merchant";
# https://docs.taler.net/taler-merchant-manual.html#launching-the-backend
servicesDB = [
"httpd"
"webhook"
"wirewatch"
"depositcheck"
"exchange"
];
in
{
imports = [
(import ./common.nix { inherit talerComponent servicesDB; })
];
options.services.taler.merchant = {
settings = lib.mkOption {
description = ''
Configuration options for the taler merchant config file.
For a list of all possible options, please see the man page [`taler-merchant.conf(5)`](https://docs.taler.net/manpages/taler-merchant.conf.5.html)
'';
type = lib.types.submodule {
inherit (options.services.taler.settings.type.nestedTypes) freeformType;
options = {
merchant = {
DB = lib.mkOption {
type = lib.types.enum [ "postgres" ];
default = "postgres";
description = "Plugin to use for the database.";
};
PORT = lib.mkOption {
type = lib.types.port;
default = 8083;
description = "Port on which the HTTP server listens.";
};
SERVE = lib.mkOption {
type = lib.types.enum [
"tcp"
"unix"
];
default = "tcp";
description = ''
Whether the HTTP server should listen on a UNIX domain socket ("unix") or on a TCP socket ("tcp").
'';
};
LEGAL_PRESERVATION = lib.mkOption {
type = lib.types.str;
default = "10 years";
description = "How long to keep data in the database for tax audits after the transaction has completed.";
};
};
merchantdb-postgres = {
CONFIG = lib.mkOption {
type = lib.types.nonEmptyStr;
default = "postgres:///taler-merchant-httpd";
description = "Database connection URI.";
};
SQL_DIR = lib.mkOption {
type = lib.types.str;
internal = true;
default = "${cfg.package}/share/taler/sql/merchant/";
description = "The location for the SQL files to setup the database tables.";
};
};
};
};
default = { };
};
};
config = lib.mkIf cfg.enable {
systemd.services.taler-merchant-depositcheck = {
# taler-merchant-depositcheck needs its executable is in the PATH
# NOTE: couldn't use `lib.getExe` to only get that single executable
path = [ cfg.package ];
};
systemd.services."taler-${talerComponent}-dbinit".script =
let
# NOTE: not documented, but is necessary
dbScript = pkgs.writers.writeText "taler-merchant-db-permissions.sql" (
lib.concatStrings (
map (name: ''
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA merchant TO "taler-merchant-${name}";
GRANT USAGE ON SCHEMA merchant TO "taler-merchant-${name}";
'') servicesDB
)
);
in
''
${lib.getExe' cfg.package "taler-merchant-dbinit"}
psql -U taler-${talerComponent}-httpd -f ${dbScript}
'';
};
}
@@ -0,0 +1,93 @@
{
lib,
pkgs,
config,
...
}:
let
cfg = config.services.taler;
settingsFormat = pkgs.formats.ini { };
in
{
# TODO turn this into a generic taler-like service thingy?
options.services.taler = {
enable = lib.mkEnableOption "the GNU Taler system" // lib.mkOption { internal = true; };
includes = lib.mkOption {
type = lib.types.listOf lib.types.path;
default = [ ];
description = ''
Files to include into the config file using Taler's `@inline@` directive.
This allows including arbitrary INI files, including imperatively managed ones.
'';
};
settings = lib.mkOption {
description = ''
Global configuration options for the taler config file.
For a list of all possible options, please see the man page [`taler.conf(5)`](https://docs.taler.net/manpages/taler.conf.5.html)
'';
type = lib.types.submodule {
freeformType = settingsFormat.type;
options = {
taler = {
CURRENCY = lib.mkOption {
type = lib.types.nonEmptyStr;
description = ''
The currency which taler services will operate with. This cannot be changed later.
'';
};
CURRENCY_ROUND_UNIT = lib.mkOption {
type = lib.types.str;
default = "${cfg.settings.taler.CURRENCY}:0.01";
defaultText = lib.literalExpression ''
"''${config.services.taler.settings.taler.CURRENCY}:0.01"
'';
description = ''
Smallest amount in this currency that can be transferred using the underlying RTGS.
You should probably not touch this.
'';
};
};
};
};
default = { };
};
runtimeDir = lib.mkOption {
type = lib.types.str;
default = "/run/taler-system-runtime/";
description = ''
Runtime directory shared between the taler services.
Crypto helpers put their sockets here for instance and the httpd
connects to them.
'';
};
};
config = lib.mkIf cfg.enable {
services.taler.settings.PATHS = {
TALER_DATA_HOME = "\${STATE_DIRECTORY}/";
TALER_CACHE_HOME = "\${CACHE_DIRECTORY}/";
TALER_RUNTIME_DIR = cfg.runtimeDir;
};
environment.etc."taler/taler.conf".source =
let
includes = pkgs.writers.writeText "includes.conf" (
lib.concatStringsSep "\n" (map (include: "@inline@ ${include}") cfg.includes)
);
generatedConfig = settingsFormat.generate "generated-taler.conf" cfg.settings;
in
pkgs.runCommand "taler.conf" { } ''
cat ${includes} > $out
echo >> $out
echo >> $out
cat ${generatedConfig} >> $out
'';
};
}
+4 -3
View File
@@ -138,9 +138,10 @@ in
script = ''
${lib.concatStringsSep "\n" (
builtins.map (name: "export ${name}=$(systemd-creds cat 'SECRET-${name}')") (
lib.attrNames cfg.credentials
)
builtins.map (name: ''
${name}="$(systemd-creds cat 'SECRET-${name}')"
export ${name}
'') (lib.attrNames cfg.credentials)
)}
exec ${lib.escapeShellArg (lib.getExe cfg.package)}
'';
+121
View File
@@ -0,0 +1,121 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.echoip;
in
{
meta.maintainers = with lib.maintainers; [ defelo ];
options.services.echoip = {
enable = lib.mkEnableOption "echoip";
package = lib.mkPackageOption pkgs "echoip" { };
virtualHost = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = ''
Name of the nginx virtual host to use and setup. If null, do not setup anything.
'';
default = null;
};
extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "Extra command line arguments to pass to echoip. See <https://github.com/mpolden/echoip> for details.";
default = [ ];
};
listenAddress = lib.mkOption {
type = lib.types.str;
description = "The address echoip should listen on";
default = ":8080";
example = "127.0.0.1:8000";
};
enablePortLookup = lib.mkEnableOption "port lookup";
enableReverseHostnameLookups = lib.mkEnableOption "reverse hostname lookups";
remoteIpHeader = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = "Header to trust for remote IP, if present";
default = null;
example = "X-Real-IP";
};
};
config = lib.mkIf cfg.enable {
systemd.services.echoip = {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
User = "echoip";
Group = "echoip";
DynamicUser = true;
ExecStart = lib.escapeShellArgs (
[
(lib.getExe cfg.package)
"-l"
cfg.listenAddress
]
++ lib.optional cfg.enablePortLookup "-p"
++ lib.optional cfg.enableReverseHostnameLookups "-r"
++ lib.optionals (cfg.remoteIpHeader != null) [
"-H"
cfg.remoteIpHeader
]
++ cfg.extraArgs
);
# Hardening
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
PrivateDevices = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
};
};
services.nginx = lib.mkIf (cfg.virtualHost != null) {
enable = true;
virtualHosts.${cfg.virtualHost} = {
locations."/" = {
proxyPass = "http://${cfg.listenAddress}";
recommendedProxySettings = true;
};
};
};
services.echoip = lib.mkIf (cfg.virtualHost != null) {
listenAddress = lib.mkDefault "127.0.0.1:8080";
remoteIpHeader = "X-Real-IP";
};
};
}
@@ -192,7 +192,7 @@ let
script =
''
state="/run/nixos/network/addresses/${i.name}"
mkdir -p $(dirname "$state")
mkdir -p "$(dirname "$state")"
ip link set dev "${i.name}" up
@@ -206,14 +206,14 @@ let
if out=$(ip addr replace "${cidr}" dev "${i.name}" 2>&1); then
echo "done"
else
echo "'ip addr replace "${cidr}" dev "${i.name}"' failed: $out"
echo "'ip addr replace \"${cidr}\" dev \"${i.name}\"' failed: $out"
exit 1
fi
''
)}
state="/run/nixos/network/routes/${i.name}"
mkdir -p $(dirname "$state")
mkdir -p "$(dirname "$state")"
${flip concatMapStrings (i.ipv4.routes ++ i.ipv6.routes) (route:
let
@@ -228,7 +228,7 @@ let
if out=$(ip route add ${type} "${cidr}" ${options} ${via} dev "${i.name}" proto static 2>&1); then
echo "done"
elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then
echo "'ip route add ${type} "${cidr}" ${options} ${via} dev "${i.name}"' failed: $out"
echo "'ip route add ${type} \"${cidr}\" ${options} ${via} dev \"${i.name}\"' failed: $out"
exit 1
fi
''
+12 -1
View File
@@ -19,8 +19,19 @@ let
export HOME=/root
export DISPLAY=:0.0
# Determine if this script is ran with nounset
strict="false"
if set -o | grep --quiet --perl-regexp "nounset\s+on"; then
strict="true"
fi
if [[ -e /etc/profile ]]; then
# TODO: Currently shell profiles are not checked at build time,
# so we need to unset stricter options to source them
set +o nounset
# shellcheck disable=SC1091
source /etc/profile
[ "$strict" = "true" ] && set -o nounset
fi
# Don't use a pager when executing backdoor
@@ -45,7 +56,7 @@ let
# we can also run non-NixOS guests during tests. This, however, is
# mostly futureproofing as the test instrumentation is still very
# tightly coupled to NixOS.
PS1= exec ${pkgs.coreutils}/bin/env bash --norc /dev/hvc0
PS1="" exec ${pkgs.coreutils}/bin/env bash --norc /dev/hvc0
'';
serviceConfig.KillSignal = "SIGHUP";
};
+2
View File
@@ -294,6 +294,7 @@ in {
early-mount-options = handleTest ./early-mount-options.nix {};
ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {};
ec2-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {};
echoip = handleTest ./echoip.nix {};
ecryptfs = handleTest ./ecryptfs.nix {};
fscrypt = handleTest ./fscrypt.nix {};
fastnetmon-advanced = runTest ./fastnetmon-advanced.nix;
@@ -1064,6 +1065,7 @@ in {
systemd-userdbd = handleTest ./systemd-userdbd.nix {};
systemd-homed = handleTest ./systemd-homed.nix {};
systemtap = handleTest ./systemtap.nix {};
taler = handleTest ./taler {};
tandoor-recipes = handleTest ./tandoor-recipes.nix {};
tandoor-recipes-script-name = handleTest ./tandoor-recipes-script-name.nix {};
tang = handleTest ./tang.nix {};
+29
View File
@@ -0,0 +1,29 @@
import ./make-test-python.nix (
{ lib, ... }:
{
name = "echoip";
meta.maintainers = with lib.maintainers; [ defelo ];
nodes.machine = {
services.echoip = {
enable = true;
virtualHost = "echoip.local";
};
networking.hosts = {
"127.0.0.1" = [ "echoip.local" ];
"::1" = [ "echoip.local" ];
};
};
testScript = ''
machine.wait_for_unit("echoip.service")
machine.wait_for_open_port(8080)
resp = machine.succeed("curl -4 http://echoip.local/ip")
assert resp.strip() == "127.0.0.1"
resp = machine.succeed("curl -6 http://echoip.local/ip")
assert resp.strip() == "::1"
'';
}
)
+18
View File
@@ -52,6 +52,16 @@ import ./make-test-python.nix (
];
};
immutable = makeMattermost {
package = pkgs.mattermost.overrideAttrs (prev: {
webapp = prev.webapp.overrideAttrs (prevWebapp: {
# Ensure that users can add patches.
postPatch =
prevWebapp.postPatch or ""
+ ''
substituteInPlace channels/src/root.html --replace-fail "Mattermost" "Patched Mattermost"
'';
});
});
mutableConfig = false;
extraConfig.SupportSettings.HelpLink = "https://search.nixos.org";
};
@@ -94,6 +104,8 @@ import ./make-test-python.nix (
## Mutable node tests ##
mutable.wait_for_unit("mattermost.service")
mutable.wait_for_open_port(8065)
mutable.succeed("curl -L http://localhost:8065/index.html | grep '${siteName}'")
mutable.succeed("curl -L http://localhost:8065/index.html | grep 'Mattermost'")
# Get the initial config
mutable.succeed("${expectConfig ''.AboutLink == "https://nixos.org" and .HelpLink == "https://search.nixos.org"''}")
@@ -110,6 +122,8 @@ import ./make-test-python.nix (
## Mostly mutable node tests ##
mostlyMutable.wait_for_unit("mattermost.service")
mostlyMutable.wait_for_open_port(8065)
mostlyMutable.succeed("curl -L http://localhost:8065/index.html | grep '${siteName}'")
mostlyMutable.succeed("curl -L http://localhost:8065/index.html | grep 'Mattermost'")
# Get the initial config
mostlyMutable.succeed("${expectConfig ''.AboutLink == "https://nixos.org"''}")
@@ -126,6 +140,8 @@ import ./make-test-python.nix (
## Immutable node tests ##
immutable.wait_for_unit("mattermost.service")
immutable.wait_for_open_port(8065)
# Since we patched it, it doesn't replace the site name at runtime anymore
immutable.succeed("curl -L http://localhost:8065/index.html | grep 'Patched Mattermost'")
# Get the initial config
immutable.succeed("${expectConfig ''.AboutLink == "https://nixos.org" and .HelpLink == "https://search.nixos.org"''}")
@@ -143,6 +159,8 @@ import ./make-test-python.nix (
## Environment File node tests ##
environmentFile.wait_for_unit("mattermost.service")
environmentFile.wait_for_open_port(8065)
environmentFile.succeed("curl -L http://localhost:8065/index.html | grep '${siteName}'")
environmentFile.succeed("curl -L http://localhost:8065/index.html | grep 'Mattermost'")
# Settings in the environment file should override settings set otherwise
environmentFile.succeed("${expectConfig ''.AboutLink == "https://nixos.org"''}")
+2
View File
@@ -31,6 +31,8 @@ import ./make-test-python.nix (
enable = true;
settings.server.HTTP_PORT = 3000;
};
# Uncomment the next line to lint service scripts (Note: breaks VM startup; see #373166)
#systemd.enableStrictShellChecks = true;
};
testScript = ''
+200
View File
@@ -0,0 +1,200 @@
{ lib, ... }:
let
# Forward SSH and WebUI ports to host machine
#
# Connect with: ssh root@localhost -p <hostPort>
# Access WebUI from: http://localhost:<hostPort>
#
# NOTE: This is only accessible from an interactive test, for example:
# $ eval $(nix-build -A nixosTests.taler.basic.driver)/bin/nixos-test-driver
mkNode =
{
sshPort ? 0,
webuiPort ? 0,
nodeSettings ? { },
}:
lib.recursiveUpdate {
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "yes";
PermitEmptyPasswords = "yes";
};
};
security.pam.services.sshd.allowNullPassword = true;
virtualisation.forwardPorts =
(lib.optionals (sshPort != 0) [
{
from = "host";
host.port = sshPort;
guest.port = 22;
}
])
++ (lib.optionals (webuiPort != 0) [
{
from = "host";
host.port = webuiPort;
guest.port = webuiPort;
}
]);
} nodeSettings;
in
rec {
CURRENCY = "KUDOS";
FIAT_CURRENCY = "CHF";
nodes = {
exchange =
{ config, lib, ... }:
mkNode {
sshPort = 1111;
webuiPort = 8081;
nodeSettings = {
services.taler = {
settings = {
taler.CURRENCY = CURRENCY;
};
includes = [ ../conf/taler-accounts.conf ];
exchange = {
enable = true;
debug = true;
openFirewall = true;
denominationConfig = lib.readFile ../conf/taler-denominations.conf;
settings = {
exchange = {
MASTER_PUBLIC_KEY = "2TQSTPFZBC2MC4E52NHPA050YXYG02VC3AB50QESM6JX1QJEYVQ0";
BASE_URL = "http://exchange:8081/";
};
exchange-offline = {
MASTER_PRIV_FILE = "${../conf/private.key}";
};
};
};
};
};
};
bank =
{ config, ... }:
mkNode {
sshPort = 2222;
webuiPort = 8082;
nodeSettings = {
services.libeufin.bank = {
enable = true;
debug = true;
openFirewall = true;
createLocalDatabase = true;
initialAccounts = [
{
username = "exchange";
password = "exchange";
name = "Exchange";
}
];
settings = {
libeufin-bank = {
WIRE_TYPE = "x-taler-bank";
# WIRE_TYPE = "iban";
X_TALER_BANK_PAYTO_HOSTNAME = "bank:8082";
# IBAN_PAYTO_BIC = "SANDBOXX";
BASE_URL = "bank:8082";
# Allow creating new accounts
ALLOW_REGISTRATION = "yes";
# A registration bonus makes withdrawals easier since the
# bank account balance is not empty
REGISTRATION_BONUS_ENABLED = "yes";
REGISTRATION_BONUS = "${CURRENCY}:100";
DEFAULT_DEBT_LIMIT = "${CURRENCY}:500";
# NOTE: The exchange's bank account must be initialised before
# the main bank service starts, else it doesn't work.
# The `services.libeufin.bank.initialAccounts` option can be used to do this.
ALLOW_CONVERSION = "yes";
ALLOW_EDIT_CASHOUT_PAYTO_URI = "yes";
SUGGESTED_WITHDRAWAL_EXCHANGE = "http://exchange:8081/";
inherit CURRENCY FIAT_CURRENCY;
};
};
};
services.libeufin.nexus = {
enable = true;
debug = true;
openFirewall = true;
createLocalDatabase = true;
settings = {
# https://docs.taler.net/libeufin/setup-ebics-at-postfinance.html
nexus-ebics = {
# == Mandatory ==
CURRENCY = FIAT_CURRENCY;
# Bank
HOST_BASE_URL = "https://isotest.postfinance.ch/ebicsweb/ebicsweb";
BANK_DIALECT = "postfinance";
# EBICS IDs
HOST_ID = "PFEBICS";
USER_ID = "PFC00639";
PARTNER_ID = "PFC00639";
# Account information
IBAN = "CH4740123RW4167362694";
BIC = "BIC";
NAME = "nixosTest nixosTest";
# == Optional ==
CLIENT_PRIVATE_KEYS_FILE = "${../conf/client-ebics-keys.json}";
BANK_PUBLIC_KEYS_FILE = "${../conf/bank-ebics-keys.json}";
};
};
};
};
};
merchant =
{ config, ... }:
mkNode {
sshPort = 3333;
webuiPort = 8083;
nodeSettings = {
services.taler = {
settings = {
taler.CURRENCY = CURRENCY;
};
merchant = {
enable = true;
debug = true;
openFirewall = true;
settings.merchant-exchange-test = {
EXCHANGE_BASE_URL = "http://exchange:8081/";
MASTER_KEY = "2TQSTPFZBC2MC4E52NHPA050YXYG02VC3AB50QESM6JX1QJEYVQ0";
inherit CURRENCY;
};
};
};
};
};
client =
{ pkgs, ... }:
mkNode {
sshPort = 4444;
nodeSettings = {
environment.systemPackages = [ pkgs.taler-wallet-core ];
};
};
};
}
+107
View File
@@ -0,0 +1,107 @@
{
lib,
pkgs,
nodes,
...
}:
let
cfgNodes = pkgs.callPackage ./nodes.nix { inherit lib; };
bankConfig = nodes.bank.config.environment.etc."libeufin/libeufin.conf".source;
inherit (cfgNodes) CURRENCY FIAT_CURRENCY;
in
{
commonScripts =
# python
''
def succeed(machine, commands):
"""A more convenient `machine.succeed` that supports multi-line inputs"""
flattened_commands = [c.replace("\n", "") for c in commands] # flatten multi-line
return machine.succeed(" ".join(flattened_commands))
def systemd_run(machine, cmd, user="nobody", group="nobody"):
"""Execute command as a systemd DynamicUser"""
machine.log(f"Executing command (via systemd-run): \"{cmd}\"")
(status, out) = machine.execute( " ".join([
"systemd-run",
"--service-type=exec",
"--quiet",
"--wait",
"-E PATH=\"$PATH\"",
"-p StandardOutput=journal",
"-p StandardError=journal",
"-p DynamicUser=yes",
f"-p Group={group}" if group != "nobody" else "",
f"-p User={user}" if user != "nobody" else "",
f"$SHELL -c '{cmd}'"
]) )
if status != 0:
raise Exception(f"systemd_run failed (status {status})")
machine.log("systemd-run finished successfully")
def register_bank_account(username, password, name, is_exchange=False):
"""Register Libeufin bank account for the x-taler-bank wire method"""
return systemd_run(bank, " ".join([
'libeufin-bank',
'create-account',
'-c ${bankConfig}',
f'--username {username}',
f'--password {password}',
f'--name {name}',
f'--payto_uri="payto://x-taler-bank/bank:8082/{username}?receiver-name={name}"',
'--exchange' if (is_exchange or username.lower()=="exchange") else ' '
]),
user="libeufin-bank")
def wallet_cli(command):
"""Wrapper for the Taler CLI wallet"""
return client.succeed(
"taler-wallet-cli "
"--no-throttle " # don't do any request throttling
+ command
)
def verify_balance(balanceWanted: str):
"""Compare Taler CLI wallet balance with expected amount"""
balance = wallet_cli("balance --json")
try:
balanceGot = json.loads(balance)["balances"][0]["available"]
except:
balanceGot = "${CURRENCY}:0"
# Compare balance with expected value
if balanceGot != balanceWanted:
client.fail(f'echo Wanted balance: "{balanceWanted}", got: "{balanceGot}"')
else:
client.succeed(f"echo Withdraw successfully made. New balance: {balanceWanted}")
def verify_conversion(regionalWanted: str):
"""Compare converted Libeufin Nexus funds with expected regional currency"""
# Get transaction details
response = json.loads(
succeed(bank, [
"curl -sSfL",
# TODO: get exchange from config?
"-u exchange:exchange",
"http://bank:8082/accounts/exchange/transactions"
])
)
amount = response["transactions"][0]["amount"].split(":") # CURRENCY:VALUE
currencyGot, regionalGot = amount
# Check conversion (1:1 ratio)
if (regionalGot != regionalWanted) or (currencyGot != "${CURRENCY}"):
client.fail(f'echo Wanted "${CURRENCY}:{regionalWanted}", got: "{currencyGot}:{regionalGot}"')
else:
client.succeed(f'echo Conversion successfully made: "${FIAT_CURRENCY}:{regionalWanted}" -> "{currencyGot}:{regionalGot}"')
'';
}
@@ -0,0 +1 @@
{"bank_encryption_public_key":"621028HG1M30JAM6923FE381040GA003G80GY01GG80GM0M2040G1EACATA11EF5SVKNBNBYF1S3WSKQ2A2R9VZ7RW2HRX00293JPZ7VQ780RFRVYTQKKDDNJAQGBH4659GT9QYBMJCG1RKZEH1WDJ0GAAY7B7NBMW6FWXCKFYRMZQME0WBGZ1AAMY2VBQ5XAFV8216EFNF2EPG6M5ZGHG9RG6EGED56TK9JESQ02Q7AAVBRAAARVBN9NHCN64KQ3SRRHYXB8RWRK4TSSC93XG8RWMQH4ZDJSBYDCEXFY6G3AWTZ0EZNCJJAYB98T4GNFWZMN81AVYCQHXT1APX81AXCAYNK7J9XETF5CN1J1WV0BVA2BYG4VAMAW123REPN67JF1TNWPTADBMHS17N2V1GFYT8JRWX4TGM2996NXTEPMA8C2CDDE0CRY2A6HT8C5H2D6C62YGRSCF820C0G008","bank_authentication_public_key":"621028HG1M30JAM6923FE381040GA003G80GY01GG80GM0M2040G1EACATA11EF5SVKNBNBYF1S3WSKQ2A2R9VZ7RW2HRX00293JPZ7VQ780RFRVYTQKKDDNJAQGBH4659GT9QYBMJCG1RKZEH1WDJ0GAAY7B7NBMW6FWXCKFYRMZQME0WBGZ1AAMY2VBQ5XAFV8216EFNF2EPG6M5ZGHG9RG6EGED56TK9JESQ02Q7AAVBRAAARVBN9NHCN64KQ3SRRHYXB8RWRK4TSSC93XG8RWMQH4ZDJSBYDCEXFY6G3AWTZ0EZNCJJAYB98T4GNFWZMN81AVYCQHXT1APX81AXCAYNK7J9XETF5CN1J1WV0BVA2BYG4VAMAW123REPN67JF1TNWPTADBMHS17N2V1GFYT8JRWX4TGM2996NXTEPMA8C2CDDE0CRY2A6HT8C5H2D6C62YGRSCF820C0G008","accepted":true}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
[
{
"operation": "exchange-enable-wire-0",
"arguments": {
"payto_uri": "payto://x-taler-bank/bank:8082/exchange?receiver-name=Exchange",
"debit_restrictions": [],
"credit_restrictions": [],
"priority": 0,
"validity_start": {
"t_s": 1725886541
},
"master_sig_add": "68WDT3JX1S5GQ9D3RZWXQVZK9AHFZ46YY5DA993720YA3SCBR4SW3X09NH5DECTXGWBKSN0MGKE1ANA9QZ95SKSNYPS9T9G46PCJC20",
"master_sig_wire": "39CEN9007DEXXMSDFZX1R2YYNANZYAFHX4EZC4ZX3C8DQEYT83JNVCVYMWYDGWEX6S891ZPXD6QHJE9J41YV9EN703Q0NM0MVE4FP18"
}
}
]
+1
View File
@@ -0,0 +1 @@
Ř'IŐ‚–v&©űľ˘¶ßH{VWýr¶CjÜ
@@ -0,0 +1,10 @@
[exchange-account-test]
PAYTO_URI = payto://x-taler-bank/bank:8082/exchange?receiver-name=Exchange
ENABLE_DEBIT = YES
ENABLE_CREDIT = YES
[exchange-accountcredentials-test]
WIRE_GATEWAY_URL = http://bank:8082/accounts/exchange/taler-wire-gateway/
WIRE_GATEWAY_AUTH_METHOD = BASIC
USERNAME = exchange
PASSWORD = exchange
@@ -0,0 +1,95 @@
[COIN-KUDOS-n1-t1726827661]
VALUE = KUDOS:0.1
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
[COIN-KUDOS-n2-t1726827661]
VALUE = KUDOS:0.2
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
[COIN-KUDOS-n3-t1726827661]
VALUE = KUDOS:0.4
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
[COIN-KUDOS-n4-t1726827661]
VALUE = KUDOS:0.8
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
[COIN-KUDOS-n5-t1726827661]
VALUE = KUDOS:1.6
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
[COIN-KUDOS-n6-t1726827661]
VALUE = KUDOS:3.2
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
[COIN-KUDOS-n7-t1726827661]
VALUE = KUDOS:6.4
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
[COIN-KUDOS-n8-t1726827661]
VALUE = KUDOS:12.8
DURATION_WITHDRAW = 7 days
DURATION_SPEND = 2 years
DURATION_LEGAL = 6 years
FEE_WITHDRAW = KUDOS:0
FEE_DEPOSIT = KUDOS:0
FEE_REFRESH = KUDOS:0
FEE_REFUND = KUDOS:0
RSA_KEYSIZE = 2048
CIPHER = RSA
+7
View File
@@ -0,0 +1,7 @@
{
system ? builtins.currentSystem,
pkgs ? import ../../.. { inherit system; },
}:
{
basic = import ./tests/basic.nix { inherit system pkgs; };
}
+270
View File
@@ -0,0 +1,270 @@
import ../../make-test-python.nix (
{ pkgs, lib, ... }:
let
cfgNodes = pkgs.callPackage ../common/nodes.nix { inherit lib; };
in
{
# NOTE: The Nexus conversion subtest requires internet access, so to run it
# you must run the test with:
# - nix run .#nixosTests.taler.basic.driver
# or interactively:
# - nix run .#nixosTests.taler.basic.driverInteractive
# - run_tests()
name = "GNU Taler Basic Test";
meta = {
maintainers = lib.teams.ngi.members;
};
# Taler components virtual-machine nodes
nodes = {
inherit (cfgNodes.nodes)
bank
client
exchange
merchant
;
};
# TODO: make tests for each component?
testScript =
{ nodes, ... }:
let
cfgScripts = pkgs.callPackage ../common/scripts.nix { inherit lib pkgs nodes; };
inherit (cfgNodes) CURRENCY FIAT_CURRENCY;
inherit (cfgScripts) commonScripts;
bankConfig = nodes.bank.config.environment.etc."libeufin/libeufin.conf".source;
bankSettings = nodes.bank.services.libeufin.settings.libeufin-bank;
nexusSettings = nodes.bank.services.libeufin.nexus.settings;
# Bank admin account credentials
AUSER = "admin";
APASS = "admin";
TUSER = "testUser";
TPASS = "testUser";
exchangeAccount = ../conf/exchange-account.json;
in
# python
''
import json
# import common scripts
${commonScripts}
# NOTE: start components up individually so they don't conflict before their setup is done
bank.start()
client.start()
bank.wait_for_open_port(8082)
with subtest("Set up Libeufin bank"):
# Modify admin account password, increase debit threshold
systemd_run(bank, 'libeufin-bank passwd -c "${bankConfig}" "${AUSER}" "${APASS}"', "libeufin-bank")
systemd_run(bank, 'libeufin-bank edit-account -c ${bankConfig} --debit_threshold="${bankSettings.CURRENCY}:1000000" ${AUSER}', "libeufin-bank")
# NOTE: the exchange is enabled before the bank starts using the `initialAccounts` option
# TODO: just use that option instead of this?
with subtest("Register bank accounts"):
# username, password, name
register_bank_account("testUser", "testUser", "User")
register_bank_account("merchant", "merchant", "Merchant")
exchange.start()
exchange.wait_for_open_port(8081)
with subtest("Set up exchange"):
exchange.wait_until_succeeds("taler-exchange-offline download sign upload")
# Enable exchange wire account
exchange.succeed('taler-exchange-offline upload < ${exchangeAccount}')
# NOTE: cannot deposit coins/pay merchant if wire fees are not set up
exchange.succeed('taler-exchange-offline wire-fee now x-taler-bank "${CURRENCY}:0" "${CURRENCY}:0" upload')
exchange.succeed('taler-exchange-offline global-fee now "${CURRENCY}:0" "${CURRENCY}:0" "${CURRENCY}:0" 1h 6a 0 upload')
# Verify that exchange keys exist
bank.succeed("curl -s http://exchange:8081/keys")
merchant.start()
merchant.wait_for_open_port(8083)
with subtest("Set up merchant"):
# Create default instance (similar to admin)
succeed(merchant, [
"curl -X POST",
"-H 'Authorization: Bearer secret-token:super_secret'",
"""
--data '{
"auth": { "method": "external" },
"id": "default",
"name": "default",
"user_type": "business",
"address": {},
"jurisdiction": {},
"use_stefan": true,
"default_wire_transfer_delay": { "d_us": 3600000000 },
"default_pay_delay": { "d_us": 3600000000 }
}'
""",
"-sSfL 'http://merchant:8083/management/instances'"
])
# Register bank account address
succeed(merchant, [
"curl -X POST",
"-H 'Content-Type: application/json'",
"""
--data '{
"payto_uri": "payto://x-taler-bank/bank:8082/merchant?receiver-name=Merchant",
"credit_facade_url": "http://bank:8082/accounts/merchant/taler-revenue/",
"credit_facade_credentials":{"type":"basic","username":"merchant","password":"merchant"}
}'
""",
"-sSfL 'http://merchant:8083/private/accounts'"
])
# Register a new product to be ordered
succeed(merchant, [
"curl -X POST",
"-H 'Content-Type: application/json'",
"""
--data '{
"product_id": "1",
"description": "Product with id 1 and price 1",
"price": "${CURRENCY}:1",
"total_stock": 20,
"unit": "packages",
"next_restock": { "t_s": "never" }
}'
""",
"-sSfL 'http://merchant:8083/private/products'"
])
client.succeed("curl -s http://exchange:8081/")
# Make a withdrawal from the CLI wallet
with subtest("Make a withdrawal from the CLI wallet"):
balanceWanted = "${CURRENCY}:10"
# Register exchange
with subtest("Register exchange"):
wallet_cli("exchanges add http://exchange:8081/")
wallet_cli("exchanges accept-tos http://exchange:8081/")
# Request withdrawal from the bank
withdrawal = json.loads(
succeed(client, [
"curl -X POST",
"-u ${TUSER}:${TPASS}",
"-H 'Content-Type: application/json'",
f"""--data '{{"amount": "{balanceWanted}"}}'""", # double brackets escapes them
"-sSfL 'http://bank:8082/accounts/${TUSER}/withdrawals'"
])
)
# Accept & confirm withdrawal
with subtest("Accept & confirm withdrawal"):
wallet_cli(f"withdraw accept-uri {withdrawal["taler_withdraw_uri"]} --exchange http://exchange:8081/")
succeed(client, [
"curl -X POST",
"-u ${TUSER}:${TPASS}",
"-H 'Content-Type: application/json'",
f"-sSfL 'http://bank:8082/accounts/${TUSER}/withdrawals/{withdrawal["withdrawal_id"]}/confirm'"
])
# Process transactions
wallet_cli("run-until-done")
verify_balance(balanceWanted)
with subtest("Pay for an order"):
balanceWanted = "${CURRENCY}:9" # after paying
# Create an order to be paid
response = json.loads(
succeed(merchant, [
"curl -X POST",
"-H 'Content-Type: application/json'",
"""
--data '{
"order": { "amount": "${CURRENCY}:1", "summary": "Test Order" },
"inventory_products": [{ "product_id": "1", "quantity": 1 }]
}'
""",
"-sSfL 'http://merchant:8083/private/orders'"
])
)
order_id = response["order_id"]
token = response["token"]
# Get order pay URI
response = json.loads(
succeed(merchant, [
"curl -sSfL",
f"http://merchant:8083/private/orders/{order_id}"
])
)
wallet_cli("run-until-done")
# Process transaction
wallet_cli(f"""handle-uri -y '{response["taler_pay_uri"]}'""")
wallet_cli("run-until-done")
verify_balance(balanceWanted)
# Only run Nexus conversion test if ebics server is available
(status, out) = bank.execute('curl -sSfL "${nexusSettings.nexus-ebics.HOST_BASE_URL}"')
if status != 0:
bank.log("Can't connect to ebics server. Skipping Nexus conversion subtest.")
else:
with subtest("Libeufin Nexus currency conversion"):
regionalWanted = "20"
# Setup Nexus ebics keys
systemd_run(bank, "libeufin-nexus ebics-setup -L debug -c /etc/libeufin/libeufin.conf", "libeufin-nexus")
# Set currency conversion rates (1:1)
succeed(bank, [
"curl -X POST",
"-H 'Content-Type: application/json'",
"-u ${AUSER}:${APASS}",
"""
--data '{
"cashin_ratio": "1",
"cashin_fee": "${CURRENCY}:0",
"cashin_tiny_amount": "${CURRENCY}:0.01",
"cashin_rounding_mode": "nearest",
"cashin_min_amount": "${FIAT_CURRENCY}:1",
"cashout_ratio": "1",
"cashout_fee": "${FIAT_CURRENCY}:0",
"cashout_tiny_amount": "${FIAT_CURRENCY}:0.01",
"cashout_rounding_mode": "nearest",
"cashout_min_amount": "${CURRENCY}:1"
}'
""",
"-sSfL 'http://bank:8082/conversion-info/conversion-rate'"
])
# Make fake transaction (we only need reservePub)
response = wallet_cli("""api 'acceptManualWithdrawal' '{ "exchangeBaseUrl":"http://exchange:8081/", "amount":"${CURRENCY}:5" }'""")
reservePub = json.loads(response)["result"]["reservePub"]
# Convert fiat currency to regional
systemd_run(bank, f"""libeufin-nexus testing fake-incoming -c ${bankConfig} --amount="${FIAT_CURRENCY}:{regionalWanted}" --subject="{reservePub}" "payto://iban/CH4740123RW4167362694" """, "libeufin-nexus")
wallet_cli("run-until-done")
verify_conversion(regionalWanted)
'';
}
)
+3 -3
View File
@@ -69,9 +69,9 @@ in rec {
unstable = fetchurl rec {
# NOTE: Don't forget to change the hash for staging as well.
version = "10.0-rc4";
version = "10.0-rc5";
url = "https://dl.winehq.org/wine/source/10.0/wine-${version}.tar.xz";
hash = "sha256-/oos3wn91MNBpew0ascvCyJN4L3Qp64J+RGwLpyvEAg=";
hash = "sha256-7IlPe1wH0tTCHVNNf0OUZnuO8ngH4w4hKJhpp02XbtI=";
inherit (stable) patches;
## see http://wiki.winehq.org/Gecko
@@ -117,7 +117,7 @@ in rec {
staging = fetchFromGitLab rec {
# https://gitlab.winehq.org/wine/wine-staging
inherit (unstable) version;
hash = "sha256-Hfpsi/XJOa7KmW1tEz8wibkM5SnskKMldNqjigRmmMs=";
hash = "sha256-no+yYF/xhy0kRfBqPer0UbpJNEh9LtKCmyVvhQB58K4=";
domain = "gitlab.winehq.org";
owner = "wine";
repo = "wine-staging";
+2 -2
View File
@@ -14,13 +14,13 @@
stdenv.mkDerivation (finalAttrs: {
pname = "albert";
version = "0.26.11";
version = "0.26.13";
src = fetchFromGitHub {
owner = "albertlauncher";
repo = "albert";
rev = "v${finalAttrs.version}";
hash = "sha256-rPQ6nxUT7qiuOgmmQKCrYHl4kKJODe+nw4VNGjF+n/g=";
hash = "sha256-p/8kCj9dN9x7gEvXnHGABL9Ab5zUJP5jI2L6AvCT8Qs=";
fetchSubmodules = true;
};
+19 -14
View File
@@ -49,13 +49,23 @@ stdenv.mkDerivation (finalAttrs: {
"man"
];
nativeBuildInputs = [
cmake
gtest
(lib.getBin libxslt)
pkg-config
triehash
];
nativeBuildInputs =
[
cmake
dpkg # dpkg-architecture
gettext # msgfmt
gtest
(lib.getBin libxslt)
pkg-config
triehash
perlPackages.perl
]
++ lib.optionals withDocs [
docbook_xml_dtd_45
doxygen
perlPackages.Po4a
w3m
];
buildInputs =
[
@@ -64,30 +74,25 @@ stdenv.mkDerivation (finalAttrs: {
db
dpkg
gnutls
gtest
libgcrypt
libgpg-error
libseccomp
libtasn1
lz4
p11-kit
perlPackages.perl
udev
xxHash
xz
zstd
]
++ lib.optionals withDocs [
docbook_xml_dtd_45
doxygen
perlPackages.Po4a
w3m
]
++ lib.optionals withNLS [
gettext
];
cmakeFlags = [
(lib.cmakeOptionType "filepath" "BERKELEY_INCLUDE_DIRS" "${lib.getDev db}/include")
(lib.cmakeOptionType "filepath" "DPKG_DATADIR" "${dpkg}/share/dpkg")
(lib.cmakeOptionType "filepath" "DOCBOOK_XSL" "${docbook_xsl}/share/xml/docbook-xsl")
(lib.cmakeOptionType "filepath" "GNUTLS_INCLUDE_DIR" "${lib.getDev gnutls}/include")
(lib.cmakeFeature "DROOT_GROUP" "root")
+122
View File
@@ -0,0 +1,122 @@
{
mkDerivation,
aeson,
aeson-pretty,
ansi-terminal,
attoparsec,
base,
bytestring,
clock,
containers,
criterion-measurement,
deepseq,
dlist,
filepath,
formatting,
hashable,
haxl,
hspec,
hspec-core,
hspec-expectations,
lib,
mtl,
network-uri,
optparse-applicative,
postgresql-libpq,
postgresql-simple,
QuickCheck,
random,
resourcet,
statistics,
streaming,
text,
time,
transformers,
typed-process,
unliftio,
unliftio-core,
unordered-containers,
uuid,
vector,
}:
mkDerivation {
pname = "codd";
version = "0.1.6";
src = ./.;
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [
aeson
aeson-pretty
ansi-terminal
attoparsec
base
bytestring
clock
containers
deepseq
dlist
filepath
formatting
hashable
haxl
mtl
network-uri
postgresql-libpq
postgresql-simple
resourcet
streaming
text
time
transformers
unliftio
unliftio-core
unordered-containers
vector
];
executableHaskellDepends = [
base
optparse-applicative
postgresql-simple
text
time
];
testHaskellDepends = [
aeson
attoparsec
base
containers
filepath
hashable
hspec
hspec-core
mtl
network-uri
postgresql-simple
QuickCheck
random
resourcet
streaming
text
time
typed-process
unliftio
uuid
];
benchmarkHaskellDepends = [
aeson
base
criterion-measurement
deepseq
hspec
hspec-core
hspec-expectations
statistics
streaming
text
vector
];
homepage = "https://github.com/mzabani/codd#readme";
license = lib.licenses.bsd3;
mainProgram = "codd";
}
+53
View File
@@ -0,0 +1,53 @@
{
lib,
fetchFromGitHub,
haskell,
haskellPackages,
}:
##############
# To upgrade codd you typically only need to change the version, revision and SHA hash
# in this very file.
# If codd's dependencies change, however, clone codd at https://github.com/mzabani/codd,
# checkout the desired tag and run `cabal2nix .` to produce and replace the generated.nix
# file. Finally, do change the version in this file.
##############
let
# Haxl has relatively tight version requirements and is thus often marked as broken.
haxlJailbroken = haskell.lib.markUnbroken (haskell.lib.doJailbreak haskellPackages.haxl);
generated = haskellPackages.callPackage ./generated.nix { haxl = haxlJailbroken; };
derivationWithVersion = haskell.lib.compose.overrideCabal (rec {
version = "0.1.6";
src = fetchFromGitHub {
owner = "mzabani";
repo = "codd";
rev = "refs/tags/v${version}";
hash = "sha256-KdZCL09TERy/PolQyYYykEbPtG5yhxrLZSSo9n6p2WE=";
};
# We only run codd's tests that don't require postgresql nor strace. We need to support unix sockets in codd's test suite
# before enabling postgresql's tests, and SystemResourcesSpecs might fail on macOS because of the need for strace and parsing
# libc calls. Not that we really gain much from running SystemResourcesSpecs here anyway.
testFlags = [
"--skip"
"/DbDependentSpecs/"
"--skip"
"/SystemResourcesSpecs/"
];
isLibrary = false;
testToolDepends = [ haskellPackages.hspec-discover ];
description = "CLI tool that applies postgres SQL migrations atomically with schema equality checks";
homepage = "https://github.com/mzabani/codd";
changelog = "https://github.com/mzabani/codd/releases/tag/v${version}";
maintainers = with lib.maintainers; [ mzabani ];
}) generated;
in
haskell.lib.compose.justStaticExecutables derivationWithVersion
+5 -1
View File
@@ -49,10 +49,14 @@ stdenv.mkDerivation rec {
for i in $(find . -name Makefile.in); do
substituteInPlace $i --replace "install-data-local:" "disabled:" ;
done
# Skip check broken when cross-compiling.
substituteInPlace configure \
--replace-fail 'as_fn_error $? "cannot find a GNU tar program"' "#"
'';
postPatch = ''
patchShebangs .
patchShebangs --host .
# Dpkg commands sometimes calls out to shell commands
substituteInPlace lib/dpkg/dpkg.h \
+11 -7
View File
@@ -3,17 +3,18 @@
buildGoModule,
fetchFromGitHub,
makeWrapper,
nixosTests,
}:
buildGoModule {
pname = "echoip";
version = "unstable-2021-08-03";
version = "unstable-2023-05-21";
src = fetchFromGitHub {
owner = "mpolden";
repo = "echoip";
rev = "ffa6674637a5bf906d78ae6675f9a4680a78ab7b";
sha256 = "sha256-yN7PIwoIi2SPwwFWnHDoXnwvKohkPPf4kVsNxHLpqCE=";
rev = "d84665c26cf7df612061e9c35abe325ba9d86b8d";
hash = "sha256-7qc1NZu0hC1np/EKf5fU5Cnd7ikC1+tIrYOXhxK/++Y=";
};
vendorHash = "sha256-lXYpkeGpBK+WGHqyLxJz7kS3t7a55q55QQLTqtxzroc=";
@@ -26,15 +27,18 @@ buildGoModule {
--add-flags "-t $out/share/echoip/html"
'';
doCheck = false;
passthru = {
tests = { inherit (nixosTests) echoip; };
};
meta = with lib; {
meta = {
description = "IP address lookup service";
homepage = "https://github.com/mpolden/echoip";
license = licenses.bsd3;
maintainers = with maintainers; [
license = lib.licenses.bsd3;
maintainers = with lib.maintainers; [
rvolosatovs
SuperSandro2000
defelo
];
mainProgram = "echoip";
};
+7 -1
View File
@@ -29,7 +29,13 @@ stdenv.mkDerivation rec {
done
'';
env.CFLAGS = lib.optionalString stdenv.cc.isClang "-Wno-return-type -Wno-error=implicit-function-declaration -Wno-error=implicit-int";
# lib.escapeShellArgs does not work
env.CFLAGS = lib.concatStringsSep " " [
"-Wno-error=implicit-function-declaration"
"-Wno-error=implicit-int"
"-Wno-error=return-mismatch"
"-Wno-error=incompatible-pointer-types"
];
doCheck = true;
@@ -4,6 +4,7 @@
fetchFromGitLab,
makeWrapper,
ocamlPackages,
fetchpatch,
}:
stdenv.mkDerivation (finalAttrs: {
@@ -18,6 +19,13 @@ stdenv.mkDerivation (finalAttrs: {
hash = "sha256-b4O48MQT3Neh8a1Z5wRgS701w6XrwpsbSMprlqTT+CE=";
};
patches = [
(fetchpatch {
url = "https://gitlab.inria.fr/synchrone/heptagon/-/commit/f10405e385ca25dc737727e0c210a44986929bf0.patch";
hash = "sha256-Sn55jEoRDYnEUg4SjuBDCNN4TNl2Dwn1fTjb9O8O1bo=";
})
];
strictDeps = true;
nativeBuildInputs = with ocamlPackages; [
@@ -1,60 +1,45 @@
{
mkDerivation,
fetchpatch,
stdenv,
fetchurl,
lib,
extra-cmake-modules,
kdoctools,
wrapGAppsHook3,
exiv2,
ffmpeg,
libkdcraw,
phonon,
libvlc,
kconfig,
kiconthemes,
kio,
kinit,
kpurpose,
kdePackages,
}:
mkDerivation rec {
stdenv.mkDerivation (finalAttrs: {
pname = "kphotoalbum";
version = "5.11.0";
version = "6.0.1";
src = fetchurl {
url = "mirror://kde/stable/${pname}/${version}/${pname}-${version}.tar.xz";
hash = "sha256-NWtOIHJXtc8PlltYbbp2YwDf/3QI3MdHNDX7WVQMig4=";
url = "mirror://kde/stable/kphotoalbum/${finalAttrs.version}/kphotoalbum-${finalAttrs.version}.tar.xz";
hash = "sha256-LLsQ66wKDg77nZUIxjcfzvC3AwLOtojuuDgkJm2dsww=";
};
# Fix build against exiv2 0.28.1
patches = [
(fetchpatch {
url = "https://invent.kde.org/graphics/kphotoalbum/-/commit/1ceb1ae37f3f95aa290b0846969af4b26f616760.patch";
hash = "sha256-SfBJHyJZcysvemc/F09GPczBjcofxGomgjJ814PSU+c=";
})
];
env.LANG = "C.UTF-8";
# not sure if we really need phonon when we have vlc, but on KDE it's bound to
# be on the system anyway, so there is no real harm including it
buildInputs = [
kdePackages.qtbase
exiv2
phonon
libvlc
];
nativeBuildInputs = [
extra-cmake-modules
kdoctools
wrapGAppsHook3
kdePackages.wrapQtAppsHook
];
propagatedBuildInputs = [
# not sure if we really need phonon when we have vlc, but on KDE it's bound to
# be on the system anyway, so there is no real harm including it
propagatedBuildInputs = with kdePackages; [
kconfig
kiconthemes
kio
kinit
kpurpose
kxmlgui
phonon
purpose
libkdcraw
];
@@ -67,6 +52,6 @@ mkDerivation rec {
homepage = "https://www.kphotoalbum.org/";
license = licenses.gpl2Plus;
maintainers = with maintainers; [ peterhoeg ];
inherit (kconfig.meta) platforms;
inherit (kdePackages.kconfig.meta) platforms;
};
}
})
+66 -42
View File
@@ -1,57 +1,72 @@
{
lib,
stdenv,
fetchurl,
fetchFromGitHub,
buildNpmPackage,
electron,
makeWrapper,
testers,
mattermost-desktop,
nix-update-script,
}:
let
buildNpmPackage rec {
pname = "mattermost-desktop";
version = "5.9.0";
version = "5.10.2";
srcs = {
"x86_64-linux" = {
url = "https://releases.mattermost.com/desktop/${version}/${pname}-${version}-linux-x64.tar.gz";
hash = "sha256-zLKdfu5p7TyJOw8vJX7i/uu4j0PrUf2/BDmb1kdqqMc=";
};
"aarch64-linux" = {
url = "https://releases.mattermost.com/desktop/${version}/${pname}-${version}-linux-arm64.tar.gz";
hash = "sha256-JljK7d4KLAn1+NwF+VcedL/7hEsp/9LzLdzROa1fgJA=";
};
src = fetchFromGitHub {
owner = "mattermost";
repo = "desktop";
tag = "v${version}";
hash = "sha256-LHjVmrsOdk8vfsqvNEWkzpusm6jbz3SOb3bEaIb7rb4=";
};
inherit (stdenv.hostPlatform) system;
in
stdenv.mkDerivation {
inherit pname version;
src = fetchurl (srcs."${system}" or (throw "Unsupported system ${system}"));
npmDepsHash = "sha256-LAbqsMdMmmHGgvg2ilz6neQxMOK3jtCKt8K0M8BWifs=";
npmBuildScript = "build-prod";
makeCacheWritable = true;
nativeBuildInputs = [ makeWrapper ];
env.ELECTRON_SKIP_BINARY_DOWNLOAD = "1";
postPatch = ''
substituteInPlace webpack.config.base.js \
--replace-fail \
"const VERSION = childProcess.execSync('git rev-parse --short HEAD', {cwd: __dirname}).toString();" \
"const VERSION = process.env.version;"
'';
postBuild = ''
# electronDist needs to be writable
cp -r ${electron.dist} electron-dist
chmod -R u+w electron-dist
npm exec electron-builder -- \
--config electron-builder.json \
--dir \
-c.electronDist=electron-dist \
-c.electronVersion=${electron.version}
'';
installPhase = ''
runHook preInstall
# Mattermost tarball comes with executable bit set for everything.
# Well apply it only to files that need it.
find . -type f -print0 | xargs -0 chmod -x
find . -type f \( -name '*.so.*' -o -name '*.s[oh]' \) -print0 | xargs -0 chmod +x
chmod +x mattermost-desktop chrome-sandbox
mkdir --parents \
$out/bin \
$out/share/applications \
$out/share/icons/hicolor/512x512/apps
mkdir -p $out/bin $out/share/applications $out/share/${pname}/
cp -r app_icon.png create_desktop_file.sh locales/ resources/* $out/share/${pname}/
readonly dist=release/linux-unpacked
patchShebangs $out/share/${pname}/create_desktop_file.sh
$out/share/${pname}/create_desktop_file.sh
rm $out/share/${pname}/create_desktop_file.sh
mv Mattermost.desktop $out/share/applications/Mattermost.desktop
cp -a $dist/resources $out/share/${pname}
patchShebangs $dist/create_desktop_file.sh
$dist/create_desktop_file.sh
mv Mattermost.desktop $out/share/applications/
substituteInPlace $out/share/applications/Mattermost.desktop \
--replace /share/mattermost-desktop/mattermost-desktop /bin/mattermost-desktop
--replace-fail /build/source/$dist/app_icon.png ${pname} \
--replace-fail /build/source/$dist/ $out/bin/
cp src/assets/linux/app_icon.png $out/share/icons/hicolor/512x512/apps/${pname}.png
makeWrapper '${lib.getExe electron}' $out/bin/${pname} \
--set-default ELECTRON_IS_DEV 0 \
@@ -61,16 +76,25 @@ stdenv.mkDerivation {
runHook postInstall
'';
meta = with lib; {
passthru = {
tests.version = testers.testVersion {
package = mattermost-desktop;
# Invoking with `--version` insists on being able to write to a log file.
command = "env HOME=/tmp ${meta.mainProgram} --version";
};
updateScript = nix-update-script { };
};
meta = {
description = "Mattermost Desktop client";
mainProgram = "mattermost-desktop";
homepage = "https://about.mattermost.com/";
sourceProvenance = with sourceTypes; [ binaryNativeCode ];
license = licenses.asl20;
platforms = [
"x86_64-linux"
"aarch64-linux"
changelog = "https://github.com/mattermost/desktop/releases/tag/${src.tag}";
license = lib.licenses.asl20;
platforms = electron.meta.platforms;
maintainers = with lib.maintainers; [
joko
liff
];
maintainers = [ maintainers.joko ];
};
}
+15 -7
View File
@@ -6,7 +6,6 @@
nix-update-script,
npm-lockfile-fix,
fetchNpmDeps,
diffutils,
jq,
nixosTests,
}:
@@ -94,7 +93,7 @@ buildGoModule rec {
runHook preInstall
mkdir -p $out
cp -r channels/dist/* $out
cp -a channels/dist/* $out
runHook postInstall
'';
@@ -123,11 +122,20 @@ buildGoModule rec {
];
postInstall = ''
mkdir -p $out/{client,i18n,fonts,templates,config}
cp -r ${webapp}/* $out/client/
cp -r ${src}/server/i18n/* $out/i18n/
cp -r ${src}/server/fonts/* $out/fonts/
cp -r ${src}/server/templates/* $out/templates/
shopt -s extglob
mkdir -p $out/{i18n,fonts,templates,config}
# Link in the client and copy the language packs.
ln -sf $webapp $out/client
cp -a $src/server/i18n/* $out/i18n/
# Fonts have the execute bit set, remove it.
cp --no-preserve=mode $src/server/fonts/* $out/fonts/
# Don't copy the Makefile.
cp -a $src/server/templates/!(Makefile) $out/templates/
# Generate the config.
OUTPUT_CONFIG=$out/config/config.json \
go run -tags production ./scripts/config_generator
'';
+3 -3
View File
@@ -6,16 +6,16 @@
buildGoModule rec {
pname = "mieru";
version = "3.10.0";
version = "3.11.0";
src = fetchFromGitHub {
owner = "enfein";
repo = "mieru";
rev = "v${version}";
hash = "sha256-4uJi8+kpVBjigTkLmV9fL0igmcOt5Gb40qkQHYR8kCU=";
hash = "sha256-xwi9T7M4FEl79kyGj+F1HX8000PFLrBfTmnEaLwnEFg=";
};
vendorHash = "sha256-hSTKhn39xKZx1N9x66EH/ql4oP4qn0eysGTbUk9mRAk=";
vendorHash = "sha256-AOtq6bGijQqpNMNZA3XeMjzKAo7tWTpdrKB6KxQsdMM=";
proxyVendor = true;
ldflags = [
+2 -2
View File
@@ -7,13 +7,13 @@
python3Packages.buildPythonApplication rec {
pname = "nvitop";
version = "1.4.0";
version = "1.4.1";
src = fetchFromGitHub {
owner = "XuehaiPan";
repo = "nvitop";
tag = "v${version}";
hash = "sha256-Z0JGW7vcZFxguQqhqhpPpOvcOct7B9z8RoEFu5NsOl0=";
hash = "sha256-H5WfSGQpShmJGffGMIejs0A9ksht43I1d3BvXbvP6vI=";
};
pythonRelaxDeps = [ "nvidia-ml-py" ];
+5 -14
View File
@@ -3,11 +3,10 @@
stdenv,
rustPlatform,
fetchFromGitHub,
fetchpatch,
pkg-config,
installShellFiles,
libgit2,
openssl,
installShellFiles,
buildPackages,
versionCheckHook,
nix-update-script,
@@ -15,26 +14,17 @@
rustPlatform.buildRustPackage rec {
pname = "pixi";
version = "0.39.5";
version = "0.40.0";
src = fetchFromGitHub {
owner = "prefix-dev";
repo = "pixi";
tag = "v${version}";
hash = "sha256-Y4d8eMfsag2cNTaK8qnOGfi35kwwPrUy2y51EwVFrss=";
hash = "sha256-LuRnPG8vag8SNSChZlWBBavxAlLRk1P73N+VpO0SeTA=";
};
# TODO: Remove this patch when the next version is released.
cargoPatches = [
(fetchpatch {
# chore: make sure we only build one version of version-ranges
# https://github.com/prefix-dev/pixi/commit/82fc219be3f5d1499922e89a5c458b7c154a7b8e
url = "https://github.com/prefix-dev/pixi/commit/82fc219be3f5d1499922e89a5c458b7c154a7b8e.patch";
hash = "sha256-fKDqUJtjxIQsCez95RObnJHQvdlxhmjJ+G7fJitE6v0=";
})
];
useFetchCargoVendor = true;
cargoHash = "sha256-oGlPxFwJVpBajJQ5XED98SUP8qw312nUSRND6ycEOjk=";
cargoHash = "sha256-I3TnZ9ZHU4TUOUkBIeeRjP+sc/k2qVNtltzkyN87aZo=";
nativeBuildInputs = [
pkg-config
@@ -77,6 +67,7 @@ rustPlatform.buildRustPackage rec {
meta = {
description = "Package management made easy";
homepage = "https://pixi.sh/";
changelog = "https://pixi.sh/latest/CHANGELOG";
license = lib.licenses.bsd3;
maintainers = with lib.maintainers; [
aaronjheng
@@ -34,13 +34,13 @@ assert lib.assertMsg (
stdenv.mkDerivation (finalAttrs: {
pname = "prismlauncher-unwrapped";
version = "9.1";
version = "9.2";
src = fetchFromGitHub {
owner = "PrismLauncher";
repo = "PrismLauncher";
tag = finalAttrs.version;
hash = "sha256-LVrWFBsI4+BOY5hlevfzqfRXQM6AFd5bMnXbBqTrxzA=";
hash = "sha256-0KDhX8mfh11pyYQS/lB6qlUvRSOcYEbQKgsdQVA+Q3U=";
};
postUnpack = ''
+13 -9
View File
@@ -11,7 +11,7 @@
libX11,
libdrm,
libgbm,
vaapiSupport ? true,
vaapiSupport ? !stdenv.hostPlatform.isDarwin,
libva,
gitUpdater,
}:
@@ -27,13 +27,17 @@ stdenv.mkDerivation rec {
separateDebugInfo = true;
buildInputs = [
libGLU
libepoxy
libX11
libdrm
libgbm
] ++ lib.optionals vaapiSupport [ libva ];
buildInputs =
[
libepoxy
]
++ lib.optionals vaapiSupport [ libva ]
++ lib.optionals stdenv.hostPlatform.isLinux [
libGLU
libX11
libdrm
libgbm
];
nativeBuildInputs = [
meson
@@ -58,7 +62,7 @@ stdenv.mkDerivation rec {
mainProgram = "virgl_test_server";
homepage = "https://virgil3d.github.io/";
license = licenses.mit;
platforms = platforms.linux;
platforms = platforms.unix;
maintainers = [ maintainers.xeji ];
};
}
+2
View File
@@ -33,6 +33,8 @@ stdenv.mkDerivation rec {
./0001-Fix-build-for-glibc-2.32.patch
];
NIX_CFLAGS_COMPILE = "-Wno-error=implicit-function-declaration";
buildInputs = [
ncurses
libjpeg
+2 -2
View File
@@ -17,13 +17,13 @@ python3Packages.buildPythonApplication rec {
# The websites yt-dlp deals with are a very moving target. That means that
# downloads break constantly. Because of that, updates should always be backported
# to the latest stable release.
version = "2024.12.23";
version = "2025.1.12";
pyproject = true;
src = fetchPypi {
inherit version;
pname = "yt_dlp";
hash = "sha256-rA5ytakBe6EEtCWFRiAafO3DjovSByfgxjt3yCm0Jek=";
hash = "sha256-jn4kbipaLP8KnBPbRoRKN6VHaAcCASBYyU7Bj84Molo=";
};
build-system = with python3Packages; [
@@ -0,0 +1,88 @@
{
lib,
stdenv,
fetchFromGitHub,
glib,
wrapGAppsHook3,
gobject-introspection,
meson,
pkg-config,
ninja,
vala,
wayland,
wayland-scanner,
python3,
}:
let
cleanArgs = lib.flip builtins.removeAttrs [
"name"
"sourceRoot"
"nativeBuildInputs"
"buildInputs"
"website-path"
"meta"
];
buildAstalModule =
{
name,
sourceRoot ? "lib/${name}",
nativeBuildInputs ? [ ],
buildInputs ? [ ],
website-path ? name,
meta ? { },
...
}@args:
stdenv.mkDerivation (
finalAttrs:
cleanArgs args
// {
pname = "astal-${name}";
version = "0-unstable-2025-01-12";
__structuredAttrs = true;
strictDeps = true;
src = fetchFromGitHub {
owner = "Aylur";
repo = "astal";
rev = "6fd7ae514af36ff9baf1209a2eeebd3a26cf94ce";
hash = "sha256-IjLW96gjrCAjx/QZOvYyNpoeb53bkOJ6dDQt8ubaMMY=";
};
sourceRoot = "${finalAttrs.src.name}/${sourceRoot}";
nativeBuildInputs = nativeBuildInputs ++ [
wrapGAppsHook3
gobject-introspection
meson
pkg-config
ninja
vala
wayland
wayland-scanner
python3
];
buildInputs = [ glib ] ++ buildInputs;
meta = {
homepage = "https://aylur.github.io/astal/guide/libraries/${website-path}";
license = lib.licenses.lgpl21;
maintainers = with lib.maintainers; [ perchun ];
platforms = [
"aarch64-linux"
"x86_64-linux"
];
} // meta;
}
);
in
args:
# to support (finalAttrs: {...})
if builtins.typeOf args == "function" then
buildAstalModule (lib.fix args)
else
buildAstalModule args
@@ -0,0 +1,23 @@
{ wireplumber }:
self: {
buildAstalModule = self.callPackage ./buildAstalModule.nix { };
apps = self.callPackage ./modules/apps.nix { };
astal3 = self.callPackage ./modules/astal3.nix { };
astal4 = self.callPackage ./modules/astal4.nix { };
auth = self.callPackage ./modules/auth.nix { };
battery = self.callPackage ./modules/battery.nix { };
bluetooth = self.callPackage ./modules/bluetooth.nix { };
cava = self.callPackage ./modules/cava.nix { };
gjs = self.callPackage ./modules/gjs.nix { };
greet = self.callPackage ./modules/greet.nix { };
hyprland = self.callPackage ./modules/hyprland.nix { };
io = self.callPackage ./modules/io.nix { };
mpris = self.callPackage ./modules/mpris.nix { };
network = self.callPackage ./modules/network.nix { };
notifd = self.callPackage ./modules/notifd.nix { };
powerprofiles = self.callPackage ./modules/powerprofiles.nix { };
river = self.callPackage ./modules/river.nix { };
tray = self.callPackage ./modules/tray.nix { };
wireplumber = self.callPackage ./modules/wireplumber.nix { inherit wireplumber; };
}
@@ -0,0 +1,9 @@
{
buildAstalModule,
json-glib,
}:
buildAstalModule {
name = "apps";
buildInputs = [ json-glib ];
meta.description = "Astal module for application query";
}
@@ -0,0 +1,16 @@
{
buildAstalModule,
gtk3,
gtk-layer-shell,
io,
}:
buildAstalModule {
name = "astal3";
sourceRoot = "lib/astal/gtk3";
buildInputs = [ io ];
propagatedBuildInputs = [
gtk3
gtk-layer-shell
];
meta.description = "Astal module for GTK3 widgets";
}
@@ -0,0 +1,16 @@
{
buildAstalModule,
gtk4,
gtk4-layer-shell,
io,
}:
buildAstalModule {
name = "astal4";
sourceRoot = "lib/astal/gtk4";
buildInputs = [
io
gtk4
gtk4-layer-shell
];
meta.description = "Astal module for GTK4 widgets";
}
@@ -0,0 +1,9 @@
{
buildAstalModule,
pam,
}:
buildAstalModule {
name = "auth";
buildInputs = [ pam ];
meta.description = "Astal module for authentication using pam";
}
@@ -0,0 +1,9 @@
{
buildAstalModule,
json-glib,
}:
buildAstalModule {
name = "battery";
buildInputs = [ json-glib ];
meta.description = "Astal module for upowerd devices (DBus proxy)";
}
@@ -0,0 +1,5 @@
{ buildAstalModule }:
buildAstalModule {
name = "bluetooth";
meta.description = "Astal module for bluez using DBus";
}
@@ -0,0 +1,6 @@
{ buildAstalModule }:
buildAstalModule {
name = "cava";
meta.description = "Astal module for audio visualization using cava";
meta.broken = true; # https://github.com/NixOS/nixpkgs/pull/368312
}
@@ -0,0 +1,27 @@
{
buildAstalModule,
astal3,
io,
meson,
ninja,
pkg-config,
}:
(buildAstalModule {
name = "gjs";
sourceRoot = "lang/gjs";
meta.description = "Astal module for GJS";
}).overrideAttrs
{
# Remove all unused here inputs
nativeBuildInputs = [
meson
ninja
pkg-config
];
buildInputs = [
astal3
io
];
propagatedBuildInputs = [ ];
}
@@ -0,0 +1,6 @@
{ buildAstalModule, json-glib }:
buildAstalModule {
name = "greet";
buildInputs = [ json-glib ];
meta.description = "Astal module for greetd using IPC";
}
@@ -0,0 +1,6 @@
{ buildAstalModule, json-glib }:
buildAstalModule {
name = "hyprland";
buildInputs = [ json-glib ];
meta.description = "Astal module for Hyprland using IPC";
}
@@ -0,0 +1,11 @@
{ buildAstalModule, nix-update-script }:
(buildAstalModule {
name = "io";
sourceRoot = "lib/astal/io";
meta.description = "Astal core library";
}).overrideAttrs
{
# add an update script only in one place,
# so r-ryantm won't run it multiple times
passthru.updateScript = nix-update-script { extraArgs = [ "--version=branch" ]; };
}
@@ -0,0 +1,13 @@
{
buildAstalModule,
gvfs,
json-glib,
}:
buildAstalModule {
name = "mpris";
buildInputs = [
gvfs
json-glib
];
meta.description = "Astal module for mpris players";
}
@@ -0,0 +1,6 @@
{ buildAstalModule, networkmanager }:
buildAstalModule {
name = "network";
buildInputs = [ networkmanager ];
meta.description = "Astal module for NetworkManager";
}
@@ -0,0 +1,13 @@
{
buildAstalModule,
json-glib,
gdk-pixbuf,
}:
buildAstalModule {
name = "notifd";
buildInputs = [
json-glib
gdk-pixbuf
];
meta.description = "Astal module for notification daemon";
}
@@ -0,0 +1,6 @@
{ buildAstalModule, json-glib }:
buildAstalModule {
name = "powerprofiles";
buildInputs = [ json-glib ];
meta.description = "Astal module for upowerd profiles using DBus";
}
@@ -0,0 +1,12 @@
{ buildAstalModule, json-glib }:
buildAstalModule {
name = "river";
buildInputs = [ json-glib ];
meta.description = "Astal module for River using IPC";
postUnpack = ''
rm -rf $sourceRoot/subprojects
mkdir -p $sourceRoot/subprojects
cp -r --remove-destination $src/lib/wayland-glib $sourceRoot/subprojects/wayland-glib
'';
}
@@ -0,0 +1,10 @@
{
buildAstalModule,
json-glib,
}:
buildAstalModule {
name = "tray";
buildInputs = [ json-glib ];
meta.description = "Astal module for StatusNotifierItem";
meta.broken = true; # https://github.com/NixOS/nixpkgs/issues/337630
}
@@ -0,0 +1,6 @@
{ buildAstalModule, wireplumber }:
buildAstalModule {
name = "wireplumber";
buildInputs = [ wireplumber ];
meta.description = "Astal module for wireplumber";
}
@@ -4,40 +4,34 @@
fetchFromGitHub,
qmake,
qtbase,
protobuf,
}:
stdenv.mkDerivation rec {
pname = "qtpbfimageplugin";
version = "3.2";
version = "4.0";
src = fetchFromGitHub {
owner = "tumic0";
repo = "QtPBFImagePlugin";
rev = version;
sha256 = "sha256-RbGVjwVIwO6Rj/hbNEowtZLqJdtkTfnq5YdnEYnbkTM=";
tag = version;
hash = "sha256-17mQ7aTpZhmsoAHhnueHSRTvCIHRcpWwZHZM+YUdeps=";
};
nativeBuildInputs = [ qmake ];
nativeBuildInputs = [
qmake
];
buildInputs = [
qtbase
protobuf
];
dontWrapQtApps = true;
postPatch =
''
# Fix plugin dir
substituteInPlace pbfplugin.pro \
--replace "\$\$[QT_INSTALL_PLUGINS]" "$out/$qtPluginPrefix"
''
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
# Fix darwin build
substituteInPlace pbfplugin.pro \
--replace '$$PROTOBUF/include' '${protobuf}/include' \
--replace '$$PROTOBUF/lib/libprotobuf-lite.a' '${protobuf}/lib/libprotobuf-lite.dylib'
'';
postPatch = ''
# Fix plugin dir
substituteInPlace pbfplugin.pro \
--replace "\$\$[QT_INSTALL_PLUGINS]" "$out/$qtPluginPrefix"
'';
meta = with lib; {
description = "Qt image plugin for displaying Mapbox vector tiles";
@@ -7,30 +7,34 @@
camlp4,
}:
stdenv.mkDerivation rec {
pname = "ocaml-config-file";
version = "1.2";
lib.throwIf (lib.versionAtLeast ocaml.version "5.0")
"config-file is not available for OCaml ${ocaml.version}"
src = fetchurl {
url = "https://forge.ocamlcore.org/frs/download.php/1387/config-file-${version}.tar.gz";
sha256 = "1b02yxcnsjhr05ssh2br2ka4hxsjpdw34ldl3nk33wfnkwk7g67q";
};
stdenv.mkDerivation
rec {
pname = "ocaml-config-file";
version = "1.2";
nativeBuildInputs = [
ocaml
findlib
camlp4
];
src = fetchurl {
url = "https://forge.ocamlcore.org/frs/download.php/1387/config-file-${version}.tar.gz";
sha256 = "1b02yxcnsjhr05ssh2br2ka4hxsjpdw34ldl3nk33wfnkwk7g67q";
};
strictDeps = true;
nativeBuildInputs = [
ocaml
findlib
camlp4
];
createFindlibDestdir = true;
strictDeps = true;
meta = {
homepage = "http://config-file.forge.ocamlcore.org/";
platforms = ocaml.meta.platforms or [ ];
description = "OCaml library used to manage the configuration file(s) of an application";
license = lib.licenses.lgpl2Plus;
maintainers = with lib.maintainers; [ vbgl ];
};
}
createFindlibDestdir = true;
meta = {
homepage = "http://config-file.forge.ocamlcore.org/";
platforms = ocaml.meta.platforms or [ ];
description = "OCaml library used to manage the configuration file(s) of an application";
license = lib.licenses.lgpl2Plus;
maintainers = with lib.maintainers; [ vbgl ];
};
}
+34 -30
View File
@@ -23,39 +23,43 @@ let
};
in
stdenv.mkDerivation rec {
name = "ocaml${ocaml.version}-${pname}-${version}";
inherit (param) version;
lib.throwIf (lib.versionAtLeast ocaml.version "5.0")
"ulex is not available for OCaml ${ocaml.version}"
src = fetchFromGitHub {
owner = "whitequark";
repo = pname;
rev = "v${version}";
inherit (param) sha256;
};
stdenv.mkDerivation
rec {
name = "ocaml${ocaml.version}-${pname}-${version}";
inherit (param) version;
createFindlibDestdir = true;
src = fetchFromGitHub {
owner = "whitequark";
repo = pname;
rev = "v${version}";
inherit (param) sha256;
};
nativeBuildInputs = [
ocaml
findlib
ocamlbuild
camlp4
];
propagatedBuildInputs = [ camlp4 ];
createFindlibDestdir = true;
strictDeps = true;
nativeBuildInputs = [
ocaml
findlib
ocamlbuild
camlp4
];
propagatedBuildInputs = [ camlp4 ];
buildFlags = [
"all"
"all.opt"
];
strictDeps = true;
meta = {
inherit (src.meta) homepage;
description = "Lexer generator for Unicode and OCaml";
license = lib.licenses.mit;
inherit (ocaml.meta) platforms;
maintainers = [ lib.maintainers.roconnor ];
};
}
buildFlags = [
"all"
"all.opt"
];
meta = {
inherit (src.meta) homepage;
description = "Lexer generator for Unicode and OCaml";
license = lib.licenses.mit;
inherit (ocaml.meta) platforms;
maintainers = [ lib.maintainers.roconnor ];
};
}
@@ -1,67 +0,0 @@
{
lib,
buildPythonPackage,
pythonOlder,
fetchFromGitHub,
setuptools,
aesara,
numpy,
scipy,
numdifftools,
pytestCheckHook,
}:
buildPythonPackage rec {
pname = "aeppl";
version = "0.1.5";
pyproject = true;
disabled = pythonOlder "3.8";
src = fetchFromGitHub {
owner = "aesara-devs";
repo = "aeppl";
rev = "refs/tags/v${version}";
hash = "sha256-mqBbXwWJwQA2wSHuEdBeXQMfTIcgwYEjpq8AVmOjmHM=";
};
build-system = [ setuptools ];
dependencies = [
aesara
numpy
scipy
];
nativeCheckInputs = [
numdifftools
pytestCheckHook
];
preCheck = ''
export HOME=$(mktemp -d);
'';
pythonImportsCheck = [ "aeppl" ];
disabledTests = [
# Compute issue
"test_initial_values"
];
pytestFlagsArray = [
# `numpy.distutils` is deprecated since NumPy 1.23.0, as a result of the deprecation of `distutils` itself.
# It will be removed for Python >= 3.12. For older Python versions it will remain present.
"-Wignore::DeprecationWarning"
# Blas cannot be found, allow fallback to the numpy slower implementation
"-Wignore::UserWarning"
];
meta = with lib; {
description = "Library for an Aesara-based PPL";
homepage = "https://github.com/aesara-devs/aeppl";
changelog = "https://github.com/aesara-devs/aeppl/releases/tag/v${version}";
license = licenses.mit;
maintainers = with maintainers; [ fab ];
};
}
@@ -1,113 +0,0 @@
{
lib,
stdenv,
buildPythonPackage,
cons,
cython,
etuples,
fetchFromGitHub,
filelock,
hatch-vcs,
hatchling,
jax,
jaxlib,
logical-unification,
minikanren,
numba,
numba-scipy,
numpy,
pytestCheckHook,
pythonAtLeast,
pythonOlder,
scipy,
typing-extensions,
}:
buildPythonPackage rec {
pname = "aesara";
version = "2.9.4";
pyproject = true;
# Python 3.12 is not supported: https://github.com/aesara-devs/aesara/issues/1520
disabled = pythonOlder "3.8" || pythonAtLeast "3.12";
src = fetchFromGitHub {
owner = "aesara-devs";
repo = "aesara";
rev = "refs/tags/rel-${version}";
hash = "sha256-V34uP50TfH6cLU7nWOx+8oXY1QawtaoIaKQpbLnz7eo=";
};
build-system = [
cython
hatch-vcs
hatchling
];
dependencies = [
cons
etuples
filelock
logical-unification
minikanren
numpy
scipy
typing-extensions
];
nativeCheckInputs = [
jax
jaxlib
numba
numba-scipy
pytestCheckHook
];
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "--durations=50" "" \
--replace-fail "hatch-vcs >=0.3.0,<0.4.0" "hatch-vcs"
'';
preBuild = ''
export HOME=$(mktemp -d)
'';
pythonImportsCheck = [ "aesara" ];
disabledTestPaths = [
# Don't run the most compute-intense tests
"tests/scan/"
"tests/tensor/"
"tests/sandbox/"
"tests/sparse/sandbox/"
# JAX is not available on all platform and often broken
"tests/link/jax/"
# 2024-04-27: The current nixpkgs numba version is too recent and incompatible with aesara 2.9.3
"tests/link/numba/"
];
disabledTests = [
# Disable all benchmark tests
"test_scan_multiple_output"
"test_logsumexp_benchmark"
# TypeError: exceptions must be derived from Warning, not <class 'NoneType'>
"test_api_deprecation_warning"
# AssertionError: assert ['Elemwise{Co..._i{0} 0', ...] == ['Elemwise{Co..._i{0} 0', ...]
# At index 3 diff: '| |Gemv{inplace} d={0: [0]} 2' != '| |CGemv{inplace} d={0: [0]} 2'
"test_debugprint"
# ValueError: too many values to unpack (expected 3)
"test_ExternalCOp_c_code_cache_version"
];
meta = with lib; {
description = "Python library to define, optimize, and efficiently evaluate mathematical expressions involving multi-dimensional arrays";
homepage = "https://github.com/aesara-devs/aesara";
changelog = "https://github.com/aesara-devs/aesara/releases/tag/rel-${version}";
license = licenses.bsd3;
maintainers = with maintainers; [ Etjean ];
broken = (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isAarch64);
};
}
@@ -12,7 +12,6 @@
freezegun,
pytest-mock,
pytestCheckHook,
tornado_4,
}:
buildPythonPackage rec {
@@ -38,7 +37,7 @@ buildPythonPackage rec {
freezegun
pytest-mock
pytestCheckHook
] ++ lib.optionals (pythonOlder "3.10") [ tornado_4 ];
];
disabledTests =
[
@@ -51,7 +50,7 @@ buildPythonPackage rec {
"test_that_on_ping_responds_with_pong"
];
disabledTestPaths = lib.optionals (pythonAtLeast "3.10") [
disabledTestPaths = [
# requires tornado_4, which is not compatible with python3.10
"tests/test_integration.py"
];
@@ -1,42 +0,0 @@
{
lib,
unittestCheckHook,
buildPythonPackage,
fetchPypi,
fetchpatch,
isPy27,
pythonAtLeast,
}:
buildPythonPackage rec {
pname = "tornado";
version = "4.5.3";
disabled = isPy27 || pythonAtLeast "3.10";
src = fetchPypi {
inherit pname version;
sha256 = "02jzd23l4r6fswmwxaica9ldlyc2p6q8dk6dyff7j58fmdzf853d";
};
patches = [
(fetchpatch {
name = "CVE-2023-28370.patch";
url = "https://github.com/tornadoweb/tornado/commit/32ad07c54e607839273b4e1819c347f5c8976b2f.patch";
hash = "sha256-2dpPHkNThOaZD8T2g1vb/I5WYZ/vy/t690539uprJyc=";
})
];
nativeCheckInputs = [ unittestCheckHook ];
# We specify the name of the test files to prevent
# https://github.com/NixOS/nixpkgs/issues/14634
unittestFlagsArray = [ "*_test.py" ];
__darwinAllowLocalNetworking = true;
meta = {
description = "Web framework and asynchronous networking library";
homepage = "https://www.tornadoweb.org/";
license = lib.licenses.asl20;
};
}
@@ -1,42 +0,0 @@
{
lib,
unittestCheckHook,
buildPythonPackage,
fetchPypi,
fetchpatch,
isPy27,
pythonAtLeast,
}:
buildPythonPackage rec {
pname = "tornado";
version = "5.1.1";
disabled = isPy27 || pythonAtLeast "3.10";
src = fetchPypi {
inherit pname version;
sha256 = "4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409";
};
patches = [
(fetchpatch {
name = "CVE-2023-28370.patch";
url = "https://github.com/tornadoweb/tornado/commit/32ad07c54e607839273b4e1819c347f5c8976b2f.patch";
hash = "sha256-2dpPHkNThOaZD8T2g1vb/I5WYZ/vy/t690539uprJyc=";
})
];
nativeCheckInputs = [ unittestCheckHook ];
# We specify the name of the test files to prevent
# https://github.com/NixOS/nixpkgs/issues/14634
unittestFlagsArray = [ "*_test.py" ];
__darwinAllowLocalNetworking = true;
meta = {
description = "Web framework and asynchronous networking library";
homepage = "https://www.tornadoweb.org/";
license = lib.licenses.asl20;
};
}
@@ -1,7 +1,7 @@
{ lib, fetchzip }:
let
version = "2.8.2";
srcHash = "sha256-1TfD5CXOQKHyO7ARo7oqc2LdiHOyOU/OYNY8j+9QpQ8=";
version = "2.8.3";
srcHash = "sha256-/Ozzibz2BhVSxQeH9tg3cC5uVl0gEA/Hw2AMOELW/I8=";
# The tarball contains vendored dependencies
vendorHash = null;
in
@@ -4,10 +4,12 @@
fetchzip,
which,
ocaml,
camlp-streams,
ocamlbuild,
findlib,
}:
if lib.versionAtLeast ocaml.version "4.15" then
if lib.versionAtLeast ocaml.version "5.4" then
throw "camlp4 is not available for OCaml ${ocaml.version}"
else
@@ -66,6 +68,22 @@ else
version = "4.14+1";
sha256 = "sha256-cPN3GioZT/Zt6uzbjGUPEGVJcPQdsAnCkU/AQoPfvuo=";
};
"5.0" = {
version = "5.0";
sha256 = "sha256-oZptFNPUEAq5YlcqAoDWfLghGMF9AN7E7hUN55SAX+4=";
};
"5.1" = {
version = "5.1";
sha256 = "sha256-Ubedjg3BeHA0bJbEalQN9eEk5+LRAI/er+8mWfVYchg=";
};
"5.2" = {
version = "5.2";
sha256 = "sha256-lzbc9xsgeYlbVf71O+PWYS14QivAH1aPdnvWhe0HHME=";
};
"5.3" = {
version = "5.3";
sha256 = "sha256-V/kKhTP9U4jWDFuQKuB7BS3XICg1lq/2Avj7UJR55+k=";
};
}
.${ocaml.meta.branch};
in
@@ -81,9 +99,18 @@ else
strictDeps = true;
nativeBuildInputs = [
which
ocaml
nativeBuildInputs =
[
which
ocaml
ocamlbuild
]
++ lib.optionals (lib.versionAtLeast ocaml.version "5.0") [
findlib
];
buildInputs = lib.optionals (lib.versionAtLeast ocaml.version "5.0") [
camlp-streams
ocamlbuild
];
+19 -8
View File
@@ -1,5 +1,5 @@
{ lib, stdenv, runtimeShell, pkg-config, gettext, ncurses, CoreFoundation
, tiles, SDL2, SDL2_image, SDL2_mixer, SDL2_ttf, freetype, Cocoa
{ lib, stdenv, runtimeShell, pkg-config, gettext, ncurses
, tiles, SDL2, SDL2_image, SDL2_mixer, SDL2_ttf, freetype, zlib
, debug
, useXdgDir
}:
@@ -7,15 +7,26 @@
let
inherit (lib) optionals optionalString;
cursesDeps = [ gettext ncurses ]
++ optionals stdenv.hostPlatform.isDarwin [ CoreFoundation ];
commonDeps = [
gettext
zlib
];
tilesDeps = [ SDL2 SDL2_image SDL2_mixer SDL2_ttf freetype ]
++ optionals stdenv.hostPlatform.isDarwin [ Cocoa ];
cursesDeps = commonDeps ++ [ ncurses ];
tilesDeps =
commonDeps
++ [
SDL2
SDL2_image
SDL2_mixer
SDL2_ttf
freetype
];
patchDesktopFile = ''
substituteInPlace $out/share/applications/org.cataclysmdda.CataclysmDDA.desktop \
--replace "Exec=cataclysm-tiles" "Exec=$out/bin/cataclysm-tiles"
--replace-fail "Exec=cataclysm-tiles" "Exec=$out/bin/cataclysm-tiles"
'';
installMacOSAppLauncher = ''
@@ -37,7 +48,7 @@ stdenv.mkDerivation {
nativeBuildInputs = [ pkg-config ];
buildInputs = cursesDeps ++ optionals tiles tilesDeps;
buildInputs = if tiles then tilesDeps else cursesDeps;
postPatch = ''
patchShebangs lang/compile_mo.sh
+3 -7
View File
@@ -1,20 +1,16 @@
{ newScope, darwin }:
{ newScope }:
let
callPackage = newScope self;
stable = rec {
tiles = callPackage ./stable.nix {
inherit (darwin.apple_sdk.frameworks) CoreFoundation Cocoa;
};
tiles = callPackage ./stable.nix { };
curses = tiles.override { tiles = false; };
};
git = rec {
tiles = callPackage ./git.nix {
inherit (darwin.apple_sdk.frameworks) CoreFoundation Cocoa;
};
tiles = callPackage ./git.nix { };
curses = tiles.override { tiles = false; };
};
+6 -6
View File
@@ -1,15 +1,15 @@
{ lib, callPackage, CoreFoundation, fetchFromGitHub, fetchpatch, pkgs, wrapCDDA, attachPkgs
, tiles ? true, Cocoa
{ lib, callPackage, fetchFromGitHub, fetchpatch, pkgs, wrapCDDA, attachPkgs
, tiles ? true
, debug ? false
, useXdgDir ? false
, version ? "2024-07-28"
, rev ? "bfeb1fffc4179fed242a042f24b1c97f6cfaff3d"
, sha256 ? "sha256-IodXEA+pWfDdR9huRXieP3+J3WZJO19C8PUPT18dFBw="
, version ? "2024-12-11"
, rev ? "b871679a2d54dbc6bf3e6566033fadd2dc651592"
, sha256 ? "sha256-t9R0QPky7zvjgGMq4kV8DdQFToJ/qngbJCw+8FlQztM="
}:
let
common = callPackage ./common.nix {
inherit CoreFoundation tiles Cocoa debug useXdgDir;
inherit tiles debug useXdgDir;
};
self = common.overrideAttrs (common: rec {
-28
View File
@@ -1,28 +0,0 @@
diff --git a/src/debug.cpp b/src/debug.cpp
index fa63a3b..1e8f554 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -1494,6 +1494,14 @@ std::string game_info::operating_system()
}
#if !defined(__CYGWIN__) && !defined (__ANDROID__) && ( defined (__linux__) || defined(unix) || defined(__unix__) || defined(__unix) || ( defined(__APPLE__) && defined(__MACH__) ) || defined(BSD) ) // linux; unix; MacOs; BSD
+ //
+class FILEDeleter
+{
+ public:
+ void operator()( FILE *f ) const noexcept {
+ pclose( f );
+ }
+};
/** Execute a command with the shell by using `popen()`.
* @param command The full command to execute.
* @note The output buffer is limited to 512 characters.
@@ -1504,7 +1512,7 @@ static std::string shell_exec( const std::string &command )
std::vector<char> buffer( 512 );
std::string output;
try {
- std::unique_ptr<FILE, decltype( &pclose )> pipe( popen( command.c_str(), "r" ), pclose );
+ std::unique_ptr<FILE, FILEDeleter> pipe( popen( command.c_str(), "r" ) );
if( pipe ) {
while( fgets( buffer.data(), buffer.size(), pipe.get() ) != nullptr ) {
output += buffer.data();
@@ -4,10 +4,10 @@ diff --git a/src/translations.cpp b/src/translations.cpp
@@ -52,13 +52,11 @@ std::string locale_dir()
#define CATA_IS_ON_BSD
#endif
-#if !defined(__ANDROID__) && ((defined(__linux__) || defined(CATA_IS_ON_BSD) || (defined(MACOSX) && !defined(TILES))))
if( !PATH_INFO::base_path().empty() ) {
loc_dir = PATH_INFO::base_path() + "share/locale";
if( !PATH_INFO::base_path().get_logical_root_path().empty() ) {
loc_dir = ( PATH_INFO::base_path() / "share" / "locale" ).generic_u8string();
} else {
loc_dir = PATH_INFO::langdir();
}
+4 -5
View File
@@ -1,12 +1,11 @@
diff --git a/src/translations.cpp b/src/translations.cpp
index 76bdfd0..6dd6109 100644
--- a/src/translations.cpp
+++ b/src/translations.cpp
@@ -61,13 +61,11 @@ std::string locale_dir()
#define BSD
@@ -52,13 +52,11 @@ std::string locale_dir()
#define CATA_IS_ON_BSD
#endif
-#if !defined(__ANDROID__) && ((defined(__linux__) || defined(BSD) || (defined(MACOSX) && !defined(TILES))))
-#if !defined(__ANDROID__) && ((defined(__linux__) || defined(CATA_IS_ON_BSD) || (defined(MACOSX) && !defined(TILES))))
if( !PATH_INFO::base_path().empty() ) {
loc_dir = PATH_INFO::base_path() + "share/locale";
} else {
+10 -34
View File
@@ -1,66 +1,42 @@
{ lib
, callPackage
, CoreFoundation
, fetchFromGitHub
, fetchpatch
, pkgs
, wrapCDDA
, attachPkgs
, tiles ? true
, Cocoa
, debug ? false
, useXdgDir ? false
}:
let
common = callPackage ./common.nix {
inherit CoreFoundation tiles Cocoa debug useXdgDir;
inherit tiles debug useXdgDir;
};
self = common.overrideAttrs (common: rec {
version = "0.G";
version = "0.H";
src = fetchFromGitHub {
owner = "CleverRaven";
repo = "Cataclysm-DDA";
rev = version;
sha256 = "sha256-Hda0dVVHNeZ8MV5CaCbSpdOCG2iqQEEmXdh16vwIBXk=";
tag = "${version}-RELEASE";
sha256 = "sha256-ZCD5qgqYSX7sS+Tc1oNYq9soYwNUUuWamY2uXfLjGoY=";
};
patches = [
# fix compilation of the vendored flatbuffers under gcc14
(fetchpatch {
name = "fix-flatbuffers-with-gcc14";
url = "https://github.com/CleverRaven/Cataclysm-DDA/commit/1400b1018ff37196bd24ba4365bd50beb571ac14.patch";
hash = "sha256-H0jct6lSQxu48eOZ4f8HICxo89qX49Ksw+Xwwtp7iFM=";
})
# Unconditionally look for translation files in $out/share/locale
./locale-path.patch
# Fixes for failing build with GCC 13, remove on updating next release after 0.G
(fetchpatch {
url = "https://sources.debian.org/data/main/c/cataclysm-dda/0.G-4/debian/patches/gcc13-dangling-reference-warning.patch";
hash = "sha256-9nPbyz49IYBOVHqr7jzCIyS8z/SQgpK4EjEz1fruIPE=";
})
(fetchpatch {
url = "https://sources.debian.org/data/main/c/cataclysm-dda/0.G-4/debian/patches/gcc13-cstdint.patch";
hash = "sha256-8IBW2OzAHVgEJZoViQ490n37sl31hA55ePuqDL/lil0=";
})
(fetchpatch {
url = "https://sources.debian.org/data/main/c/cataclysm-dda/0.G-4/debian/patches/gcc13-keyword-requires.patch";
hash = "sha256-8yvHh0YKC7AC/qzia7AZAfMewMC0RiSepMXpOkMXRd8=";
})
# Fix build w/ glibc-2.39
# From https://github.com/BrettDong/Cataclysm-DDA/commit/9b206e2dc969ad79345596e03c3980bd155d2f48
./glibc-2.39.diff
];
makeFlags = common.makeFlags ++ [
# Makefile declares version as 0.F, with no minor release number
"VERSION=${version}"
];
env.NIX_CFLAGS_COMPILE = toString [
# Needed with GCC 12
"-Wno-error=array-bounds"
];
meta = common.meta // {
maintainers = with lib.maintainers;
common.meta.maintainers;
changelog = "https://github.com/CleverRaven/Cataclysm-DDA/blob/${version}/data/changelog.txt";
};
});
+2 -6
View File
@@ -3873,8 +3873,6 @@ with pkgs;
kio-fuse = libsForQt5.callPackage ../tools/filesystems/kio-fuse { };
kphotoalbum = libsForQt5.callPackage ../applications/graphics/kphotoalbum { };
krename = libsForQt5.callPackage ../applications/misc/krename { };
krunner-pass = libsForQt5.callPackage ../tools/security/krunner-pass { };
@@ -6318,10 +6316,6 @@ with pkgs;
inherit (emacs.pkgs.melpaStablePackages) irony;
};
heptagon = callPackage ../development/compilers/heptagon {
ocamlPackages = ocaml-ng.ocamlPackages_4_14;
};
openjfx17 = openjfx;
openjfx21 = callPackage ../by-name/op/openjfx/package.nix { featureVersion = "21"; };
openjfx23 = callPackage ../by-name/op/openjfx/package.nix { featureVersion = "23"; };
@@ -8552,6 +8546,8 @@ with pkgs;
aspell = aspell.override { searchNixProfiles = false; };
};
astal = recurseIntoAttrs (lib.makeScope newScope (callPackage ../development/libraries/astal { }));
attr = callPackage ../development/libraries/attr { };
# Not moved to aliases while we decide if we should split the package again.
+4
View File
@@ -38,6 +38,8 @@ mapAliases ({
acebinf = throw "acebinf has been removed because it is abandoned and broken."; # Added 2023-05-19
acoustics = throw "acoustics has been removed because the upstream repository was archived in 2024"; # Added 2024-10-04
adafruit-nrfutil = throw "adafruit-nrfutil has been promoted to a top-level attribute name: `pkgs.adafruit-nrfutil`."; # Added 2023-11-19
aeppl = throw "aeppl was removed as it depends on aesara, which is unmaintained"; # added 2025-01-12
aesara = throw "aesara was removed as the upstream repository is unmaintained"; # added 2025-01-12
aioaladdinconnect = throw "aioaladdinconnect has been removed, as the API is supported was obsoleted on 2024-01-24."; # Added 2024-06-07
aiohttp-isal = throw "aiohttp-isal has been removed, as it has been archived and replace by aiohttp-fast-zlib"; # Added 2024-08-11
aiohttp-zlib-ng = throw "aiohttp-zlib-ng has been removed, as it has been archived and replaced by aiohttp-fast-zlib"; # Added 2024-11-14
@@ -689,6 +691,8 @@ mapAliases ({
thumborPexif = throw "thumborPexif has been removed, because it was unused."; # added 2024-01-07
tissue = throw "tissue has been removed, because it is archived since October 2022"; # added 2024-07-27
torchgpipe = throw "torchgpipe has been removed, because it appears unmaintained and Pytorch now includes pipeline parallelism support"; # added 2024-05-18
tornado_4 = throw "tornado_4 has been removed, use tornado instead"; # added 2025-01-13
tornado_5 = throw "tornado_5 has been removed, use tornado instead"; # added 2025-01-13
torrent_parser = torrent-parser; # added 2023-11-04
transip = throw "transip has been removed because it is no longer maintained. TransIP SOAP V5 API was marked as deprecated"; # added 2023-02-27
py-tree-sitter = throw "Was merged with tree-sitter."; # added 2024-03-20
-10
View File
@@ -99,12 +99,8 @@ self: super: with self; {
aenum = callPackage ../development/python-modules/aenum { };
aeppl = callPackage ../development/python-modules/aeppl { };
aerosandbox = callPackage ../development/python-modules/aerosandbox { };
aesara = callPackage ../development/python-modules/aesara { };
aesedb = callPackage ../development/python-modules/aesedb { };
aetcd = callPackage ../development/python-modules/aetcd { };
@@ -16327,12 +16323,6 @@ self: super: with self; {
tornado = callPackage ../development/python-modules/tornado { };
# Used by circus and grab-site, 2020-08-29
tornado_4 = callPackage ../development/python-modules/tornado/4.nix { };
# Used by streamlit, 2021-01-29
tornado_5 = callPackage ../development/python-modules/tornado/5.nix { };
torchprofile = callPackage ../development/python-modules/torchprofile { };
torpy = callPackage ../development/python-modules/torpy { };