commit
3bddcf5f90
@ -0,0 +1,5 @@ |
||||
{ lib, ... }: |
||||
|
||||
{ |
||||
disabledModules = [ (toString ./define-enable.nix) ]; |
||||
} |
@ -1,7 +1,7 @@ |
||||
{ |
||||
x86_64-linux = "/nix/store/3af6g226v4hsv6x7xzh23d6wqyq0nzjp-nix-2.10.3"; |
||||
i686-linux = "/nix/store/43xxh2jip6rpdhylc5z9a5fxx54dw206-nix-2.10.3"; |
||||
aarch64-linux = "/nix/store/6qw3r57nra08ars8j8zyj3fl8lz4cvnd-nix-2.10.3"; |
||||
x86_64-darwin = "/nix/store/3b7qrm0qjw57fmznrsvm0ai568i89hc2-nix-2.10.3"; |
||||
aarch64-darwin = "/nix/store/gp7k17iy1n7hgf97qwnxw28c6v9nhb1i-nix-2.10.3"; |
||||
x86_64-linux = "/nix/store/nmq5zcd93qb1yskx42rs910ff0247nn2-nix-2.11.0"; |
||||
i686-linux = "/nix/store/ja6im1sw9a8lzczi10lc0iddffl9kzmn-nix-2.11.0"; |
||||
aarch64-linux = "/nix/store/myr6fcqa9y4y2fb83zz73dck52vcn81z-nix-2.11.0"; |
||||
x86_64-darwin = "/nix/store/2pfjz9b22k9997gh7cb0hjk1qa4lxrvy-nix-2.11.0"; |
||||
aarch64-darwin = "/nix/store/lr32i0bdarx1iqsch4sy24jj1jkfw9vf-nix-2.11.0"; |
||||
} |
||||
|
@ -0,0 +1,92 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
with lib; |
||||
|
||||
let |
||||
cfg = config.programs.rust-motd; |
||||
format = pkgs.formats.toml { }; |
||||
in { |
||||
options.programs.rust-motd = { |
||||
enable = mkEnableOption "rust-motd"; |
||||
enableMotdInSSHD = mkOption { |
||||
default = true; |
||||
type = types.bool; |
||||
description = mdDoc '' |
||||
Whether to let `openssh` print the |
||||
result when entering a new `ssh`-session. |
||||
By default either nothing or a static file defined via |
||||
[](#opt-users.motd) is printed. Because of that, |
||||
the latter option is incompatible with this module. |
||||
''; |
||||
}; |
||||
refreshInterval = mkOption { |
||||
default = "*:0/5"; |
||||
type = types.str; |
||||
description = mdDoc '' |
||||
Interval in which the {manpage}`motd(5)` file is refreshed. |
||||
For possible formats, please refer to {manpage}`systemd.time(7)`. |
||||
''; |
||||
}; |
||||
settings = mkOption { |
||||
type = types.submodule { |
||||
freeformType = format.type; |
||||
}; |
||||
description = mdDoc '' |
||||
Settings on what to generate. Please read the |
||||
[upstream documentation](https://github.com/rust-motd/rust-motd/blob/main/README.md#configuration) |
||||
for further information. |
||||
''; |
||||
}; |
||||
}; |
||||
config = mkIf cfg.enable { |
||||
assertions = [ |
||||
{ assertion = config.users.motd == null; |
||||
message = '' |
||||
`programs.rust-motd` is incompatible with `users.motd`! |
||||
''; |
||||
} |
||||
]; |
||||
systemd.services.rust-motd = { |
||||
path = with pkgs; [ bash ]; |
||||
documentation = [ "https://github.com/rust-motd/rust-motd/blob/v${pkgs.rust-motd.version}/README.md" ]; |
||||
description = "motd generator"; |
||||
serviceConfig = { |
||||
ExecStart = "${pkgs.writeShellScript "update-motd" '' |
||||
${pkgs.rust-motd}/bin/rust-motd ${format.generate "motd.conf" cfg.settings} > motd |
||||
''}"; |
||||
CapabilityBoundingSet = [ "" ]; |
||||
LockPersonality = true; |
||||
MemoryDenyWriteExecute = true; |
||||
NoNewPrivileges = true; |
||||
PrivateDevices = true; |
||||
PrivateTmp = true; |
||||
ProtectClock = true; |
||||
ProtectControlGroups = true; |
||||
ProtectHome = true; |
||||
ProtectHostname = true; |
||||
ProtectKernelModules = true; |
||||
ProtectKernelLogs = true; |
||||
ProtectKernelTunables = true; |
||||
ProtectSystem = "full"; |
||||
StateDirectory = "rust-motd"; |
||||
RestrictAddressFamilies = "none"; |
||||
RestrictNamespaces = true; |
||||
RestrictRealtime = true; |
||||
RestrictSUIDSGID = true; |
||||
RemoveIPC = true; |
||||
WorkingDirectory = "/var/lib/rust-motd"; |
||||
}; |
||||
}; |
||||
systemd.timers.rust-motd = { |
||||
wantedBy = [ "timers.target" ]; |
||||
timerConfig.OnCalendar = cfg.refreshInterval; |
||||
}; |
||||
security.pam.services.sshd.text = mkIf cfg.enableMotdInSSHD (mkDefault (mkAfter '' |
||||
session optional ${pkgs.pam}/lib/security/pam_motd.so motd=/var/lib/rust-motd/motd |
||||
'')); |
||||
services.openssh.extraConfig = mkIf (cfg.settings ? last_login && cfg.settings.last_login != {}) '' |
||||
PrintLastLog no |
||||
''; |
||||
}; |
||||
meta.maintainers = with maintainers; [ ma27 ]; |
||||
} |
@ -0,0 +1,485 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
let |
||||
inherit (builtins) toString; |
||||
inherit (lib) types mkIf mkOption mkDefault; |
||||
inherit (lib) optional optionals optionalAttrs optionalString; |
||||
|
||||
inherit (pkgs) sqlite; |
||||
|
||||
format = pkgs.formats.ini { |
||||
mkKeyValue = key: value: |
||||
let |
||||
value' = if builtins.isNull value then |
||||
"" |
||||
else if builtins.isBool value then |
||||
if value == true then "true" else "false" |
||||
else |
||||
toString value; |
||||
in "${key} = ${value'}"; |
||||
}; |
||||
|
||||
cfg = config.services.writefreely; |
||||
|
||||
isSqlite = cfg.database.type == "sqlite3"; |
||||
isMysql = cfg.database.type == "mysql"; |
||||
isMysqlLocal = isMysql && cfg.database.createLocally == true; |
||||
|
||||
hostProtocol = if cfg.acme.enable then "https" else "http"; |
||||
|
||||
settings = cfg.settings // { |
||||
app = cfg.settings.app or { } // { |
||||
host = cfg.settings.app.host or "${hostProtocol}://${cfg.host}"; |
||||
}; |
||||
|
||||
database = if cfg.database.type == "sqlite3" then { |
||||
type = "sqlite3"; |
||||
filename = cfg.settings.database.filename or "writefreely.db"; |
||||
database = cfg.database.name; |
||||
} else { |
||||
type = "mysql"; |
||||
username = cfg.database.user; |
||||
password = "#dbpass#"; |
||||
database = cfg.database.name; |
||||
host = cfg.database.host; |
||||
port = cfg.database.port; |
||||
tls = cfg.database.tls; |
||||
}; |
||||
|
||||
server = cfg.settings.server or { } // { |
||||
bind = cfg.settings.server.bind or "localhost"; |
||||
gopher_port = cfg.settings.server.gopher_port or 0; |
||||
autocert = !cfg.nginx.enable && cfg.acme.enable; |
||||
templates_parent_dir = |
||||
cfg.settings.server.templates_parent_dir or cfg.package.src; |
||||
static_parent_dir = cfg.settings.server.static_parent_dir or assets; |
||||
pages_parent_dir = |
||||
cfg.settings.server.pages_parent_dir or cfg.package.src; |
||||
keys_parent_dir = cfg.settings.server.keys_parent_dir or cfg.stateDir; |
||||
}; |
||||
}; |
||||
|
||||
configFile = format.generate "config.ini" settings; |
||||
|
||||
assets = pkgs.stdenvNoCC.mkDerivation { |
||||
pname = "writefreely-assets"; |
||||
|
||||
inherit (cfg.package) version src; |
||||
|
||||
nativeBuildInputs = with pkgs.nodePackages; [ less ]; |
||||
|
||||
buildPhase = '' |
||||
mkdir -p $out |
||||
|
||||
cp -r static $out/ |
||||
''; |
||||
|
||||
installPhase = '' |
||||
less_dir=$src/less |
||||
css_dir=$out/static/css |
||||
|
||||
lessc $less_dir/app.less $css_dir/write.css |
||||
lessc $less_dir/fonts.less $css_dir/fonts.css |
||||
lessc $less_dir/icons.less $css_dir/icons.css |
||||
lessc $less_dir/prose.less $css_dir/prose.css |
||||
''; |
||||
}; |
||||
|
||||
withConfigFile = text: '' |
||||
db_pass=${ |
||||
optionalString (cfg.database.passwordFile != null) |
||||
"$(head -n1 ${cfg.database.passwordFile})" |
||||
} |
||||
|
||||
cp -f ${configFile} '${cfg.stateDir}/config.ini' |
||||
sed -e "s,#dbpass#,$db_pass,g" -i '${cfg.stateDir}/config.ini' |
||||
chmod 440 '${cfg.stateDir}/config.ini' |
||||
|
||||
${text} |
||||
''; |
||||
|
||||
withMysql = text: |
||||
withConfigFile '' |
||||
query () { |
||||
local result=$(${config.services.mysql.package}/bin/mysql \ |
||||
--user=${cfg.database.user} \ |
||||
--password=$db_pass \ |
||||
--database=${cfg.database.name} \ |
||||
--silent \ |
||||
--raw \ |
||||
--skip-column-names \ |
||||
--execute "$1" \ |
||||
) |
||||
|
||||
echo $result |
||||
} |
||||
|
||||
${text} |
||||
''; |
||||
|
||||
withSqlite = text: |
||||
withConfigFile '' |
||||
query () { |
||||
local result=$(${sqlite}/bin/sqlite3 \ |
||||
'${cfg.stateDir}/${settings.database.filename}' |
||||
"$1" \ |
||||
) |
||||
|
||||
echo $result |
||||
} |
||||
|
||||
${text} |
||||
''; |
||||
in { |
||||
options.services.writefreely = { |
||||
enable = |
||||
lib.mkEnableOption "Writefreely, build a digital writing community"; |
||||
|
||||
package = lib.mkOption { |
||||
type = lib.types.package; |
||||
default = pkgs.writefreely; |
||||
defaultText = lib.literalExpression "pkgs.writefreely"; |
||||
description = "Writefreely package to use."; |
||||
}; |
||||
|
||||
stateDir = mkOption { |
||||
type = types.path; |
||||
default = "/var/lib/writefreely"; |
||||
description = "The state directory where keys and data are stored."; |
||||
}; |
||||
|
||||
user = mkOption { |
||||
type = types.str; |
||||
default = "writefreely"; |
||||
description = "User under which Writefreely is ran."; |
||||
}; |
||||
|
||||
group = mkOption { |
||||
type = types.str; |
||||
default = "writefreely"; |
||||
description = "Group under which Writefreely is ran."; |
||||
}; |
||||
|
||||
host = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
description = "The public host name to serve."; |
||||
example = "example.com"; |
||||
}; |
||||
|
||||
settings = mkOption { |
||||
default = { }; |
||||
description = '' |
||||
Writefreely configuration (<filename>config.ini</filename>). Refer to |
||||
<link xlink:href="https://writefreely.org/docs/latest/admin/config" /> |
||||
for details. |
||||
''; |
||||
|
||||
type = types.submodule { |
||||
freeformType = format.type; |
||||
|
||||
options = { |
||||
app = { |
||||
theme = mkOption { |
||||
type = types.str; |
||||
default = "write"; |
||||
description = "The theme to apply."; |
||||
}; |
||||
}; |
||||
|
||||
server = { |
||||
port = mkOption { |
||||
type = types.port; |
||||
default = if cfg.nginx.enable then 18080 else 80; |
||||
defaultText = "80"; |
||||
description = "The port WriteFreely should listen on."; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
database = { |
||||
type = mkOption { |
||||
type = types.enum [ "sqlite3" "mysql" ]; |
||||
default = "sqlite3"; |
||||
description = "The database provider to use."; |
||||
}; |
||||
|
||||
name = mkOption { |
||||
type = types.str; |
||||
default = "writefreely"; |
||||
description = "The name of the database to store data in."; |
||||
}; |
||||
|
||||
user = mkOption { |
||||
type = types.nullOr types.str; |
||||
default = if cfg.database.type == "mysql" then "writefreely" else null; |
||||
defaultText = "writefreely"; |
||||
description = "The database user to connect as."; |
||||
}; |
||||
|
||||
passwordFile = mkOption { |
||||
type = types.nullOr types.path; |
||||
default = null; |
||||
description = "The file to load the database password from."; |
||||
}; |
||||
|
||||
host = mkOption { |
||||
type = types.str; |
||||
default = "localhost"; |
||||
description = "The database host to connect to."; |
||||
}; |
||||
|
||||
port = mkOption { |
||||
type = types.port; |
||||
default = 3306; |
||||
description = "The port used when connecting to the database host."; |
||||
}; |
||||
|
||||
tls = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = |
||||
"Whether or not TLS should be used for the database connection."; |
||||
}; |
||||
|
||||
migrate = mkOption { |
||||
type = types.bool; |
||||
default = true; |
||||
description = |
||||
"Whether or not to automatically run migrations on startup."; |
||||
}; |
||||
|
||||
createLocally = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = '' |
||||
When <option>services.writefreely.database.type</option> is set to |
||||
<code>"mysql"</code>, this option will enable the MySQL service locally. |
||||
''; |
||||
}; |
||||
}; |
||||
|
||||
admin = { |
||||
name = mkOption { |
||||
type = types.nullOr types.str; |
||||
description = "The name of the first admin user."; |
||||
default = null; |
||||
}; |
||||
|
||||
initialPasswordFile = mkOption { |
||||
type = types.path; |
||||
description = '' |
||||
Path to a file containing the initial password for the admin user. |
||||
If not provided, the default password will be set to <code>nixos</code>. |
||||
''; |
||||
default = pkgs.writeText "default-admin-pass" "nixos"; |
||||
defaultText = "/nix/store/xxx-default-admin-pass"; |
||||
}; |
||||
}; |
||||
|
||||
nginx = { |
||||
enable = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = |
||||
"Whether or not to enable and configure nginx as a proxy for WriteFreely."; |
||||
}; |
||||
|
||||
forceSSL = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = "Whether or not to force the use of SSL."; |
||||
}; |
||||
}; |
||||
|
||||
acme = { |
||||
enable = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = |
||||
"Whether or not to automatically fetch and configure SSL certs."; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
config = mkIf cfg.enable { |
||||
assertions = [ |
||||
{ |
||||
assertion = cfg.host != ""; |
||||
message = "services.writefreely.host must be set"; |
||||
} |
||||
{ |
||||
assertion = isMysqlLocal -> cfg.database.passwordFile != null; |
||||
message = |
||||
"services.writefreely.database.passwordFile must be set if services.writefreely.database.createLocally is set to true"; |
||||
} |
||||
{ |
||||
assertion = isSqlite -> !cfg.database.createLocally; |
||||
message = |
||||
"services.writefreely.database.createLocally has no use when services.writefreely.database.type is set to sqlite3"; |
||||
} |
||||
]; |
||||
|
||||
users = { |
||||
users = optionalAttrs (cfg.user == "writefreely") { |
||||
writefreely = { |
||||
group = cfg.group; |
||||
home = cfg.stateDir; |
||||
isSystemUser = true; |
||||
}; |
||||
}; |
||||
|
||||
groups = |
||||
optionalAttrs (cfg.group == "writefreely") { writefreely = { }; }; |
||||
}; |
||||
|
||||
systemd.tmpfiles.rules = |
||||
[ "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" ]; |
||||
|
||||
systemd.services.writefreely = { |
||||
after = [ "network.target" ] |
||||
++ optional isSqlite "writefreely-sqlite-init.service" |
||||
++ optional isMysql "writefreely-mysql-init.service" |
||||
++ optional isMysqlLocal "mysql.service"; |
||||
wantedBy = [ "multi-user.target" ]; |
||||
|
||||
serviceConfig = { |
||||
Type = "simple"; |
||||
User = cfg.user; |
||||
Group = cfg.group; |
||||
WorkingDirectory = cfg.stateDir; |
||||
Restart = "always"; |
||||
RestartSec = 20; |
||||
ExecStart = |
||||
"${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' serve"; |
||||
AmbientCapabilities = |
||||
optionalString (settings.server.port < 1024) "cap_net_bind_service"; |
||||
}; |
||||
|
||||
preStart = '' |
||||
if ! test -d "${cfg.stateDir}/keys"; then |
||||
mkdir -p ${cfg.stateDir}/keys |
||||
|
||||
# Key files end up with the wrong permissions by default. |
||||
# We need to correct them so that Writefreely can read them. |
||||
chmod -R 750 "${cfg.stateDir}/keys" |
||||
|
||||
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' keys generate |
||||
fi |
||||
''; |
||||
}; |
||||
|
||||
systemd.services.writefreely-sqlite-init = mkIf isSqlite { |
||||
wantedBy = [ "multi-user.target" ]; |
||||
|
||||
serviceConfig = { |
||||
Type = "oneshot"; |
||||
User = cfg.user; |
||||
Group = cfg.group; |
||||
WorkingDirectory = cfg.stateDir; |
||||
ReadOnlyPaths = optional (cfg.admin.initialPasswordFile != null) |
||||
cfg.admin.initialPasswordFile; |
||||
}; |
||||
|
||||
script = let |
||||
migrateDatabase = optionalString cfg.database.migrate '' |
||||
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate |
||||
''; |
||||
|
||||
createAdmin = optionalString (cfg.admin.name != null) '' |
||||
if [[ $(query "SELECT COUNT(*) FROM users") == 0 ]]; then |
||||
admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile}) |
||||
|
||||
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass |
||||
fi |
||||
''; |
||||
in withSqlite '' |
||||
if ! test -f '${settings.database.filename}'; then |
||||
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init |
||||
fi |
||||
|
||||
${migrateDatabase} |
||||
|
||||
${createAdmin} |
||||
''; |
||||
}; |
||||
|
||||
systemd.services.writefreely-mysql-init = mkIf isMysql { |
||||
wantedBy = [ "multi-user.target" ]; |
||||
after = optional isMysqlLocal "mysql.service"; |
||||
|
||||
serviceConfig = { |
||||
Type = "oneshot"; |
||||
User = cfg.user; |
||||
Group = cfg.group; |
||||
WorkingDirectory = cfg.stateDir; |
||||
ReadOnlyPaths = optional isMysqlLocal cfg.database.passwordFile |
||||
++ optional (cfg.admin.initialPasswordFile != null) |
||||
cfg.admin.initialPasswordFile; |
||||
}; |
||||
|
||||
script = let |
||||
updateUser = optionalString isMysqlLocal '' |
||||
# WriteFreely currently *requires* a password for authentication, so we |
||||
# need to update the user in MySQL accordingly. By default MySQL users |
||||
# authenticate with auth_socket or unix_socket. |
||||
# See: https://github.com/writefreely/writefreely/issues/568 |
||||
${config.services.mysql.package}/bin/mysql --skip-column-names --execute "ALTER USER '${cfg.database.user}'@'localhost' IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('$db_pass'); FLUSH PRIVILEGES;" |
||||
''; |
||||
|
||||
migrateDatabase = optionalString cfg.database.migrate '' |
||||
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate |
||||
''; |
||||
|
||||
createAdmin = optionalString (cfg.admin.name != null) '' |
||||
if [[ $(query 'SELECT COUNT(*) FROM users') == 0 ]]; then |
||||
admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile}) |
||||
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass |
||||
fi |
||||
''; |
||||
in withMysql '' |
||||
${updateUser} |
||||
|
||||
if [[ $(query "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '${cfg.database.name}'") == 0 ]]; then |
||||
${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init |
||||
fi |
||||
|
||||
${migrateDatabase} |
||||
|
||||
${createAdmin} |
||||
''; |
||||
}; |
||||
|
||||
services.mysql = mkIf isMysqlLocal { |
||||
enable = true; |
||||
package = mkDefault pkgs.mariadb; |
||||
ensureDatabases = [ cfg.database.name ]; |
||||
ensureUsers = [{ |
||||
name = cfg.database.user; |
||||
ensurePermissions = { |
||||
"${cfg.database.name}.*" = "ALL PRIVILEGES"; |
||||
# WriteFreely requires the use of passwords, so we need permissions |
||||
# to `ALTER` the user to add password support and also to reload |
||||
# permissions so they can be used. |
||||
"*.*" = "CREATE USER, RELOAD"; |
||||
}; |
||||
}]; |
||||
}; |
||||
|
||||
services.nginx = lib.mkIf cfg.nginx.enable { |
||||
enable = true; |
||||
recommendedProxySettings = true; |
||||
|
||||
virtualHosts."${cfg.host}" = { |
||||
enableACME = cfg.acme.enable; |
||||
forceSSL = cfg.nginx.forceSSL; |
||||
|
||||
locations."/" = { |
||||
proxyPass = "http://127.0.0.1:${toString settings.server.port}"; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
||||
} |
@ -0,0 +1,44 @@ |
||||
{ system ? builtins.currentSystem, config ? { } |
||||
, pkgs ? import ../../.. { inherit system config; } }: |
||||
|
||||
with import ../../lib/testing-python.nix { inherit system pkgs; }; |
||||
with pkgs.lib; |
||||
|
||||
let |
||||
writefreelyTest = { name, type }: |
||||
makeTest { |
||||
name = "writefreely-${name}"; |
||||
|
||||
nodes.machine = { config, pkgs, ... }: { |
||||
services.writefreely = { |
||||
enable = true; |
||||
host = "localhost:3000"; |
||||
admin.name = "nixos"; |
||||
|
||||
database = { |
||||
inherit type; |
||||
createLocally = type == "mysql"; |
||||
passwordFile = pkgs.writeText "db-pass" "pass"; |
||||
}; |
||||
|
||||
settings.server.port = 3000; |
||||
}; |
||||
}; |
||||
|
||||
testScript = '' |
||||
start_all() |
||||
machine.wait_for_unit("writefreely.service") |
||||
machine.wait_for_open_port(3000) |
||||
machine.succeed("curl --fail http://localhost:3000") |
||||
''; |
||||
}; |
||||
in { |
||||
sqlite = writefreelyTest { |
||||
name = "sqlite"; |
||||
type = "sqlite3"; |
||||
}; |
||||
mysql = writefreelyTest { |
||||
name = "mysql"; |
||||
type = "mysql"; |
||||
}; |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,20 +0,0 @@ |
||||
#!/usr/bin/env nix-shell |
||||
#!nix-shell -i bash -p coreutils ripgrep git cargo |
||||
|
||||
# Ref: https://github.com/NixOS/nixpkgs/blob/nixos-21.05/pkgs/applications/audio/netease-music-tui/update-cargo-lock.sh |
||||
|
||||
set -eu -vx |
||||
|
||||
here=$PWD |
||||
version=$(rg '^ version = "' default.nix | cut -d '"' -f 2) |
||||
checkout=$(mktemp -d) |
||||
|
||||
git clone -b "$version" --depth=1 https://github.com/gmg137/netease-cloud-music-gtk "$checkout" |
||||
cd "$checkout" |
||||
|
||||
cargo generate-lockfile |
||||
git add -f Cargo.lock |
||||
git diff HEAD -- Cargo.lock > "$here"/cargo-lock.patch |
||||
|
||||
cd "$here" |
||||
rm -rf "$checkout" |
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@ |
||||
{ callPackage, ... } @ args: |
||||
|
||||
callPackage ./generic.nix (args // { |
||||
version = "5.0.8"; |
||||
version = "5.1.0"; |
||||
kde-channel = "stable"; |
||||
sha256 = "sha256:7R0fpQc+4MQVDh/enhCTgpgOqU0y5YRShrv/ILa/XkU="; |
||||
sha256 = "sha256-mjs/WFhIC3CRvUhEmSbmE1OOqKTcBiSchg/+PaWs2II="; |
||||
}) |
||||
|
@ -1,32 +1,48 @@ |
||||
{ lib, stdenv, fetchFromGitHub, cmake, pkg-config, gtk3, ncurses |
||||
, libcpuid, pciutils, procps, wrapGAppsHook, nasm, makeWrapper }: |
||||
, libcpuid, pciutils, procps, wrapGAppsHook, nasm, makeWrapper |
||||
, opencl-headers, ocl-icd |
||||
, vulkan-headers, vulkan-loader, glfw |
||||
, libXdmcp, pcre, util-linux |
||||
, libselinux, libsepol |
||||
, libthai, libdatrie, libxkbcommon, libepoxy |
||||
, dbus, at-spi2-core |
||||
, libXtst |
||||
}: |
||||
|
||||
stdenv.mkDerivation rec { |
||||
pname = "cpu-x"; |
||||
version = "4.3.1"; |
||||
version = "4.4.0"; |
||||
|
||||
src = fetchFromGitHub { |
||||
owner = "X0rg"; |
||||
repo = "CPU-X"; |
||||
rev = "v${version}"; |
||||
sha256 = "sha256-9oRNyspFmvIG63aJ8qyaVmi1GW1eW+Rg0+z8la3LuKA="; |
||||
sha256 = "sha256-PNfEiin4Hble/H8cOvSK+A7wmoeOlyITRUTwGTd3B6s="; |
||||
}; |
||||
|
||||
nativeBuildInputs = [ cmake pkg-config wrapGAppsHook nasm makeWrapper ]; |
||||
buildInputs = [ |
||||
gtk3 ncurses libcpuid pciutils procps |
||||
vulkan-headers vulkan-loader glfw |
||||
opencl-headers ocl-icd |
||||
libXdmcp pcre util-linux |
||||
libselinux libsepol |
||||
libthai libdatrie libxkbcommon libepoxy |
||||
dbus at-spi2-core |
||||
libXtst |
||||
]; |
||||
|
||||
postInstall = '' |
||||
wrapProgram $out/bin/cpu-x \ |
||||
--prefix PATH : ${lib.makeBinPath [ stdenv.cc ]} |
||||
--prefix PATH : ${lib.makeBinPath [ stdenv.cc ]} \ |
||||
--prefix LD_LIBRARY_PATH : ${vulkan-loader}/lib |
||||
''; |
||||
|
||||
meta = with lib; { |
||||
description = "Free software that gathers information on CPU, motherboard and more"; |
||||
homepage = src.meta.homepage; |
||||
license = licenses.gpl3; |
||||
license = licenses.gpl3Plus; |
||||
platforms = [ "x86_64-linux" ]; |
||||
maintainers = with maintainers; [ ]; |
||||
maintainers = with maintainers; [ viraptor ]; |
||||
}; |
||||
} |
||||
|
@ -0,0 +1,16 @@ |
||||
diff -Nurp sigal-2.3.orig/sigal/writer.py sigal-2.3/sigal/writer.py
|
||||
--- sigal-2.3.orig/sigal/writer.py 2022-08-08 19:43:10.934707194 +0200
|
||||
+++ sigal-2.3/sigal/writer.py 2022-08-08 19:44:57.542382532 +0200
|
||||
@@ -103,7 +103,11 @@ class AbstractWriter:
|
||||
os.path.join(THEMES_PATH, 'default', 'static'),
|
||||
os.path.join(self.theme, 'static'),
|
||||
):
|
||||
- shutil.copytree(static_path, self.theme_path, dirs_exist_ok=True)
|
||||
+ # https://stackoverflow.com/a/17022146/4935114
|
||||
+ orig_copystat = shutil.copystat
|
||||
+ shutil.copystat = lambda x, y: x
|
||||
+ shutil.copytree(static_path, self.theme_path, dirs_exist_ok=True, copy_function=shutil.copy)
|
||||
+ shutil.copystat = orig_copystat
|
||||
|
||||
if self.settings["user_css"]:
|
||||
if not os.path.exists(self.settings["user_css"]):
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue