mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-06-05 21:03:40 +00:00
Merge remote-tracking branch 'origin/master' into staging-next
This commit is contained in:
@@ -1726,11 +1726,21 @@ let
|
||||
|
||||
`from`
|
||||
|
||||
: 1\. Function argument
|
||||
: The "from" option path as list of strings.
|
||||
Option must not exist in the current module set.
|
||||
|
||||
`to`
|
||||
|
||||
: 2\. Function argument
|
||||
: The "to" option path as list of strings.
|
||||
Option must already exist in the current module set.
|
||||
|
||||
# Limitations
|
||||
|
||||
- The "to" option must already be declared.
|
||||
- The "from" option should not be declared, as this function will declare it.
|
||||
- "to" Options whose types don't support merging at any level of their structure (like `types.raw`,
|
||||
or `types.attrsOf types.raw` where the attribute values can't merge) are not well-supported
|
||||
because this function wraps aliased definitions in `mkMerge`.
|
||||
*/
|
||||
mkRenamedOptionModule =
|
||||
from: to:
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
# Ad-Hoc Configuration {#ad-hoc-network-config}
|
||||
|
||||
You can use [](#opt-networking.localCommands) to
|
||||
specify shell commands to be run at the end of `network-setup.service`. This
|
||||
is useful for doing network configuration not covered by the existing NixOS
|
||||
modules. For instance, to statically configure an IPv6 address:
|
||||
You can use [](#opt-networking.localCommands) to specify shell commands to be
|
||||
run after the network interfaces have been created, but not necessarily fully
|
||||
configured.
|
||||
This is useful for doing network configuration not covered by the existing
|
||||
NixOS modules. For example, you can create a network namespace and a pair
|
||||
of virtual ethernet devices like this:
|
||||
|
||||
```nix
|
||||
{
|
||||
networking.localCommands = ''
|
||||
ip -6 addr add 2001:610:685:1::1/64 dev eth0
|
||||
ip netns add mynet
|
||||
ip link add name veth-in type veth peer name veth-out
|
||||
ip link set dev veth-out netns mynet
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
The commands should ideally be idempotent, so it's recommended to perform
|
||||
cleanups of the state you create (e.g. virtual interfaces), or at least make
|
||||
sure possible failures are handled.
|
||||
:::
|
||||
|
||||
@@ -26,9 +26,16 @@ servers:
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
Statically configured interfaces are set up by the systemd service
|
||||
`interface-name-cfg.service`. The default gateway and name server
|
||||
configuration is performed by `network-setup.service`.
|
||||
Addresses and routes for statically configured interfaces and the default
|
||||
gateway are set up by systemd services named
|
||||
`network-addresses-<interface>.service`. The name servers configuration,
|
||||
instead, is performed by `network-local-commands.service` using resolvconf.
|
||||
:::
|
||||
|
||||
::: {.note}
|
||||
If needed, for example if addresses/routes were added/removed,
|
||||
you can reset the network configuration by running
|
||||
`systemctl restart networking-scripted.target`
|
||||
:::
|
||||
|
||||
The host name is set using [](#opt-networking.hostName):
|
||||
|
||||
@@ -326,6 +326,13 @@ See <https://github.com/NixOS/nixpkgs/issues/481673>.
|
||||
|
||||
Note for NetworkManager users: before these changes NetworkManager used to spawn its own wpa_supplicant daemon, but now it relies on `networking.wireless`. So, if you had `networking.wireless.enable = false` in your configuration, you should remove that line.
|
||||
|
||||
- Some implementation details of the NixOS network-interfaces module have been changed:
|
||||
|
||||
- In the "scripted" backend, `network-setup.service` has been removed and the network configuration services are now part of `network.target`, which is now directly pulled into `multi-user.target`.
|
||||
- Interface addresses, routes and default gateways are now configured asynchronously as soon as the underlying network devices become available (fixes issue [#154737](https://github.com/NixOS/nixpkgs/issues/154737)).
|
||||
- In both "networkd" and "scripted" backends, the configuration of name servers is now part of `network-local-commands.service` (fixes issue [#445496](https://github.com/NixOS/nixpkgs/issues/445496)).
|
||||
- The issue that resulted in a completely unconfigured network if both `resolvconf` was disabled and no default gateway configured, has also been fixed.
|
||||
|
||||
- `kratos` has been updated from 1.3.1 to [25.4.0](https://github.com/ory/kratos/releases/tag/v25.4.0). Upstream switched to a new versioning scheme (year.major.minor). Notable breaking changes:
|
||||
|
||||
- The `migrate sql` CLI command is now `migrate sql up`
|
||||
|
||||
@@ -24,10 +24,12 @@ let
|
||||
'';
|
||||
|
||||
# Sadly, systemd-vconsole-setup doesn't support binary keymaps.
|
||||
vconsoleConf = pkgs.writeText "vconsole.conf" ''
|
||||
KEYMAP=${cfg.keyMap}
|
||||
${lib.optionalString (cfg.font != null) "FONT=${cfg.font}"}
|
||||
'';
|
||||
vconsoleConf =
|
||||
withFont:
|
||||
pkgs.writeText "vconsole.conf" ''
|
||||
KEYMAP=${cfg.keyMap}
|
||||
${lib.optionalString (withFont && cfg.font != null) "FONT=${cfg.font}"}
|
||||
'';
|
||||
|
||||
consoleEnv =
|
||||
kbd:
|
||||
@@ -165,7 +167,7 @@ in
|
||||
# Let systemd-vconsole-setup.service do the work of setting up the
|
||||
# virtual consoles. Skip when imperative so localectl can manage it.
|
||||
environment.etc."vconsole.conf" = lib.mkIf (!i18nCfg.imperativeLocale) {
|
||||
source = vconsoleConf;
|
||||
source = vconsoleConf true;
|
||||
};
|
||||
# Provide kbd with additional packages.
|
||||
environment.etc.kbd.source = "${consoleEnv pkgs.kbd}/share";
|
||||
@@ -183,7 +185,7 @@ in
|
||||
);
|
||||
|
||||
boot.initrd.systemd.contents = {
|
||||
"/etc/vconsole.conf".source = vconsoleConf;
|
||||
"/etc/vconsole.conf".source = vconsoleConf cfg.earlySetup;
|
||||
# Add everything if we want full console setup...
|
||||
"/etc/kbd" = lib.mkIf cfg.earlySetup {
|
||||
source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share";
|
||||
@@ -192,9 +194,6 @@ in
|
||||
"/etc/kbd/keymaps" = lib.mkIf (!cfg.earlySetup) {
|
||||
source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share/keymaps";
|
||||
};
|
||||
"/etc/kbd/consolefonts" = lib.mkIf (!cfg.earlySetup && cfg.font != null) {
|
||||
source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share/consolefonts";
|
||||
};
|
||||
};
|
||||
boot.initrd.systemd.additionalUpstreamUnits = [
|
||||
"systemd-vconsole-setup.service"
|
||||
@@ -204,7 +203,7 @@ in
|
||||
"${config.boot.initrd.systemd.package.kbd}/bin/setfont"
|
||||
"${config.boot.initrd.systemd.package.kbd}/bin/loadkeys"
|
||||
]
|
||||
++ lib.optionals (cfg.font != null && lib.hasPrefix builtins.storeDir cfg.font) [
|
||||
++ lib.optionals (cfg.font != null && cfg.earlySetup && lib.hasPrefix builtins.storeDir cfg.font) [
|
||||
"${cfg.font}"
|
||||
]
|
||||
++ lib.optionals (lib.hasPrefix builtins.storeDir cfg.keyMap) [
|
||||
@@ -226,7 +225,7 @@ in
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartTriggers =
|
||||
lib.optionals (!i18nCfg.imperativeLocale) [
|
||||
vconsoleConf
|
||||
(config.environment.etc."vconsole.conf".source)
|
||||
]
|
||||
++ [
|
||||
(consoleEnv pkgs.kbd)
|
||||
|
||||
@@ -76,7 +76,7 @@ let
|
||||
{
|
||||
inputs = {
|
||||
# This is pointing to an unstable release.
|
||||
# If you prefer a stable release instead, you can this to the latest number shown here: https://nixos.org/download
|
||||
# If you prefer a stable release instead, you can change the word unstable to the latest number shown here: https://nixos.org/download
|
||||
# i.e. nixos-24.11
|
||||
# Use `nix flake update` to update the flake to the latest revision of the chosen release channel.
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
@@ -119,6 +119,7 @@ let
|
||||
"smartctl"
|
||||
"smokeping"
|
||||
"snmp"
|
||||
"speedtest"
|
||||
"sql"
|
||||
"statsd"
|
||||
"storagebox"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.speedtest;
|
||||
inherit (lib)
|
||||
mkOption
|
||||
types
|
||||
concatStringsSep
|
||||
optionalString
|
||||
;
|
||||
in
|
||||
{
|
||||
port = 9798;
|
||||
|
||||
extraOpts = {
|
||||
serverID = mkOption {
|
||||
type = types.int;
|
||||
default = -1;
|
||||
description = ''
|
||||
Speedtest.net server ID to run tests against.
|
||||
-1 picks the closest server to your location.
|
||||
'';
|
||||
};
|
||||
|
||||
serverFallback = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If the configured serverID is unavailable, fall back to the closest available server.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-speedtest-exporter}/bin/speedtest_exporter \
|
||||
-listen-address ${cfg.listenAddress} \
|
||||
-port ${toString cfg.port} \
|
||||
-server_id ${toString cfg.serverID} \
|
||||
${optionalString cfg.serverFallback "-server_fallback"} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
let
|
||||
inherit (lib)
|
||||
getExe
|
||||
hasAttr
|
||||
mapAttrs
|
||||
match
|
||||
mkEnableOption
|
||||
@@ -362,6 +363,15 @@ in
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ manage ];
|
||||
|
||||
# Some settings options in LaSuite has been renamed in 5.0.0
|
||||
# Show warnings if those settings are not renamed
|
||||
# TODO: remove it when the retrocompatibility options will be gone
|
||||
warnings =
|
||||
(optional (hasAttr "AI_API_KEY" cfg.settings) "AI_API_KEY has been renamed as OPENAI_SDK_API_KEY in LaSuite Docs")
|
||||
++ (optional (hasAttr "AI_API_KEY_FILE" cfg.settings) "AI_API_KEY_FILE has been renamed as OPENAI_SDK_API_KEY_FILE in LaSuite Docs")
|
||||
++ (optional (hasAttr "AI_BASE_URL" cfg.settings) "AI_BASE_URL has been renamed as OPENAI_SDK_BASE_URL in LaSuite Docs");
|
||||
|
||||
systemd.services.lasuite-docs-postgresql-setup = mkIf cfg.postgresql.createLocally {
|
||||
wantedBy = [ "lasuite-docs.target" ];
|
||||
requiredBy = [ "lasuite-docs.service" ];
|
||||
|
||||
@@ -143,6 +143,8 @@ let
|
||||
"final.target"
|
||||
"kexec.target"
|
||||
"systemd-kexec.service"
|
||||
"soft-reboot.target"
|
||||
"systemd-soft-reboot.service"
|
||||
]
|
||||
++ lib.optional cfg.package.withUtmp "systemd-update-utmp.service"
|
||||
++ [
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
@@ -51,6 +50,9 @@
|
||||
];
|
||||
|
||||
boot.initrd.systemd = {
|
||||
storePaths = lib.mkIf config.system.etc.overlay.mutable [
|
||||
"${config.system.nixos-init.package}/bin/clear-etc-opaque"
|
||||
];
|
||||
mounts = [
|
||||
{
|
||||
where = "/run/nixos-etc-metadata";
|
||||
@@ -131,13 +133,20 @@
|
||||
before = [ "initrd-fs.target" ];
|
||||
unitConfig = {
|
||||
DefaultDependencies = false;
|
||||
RequiresMountsFor = "/sysroot";
|
||||
RequiresMountsFor = [
|
||||
"/sysroot"
|
||||
# Needed so we can clear stale opaque markers from the
|
||||
# upperdir based on the contents of the new metadata layer
|
||||
# before the overlay is mounted.
|
||||
"/run/nixos-etc-metadata"
|
||||
];
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = ''
|
||||
/bin/mkdir -p -m 0755 /sysroot/.rw-etc/upper /sysroot/.rw-etc/work
|
||||
'';
|
||||
ExecStart = [
|
||||
"/bin/mkdir -p -m 0755 /sysroot/.rw-etc/upper /sysroot/.rw-etc/work"
|
||||
"${config.system.nixos-init.package}/bin/clear-etc-opaque /run/nixos-etc-metadata /sysroot/.rw-etc/upper"
|
||||
];
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
@@ -285,6 +285,13 @@ in
|
||||
tmpMetadataMount=$(TMPDIR="/run" mktemp --directory -t nixos-etc-metadata.XXXXXXXXXX)
|
||||
mount --type erofs --options ro,nodev,nosuid ${config.system.build.etcMetadataImage} "$tmpMetadataMount"
|
||||
|
||||
${lib.optionalString config.system.etc.overlay.mutable ''
|
||||
# Clear stale opaque markers from the upperdir so that lowerdir
|
||||
# entries added by the new generation are not hidden.
|
||||
# See https://github.com/NixOS/nixpkgs/issues/505475
|
||||
${config.system.nixos-init.package}/bin/clear-etc-opaque "$tmpMetadataMount" /.rw-etc/upper
|
||||
''}
|
||||
|
||||
# There was no previous /etc mounted. This happens when we're called
|
||||
# directly without an initrd, like with nixos-enter.
|
||||
if ! mountpoint -q /etc; then
|
||||
|
||||
@@ -51,6 +51,71 @@ let
|
||||
(lib.concatStringsSep " ")
|
||||
];
|
||||
|
||||
# Converts an IPv4 address literal to a list of bits
|
||||
parseAddr.ipv4 =
|
||||
addr:
|
||||
let
|
||||
pad = b: lib.replicate (8 - builtins.length b) 0 ++ b;
|
||||
toBin = n: pad (lib.toBaseDigits 2 (lib.toInt n));
|
||||
in
|
||||
lib.concatMap toBin (builtins.splitVersion addr);
|
||||
|
||||
# Converts an IPv6 address literal to a list of bits
|
||||
parseAddr.ipv6 =
|
||||
addr:
|
||||
let
|
||||
pad = b: lib.replicate (16 - builtins.length b) 0 ++ b;
|
||||
fromHex = n: (builtins.fromTOML "n = 0x${n}").n;
|
||||
toBin = n: pad (lib.toBaseDigits 2 (fromHex n));
|
||||
normal = (lib.network.ipv6.fromString addr).address;
|
||||
in
|
||||
lib.concatMap toBin (lib.splitString ":" normal);
|
||||
|
||||
# Checks if `addr` is part of the `net` subnet
|
||||
inSubnet =
|
||||
v: net: addr:
|
||||
let
|
||||
prefix = lib.take net.prefixLength (parseAddr.${v} net.address);
|
||||
match = lib.zipListsWith (a: b: a == b) prefix (parseAddr.${v} addr);
|
||||
in
|
||||
lib.all lib.id match;
|
||||
|
||||
# Checks if the netmask of all addresses on interface `iface` includes
|
||||
# the IP address of `gateway`
|
||||
#
|
||||
# Note: this is used to check whether networking.defaultGateway relies on
|
||||
# the given interface, either explicitly, via the `interface` (optional),
|
||||
# or explicitly, by using an address in a subnet of this interface.
|
||||
#
|
||||
# Configuration of the default gateway is then performed as part of that
|
||||
# interface setup in `configureAddrs`, below.
|
||||
isGateway =
|
||||
v: gateway: iface:
|
||||
lib.any lib.id (
|
||||
[ (iface.name == gateway.interface) ]
|
||||
++ map (net: inSubnet v net gateway.address) iface.${v}.addresses
|
||||
);
|
||||
|
||||
# Checks if `gateway` uses an address from `iface` as default source
|
||||
#
|
||||
# Note: this is needed to delay the configuration of the gateway and default
|
||||
# source until the right interfaces and address have been set up, otherwise
|
||||
# the commands will fail.
|
||||
hasSource =
|
||||
v: gateway: iface:
|
||||
builtins.elem gateway.source (map (i: i.address) iface.${v}.addresses);
|
||||
|
||||
# Interfaces corresponding to the default gateways
|
||||
gateway4Iface = builtins.filter (isGateway "ipv4" cfg.defaultGateway) interfaces;
|
||||
gateway6Iface = builtins.filter (isGateway "ipv6" cfg.defaultGateway6) interfaces;
|
||||
|
||||
# Interfaces corresponding to the default source addresses
|
||||
#
|
||||
# Note: the use of `head` here is safe because these expressions
|
||||
# are evaluated only when `needsSourceIface`, see `configureAddrs` below.
|
||||
source4Iface = builtins.head (builtins.filter (hasSource "ipv4" cfg.defaultGateway) interfaces);
|
||||
source6Iface = builtins.head (builtins.filter (hasSource "ipv6" cfg.defaultGateway6) interfaces);
|
||||
|
||||
# warn that these attributes are deprecated (2017-2-2)
|
||||
# Should be removed in the release after next
|
||||
bondDeprecation = rec {
|
||||
@@ -118,121 +183,71 @@ let
|
||||
else
|
||||
optional (!config.boot.isContainer) (subsystemDevice dev);
|
||||
|
||||
hasDefaultGatewaySet =
|
||||
(cfg.defaultGateway != null && cfg.defaultGateway.address != "")
|
||||
|| (cfg.enableIPv6 && cfg.defaultGateway6 != null && cfg.defaultGateway6.address != "");
|
||||
|
||||
needNetworkSetup =
|
||||
cfg.resolvconf.enable || cfg.defaultGateway != null || cfg.defaultGateway6 != null;
|
||||
|
||||
networkLocalCommands = lib.mkIf needNetworkSetup {
|
||||
after = [ "network-setup.service" ];
|
||||
bindsTo = [ "network-setup.service" ];
|
||||
};
|
||||
|
||||
networkSetup = lib.mkIf needNetworkSetup {
|
||||
description = "Networking Setup";
|
||||
|
||||
after = [ "network-pre.target" ];
|
||||
before = [
|
||||
"network.target"
|
||||
"shutdown.target"
|
||||
];
|
||||
wants = [ "network.target" ];
|
||||
# exclude bridges from the partOf relationship to fix container networking bug #47210
|
||||
partOf = map (i: "network-addresses-${i.name}.service") (
|
||||
filter (i: !(hasAttr i.name cfg.bridges)) interfaces
|
||||
);
|
||||
conflicts = [ "shutdown.target" ];
|
||||
wantedBy = [ "multi-user.target" ] ++ optional hasDefaultGatewaySet "network-online.target";
|
||||
|
||||
unitConfig.ConditionCapability = "CAP_NET_ADMIN";
|
||||
|
||||
path = [ pkgs.iproute2 ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
|
||||
unitConfig.DefaultDependencies = false;
|
||||
|
||||
script = ''
|
||||
${optionalString config.networking.resolvconf.enable ''
|
||||
# Set the static DNS configuration, if given.
|
||||
${pkgs.openresolv}/sbin/resolvconf -m 1 -a static <<EOF
|
||||
${optionalString (cfg.nameservers != [ ] && cfg.domain != null) ''
|
||||
domain ${cfg.domain}
|
||||
''}
|
||||
${optionalString (cfg.search != [ ]) ("search " + concatStringsSep " " cfg.search)}
|
||||
${flip concatMapStrings cfg.nameservers (ns: ''
|
||||
nameserver ${ns}
|
||||
'')}
|
||||
EOF
|
||||
''}
|
||||
|
||||
# Set the default gateway
|
||||
${flip concatMapStrings
|
||||
[
|
||||
{
|
||||
version = "-4";
|
||||
gateway = cfg.defaultGateway;
|
||||
}
|
||||
{
|
||||
version = "-6";
|
||||
gateway = cfg.defaultGateway6;
|
||||
}
|
||||
]
|
||||
(
|
||||
{ version, gateway }:
|
||||
optionalString (gateway != null && gateway.address != "") ''
|
||||
${optionalString (gateway.interface != null) ''
|
||||
ip ${version} route replace ${gateway.address} proto static ${
|
||||
formatIpArgs {
|
||||
metric = gateway.metric;
|
||||
dev = gateway.interface;
|
||||
}
|
||||
}
|
||||
''}
|
||||
ip ${version} route replace default proto static ${
|
||||
formatIpArgs {
|
||||
metric = gateway.metric;
|
||||
via = gateway.address;
|
||||
window = cfg.defaultGatewayWindowSize;
|
||||
dev = gateway.interface;
|
||||
src = gateway.source;
|
||||
}
|
||||
}
|
||||
''
|
||||
)
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# For each interface <foo>, create a job ‘network-addresses-<foo>.service"
|
||||
# that performs static address configuration. It has a "wants"
|
||||
# dependency on ‘<foo>.service’, which is supposed to create
|
||||
# the interface and need not exist (i.e. for hardware
|
||||
# interfaces). It has a binds-to dependency on the actual
|
||||
# network device, so it only gets started after the interface
|
||||
# has appeared, and it's stopped when the interface
|
||||
# disappears.
|
||||
# For each interface <foo>, creates a network-addresses-<foo>.service
|
||||
# job that performs static address configuration.
|
||||
#
|
||||
# It has a Wants dependency on <foo>-netdev.service, which creates
|
||||
# create the interface, or on a device unit (for hardware interfaces).
|
||||
# It also has a BindsTo dependency on the device unit: so, it only gets
|
||||
# started after the interface has appeared and it's stopped when the
|
||||
# interface disappears.
|
||||
#
|
||||
# Unless in a container, the job is not made part of network.target, so
|
||||
# if an interface is not found (e.g. a USB interface not plugged in) it
|
||||
# will not hang the boot sequence.
|
||||
#
|
||||
# If the interface is the default gateway, the job will also set the
|
||||
# default gateway and delay network-online.target.
|
||||
configureAddrs =
|
||||
i:
|
||||
let
|
||||
ips = interfaceIps i;
|
||||
isDefaultGateway4 = cfg.defaultGateway != null && builtins.elem i gateway4Iface;
|
||||
isDefaultGateway6 = cfg.defaultGateway6 != null && builtins.elem i gateway6Iface;
|
||||
needsSourceIface4 =
|
||||
isDefaultGateway4 && cfg.defaultGateway.source != null && i.name != source4Iface.name;
|
||||
needsSourceIface6 =
|
||||
isDefaultGateway6 && cfg.defaultGateway6.source != null && i.name != source6Iface.name;
|
||||
|
||||
configureGateway =
|
||||
version: gateway:
|
||||
optionalString (gateway.address != "") ''
|
||||
echo -n "setting ${i.name} as default IPv${version} gateway... "
|
||||
${optionalString (gateway.interface != null) ''
|
||||
ip -${version} route replace ${gateway.address} proto static ${
|
||||
formatIpArgs {
|
||||
metric = gateway.metric;
|
||||
dev = gateway.interface;
|
||||
}
|
||||
}
|
||||
''}
|
||||
ip -${version} route replace default proto static ${
|
||||
formatIpArgs {
|
||||
metric = gateway.metric;
|
||||
via = gateway.address;
|
||||
window = cfg.defaultGatewayWindowSize;
|
||||
dev = gateway.interface;
|
||||
src = gateway.source;
|
||||
}
|
||||
}
|
||||
echo "done"
|
||||
'';
|
||||
in
|
||||
nameValuePair "network-addresses-${i.name}" {
|
||||
description = "Address configuration of ${i.name}";
|
||||
wantedBy = [
|
||||
"network-setup.service"
|
||||
"network.target"
|
||||
];
|
||||
# order before network-setup because the routes that are configured
|
||||
# there may need ip addresses configured
|
||||
before = [ "network-setup.service" ];
|
||||
|
||||
wantedBy =
|
||||
deviceDependency i.name
|
||||
++ optional config.boot.isContainer "network.target"
|
||||
++ optional (isDefaultGateway4 || isDefaultGateway6) "network-online.target";
|
||||
bindsTo = deviceDependency i.name;
|
||||
after = [ "network-pre.target" ] ++ (deviceDependency i.name);
|
||||
partOf = [ "networking-scripted.target" ];
|
||||
after = [
|
||||
"network-pre.target"
|
||||
]
|
||||
++ optional needsSourceIface4 "network-addresses-${source4Iface.name}.service"
|
||||
++ optional needsSourceIface6 "network-addresses-${source6Iface.name}.service"
|
||||
++ deviceDependency i.name;
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
# Restart rather than stop+start this unit to prevent the
|
||||
@@ -284,6 +299,10 @@ let
|
||||
fi
|
||||
''
|
||||
)}
|
||||
|
||||
# Set the default gateway
|
||||
${optionalString isDefaultGateway4 (configureGateway "4" cfg.defaultGateway)}
|
||||
${optionalString isDefaultGateway6 (configureGateway "6" cfg.defaultGateway6)}
|
||||
'';
|
||||
preStop = ''
|
||||
state="/run/nixos/network/routes/${i.name}"
|
||||
@@ -311,13 +330,13 @@ let
|
||||
nameValuePair "${i.name}-netdev" {
|
||||
description = "Virtual Network Interface ${i.name}";
|
||||
bindsTo = optional (!config.boot.isContainer) "dev-net-tun.device";
|
||||
partOf = [ "networking-scripted.target" ];
|
||||
after = optional (!config.boot.isContainer) "dev-net-tun.device" ++ [ "network-pre.target" ];
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice i.name)
|
||||
];
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
path = [ pkgs.iproute2 ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
@@ -343,18 +362,21 @@ let
|
||||
description = "Bridge Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps ++ optional v.rstp "mstpd.service";
|
||||
partOf = [ "network-setup.service" ] ++ optional v.rstp "mstpd.service";
|
||||
partOf = [
|
||||
"network.target"
|
||||
"networking-scripted.target"
|
||||
]
|
||||
++ optional v.rstp "mstpd.service";
|
||||
after = [
|
||||
"network-pre.target"
|
||||
]
|
||||
++ deps
|
||||
++ optional v.rstp "mstpd.service"
|
||||
++ map (i: "network-addresses-${i}.service") v.interfaces;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
@@ -448,15 +470,14 @@ let
|
||||
description = "Open vSwitch Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
]
|
||||
++ internalConfigs;
|
||||
# before = [ "network-setup.service" ];
|
||||
# should work without internalConfigs dependencies because address/link configuration depends
|
||||
# on the device, which is created by ovs-vswitchd with type=internal, but it does not...
|
||||
before = [ "network-setup.service" ] ++ internalConfigs;
|
||||
partOf = [ "network-setup.service" ]; # shutdown the bridge when network is shutdown
|
||||
before = [ "network.target" ] ++ internalConfigs;
|
||||
partOf = [
|
||||
"network.target"
|
||||
"networking-scripted.target"
|
||||
]; # shutdown the bridge when network is shutdown
|
||||
bindsTo = [ "ovs-vswitchd.service" ]; # requires ovs-vswitchd to be alive at all times
|
||||
after = [
|
||||
"network-pre.target"
|
||||
@@ -521,12 +542,12 @@ let
|
||||
description = "Bond Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
partOf = [ "networking-scripted.target" ];
|
||||
after = [ "network-pre.target" ] ++ deps ++ map (i: "network-addresses-${i}.service") v.interfaces;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [
|
||||
@@ -570,12 +591,12 @@ let
|
||||
description = "MACVLAN Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
partOf = [ "networking-scripted.target" ];
|
||||
after = [ "network-pre.target" ] ++ deps;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
@@ -602,12 +623,12 @@ let
|
||||
description = "IPVLAN Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
partOf = [ "networking-scripted.target" ];
|
||||
after = [ "network-pre.target" ] ++ deps;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
@@ -647,12 +668,12 @@ let
|
||||
description = "FOU endpoint ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
partOf = [ "networking-scripted.target" ];
|
||||
after = [ "network-pre.target" ] ++ deps;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
@@ -677,12 +698,11 @@ let
|
||||
description = "IPv6 in IPv4 Tunnel Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
after = [ "network-pre.target" ] ++ deps;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
@@ -720,12 +740,12 @@ let
|
||||
description = "IP in IP Tunnel Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
partOf = [ "networking-scripted.target" ];
|
||||
after = [ "network-pre.target" ] ++ deps;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
@@ -768,12 +788,12 @@ let
|
||||
description = "GRE Tunnel Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
partOf = [ "networking-scripted.target" ];
|
||||
after = [ "network-pre.target" ] ++ deps;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
@@ -803,13 +823,15 @@ let
|
||||
description = "VLAN Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
partOf = [ "network-setup.service" ];
|
||||
partOf = [
|
||||
"network.target"
|
||||
"networking-scripted.target"
|
||||
];
|
||||
after = [ "network-pre.target" ] ++ deps;
|
||||
before = [ "network-setup.service" ];
|
||||
before = [ "network.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
@@ -845,13 +867,39 @@ let
|
||||
// mapAttrs' createGreDevice cfg.greTunnels
|
||||
// mapAttrs' createVlanDevice cfg.vlans
|
||||
// {
|
||||
network-setup = networkSetup;
|
||||
network-local-commands = networkLocalCommands;
|
||||
network-local-commands = {
|
||||
after = [ "network-pre.target" ];
|
||||
wantedBy = [ "network.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
services.udev.extraRules = ''
|
||||
KERNEL=="tun", TAG+="systemd"
|
||||
'';
|
||||
# Note: the scripted networking backend consistent of many
|
||||
# independent services that are linked to the network.target.
|
||||
# Since there is no daemon (e.g systemd-networkd) that is
|
||||
# started as part of the system and pulls in network.target.
|
||||
# Thus, to start these services we link network.target directly
|
||||
# to multi-user.target, this has the same result.
|
||||
systemd.targets.network.wantedBy = [ "multi-user.target" ];
|
||||
|
||||
# This target serves no purpose during the boot, but can be
|
||||
# used to quickly reset the network configuration by running
|
||||
# systemctl restart networking-scripted.target
|
||||
systemd.targets.networking-scripted = {
|
||||
description = "NixOS scripted networking setup";
|
||||
};
|
||||
|
||||
services.udev.extraRules = lib.concatStringsSep "\n" (
|
||||
[ ''KERNEL=="tun", TAG+="systemd"'' ]
|
||||
# This creates a udev rule to start each service with a WantedBy
|
||||
# dependency on a device unit. It's needed because if the service
|
||||
# unit is loaded in stage 2 but its device was already up by
|
||||
# stage 1, systemd will not automatically start it.
|
||||
++ lib.forEach (lib.attrNames cfg.interfaces) (
|
||||
iface:
|
||||
''ACTION=="add", SUBSYSTEM=="net", KERNEL=="${iface}", ''
|
||||
+ ''ENV{SYSTEMD_WANTS}="network-addresses-${iface}.service"''
|
||||
)
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -747,10 +747,9 @@ in
|
||||
default = "";
|
||||
example = "text=anything; echo You can put $text here.";
|
||||
description = ''
|
||||
Shell commands to be executed at the end of the
|
||||
`network-setup` systemd service. Note that if
|
||||
you are using DHCP to obtain the network configuration,
|
||||
interfaces may not be fully configured yet.
|
||||
Shell commands to be executed after all the network
|
||||
interfaces have been created, but not necessarily
|
||||
fully configured.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -1853,6 +1852,20 @@ in
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
networking.localCommands = lib.mkIf config.networking.resolvconf.enable ''
|
||||
# Set the static DNS configuration, if given.
|
||||
${pkgs.openresolv}/sbin/resolvconf -m 1 -a static <<EOF
|
||||
${optionalString (cfg.nameservers != [ ] && cfg.domain != null) ''
|
||||
domain ${cfg.domain}
|
||||
''}
|
||||
${optionalString (cfg.search != [ ]) ("search " + concatStringsSep " " cfg.search)}
|
||||
${flip concatMapStrings cfg.nameservers (ns: ''
|
||||
nameserver ${ns}
|
||||
'')}
|
||||
EOF
|
||||
'';
|
||||
|
||||
services.mstpd = mkIf needsMstpd { enable = true; };
|
||||
|
||||
virtualisation.vswitch = mkIf (cfg.vswitches != { }) { enable = true; };
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
|
||||
specialisation.new-generation.configuration = {
|
||||
environment.etc."newgen".text = "newgen";
|
||||
# Regression test for https://github.com/NixOS/nixpkgs/issues/505475:
|
||||
# A symlink in a subdirectory that does not exist in the base generation's
|
||||
# lowerdir. If something creates that subdirectory at runtime before
|
||||
# switching (e.g. stage-2-init.sh creating /etc/nixos), overlayfs makes it
|
||||
# opaque, hiding lowerdir content added by the new generation.
|
||||
environment.etc."nixos/newlink".source = pkgs.emptyDirectory;
|
||||
};
|
||||
specialisation.newer-generation.configuration = {
|
||||
environment.etc."newergen".text = "newergen";
|
||||
@@ -53,6 +59,13 @@
|
||||
machine.succeed("stat --format '%F' /etc/modetest2 | tee /dev/stderr | grep -Eq '^regular file$'")
|
||||
machine.succeed("stat --format '%a' /etc/modetest2 | tee /dev/stderr | grep -Eq '^300$'")
|
||||
|
||||
with subtest("/etc/nixos created by stage-2-init is opaque in upperdir"):
|
||||
# stage-2-init.sh unconditionally runs `install -d /etc/nixos`. Since
|
||||
# /nixos is not in the lowerdir, overlayfs creates it as an opaque dir
|
||||
# in the upperdir. Verify this precondition for the regression test below.
|
||||
machine.succeed("test -d /.rw-etc/upper/nixos")
|
||||
print(machine.succeed("getfattr -h -d -m 'trusted.overlay' /.rw-etc/upper/nixos 2>&1 || true"))
|
||||
|
||||
with subtest("switching to the same generation"):
|
||||
machine.succeed("/run/current-system/bin/switch-to-configuration test")
|
||||
|
||||
@@ -77,6 +90,15 @@
|
||||
assert machine.succeed("cat /etc/newgen") == "newgen"
|
||||
assert machine.succeed("cat /etc/mutable") == "mutable"
|
||||
|
||||
# Regression test for https://github.com/NixOS/nixpkgs/issues/505475:
|
||||
# The opaque /etc/nixos in the upperdir (created by stage-2-init.sh
|
||||
# before /nixos existed in the lowerdir) must not hide lowerdir entries
|
||||
# added by the new generation. The activation script must have cleared
|
||||
# the stale opaque marker.
|
||||
print(machine.succeed("ls -la /etc/nixos/"))
|
||||
machine.succeed("test -L /etc/nixos/newlink")
|
||||
machine.fail("getfattr -h -n trusted.overlay.opaque /.rw-etc/upper/nixos")
|
||||
|
||||
print(machine.succeed("findmnt /etc/mountpoint"))
|
||||
print(machine.succeed("stat /etc/mountpoint/extra-file"))
|
||||
print(machine.succeed("findmnt /etc/filemount"))
|
||||
@@ -93,5 +115,23 @@
|
||||
numOfMetaMounts = len(metaMounts.splitlines())
|
||||
assert numOfTmpMounts == 0, f"Found {numOfTmpMounts} remaining tmpmounts"
|
||||
assert numOfMetaMounts == 1, f"Found {numOfMetaMounts} remaining metamounts"
|
||||
|
||||
with subtest("stale opaque markers are cleared by initrd on boot (NixOS/nixpkgs#505475)"):
|
||||
# Simulate the bug precondition: an opaque /pam.d in the upperdir.
|
||||
# /pam.d is guaranteed to exist as a directory in the metadata layer.
|
||||
machine.succeed("mkdir -p /.rw-etc/upper/pam.d")
|
||||
machine.succeed("setfattr -h -n trusted.overlay.opaque -v y /.rw-etc/upper/pam.d")
|
||||
machine.succeed("getfattr -h -n trusted.overlay.opaque /.rw-etc/upper/pam.d")
|
||||
# Also create a non-opaque upperdir directory that exists in the
|
||||
# metadata layer, to ensure clear-etc-opaque tolerates the
|
||||
# already-clear case.
|
||||
machine.succeed("mkdir -p /.rw-etc/upper/systemd")
|
||||
|
||||
# Reboot and verify the initrd rw-etc service cleared the opaque marker.
|
||||
machine.shutdown()
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.fail("getfattr -h -n trusted.overlay.opaque /.rw-etc/upper/pam.d")
|
||||
machine.succeed("test -e /etc/pam.d/login")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -44,17 +44,13 @@ let
|
||||
defaultGateway6 = {
|
||||
address = "fd00:1234:5678:1::1";
|
||||
interface = "enp1s0";
|
||||
source = "fd00:1234:5678:1::3";
|
||||
source = "fd00:1234:5678:1::3"; # implicit dependency on enp2s0
|
||||
};
|
||||
interfaces.enp1s0.ipv6.addresses = [
|
||||
{
|
||||
address = "fd00:1234:5678:1::2";
|
||||
prefixLength = 64;
|
||||
}
|
||||
{
|
||||
address = "fd00:1234:5678:1::3";
|
||||
prefixLength = 128;
|
||||
}
|
||||
];
|
||||
interfaces.enp1s0.ipv4.addresses = [
|
||||
{
|
||||
@@ -76,6 +72,12 @@ let
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
interfaces.enp2s0.ipv6.addresses = [
|
||||
{
|
||||
address = "fd00:1234:5678:1::3";
|
||||
prefixLength = 128;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
@@ -108,6 +110,41 @@ let
|
||||
client.succeed("ip -6 route show default | grep -q 'src fd00:1234:5678:1::3'")
|
||||
'';
|
||||
};
|
||||
dynamicInterface = {
|
||||
name = "dynamicInterface";
|
||||
nodes.machine = clientConfig {
|
||||
networking.interfaces.usb0 = {
|
||||
ipv6.addresses = lib.singleton {
|
||||
address = "fd::1";
|
||||
prefixLength = 127;
|
||||
};
|
||||
};
|
||||
networking.defaultGateway6 = {
|
||||
address = "fd::";
|
||||
interface = "usb0";
|
||||
source = "fd::1";
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
with subtest("Network comes up without usb0"):
|
||||
machine.wait_for_unit("network.target")
|
||||
|
||||
with subtest("multi-user.target does not hang"):
|
||||
machine.require_unit_state("multi-user.target", "active")
|
||||
|
||||
with subtest("usb0 is configured when plugged in"):
|
||||
machine.succeed("ip link add usb0 type sit local 1.2.3.4")
|
||||
machine.wait_until_succeeds("ip addr show dev usb0 | grep -q fd::1")
|
||||
|
||||
with subtest("Network is now online"):
|
||||
machine.systemctl("start network-online.target")
|
||||
machine.require_unit_state("network-online.target", "active")
|
||||
|
||||
with subtest("Default gateway is now set"):
|
||||
machine.succeed("ip -6 route show default | grep -q 'via fd::'")
|
||||
machine.succeed("ip -6 route show default | grep -q 'src fd::1'")
|
||||
'';
|
||||
};
|
||||
routeType = {
|
||||
name = "RouteType";
|
||||
nodes.client = clientConfig {
|
||||
|
||||
@@ -65,50 +65,50 @@
|
||||
"@node-rs/jieba-win32-arm64-msvc@npm:1.10.4": "68146cf2b5324c461847da9fd36aa851aeb5655f94b0178a194630c80926e914b71f5fe60a6853c9197516e2b2680303bf28c405963f8655d0099d335c5178bd",
|
||||
"@node-rs/jieba-win32-ia32-msvc@npm:1.10.4": "38deadbf93c6ffb410a880f8938034635e2ca755b956b7cf0b751f287dbfb4b5e58a492f532f23b30e77a7b3889467055c4d9be4d76df8c4416d97f96c242f93",
|
||||
"@node-rs/jieba-win32-x64-msvc@npm:1.10.4": "073b499e19d211f416a604a791c7a29c99552b328d0565d8381258a49682f87014274eebdaafcc9477238a2fd555b0e18fedccb45a49715ad3332958c6f43905",
|
||||
"@oxfmt/binding-android-arm-eabi@npm:0.32.0": "edad7a793a30eef9d34b2d904fc50a849e8aecfcd8e2c2246cadb6fce8ae14c371100f1fa636c5b66b9118949259eefb968df4391c4047c3a92e678696697b64",
|
||||
"@oxfmt/binding-android-arm64@npm:0.32.0": "e1c3eb67b295627353f0ab9874e53aca9539a35f8157fbbfc6021ccee4d2761bf27db7905b106afe30a646af9e2c802c226f4a58c85b3431df88d352d02a4e2d",
|
||||
"@oxfmt/binding-darwin-arm64@npm:0.32.0": "0c4a98fb78f9984cda0f74f7f64145597beca8ba2916333bd9e6f4aaf49fdbe5f5cc99fe2aff4a202c7e64d640251997c3ed9d64eefa1b51382f92c47518723a",
|
||||
"@oxfmt/binding-darwin-x64@npm:0.32.0": "b97916dd2fe96a09b387f3e950efcce3f4f9b1302c7efa5e7a9b587154929d072a7105aca9d6e4e140ab30b4901d803b1ba5657d0181cbe12a75b92d94400b42",
|
||||
"@oxfmt/binding-freebsd-x64@npm:0.32.0": "5c0eb0d0e7911ee3f6e062c0bc122b92a09aba4d4d55236df331ca24eeb3e90848064c45570a44bbb1fb2cbafc0aab06ea4f85d2c07b68ff4fc1d2bac60d21a2",
|
||||
"@oxfmt/binding-linux-arm-gnueabihf@npm:0.32.0": "3e76615d5369cdc639983209994c7ede0fbc5aa2e05674cf94f5bd325e290fb772f98ad7576da30bb744634e14c82bd7ba03a3715e1977c87c0204918ea7e18d",
|
||||
"@oxfmt/binding-linux-arm-musleabihf@npm:0.32.0": "a4de9deb92d9582a6bce41316d14d9a0867812db561f8514e1f88d6783bb86d396cf39289c203cf1d840636e65687b8fab40ee3823459fae23579778743dc7a9",
|
||||
"@oxfmt/binding-linux-arm64-gnu@npm:0.32.0": "c8d7d6011b3ea535399d40790ac89ec04211dc54c066f2bd624c131df51653be47f8ddfe499bdaebeb1ef655cf72a09ebbd58446f376eae6153ed45c8513dbad",
|
||||
"@oxfmt/binding-linux-arm64-musl@npm:0.32.0": "a6d4281feb3babe222ca0c12cb837ee3f836e6c36f25f036376e8df7976c0ecd46588e202f4553d9858ceb44c277604803870ae3847cca697eef883dd16e878e",
|
||||
"@oxfmt/binding-linux-ppc64-gnu@npm:0.32.0": "69d40a7e7ffe699e07d22b8581ef4f9152075a88f8ee87f83c02aea5d8666c3445d4b121125b2db0b05d533447f8f8b15a86ce10151bfb4d5a48e9ed985cd514",
|
||||
"@oxfmt/binding-linux-riscv64-gnu@npm:0.32.0": "352e28463804f4f5774a7c6375314c8f66e910945da060e7129ea6f9ef4e2b05172f398825279c008ecd2df278fdf25ffe81ceb2c42c7be745dad1e8caea7176",
|
||||
"@oxfmt/binding-linux-riscv64-musl@npm:0.32.0": "e108350c2ebbadd6e0c7e7193f87ec816c3175478c17d63b8eebbb8901dff5c73d14265beff33b9613fc17ffa62956831f57d74eb326defed61c9238386c99d7",
|
||||
"@oxfmt/binding-linux-s390x-gnu@npm:0.32.0": "6cf9b827c188e2d2676d3e52ec5c80d07c1ec1dee8d2b8f21784e70b2f881efdc1b0566d6ff611104b62d83e880b91e253cea6f6154052a724f70e5bbe41e1b9",
|
||||
"@oxfmt/binding-linux-x64-gnu@npm:0.32.0": "65308d09753a0390eb1485297d853c943b2c28fadcb11f8e566fbeb74e58ea7b977f996eb14f2f839ae58bddc1fd9fc2562dc21807aa4a50f86be5ed5f506435",
|
||||
"@oxfmt/binding-linux-x64-musl@npm:0.32.0": "13fe9b607e30cce76e9600ac510035b27f387d57cb3424927853f74af1467580c5bfee6021774044ae12b817985a49793711d6f9f10eb368d762d7bc18ae709d",
|
||||
"@oxfmt/binding-openharmony-arm64@npm:0.32.0": "5df994c65584856841c72097fd9bdba825446cc37b36538655f440af61511bd9a7fc54691e5fa67af116f16cfc88dfe25c2d3cd292c098165cde4e598e96ca71",
|
||||
"@oxfmt/binding-win32-arm64-msvc@npm:0.32.0": "425871b575111f7738404b70d927ec99d5cea4486780371f9b7fb08165afd26988cbfd9248d6daea6a922bcfd8cbe16caa6374fdfa9d3b62b317f5cd565f83ef",
|
||||
"@oxfmt/binding-win32-ia32-msvc@npm:0.32.0": "4cd056aa20632b2b40bb29d31e6f3f29b7645113339d514bcbe67fcf532ee474e357b851366177d4e333e6e9cce8008099b7c81d2098b5c2c3dc3b1c3bef7746",
|
||||
"@oxfmt/binding-win32-x64-msvc@npm:0.32.0": "177af22b383015f3e4ebb46ae308e21c28df9a157b098533c45039de96008ab05b0f91f0148c159b4d5f6ca1627b8e600d71c2ce800826bda5961b9e23b4eb95",
|
||||
"@oxlint-tsgolint/darwin-arm64@npm:0.13.0": "452933ef927377bf5a8339abae8480168838dcf43dbac185138dced6bcb182a82415e45bceb60176cefed270f3a6f0b25b82c51407ce47b5affa33c147b9e6e3",
|
||||
"@oxlint-tsgolint/darwin-x64@npm:0.13.0": "7572222e4cc5c3fae9ba51f86f30542d9581b6e9493ebbcb54842f5321a34972e7d6d7e6cf802a096d17bafa983e000fd6a72025897e3181b64a3e5fb4440802",
|
||||
"@oxlint-tsgolint/linux-arm64@npm:0.13.0": "94cc4283f9c9857778d68030ce4e2e337b258dea153e71fe4d3505b4b4c996d8c69d18c1969953ef5030e64ff2aabb49811ba5a03069d95ed9f880a22502118e",
|
||||
"@oxlint-tsgolint/linux-x64@npm:0.13.0": "c2855e98f9bcf2ecc893c06518ab23dbcb661ba4c18bca60e6a48d12ed3a52737b23fed5ebe30f0c6afd4df9538a9c34330e15e42de4efb120b7eb0ebfeeba2a",
|
||||
"@oxlint-tsgolint/win32-arm64@npm:0.13.0": "e46e11b10c2d2e8efdbe110e99153036e34d1f1e19d0eb111c8717602228d3bfcee4aea04f2a1d2510aa6884fdf4c47f3a533782e45a6872721cb828f5065ab9",
|
||||
"@oxlint-tsgolint/win32-x64@npm:0.13.0": "d200689f40a6bc805b079230f1a731dae3b87d0747ea197ffcfaed94b2131335941c71b2e2df64df917ecf14f13cee4892195727c5fe996909d81edff499964f",
|
||||
"@oxlint/binding-android-arm-eabi@npm:1.56.0": "463bd488374f85f064d5180bbf21ce8b265d6d9784e7f63af2195d35247d545ccb356ecfa1c16ee6ab31aa187f520d348b7198f49d1d6c546c49d25fe7f7e65a",
|
||||
"@oxlint/binding-android-arm64@npm:1.56.0": "fabf10dec868c468d57fa9f291ba140a006cd8f6a03cf959e3961d072bfc776f9486b8bb4141b7ea3a31221b9a92299386b1cbb2a2e547fa66f2006b4be86ed9",
|
||||
"@oxlint/binding-darwin-arm64@npm:1.56.0": "3041dd4d4d22c59107e9694b33b7b87ca2f62f6a0bb8880812986cd795709594fd02af791f6f7c87d4433198ef772b945915a50ab2d7984b4abca1128b8ec671",
|
||||
"@oxlint/binding-darwin-x64@npm:1.56.0": "55ea3a1aca8a9dec9c91dde13e8c8a2de48256a1a548f7237bc150e12b6b861719f5d663fb0934096bc0491c5669b8628fbc68407dce01acdb49b5a505852c63",
|
||||
"@oxlint/binding-freebsd-x64@npm:1.56.0": "f76e1637d00c3aca4371c9f469c133bb3290a13a2fe51e3e9e18c6e10de17fb10477bc73d77ce43053172e9314d2662adbc9db8ac51a51d0f8f7d78d3a651306",
|
||||
"@oxlint/binding-linux-arm-gnueabihf@npm:1.56.0": "e385462613e6e5e479575c860dcd0855db092a163f0498ba9b89dd81f691704b9bc4b1818c0dc6dcc3973ad1fff1d2710797f87304ad3cfd9da6280766d7d520",
|
||||
"@oxlint/binding-linux-arm-musleabihf@npm:1.56.0": "35f796b2ec0e4bd8f086e664033c1fd4c338b392ea8b9ab96821e00c75d05e0d3aacc2f270eb03e70a00013c52e1d53578df728065c48c9193e323aabd1bd0cd",
|
||||
"@oxlint/binding-linux-arm64-gnu@npm:1.56.0": "6216ff386bb4e4fbcbb53fa69603f7e9eb1a156c0d3a34aca8cf664d8ff21a17804a905f6917626581037fc8b1a4f962302d626dee15160983c3e35960157359",
|
||||
"@oxlint/binding-linux-arm64-musl@npm:1.56.0": "4e1e8fbbe11e39549e9c1def3ce7fdcd257b5eca46458bf9c82e3a5971775617dca7c6e3a50fe2c09c69b71980fee7fdd281ed1372af25a49b3497a7effe6050",
|
||||
"@oxlint/binding-linux-ppc64-gnu@npm:1.56.0": "0688cf639b9d51c1e87c9aabcf9005cec6bfbf4d939871dc2853711935c3788bccec1a8aa3bf38af5a7a8821abca3fa68c5600424d34ebc339ab518a6b18bc21",
|
||||
"@oxlint/binding-linux-riscv64-gnu@npm:1.56.0": "8a5eb4ad619be00b4345144c2af924f91ca311578386f96f0954f1d5cb64442e8dea857aa91fda55279a8f24f58b6f99d9824646976bc35c556da406218467b8",
|
||||
"@oxlint/binding-linux-riscv64-musl@npm:1.56.0": "8e4b81e2fd1781b2017528973b37db4c46fee35a1dc8b317295ee65652e55bf8238b6560d6d48a4bd0a541b9f67730c605082842768eab67b4b06158503241c0",
|
||||
"@oxlint/binding-linux-s390x-gnu@npm:1.56.0": "9f3c598dede43a697fa53014145c895aea1e1f5390d7c5e28bd0a9a03dd32536287373a98d1ce372a41c5be1141785aef19dc63432aeddc1a86f220814cfc183",
|
||||
"@oxlint/binding-linux-x64-gnu@npm:1.56.0": "8cab5595ee3e7d39a3ea0add9813efbe57139e445b754f5dbbbfade372ef85c8784f5bd2cb0860941a1b7e9173f4b782ae20c8ecd4b59c4dab9ba80de3382aa0",
|
||||
"@oxlint/binding-linux-x64-musl@npm:1.56.0": "b7111435cc3938911aa5fc05e90a8b878f0b848e7de4cbbd2f4cd633ceeca785b6b0354dd5fd37174485694ca333292039a142bbde0e546e4d8a58ba62d296f2",
|
||||
"@oxlint/binding-openharmony-arm64@npm:1.56.0": "8d7184c5517c185f64ab6b076a9e59277bf49d46cff8e79f708992bf52d9b6fec9c83e04f7c94d8527044051709eb55e5b82e304e9af9e6cef93f66894601569",
|
||||
"@oxlint/binding-win32-arm64-msvc@npm:1.56.0": "7fb42e1b53f453c53b33ea2f6564e864bb8245669e6dc52c0d4f9a27badeb52e7764c34b6f64b4a87ab056dd636b608be161aca5f0cbe29613365c60ff98810a",
|
||||
"@oxlint/binding-win32-ia32-msvc@npm:1.56.0": "fc397d81eb0c0e319ec3e3242ce1f05efe8368e659c6aeba99e630a303b539a80adfe97bc361430b680d24ae713a163712d087205ac8c60804ca77c8018c2a1e",
|
||||
"@oxlint/binding-win32-x64-msvc@npm:1.56.0": "29693e27fceb5daba0d13a1daa9f6767b2462a7e91ab8107164bdfebf6ccd88a8f648768c2cc024faa76dd75b22f54be16cdd50146e4483b9b8da2402d38d7a1",
|
||||
"@oxfmt/binding-android-arm-eabi@npm:0.44.0": "f2b29210336a7a06da7b20dd7b793b3e5f0fb1785af1deb7ecce7a8360a694d20998cec5cdfa6ef97cf6d3ed964f7771c32ace3c762b091e4ff716663d153f40",
|
||||
"@oxfmt/binding-android-arm64@npm:0.44.0": "08581f63c72281f9abb02c8414803eb352c2b0b59d6a16ad525ae14c1f94cadec7986cfa3f1caf1f1ef6f35811c18f070b409fb087878c413d740d4da271373b",
|
||||
"@oxfmt/binding-darwin-arm64@npm:0.44.0": "e77c7798f60ac34847d861e7e26973c434d00de3ba8bcc789a9658bd55173dce42fbe2db7fa33535f77a6f3d806f95ed18a177ca1fd24035298aeec7d76ae5c0",
|
||||
"@oxfmt/binding-darwin-x64@npm:0.44.0": "8f2932eaf568c807e9f0a1b246eb43fa84d17ec904423b44b07f494bd7dd2fb77a467d2e6a983d9bcaa072950b52b9bc34d4d1a91491514251532edee0873b0b",
|
||||
"@oxfmt/binding-freebsd-x64@npm:0.44.0": "2554102821657a66f606cee2ddd283d14a0de691fb016817221ced0be39fc5af7dfe23886ea0bb4079cab48aa56beb4be7d34d38863518c48eef6fd0c64a315d",
|
||||
"@oxfmt/binding-linux-arm-gnueabihf@npm:0.44.0": "cd24da3e57c6757b07ed5e13d3e3293790ecc1c2f198356d16f3cf58b221ec7901417c275a51cf9464faf533aa6a99aaa1b9ff845f2ceb71699e6939c49b2d90",
|
||||
"@oxfmt/binding-linux-arm-musleabihf@npm:0.44.0": "5980bd7834eb040c5e0e7551d0032e17c73d446253af017c7f7053a0672d51f0346d03b6530979c6f6f6f8564cde6a11ac329c48338c16bee73d188bb7692649",
|
||||
"@oxfmt/binding-linux-arm64-gnu@npm:0.44.0": "0b79af84e92ce7200d524e04e48e59276580552763a62b05d247066f0a788729db94fd985c81b92348d794a5f654e686a17542b228b4a5ac0776c30a786abafa",
|
||||
"@oxfmt/binding-linux-arm64-musl@npm:0.44.0": "1a281d213b7f02f6e28519b2ce7a4bd5c9b540c0c37f2c3b9b786cd616fa91e134b5a17d3da593f311e7b272d5534fa913af40829463987ddf2dc70fcda63cfd",
|
||||
"@oxfmt/binding-linux-ppc64-gnu@npm:0.44.0": "b0a0d63384eeb33fed63d353b292db5ef1dac113b692455b36f462d97f66b8d719a07b71affe63f6f555856d1261c24eccccadc72f04f720b7470321aaacc67e",
|
||||
"@oxfmt/binding-linux-riscv64-gnu@npm:0.44.0": "b005497fedfde005c8165a646d4b7faf35c63242458166c130d7e15e6eb8c285cfc9907cf44885c05f4976d99366064ce13eadf2d6c7867b75f9ad28765720f0",
|
||||
"@oxfmt/binding-linux-riscv64-musl@npm:0.44.0": "2f95d5cfdbba63b9e74158ce9c64262f1be28a2483c961f7e376d27c43fc582ded2a2358d459b1f503100c766b5207e7e77fa2e27e69f2a3975ddb75bc9d93b2",
|
||||
"@oxfmt/binding-linux-s390x-gnu@npm:0.44.0": "bfd75043bd870f1b5142966383d7256f3fc596e6ce2de4365e964efc0c6f716f222d9dfccdaa901e2b55edfe24a6ef83a2ea70ad2b79c31da1c9507d157504ec",
|
||||
"@oxfmt/binding-linux-x64-gnu@npm:0.44.0": "4039e8c3027499baafd8da1e612c6fe01d0ce86c7993064c133e879c64355f02f9d9f951388919610264fd33c2917fb6535bb0c72e3b222cd3bdc4bf4beb8471",
|
||||
"@oxfmt/binding-linux-x64-musl@npm:0.44.0": "7dd406f8d19af090cc6c42aa9d420a5d074c15a0a214cfadb9c3c6a6f7588eddb38a91595371b0d9d247635ec7d130e349e93edec7be759888b702b4a8405919",
|
||||
"@oxfmt/binding-openharmony-arm64@npm:0.44.0": "5b9078488871e85d57a5af8eae390dba125f37a5ec1e1d120ee34d1d9b368f6b5715f26d3fcb3adbbc1d2f06cc928e3f73103f116f0323fa02d0f5305621e7d3",
|
||||
"@oxfmt/binding-win32-arm64-msvc@npm:0.44.0": "d9aa3808de1a6e910e463235674cad17f90f015883bd1a74bdf9a1eb17b9ff0733f39f4d0a3af9b005fd55ec5584393fd1a6effb2858bd677aa205a2b8ed153c",
|
||||
"@oxfmt/binding-win32-ia32-msvc@npm:0.44.0": "b441cb9974a64d1e6dbca885000aaa76e36e6bf99020bd7172238b60c165587de737c6715259b19ac982bb5f3d008a1cf7088f8be06e4343c4acac7702da88f3",
|
||||
"@oxfmt/binding-win32-x64-msvc@npm:0.44.0": "35e4722f8594092dde9b5ee51693766928205c7bbab44e25710584ac13ae71460bf3dfe34d7222eba5d24d8bfb58700cf551873bea876858c1cb3fdb355f9945",
|
||||
"@oxlint-tsgolint/darwin-arm64@npm:0.20.0": "34285104efbf3569d3c9dcbb4ce65c33970377fa2f5133bdc58a0b8dcedca269be03dac054c031f594782487b97a59b93084ea525e4acba5c4e45d10299f813a",
|
||||
"@oxlint-tsgolint/darwin-x64@npm:0.20.0": "d5f5f6aeeb1bc08f1c74a7952450da97eeb4a8970bcb28645121cff9c9ce3cdce03da60c4814769f355ec9cc1c8e2b70f0ed268117cc383569c7c3b4da617d24",
|
||||
"@oxlint-tsgolint/linux-arm64@npm:0.20.0": "93d1bad95440a976e8c241c1e233151bbe4bc8780bc65ea3605fb19851c59b8f7cc45fa0797398620c31b6b93c261964696bc9ab8fddf6ae625d2ba4981f171d",
|
||||
"@oxlint-tsgolint/linux-x64@npm:0.20.0": "09a6529dbc46cd4b1f4f650beff905d306c264638a27ad36c46ef8631f64f689d660acdb1ced87c72406fd380b9aaa95599e6b99c73438eabc1854fd920cf6ea",
|
||||
"@oxlint-tsgolint/win32-arm64@npm:0.20.0": "422cc8a91a65cb4bf39306da2809e963cb15fccd7600b7d99a6ada0f10cb6934ae1b6f25c881c27a2651e0bd601417f7cf6dbe65dd32f9bd862b5a76d8227a99",
|
||||
"@oxlint-tsgolint/win32-x64@npm:0.20.0": "547630cebd56abeacae7af89df6fa46b9165732b34b72e6a0c95f2d619db9307bb0d4a7bae8039426a34c3412681962f6ee8cdd1db0bd333e287da6322b91766",
|
||||
"@oxlint/binding-android-arm-eabi@npm:1.59.0": "fd7147e2bc930ffe34b5de0de3195e20372ce9a392bd0782f9d96ebe19e63cf7969da89cf7060d7f43ce1bc429ee14bd5b8dc8874fda3a5d0bc782d1cdd0662f",
|
||||
"@oxlint/binding-android-arm64@npm:1.59.0": "f674440a9751e274d0ab588539cc13e5abe0c6464abdd423968572b034ff3e54c6f2a173d22df0425e16c997caf69b84b955f8457cacc908f331f54df6de2821",
|
||||
"@oxlint/binding-darwin-arm64@npm:1.59.0": "29484896b54454e73932476adb9740c5bbac166c9fe138a6df921659efdca0b679822e463dae8b0baad54a30b0deb9038b0677ddcbc11680defac9df42b644cb",
|
||||
"@oxlint/binding-darwin-x64@npm:1.59.0": "b16f0e20b766b66e71088ef484051ea266c9f730358aa1e41e20f02ca2a1455eed8133c3f7d79486ad0aab1930915bfe75426c2c16b8204d3e10f9a489cd0d5f",
|
||||
"@oxlint/binding-freebsd-x64@npm:1.59.0": "5c00690cbe3fcdf6634e2e5424d1a415fc455cbd1bae264b3a0ce3ee3eed0eb8a0b825a2fd016c04afe79c863574557eed74734c5fecbd8643d62aa1d74219fc",
|
||||
"@oxlint/binding-linux-arm-gnueabihf@npm:1.59.0": "a55e2a9ac39526a5a432fc4bc69f056e5507ad7344b082dde448e70fbeb7c180b1edcb62c377d38a99710662d8b935ecf2bdeb75ebf2b9e9425e6179616fc7a1",
|
||||
"@oxlint/binding-linux-arm-musleabihf@npm:1.59.0": "5068f1da0497ec448e87cdc1c5ee99bfde09a050ba989b8dd3df445199360bde081eae327f52f4b37572ce300f3295444ba25a39108c19c93fa5859b9d1c8e5c",
|
||||
"@oxlint/binding-linux-arm64-gnu@npm:1.59.0": "5a3a974a344731db64951c3aa3d591f82a2c69926bfaec1d42338aaa0a65cea97c94a68121d22441b655d80bfc0e8dfa81944136ed5a0abfb1353a46105d8478",
|
||||
"@oxlint/binding-linux-arm64-musl@npm:1.59.0": "a2158b760c37796f5f416a2be77110935329a55788752073ac257de8d874a57cf954b90740dd1952c2f63c6d3958dad0077681de098406d4c3586ca92061804a",
|
||||
"@oxlint/binding-linux-ppc64-gnu@npm:1.59.0": "88feb1b571f3c0eed7f020c5f06d729087571e9515a309eb3a54b25630ef0f951c07f81495598d634b0edc75abad07f1c1e595e2f42b5849fc82c90acf98825c",
|
||||
"@oxlint/binding-linux-riscv64-gnu@npm:1.59.0": "88805ce56f0aef2dd0bc943bda3f1d2a4ca4e68765478714c26dbe95c42a7c3c8087b2658501ea36d1303b8f2aabb9c0d68586124cc0a20f8fca70bddfd598c4",
|
||||
"@oxlint/binding-linux-riscv64-musl@npm:1.59.0": "1d99bb0491a1b02f2b2a71707d73527b1e43d18d0a5b1d964d6752af748f1e6ea73eb60d66dbce1681feba48152c636639949e9d3ab558e2c76ba58372ce280e",
|
||||
"@oxlint/binding-linux-s390x-gnu@npm:1.59.0": "d5c3a9da18eb31597c59c17bb03eed3ca77360c0a8609097bf367f1fdcd33cf0c1a604cdec46376ff63c7741c723df060fc5b78adb256913f567a424996f665b",
|
||||
"@oxlint/binding-linux-x64-gnu@npm:1.59.0": "963388bfd60e5497ec0f3e6d05b4567ed795f132f47cc7c112acc18231225403361e6d4f8b35923bbead94d9864e6c76754014dd6ef779dd85d4f9070605dd14",
|
||||
"@oxlint/binding-linux-x64-musl@npm:1.59.0": "782a7fa5b28a87c2fb96fdce112625906c78df953b141f0d43e7c064eadbe4694535cddcc2bd05c7312eed0147002f4c45faabb1990e282cc0471de8e841628a",
|
||||
"@oxlint/binding-openharmony-arm64@npm:1.59.0": "2a6bfe67c9b1ea1cd202bb84a7dd938343735afedcd2ef975f11879a0cb24a1fb7969ef47c9aa1d3f4255134483254ea83dfed7c1c674eaf9e0412371fa69b1e",
|
||||
"@oxlint/binding-win32-arm64-msvc@npm:1.59.0": "2d8a5052bc2d959ddc57ce3ccaba237e4976e91a8bfaa0b3a658c05ba7b771f44098b406bfc610e0a2b25252d0b11f6d6240af9f095850e49d5252cd628914ba",
|
||||
"@oxlint/binding-win32-ia32-msvc@npm:1.59.0": "1f17010c128674db9782107427e6db331aa53f437bc9fe2e97a9d37d8b25f9a011b709981af0ec1e0af7375840ffa4e3dbe9e10494c2aac949b71206cc934a63",
|
||||
"@oxlint/binding-win32-x64-msvc@npm:1.59.0": "7d0562b3977c612e1278f8a2ed06e7e3f19a1242ba50510a68ca6adec5e6fa0d5e2aca50dbdbce69088991b233598aa8c514c5d84f5a5c1fa039b29bb453d49a",
|
||||
"@parcel/watcher-android-arm64@npm:2.5.1": "e9c94ede3bd5c5d999d117d22ac8032a17f8ebc72db3eff04ccb2b4e6718db19f24bf29a66a610e03f4ee95e2cd7b2d30c15b1845eb897b971fec75dbdd76141",
|
||||
"@parcel/watcher-darwin-arm64@npm:2.5.1": "0cab55a55c128ac5742388fc8dbfeb9877018509943801ce8a52b57bb6dca24189d025d38684b1e482cb7816368a52c6434dfe45d3997e2fd2509276f48774ea",
|
||||
"@parcel/watcher-darwin-x64@npm:2.5.1": "bf07b8ca9a435fb885fb0ca6565204d2f2098d7f632faf26a6478bb39f538c73b50afca17c193dc189a80a864d85e40f924ec7f21a0e7ad7d0de6f97f7154134",
|
||||
@@ -122,21 +122,21 @@
|
||||
"@parcel/watcher-win32-arm64@npm:2.5.1": "0f467a731cf9403b8bc7d35418d991596cf5e7898029796b4c769bcbb38cd07ae6ec05ef0f19298e5f11e73ec5198bc474d79b056bdfbaea513525725103d7dd",
|
||||
"@parcel/watcher-win32-ia32@npm:2.5.1": "9ab5f3e9849a6077c8c2aba7bdf9030dea38f0ab9180792ecd30094520cddf16f3b68006f666845b86c5ef0e05c648364475c9ba151e0269561891ca3e276667",
|
||||
"@parcel/watcher-win32-x64@npm:2.5.1": "e588d87d5b892484d252ac8e1ec3f4bf7a664d91f0d03dd93764be8db2c35f81879275908dcbec42b0e43bc99c7afdfd29fe687ec022bb2c8c4bc7edd29eaa15",
|
||||
"@rolldown/binding-android-arm64@npm:1.0.0-rc.9": "681d0f60ac8346ed1472b446dbb04c89f082d05eaadd643093f861d9782b8b9c961af1529ac50ede6e1d0d82162413be7996cda3582c6839fe8ce110e6a8fe47",
|
||||
"@rolldown/binding-darwin-arm64@npm:1.0.0-rc.9": "1aa953031ac0743e3c21c30d5423f91910228d3ca626178dfb6c526d7101ce0f782738c4508fd5c8c8b13db1a7cae7c60f56645903d1eeb6acfcd62d6038a62a",
|
||||
"@rolldown/binding-darwin-x64@npm:1.0.0-rc.9": "04b667387c89dd09c16f19d89779faab109ef77747d574c9d19f03a45c6199d761c50f252ebcd72bb2f1a963d5159562e6b9c812412b59191cb5ad39976faf85",
|
||||
"@rolldown/binding-freebsd-x64@npm:1.0.0-rc.9": "be6560cb62878c11073455c3f8c9d60f27d42e847e6280341bb3f203344b45f6ad0045217229488c13f02a41b5b3f9c92cc4e3e5eda3167e92975ec6690559de",
|
||||
"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.9": "d943e78b207ab210e0e30080f3ee67294e22346d44535e1e06252b954cb0df5188cc0808412b3c74a90b07f4b380f0ba00ab3c0500f8f59ac97c5a79d52a256a",
|
||||
"@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.9": "db9fbe0bc638788fc2bad53d63b9943af0472f01f37eecd552d06bb773f3ce6594fe7cf50b2bd8f2d5b72bc60b9bdcfc5b8e45ea8ea5d368bdc062d3104f37f2",
|
||||
"@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.9": "1284b2b09a688dfa979d0b3ba1969ae30ebd29fa56f700d267f1862aa14327fd58bb92e8e201f166c31e916d9c2b3e56a991dd5a83efeedde6c6b3925f066aab",
|
||||
"@rolldown/binding-linux-ppc64-gnu@npm:1.0.0-rc.9": "4c051717e829c1a412c924e8c02f2b665fece40d00945d73c533dae75d68f3a0c7a219abab602234a6bf15049c9a1861e3788a97e9f322aac95e91c6d12a2db6",
|
||||
"@rolldown/binding-linux-s390x-gnu@npm:1.0.0-rc.9": "63528c47def8780bd56f0851d9d63fa9a4aff24e87766989cd3b30478f3e0240a38ada7df67343cc8c075f2f907b0ba3feff1de1fa312727446fd762b313b3ff",
|
||||
"@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.9": "9eee8d3facd1d0249f0e8c96a0cd0021875a6df39b00fee0a88629a1d3f83210e4c8216b35ce31b3cbe8e3399829fb10b805bf6ca6d2116658c8bbe5a63b93de",
|
||||
"@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.9": "542bc8bebc8c0373a3d6a7d9a8a3241cddf1cfb64bea0a93e208410d88ea4b6b40e3ade7615728203460c98055269386931faf79e3b94f184446241f2873a55b",
|
||||
"@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.9": "4c3f8c7e29c7f2e23c8a98f16bc88584b6c770e03ba4278d7730d844b9595cc9fe486dd8db8b5df514351c202de41dfeec29e9cb49a345b68fb89e751046355a",
|
||||
"@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.9": "a4f8b94a3c8fc67890e4ca4115a58fa096cd17060ff6a04f296fdf4e9925f88dae82e6ac9213b63b3bd1e44dd5454f7f37d24c5710e93466bc565f2eada56508",
|
||||
"@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.9": "ea4b5f173b212c0facc574814c7f303cf7ff3819e190ad2cbe0cc945853e01f984e3db475d586276c9d57bb33eaec3cbbfffda202dfba22a969457808b8f9037",
|
||||
"@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.9": "33ee0f9797ff858c5af077b5907a7becbd2719c76afaa8069cda7fb911d404fb4b038825f8c976efc3ee0bd6dc882a9d4c4b240ab9cf8000ddd720d551ef5a8a",
|
||||
"@rolldown/binding-android-arm64@npm:1.0.0-rc.15": "d93872015985b19d82db7a99deddfd1bc65c3eed7928004c36cec11b70e405b82907250c183367b47ebfa2bec83582b3369b91d288ad5308152ceff860ec2a8f",
|
||||
"@rolldown/binding-darwin-arm64@npm:1.0.0-rc.15": "1b8240d7b1f0601d6efa84d48a232e8b0e6239477634c1b7af5b27055a10aacb893522ceb08fea8800e7ce5ec882307e069077ec8626039684a323a815ea1639",
|
||||
"@rolldown/binding-darwin-x64@npm:1.0.0-rc.15": "a73ed937b8e7dde059cd600612c359ba02dd4ef3ebcd0df3e5a2e5c0e1a7e4c8360fbfd40c066de9a6f2af471b8322b49471a6261bd322417e9c7f955eb52335",
|
||||
"@rolldown/binding-freebsd-x64@npm:1.0.0-rc.15": "f7c48373838b49a1f3ca592299c9e21b829e4efae62e9980a097655c01c9ca65f079e0d04bb5604887b09660d71ed6c83115dfeb94cd7d7cbcd67000a4e84edf",
|
||||
"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.15": "0681132aee29f8ffca4f436034f4bd6ebc4ac9ef15ac9857be09f991e9a1367f3e97d98f88e136659b5a5cab520f5a304e0551cb0f08320426f718c6475e64db",
|
||||
"@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.15": "9f1be6a7f61d913d678d77b21c499dce756d5b4d496c7665eb5015a7f9b0e52038121ab313b223448502a1f23f39f4952ccaf4651d65821ef8d0428730dc5d43",
|
||||
"@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.15": "c13142d79451dfe6c38cc18f1ec170b87ef95546f45a465b9965b6f8ae8b162d278c77654400e69c9af7c09c8eb84c59edce6f741bc08e2f3553b019c40f51ae",
|
||||
"@rolldown/binding-linux-ppc64-gnu@npm:1.0.0-rc.15": "10a94ad784a1997f5fb3756e44282b33524b32cfc52c622e81bcc1c178fcda3ca44734bd2562dae900e0637233bccc94f298764fd43acd5037c4b66aafab7651",
|
||||
"@rolldown/binding-linux-s390x-gnu@npm:1.0.0-rc.15": "ef16b67d35aea455ae16c07dee6e58ec5515e2dee2b9ce0fa38752e15d12b2398f3e032485041e6234028d8ed85028c1072d73d2b0a912e0de5082ea89144cc6",
|
||||
"@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.15": "8eb51515e2a1bd05120ff74728e972aa563b0c6d6968f78a79a9949b008c9826875c4fb74aadc7c2a1bff065d91970b706290a973128066c076007f471940f31",
|
||||
"@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.15": "1169f12fb17b8a58d5085a9968e4bd92b63bd05a9a693b9113b15b01d53c482150bdfa2226790d59c398f49e58d93200aa7a297a7994a31cd343152303a000de",
|
||||
"@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.15": "c34353635835a2fae1e637f7a02266204767901211438bd85c8d887bf741b81367ed3b5eed595f3cd707fe3b8af14a7ff53ad211f2a944e6e9e74dd4ca09d73c",
|
||||
"@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.15": "429df3739d6257244ab5d481fcc4b575c6c3f50bba7afdd9f3515832e7ae5175a215dbf591eade537fb2e6f7af38bc8022bc55bfffabfe650048563d65151304",
|
||||
"@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.15": "3cf2f7babe9e9b02b0dfa58b3eb8204753b4ed1eaa1e8567a932d21a5d90003dbb4b6279c928f15dfd9247dcbc8aca36fa6cae7790f25cffb91c3d4eacb7c0e1",
|
||||
"@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.15": "cb262337da8a42a84b53430c101407a72c142b947a4588e55d6d1ff667e853fc704269436703761b127bf4895c1e205ab33b4630e603b8b5bef35aebe2c36afe",
|
||||
"@rollup/rollup-android-arm-eabi@npm:4.40.1": "24131de0516010cd1c52d399fb17dbbe93b3ed6a981b57d82f363b9102a04083d470d0d7ead324fcc16e0eee7d54b7300ed3ce72bf43a4d277b959eb79f7490c",
|
||||
"@rollup/rollup-android-arm64@npm:4.40.1": "6b02d5c1a8e5cb045ea9d382d71a9bfcd81da1d508ebeddf5c5118f99ce13b431af357a0458d922c03b26a00ca6ea72a861b1e15b370f20275ee73eff91fd7ce",
|
||||
"@rollup/rollup-darwin-arm64@npm:4.40.1": "2c47b17a3670ff37a3a4ba6615f1514284317adedbf629b9d989f879f2ccd0c299f69c7733727150206b1edd96605ab9d94b6f0eae70cd7556542b436111d5c6",
|
||||
@@ -157,23 +157,13 @@
|
||||
"@rollup/rollup-win32-arm64-msvc@npm:4.40.1": "d4c9002b95c4b6ee842faaa5087582a0772578c0969c9ee470697a6d3fd251845481285f5a4027bc8c0524bf277f3437844cae9936c5f96ca753dcca61e2f47f",
|
||||
"@rollup/rollup-win32-ia32-msvc@npm:4.40.1": "446e3ce5b037d1847af84e9a2b52734ae9f5425937fec2558d26ffb5c253dd8925dc35591abd78b0d43f7154222e47ee9aaeb3b167b3d69627805a97c5147185",
|
||||
"@rollup/rollup-win32-x64-msvc@npm:4.40.1": "39fe3c6b86ef880fb1d1261f6096d19707584c628271d6ae01f5a5f50d8a24ef62128b5929064c0aed4390c7c0c0b7cc9590e300fa5f10ed624816748da2fbb2",
|
||||
"@swc/core-darwin-arm64@npm:1.15.18": "1597877545538954d6445a21f4a102766f098aa2b0d55ded3a766993b527bf1bae9bca54e50e3289b8f6a0cdb42b550f65da38564340d954690df15d2e27f56a",
|
||||
"@swc/core-darwin-x64@npm:1.15.18": "326b8c3309c303a53bf4ed6afbfb0baee0acdb527253e734fe5cefc6916cea598d75fb508265e482143e92fabaf2cacfe9e3a30301ed527c32a727f998a65239",
|
||||
"@swc/core-linux-arm-gnueabihf@npm:1.15.18": "0d26738b4675ee1ff5b0322295c947f351e6d2494303248971b601e2fcfd666a17357a030f0a745e11b60065329652daa58db44abcfc7620f2da8d92733dd0ee",
|
||||
"@swc/core-linux-arm64-gnu@npm:1.15.18": "96aa824334204b6ae8a9c337a745a64dedd4913331f313561eb9544b853e142d9a933230d06052eb677cffbed0b1c961389f1d626936a9b5fad6400ad254229e",
|
||||
"@swc/core-linux-arm64-musl@npm:1.15.18": "3781cb4bfce767fb85506a69bc6fb7745ec53be2a53735750ae88f51c3d6803725a3a906cb954888c529e7f675d3ff0f746bb22c646f1ac2caebdc2be64a852e",
|
||||
"@swc/core-linux-x64-gnu@npm:1.15.18": "26f6fe774e88f8d58a48c18666eda6345cd7064cf065f02eae683f6eaac3e345a5fdbef22a8b3aa7069e332fe95c4b496cbab438bc2b474a9fdc8b37a616be0a",
|
||||
"@swc/core-linux-x64-musl@npm:1.15.18": "96b5bd1bbacebbf806f9a6a02698d68ba2a677ce86b5c2d7a92ea6083b40d55a0a84abebd16b5afd7a574e727b8c19e9039315e8ef40f6c852bbfaee26f999cd",
|
||||
"@swc/core-win32-arm64-msvc@npm:1.15.18": "3a170183da529015301e48bd305f9ea1bcbd38259ff25f1f6e778ee4bb68fda44552c696f067005729aa77407295b1388717a31d9429844725d7ee29645bde82",
|
||||
"@swc/core-win32-ia32-msvc@npm:1.15.18": "a950c9d1d6338939734249ddb766c495e86e05509bb6a42f58d2713d419d4412c06fb0c11c7711c6612ab3e74520a8c1581449340aa3f4fe26f71c53675f37b4",
|
||||
"@swc/core-win32-x64-msvc@npm:1.15.18": "68eac0d5148e7326b748a0f0adf44bffcfb1d0c78e366448aad9859eda537941391ea95e1863118460a49a58235ce9791ae1b20afc04a034677167e6ea43a5e2",
|
||||
"@typescript/native-preview-darwin-arm64@npm:7.0.0-dev.20260309.1": "437a0ffe06d99181f7dc9af64bd049ec1ec84f2a4587d2cfdc8fb64cffac527de6cb710b100f87a7ae4b97fe3cdd876466f570424399a1b71496c526c7cbec13",
|
||||
"@typescript/native-preview-darwin-x64@npm:7.0.0-dev.20260309.1": "02f218b9974f2ff8afcdc1716ee04d4021084c278d0e51a5cc5db2b8ffc590cf96877c95178d86157e0440513d7427e562c5d63b9e00ea81396dcb796385e789",
|
||||
"@typescript/native-preview-linux-arm64@npm:7.0.0-dev.20260309.1": "c3a070ae31cd0c2e2750c5ba2332352bc575a0be06e6923b8aa0f425d50c95b922df9ae540c17f87affb61948555db63ea9f21df6cb70b2345632f1bcedb2d87",
|
||||
"@typescript/native-preview-linux-arm@npm:7.0.0-dev.20260309.1": "08c8f9a22cf9f1508c84cd8710a44e4983d41df95a58e79a9b32c177e1044f86d0b19b993cc0bfcbdba0b9ff12df1f22b878cd33cd20288eedd6903b25b69608",
|
||||
"@typescript/native-preview-linux-x64@npm:7.0.0-dev.20260309.1": "7baa4d2aa516e2af41a255c2596c795f8a782d4f053ae109e08741eb67a6d5ebea630e29656519f4369b3a71d23467a50914b02206f4118d5135d0a71398724f",
|
||||
"@typescript/native-preview-win32-arm64@npm:7.0.0-dev.20260309.1": "0b6ff10d8ed63f11655d8750c723711c22e8f8eaf0a9a5958f6059dbbaf485fbbb2e673a62bf913178b3ea3d101a60ca33a667e059d1739714feb46e41f8079b",
|
||||
"@typescript/native-preview-win32-x64@npm:7.0.0-dev.20260309.1": "d55b53ab9065c600e50f1f029692d1fed4cc62ff9672ef758c70754168c310853aebd7f231cdbf8eaaf8af85015b42a9a6985dbe387bc88e648adab511a00873",
|
||||
"@typescript/native-preview-darwin-arm64@npm:7.0.0-dev.20260421.2": "12273bab953bbacf429e4895db7ac5e40b05f3e1511b7053119eafad99af9241f893e975e29735403f7247a4a1a22f56a5eca0d84ec300dc705c77ebc4292b61",
|
||||
"@typescript/native-preview-darwin-x64@npm:7.0.0-dev.20260421.2": "711451bef67dbe18e0a7fdfd5915f74935d76c8d22ac1f0bc74df55af66d6a782f7b91f3cdc7ff4773f02c5c84fbd3c79061e3888707735089d45148dc262910",
|
||||
"@typescript/native-preview-linux-arm64@npm:7.0.0-dev.20260421.2": "b1ffbf30be075be6cf8ed9da314326ca4050a31ed33fde3daa90fddc37518d62695abbbc1b1f212cbf160c22fff760fa2ee9b447a16fe6e14fcf36329df9bad5",
|
||||
"@typescript/native-preview-linux-arm@npm:7.0.0-dev.20260421.2": "c7e6be5c67f8010519e3240eb821b452beed3dfffe880a5cd8ca19f1873e1c27283af100d9e2c0175b624dd4042337e1898b1c3e3c1122605f1e9d7c56638b24",
|
||||
"@typescript/native-preview-linux-x64@npm:7.0.0-dev.20260421.2": "73a130ffe78755e48254d12d82399a5c479998142e98273d4edda8f10806ac31a4e52ea4ee61dd52999930545b93471e8620746f8552ea275b2a2f32b1cf4c8e",
|
||||
"@typescript/native-preview-win32-arm64@npm:7.0.0-dev.20260421.2": "903319a110c6348185aaa508db50d48ce0c981c5a745cbc57c36271caf6f3b37b7a577e549594edd1b185cd45f7bb50c7c98ac1bbea7f800bfef5dbd6d3d42bf",
|
||||
"@typescript/native-preview-win32-x64@npm:7.0.0-dev.20260421.2": "a46bf36e4df25ac9bf60a39b4a4953d4cc43ec40c55bd1de9bb088ee4622d53955b39c07c8ed16b21c4bf841f22f997e17d9af50a376fd3c0349cf36e3857dfc",
|
||||
"dmg-license@npm:1.0.11": "36c0a7b030801b91216affa9b2bb00caa345b2327f298accb2263a80a0320ca305f90b99da68007d187c830c543410d58a0a2bbc229e8d169b0e1d1652ff42aa",
|
||||
"glob-hasher-darwin-arm64@npm:1.4.2": "1abc74c6f6c6251b8bea6e412090eff4e4918f3489a371971840ee81534344b9f9e62a610efb98157970fc46561161bf23382c8572578da98a7e884d6fb6853e",
|
||||
"glob-hasher-darwin-x64@npm:1.4.2": "44110045f0b2e0b3abaf4f70f917a3c57b9b0c6ee56e5d02932e1772cc63a36b066fb3bc1e6a275c40978b3b2d2ad62752e899bcd966930d4df8884b1d554764",
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
let
|
||||
nodejs = nodejs_22;
|
||||
yarn-berry = yarn-berry_4.override { inherit nodejs; };
|
||||
version = "26.4.0";
|
||||
version = "26.5.2";
|
||||
src = fetchFromGitHub {
|
||||
name = "actualbudget-actual-source";
|
||||
owner = "actualbudget";
|
||||
repo = "actual";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-Gc2klYxGv+vd1Yc2ftj25B4Kea0GKkpjYcVDN9HvLPk=";
|
||||
hash = "sha256-bcQAlG9acxTSqOQiSr1pmk4A6yjDWD/QH3AeYtqgAdo=";
|
||||
};
|
||||
translations = fetchFromGitHub {
|
||||
name = "actualbudget-translations-source";
|
||||
@@ -28,8 +28,8 @@ let
|
||||
repo = "translations";
|
||||
# Note to updaters: this repo is not tagged, so just update this to the Git
|
||||
# tip at the time the update is performed.
|
||||
rev = "14c3f5e7ed4e47dedab8cebeaf5e2170cfa5f9d0";
|
||||
hash = "sha256-+4hENE9unsta1YoIDE7shcjy1AlWfnPczvm4jYnw5Dw=";
|
||||
rev = "1713f1230b8643c39aece866de755976707a4060";
|
||||
hash = "sha256-79WpnFsGkpkWA7qm19YQ41TYu5qxXCcecYHNvx3KGQ4=";
|
||||
};
|
||||
|
||||
in
|
||||
@@ -105,7 +105,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
missingHashes = ./missing-hashes.json;
|
||||
offlineCache = yarn-berry.fetchYarnBerryDeps {
|
||||
inherit (finalAttrs) src missingHashes patches;
|
||||
hash = "sha256-7Vlc9hPv7Sr2ZUw7fasl3xf7ZYU31oS4tWW46UBJ1F0=";
|
||||
hash = "sha256-yHvnahriFO4Yuuf+NrfHWQhH35T2eHmVOGw8SqP856Y=";
|
||||
};
|
||||
|
||||
pname = "actual-server";
|
||||
@@ -130,6 +130,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
yarn workspaces focus @actual-app/sync-server --production
|
||||
rm -r node_modules/.bin
|
||||
cp -r ./node_modules $out/lib/actual/
|
||||
cp -r ./packages/crdt $out/lib/actual/packages/crdt
|
||||
|
||||
makeBinaryWrapper ${lib.getExe nodejs} "$out/bin/actual-server" \
|
||||
--add-flags "$out/lib/actual/packages/sync-server/bin/actual-server.js" \
|
||||
|
||||
@@ -2,10 +2,10 @@ diff --git a/.yarnrc.yml b/.yarnrc.yml
|
||||
--- a/.yarnrc.yml
|
||||
+++ b/.yarnrc.yml
|
||||
@@ -6,4 +6,7 @@ enableTransparentWorkspaces: false
|
||||
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
-yarnPath: .yarn/releases/yarn-4.10.3.cjs
|
||||
|
||||
-yarnPath: .yarn/releases/yarn-4.13.0.cjs
|
||||
+approvedGitRepositories:
|
||||
+ - "**"
|
||||
+
|
||||
@@ -15,9 +15,9 @@ diff --git a/yarn.lock b/yarn.lock
|
||||
+++ b/yarn.lock
|
||||
@@ -2,6 +2,6 @@
|
||||
# Manual changes might be lost - proceed with caution!
|
||||
|
||||
|
||||
__metadata:
|
||||
- version: 8
|
||||
+ version: 9
|
||||
cacheKey: 10
|
||||
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ python.pkgs.buildPythonApplication rec {
|
||||
patches = [
|
||||
# Backport authlib 1.7 compatibility.
|
||||
(fetchpatch2 {
|
||||
url = "https://gitlab.com/yaal/canaille/-/commit/b356baa82109a7fdf61a8258572d199ffd3c9604.patch";
|
||||
hash = "sha256-f5zJBtm9mJpWra5x4vr07eL9xe381lLFp3lfehc4Ypk=";
|
||||
url = "https://gitlab.com/yaal/canaille/-/commit/b356baa82109a7fdf61a8258572d199ffd3c9604.diff";
|
||||
hash = "sha256-/U6S3h6qIl763ZsGpOm6CVk4NaY3A7mq3PkT193aLEs=";
|
||||
})
|
||||
# Update OIDC tests for authlib 1.7 behavior.
|
||||
(fetchpatch2 {
|
||||
url = "https://gitlab.com/yaal/canaille/-/commit/c1b6d103ebf374cd6a21d9af8376c910c2d0d5d9.patch";
|
||||
hash = "sha256-N9kxiKU6iwXq6cw6itZQHairSOgyDgwAVByj0NnxMqY=";
|
||||
url = "https://gitlab.com/yaal/canaille/-/commit/c1b6d103ebf374cd6a21d9af8376c910c2d0d5d9.diff";
|
||||
hash = "sha256-MjwkUb54ikt1+xUXBTOIBi9E+DmPdwYhw0W0c0prF/Q=";
|
||||
includes = [ "tests/oidc/*" ];
|
||||
})
|
||||
];
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "grafana";
|
||||
version = "13.0.1";
|
||||
version = "13.0.1+security-01";
|
||||
|
||||
subPackages = [
|
||||
"pkg/cmd/grafana"
|
||||
@@ -33,7 +33,7 @@ buildGoModule (finalAttrs: {
|
||||
owner = "grafana";
|
||||
repo = "grafana";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-fGRvCDIOQcF743SimatyNmX0gZtO0tvgEAFuk38rl88=";
|
||||
hash = "sha256-v/6a0Xlj11nZ0u8xtFzw5i674rB1YV21iLCuLc5af+I=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
@@ -55,7 +55,7 @@ buildGoModule (finalAttrs: {
|
||||
# Since this is not a dependency attribute the buildPackages has to be specified.
|
||||
offlineCache = buildPackages.yarn-berry_4-fetcher.fetchYarnBerryDeps {
|
||||
inherit (finalAttrs) src missingHashes patches;
|
||||
hash = "sha256-l+X7vgU+wuuq+Usdp0ffY1SpT70QlmdsjrHnyyJufjw=";
|
||||
hash = "sha256-uOl9PemVZiKwGfhLUpAAByMvt5A8JyA5qyJ6Cdl6od4=";
|
||||
};
|
||||
|
||||
disallowedRequisites = [ finalAttrs.offlineCache ];
|
||||
|
||||
@@ -13,20 +13,20 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "lasuite-docs-collaboration-server";
|
||||
version = "4.8.6";
|
||||
version = "5.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "suitenumerique";
|
||||
repo = "docs";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-8xMHHyj9qUdrd5dFYVlN2bi7EVjcEqoBBxIifC8xk3k=";
|
||||
hash = "sha256-yjcnXC46C2Z453oN4/fJc2q+B0yQKL3jKaIIpRlzu5s=";
|
||||
};
|
||||
|
||||
sourceRoot = "${finalAttrs.src.name}/src/frontend";
|
||||
|
||||
offlineCache = fetchYarnDeps {
|
||||
yarnLock = "${finalAttrs.src}/src/frontend/yarn.lock";
|
||||
hash = "sha256-4jaKWepa3+SxEVS+gF5QrOeJaOpS8vzFXZyN9SxClUE=";
|
||||
hash = "sha256-K7AvCt2GMwo+mtTqa3c0OGUGM3Whfo/WfeYG/Vjxhtg=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -12,20 +12,20 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "lasuite-docs-frontend";
|
||||
version = "4.8.6";
|
||||
version = "5.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "suitenumerique";
|
||||
repo = "docs";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-8xMHHyj9qUdrd5dFYVlN2bi7EVjcEqoBBxIifC8xk3k=";
|
||||
hash = "sha256-yjcnXC46C2Z453oN4/fJc2q+B0yQKL3jKaIIpRlzu5s=";
|
||||
};
|
||||
|
||||
sourceRoot = "${finalAttrs.src.name}/src/frontend";
|
||||
|
||||
offlineCache = fetchYarnDeps {
|
||||
yarnLock = "${finalAttrs.src}/src/frontend/yarn.lock";
|
||||
hash = "sha256-4jaKWepa3+SxEVS+gF5QrOeJaOpS8vzFXZyN9SxClUE=";
|
||||
hash = "sha256-K7AvCt2GMwo+mtTqa3c0OGUGM3Whfo/WfeYG/Vjxhtg=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
yarnConfigHook,
|
||||
}:
|
||||
let
|
||||
version = "4.8.6";
|
||||
version = "5.0.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "suitenumerique";
|
||||
repo = "docs";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-8xMHHyj9qUdrd5dFYVlN2bi7EVjcEqoBBxIifC8xk3k=";
|
||||
hash = "sha256-yjcnXC46C2Z453oN4/fJc2q+B0yQKL3jKaIIpRlzu5s=";
|
||||
};
|
||||
|
||||
mail-templates = stdenv.mkDerivation {
|
||||
@@ -29,7 +29,7 @@ let
|
||||
|
||||
offlineCache = fetchYarnDeps {
|
||||
yarnLock = "${src}/src/mail/yarn.lock";
|
||||
hash = "sha256-B2vtdQYFhhsA7dK5nwAJl65kaedspfYySJJBjVwYeBM=";
|
||||
hash = "sha256-g5MYtHvs0i0AOAydMxJNx1xTwbZtXS0CYDNQC+cnIOM=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
@@ -57,9 +57,17 @@ python3Packages.buildPythonApplication (finalAttrs: {
|
||||
./postgresql_fix.patch
|
||||
];
|
||||
|
||||
# They use a old version of mistralai which exported a class
|
||||
# at the top level
|
||||
postPatch = ''
|
||||
substituteInPlace core/services/ai_services/legacy.py \
|
||||
--replace-fail \
|
||||
"from mistralai import Mistral" \
|
||||
"from mistralai.client import Mistral"
|
||||
''
|
||||
# Otherwise fails with:
|
||||
# socket.gaierror: [Errno 8] nodename nor servname provided, or not known
|
||||
postPatch = lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
substituteInPlace impress/settings.py \
|
||||
--replace-fail \
|
||||
"gethostname()" \
|
||||
@@ -75,6 +83,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
|
||||
beautifulsoup4
|
||||
boto3
|
||||
celery
|
||||
emoji
|
||||
django
|
||||
django-configurations
|
||||
django-cors-headers
|
||||
@@ -100,6 +109,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
|
||||
langfuse
|
||||
lxml
|
||||
markdown
|
||||
mistralai
|
||||
mozilla-django-oidc
|
||||
nested-multipart-parser
|
||||
openai
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
version = "4.3.0";
|
||||
version = "4.4.0";
|
||||
pname = "libdigidocpp";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "open-eid";
|
||||
repo = "libdigidocpp";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-f5wU3C6NC4op+9Wy+khwNJ6slFyPhq7hZl1Tj5hnYc8=";
|
||||
hash = "sha256-Rf4ex9UT+Bspkf+WNNpYpdIt7y+QjAZ+eg786FZ0ZsA=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -39,7 +39,7 @@ in
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "lsp-plugins";
|
||||
version = "1.2.27";
|
||||
version = "1.2.29";
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
@@ -49,7 +49,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/lsp-plugins/lsp-plugins/releases/download/${finalAttrs.version}/lsp-plugins-src-${finalAttrs.version}.tar.gz";
|
||||
hash = "sha256-AirMrXIb7ShPrURdzImss7nR8Scxkh2+HtvQzeZy4aM=";
|
||||
hash = "sha256-QEKXw63YecUI2wbVEZ4R78HQRzUn0qae057HfB0ZcvI=";
|
||||
};
|
||||
|
||||
# By default, GStreamer plugins are installed right alongside GStreamer itself
|
||||
|
||||
@@ -30,11 +30,11 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "netatalk";
|
||||
version = "4.4.2";
|
||||
version = "4.4.3";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://sourceforge/netatalk/netatalk/netatalk-${finalAttrs.version}.tar.xz";
|
||||
hash = "sha256-Mfyjs3kBSBDkudakmK7ihtKdPp/3AybofhTZPqptCl4=";
|
||||
hash = "sha256-hj1kDsyZ9JI+rWxY6NNAarOhyp3TsNR8zfb967bv46s=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -67,16 +67,16 @@ let
|
||||
in
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "netbird-${componentName}";
|
||||
version = "0.70.4";
|
||||
version = "0.70.5";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "netbirdio";
|
||||
repo = "netbird";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-tfScscRllUlV1V6D66rfT6JEsReDQfVGryVzNebm0vg=";
|
||||
hash = "sha256-AsM+MEeBqxnwD1jE8ocI93tF3l/7s+s5nF073ZMAi/Y=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-IRV1GxdUKgan0GwmBg9acpl7plW01CtEO2FrKrlDdeE=";
|
||||
vendorHash = "sha256-ebhjN6o/519ayxWTcscNinKuiL3LSPmE2VNgSitxj5g=";
|
||||
|
||||
nativeBuildInputs = [ installShellFiles ] ++ lib.optional (componentName == "ui") pkg-config;
|
||||
|
||||
|
||||
11
pkgs/by-name/ni/nixos-init/Cargo.lock
generated
11
pkgs/by-name/ni/nixos-init/Cargo.lock
generated
@@ -142,6 +142,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -506,3 +507,13 @@ checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
@@ -11,6 +11,7 @@ pathrs = "0.2.2"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.145"
|
||||
bootspec = "2.0.0"
|
||||
xattr = "1.6.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.20.0"
|
||||
|
||||
@@ -52,6 +52,9 @@ closure. Currently nixos-init comes in at ~500 KiB.
|
||||
- `find-etc`: Finds the `/etc` paths in `/sysroot` so that the initrd doesn't
|
||||
directly depend on the toplevel, reducing the need to rebuild the initrd on
|
||||
every generation.
|
||||
- `clear-etc-opaque`: Clears stale `trusted.overlay.opaque` xattrs from the
|
||||
mutable `/etc` overlay's upperdir before it is mounted, so that lowerdir
|
||||
entries added by a new generation are not hidden.
|
||||
- `resolve-in-root`: Figures out the canonical path inside a chroot.
|
||||
|
||||
## Future
|
||||
|
||||
@@ -47,6 +47,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
|
||||
binaries = [
|
||||
"initrd-init"
|
||||
"find-etc"
|
||||
"clear-etc-opaque"
|
||||
"resolve-in-root"
|
||||
"env-generator"
|
||||
];
|
||||
|
||||
170
pkgs/by-name/ni/nixos-init/src/etc_overlay.rs
Normal file
170
pkgs/by-name/ni/nixos-init/src/etc_overlay.rs
Normal file
@@ -0,0 +1,170 @@
|
||||
use std::{
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use anyhow::{Context, Result, bail};
|
||||
|
||||
const OVERLAY_OPAQUE_XATTR: &str = "trusted.overlay.opaque";
|
||||
|
||||
/// Entrypoint for the `clear-etc-opaque` binary.
|
||||
///
|
||||
/// When a directory is created in the mutable `/etc` overlay that does not yet
|
||||
/// exist in the lowerdir, overlayfs marks it opaque in the upperdir. This is
|
||||
/// correct at creation time, but becomes stale when a later generation adds
|
||||
/// entries under that same directory to the metadata layer: the opaque marker
|
||||
/// hides them.
|
||||
///
|
||||
/// This walks the (newly mounted) metadata layer and removes
|
||||
/// `trusted.overlay.opaque` from any upperdir directory that now has a
|
||||
/// directory counterpart in the lowerdir, turning it back into a merged view.
|
||||
/// Files the user placed in the upperdir remain visible (upperdir wins
|
||||
/// per-entry) and individual whiteouts are preserved; only the blanket hiding
|
||||
/// of lowerdir content is undone.
|
||||
///
|
||||
/// See <https://github.com/NixOS/nixpkgs/issues/505475>.
|
||||
///
|
||||
/// Usage: `clear-etc-opaque <metadata-mount> <upperdir>`
|
||||
pub fn clear_etc_opaque() -> Result<()> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
if args.len() != 3 {
|
||||
bail!("Usage: {} <metadata-mount> <upperdir>", args[0]);
|
||||
}
|
||||
|
||||
let metadata_mount = PathBuf::from(&args[1]);
|
||||
let upperdir = PathBuf::from(&args[2]);
|
||||
|
||||
if !upperdir.is_dir() {
|
||||
// Nothing to clear (e.g. first boot before the upperdir is created).
|
||||
log::info!(
|
||||
"Upperdir {} does not exist, nothing to clear.",
|
||||
upperdir.display()
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
clear_opaque_markers(&metadata_mount, &metadata_mount, &upperdir)
|
||||
}
|
||||
|
||||
/// Recursively walk `current` (a subtree of `metadata_root`) and clear the
|
||||
/// opaque xattr from the corresponding directory in `upperdir`.
|
||||
fn clear_opaque_markers(metadata_root: &Path, current: &Path, upperdir: &Path) -> Result<()> {
|
||||
let entries = fs::read_dir(current)
|
||||
.with_context(|| format!("Failed to read directory {}", current.display()))?;
|
||||
|
||||
for entry in entries {
|
||||
let entry =
|
||||
entry.with_context(|| format!("Failed to read entry in {}", current.display()))?;
|
||||
|
||||
// Use the entry's own type info (no symlink following) so we only
|
||||
// recurse into real directories of the metadata image.
|
||||
if !entry
|
||||
.file_type()
|
||||
.with_context(|| format!("Failed to stat {}", entry.path().display()))?
|
||||
.is_dir()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let path = entry.path();
|
||||
let rel = path
|
||||
.strip_prefix(metadata_root)
|
||||
.context("Failed to strip metadata root prefix")?;
|
||||
let target = upperdir.join(rel);
|
||||
|
||||
// Only act on real directories in the upperdir; an opaque marker on a
|
||||
// non-directory would be meaningless and we must not follow symlinks
|
||||
// out of the upperdir.
|
||||
match fs::symlink_metadata(&target) {
|
||||
Ok(meta) if meta.is_dir() => {
|
||||
remove_opaque_xattr(&target);
|
||||
// Only recurse when the upperdir also has this directory:
|
||||
// deeper lowerdir directories without an upperdir counterpart
|
||||
// cannot carry stale markers.
|
||||
clear_opaque_markers(metadata_root, &path, upperdir)?;
|
||||
}
|
||||
// Missing or not a directory: nothing to do for this subtree.
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove the `trusted.overlay.opaque` xattr from `path` if present.
|
||||
fn remove_opaque_xattr(path: &Path) {
|
||||
// Check first instead of removing unconditionally: lremovexattr(2) reports
|
||||
// a missing attribute as ENODATA, which std does not map to a stable
|
||||
// io::ErrorKind, so distinguishing it from real errors is awkward.
|
||||
match xattr::get(path, OVERLAY_OPAQUE_XATTR) {
|
||||
Ok(None) => return,
|
||||
Ok(Some(_)) => {}
|
||||
Err(err) => {
|
||||
log::warn!(
|
||||
"Failed to read {OVERLAY_OPAQUE_XATTR} on {}: {err}.",
|
||||
path.display()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
match xattr::remove(path, OVERLAY_OPAQUE_XATTR) {
|
||||
Ok(()) => {
|
||||
log::info!("Cleared stale opaque marker from {}.", path.display());
|
||||
}
|
||||
Err(err) => {
|
||||
// Don't abort the boot over this; the worst case is that some
|
||||
// declaratively-managed /etc entries stay hidden, which is what
|
||||
// would happen anyway without this fixup.
|
||||
log::warn!(
|
||||
"Failed to remove {OVERLAY_OPAQUE_XATTR} from {}: {err}.",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[test]
|
||||
fn clears_opaque_only_for_matching_dirs() -> Result<()> {
|
||||
if !xattr::SUPPORTED_PLATFORM {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let metadata = tempdir()?;
|
||||
let upper = tempdir()?;
|
||||
|
||||
// lowerdir gained nixos/sub in the new generation.
|
||||
fs::create_dir_all(metadata.path().join("nixos/sub"))?;
|
||||
// upperdir has an opaque nixos/ from before.
|
||||
fs::create_dir_all(upper.path().join("nixos"))?;
|
||||
// upperdir directory without a lowerdir counterpart: we only clear
|
||||
// markers where the lowerdir has a matching directory, so this one
|
||||
// must stay opaque.
|
||||
fs::create_dir_all(upper.path().join("only-upper"))?;
|
||||
|
||||
// The build sandbox usually lacks CAP_SYS_ADMIN, so trusted.* xattrs
|
||||
// cannot be set. Skip in that case rather than fail the build.
|
||||
if xattr::set(upper.path().join("nixos"), OVERLAY_OPAQUE_XATTR, b"y").is_err() {
|
||||
eprintln!("skipping: cannot set trusted.* xattrs in this environment");
|
||||
return Ok(());
|
||||
}
|
||||
xattr::set(upper.path().join("only-upper"), OVERLAY_OPAQUE_XATTR, b"y")?;
|
||||
|
||||
clear_opaque_markers(metadata.path(), metadata.path(), upper.path())?;
|
||||
|
||||
assert!(xattr::get(upper.path().join("nixos"), OVERLAY_OPAQUE_XATTR)?.is_none());
|
||||
assert_eq!(
|
||||
xattr::get(upper.path().join("only-upper"), OVERLAY_OPAQUE_XATTR)?.as_deref(),
|
||||
Some(b"y".as_slice())
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
mod activate;
|
||||
mod config;
|
||||
mod env_generator;
|
||||
mod etc_overlay;
|
||||
mod find_etc;
|
||||
mod fs;
|
||||
mod init;
|
||||
@@ -16,6 +17,7 @@ use anyhow::{Context, Result, bail};
|
||||
pub use crate::{
|
||||
activate::activate,
|
||||
env_generator::env_generator,
|
||||
etc_overlay::clear_etc_opaque,
|
||||
find_etc::find_etc,
|
||||
init::init,
|
||||
initrd_init::initrd_init,
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{env, io::Write, process::ExitCode};
|
||||
|
||||
use log::Level;
|
||||
|
||||
use nixos_init::{env_generator, find_etc, initrd_init, resolve_in_root};
|
||||
use nixos_init::{clear_etc_opaque, env_generator, find_etc, initrd_init, resolve_in_root};
|
||||
|
||||
fn main() -> ExitCode {
|
||||
let arg0 = env::args()
|
||||
@@ -12,6 +12,7 @@ fn main() -> ExitCode {
|
||||
|
||||
setup_logger();
|
||||
let entrypoint = match arg0.as_str() {
|
||||
"clear-etc-opaque" => clear_etc_opaque,
|
||||
"find-etc" => find_etc,
|
||||
"resolve-in-root" => resolve_in_root,
|
||||
"initrd-init" => initrd_init,
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
cacert,
|
||||
git,
|
||||
nix,
|
||||
nix-eval-jobs,
|
||||
versionCheckHook,
|
||||
|
||||
withAutocomplete ? true,
|
||||
@@ -55,6 +56,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
|
||||
let
|
||||
binPath = [
|
||||
nix
|
||||
nix-eval-jobs
|
||||
git
|
||||
]
|
||||
++ lib.optional withSandboxSupport bubblewrap
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
}:
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "oh-my-posh";
|
||||
version = "29.12.0";
|
||||
version = "29.13.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jandedobbeleer";
|
||||
repo = "oh-my-posh";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-Gtv3h46+T3+hB4e2KJjS128RCNx/0wh/Qz52T+xxClI=";
|
||||
hash = "sha256-mH727EMcIkORPEvI2OJRaGw+PAI4PRuUvwlVUfL67B8=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-xDMSfuzREtn/Bm1rkRoUS3Ykec81WeA81VW6dp1wLb4=";
|
||||
vendorHash = "sha256-cVn5QCpYc5FIY8hNaQnJ+eL0ZtVf6u2dWnWmHYJoJRk=";
|
||||
|
||||
sourceRoot = "${finalAttrs.src.name}/src";
|
||||
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "otel-tui";
|
||||
version = "0.7.2";
|
||||
version = "0.7.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ymtdzzz";
|
||||
repo = "otel-tui";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-teTV4i27Xjf5E1/2C1e8HFf6Tkct2wgZZfu9SSM18II=";
|
||||
hash = "sha256-RYGSMdJQ2qj6930PX/UWFrN2orQzRpufHiKDv6lmAw4=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-5ki/hR809LmMEHV8Mb7n2nEETAZR2Qs29AW5vvSzuu4=";
|
||||
vendorHash = "sha256-dItC0l6BawbW2OCjg1KoDo8jHGX7Dbo2gSiVi1lynwI=";
|
||||
|
||||
env.GOWORK = "off";
|
||||
|
||||
|
||||
28
pkgs/by-name/pr/prometheus-speedtest-exporter/package.nix
Normal file
28
pkgs/by-name/pr/prometheus-speedtest-exporter/package.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
buildGoModule,
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
|
||||
buildGoModule (finalAttrs: {
|
||||
__structuredAttrs = true;
|
||||
pname = "prometheus-speedtest-exporter";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "podocarp";
|
||||
repo = "speedtest_exporter";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-n9eunZRssS13mTOeFeZ/PpfSj430DKf3ZRS10hY4Ps8=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-HBg44D0CUc4HYCBwGrswnrqG5o5ltA6UT8L0oWetlIc=";
|
||||
|
||||
meta = {
|
||||
description = "Speedtest.net Exporter for the Prometheus monitoring system";
|
||||
mainProgram = "speedtest_exporter";
|
||||
homepage = "https://github.com/podocarp/speedtest_exporter";
|
||||
license = lib.licenses.gpl3Only;
|
||||
maintainers = with lib.maintainers; [ podocarp ];
|
||||
};
|
||||
})
|
||||
@@ -7,14 +7,14 @@
|
||||
|
||||
python3.pkgs.buildPythonApplication (finalAttrs: {
|
||||
pname = "radicale";
|
||||
version = "3.7.2";
|
||||
version = "3.7.3";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Kozea";
|
||||
repo = "Radicale";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-eZnm3mlG+HoqOXlKxv4UIdN99z04ty0qiwaJeNo3zEM=";
|
||||
hash = "sha256-4xTfQ+E9ys0ox9AwQ/drQWLaA4YLZBBdyXUFUvBa8sk=";
|
||||
};
|
||||
|
||||
build-system = with python3.pkgs; [
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "bypass.yazi";
|
||||
version = "25.3.2-unstable-2025-06-01";
|
||||
version = "0-unstable-2025-06-01";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Rolv-Apneseth";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "chmod.yazi";
|
||||
version = "26.1.22-unstable-2026-02-27";
|
||||
version = "0-unstable-2026-02-27";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "clipboard.yazi";
|
||||
version = "0-unstable-2026-04-24";
|
||||
version = "0-unstable-2026-05-10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "XYenon";
|
||||
repo = "clipboard.yazi";
|
||||
rev = "d6fc53152a20aebad8dc6e2550940f7efe226838";
|
||||
hash = "sha256-6jlMzVPgkbQRwVbfUCEtXVWLxBKdPymQeHVoh5z9mO8=";
|
||||
rev = "68b506d9a9c2c5dde01a078a589520f551d05fe5";
|
||||
hash = "sha256-jNBwkcFb9i5Z6BSMfkTOyrK7HZohAT/yB3cxcCOG54w=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "close-and-restore-tab.yazi";
|
||||
version = "0-unstable-2026-04-22";
|
||||
version = "0-unstable-2025-05-29";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "MasouShizuka";
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "compress.yazi";
|
||||
version = "25.12.29-unstable-2026-03-15";
|
||||
version = "0.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "KKV9";
|
||||
repo = "compress.yazi";
|
||||
rev = "46a6b9f02ff2f8aced466a1f01a3fe241f1cd45f";
|
||||
tag = "0.6";
|
||||
hash = "sha256-Mby185FCJY6nqHcHDQu+D5SLk+wGcyeUHK8yAvrd4TM=";
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "convert.yazi";
|
||||
version = "0-unstable-2026-04-22";
|
||||
version = "0-unstable-2025-06-28";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "atareao";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "diff.yazi";
|
||||
version = "26.1.22-unstable-2026-01-24";
|
||||
version = "0-unstable-2026-01-24";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "full-border.yazi";
|
||||
version = "25.2.26-unstable-2026-04-22";
|
||||
version = "0-unstable-2026-04-22";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "git.yazi";
|
||||
version = "26.1.22-unstable-2026-02-27";
|
||||
version = "0-unstable-2026-02-27";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "gvfs.yazi";
|
||||
version = "25.5.31-unstable-2026-03-29";
|
||||
version = "0-unstable-2026-03-29";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "boydaihungst";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "jump-to-char.yazi";
|
||||
version = "25.5.31-unstable-2025-06-18";
|
||||
version = "0-unstable-2025-06-18";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "lazygit.yazi";
|
||||
version = "0-unstable-2026-03-12";
|
||||
version = "0-unstable-2026-05-02";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Lil-Dank";
|
||||
repo = "lazygit.yazi";
|
||||
rev = "8c4086c813c5856ab9571ae9142ed7d40ed3211e";
|
||||
hash = "sha256-YpRWnR5fEXzHY9yBFNKy1NvTzHa8B1UhS2Qrfe9+Tpg=";
|
||||
rev = "e73fd74c2af3300368b33da1cfbab6a8649a41a8";
|
||||
hash = "sha256-KPvjXjYE0W4Q2xZiVfMwZbtalHt0FbgLtEK4sUWbYOI=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "lsar.yazi";
|
||||
version = "26.1.22-unstable-2026-01-24";
|
||||
version = "0-unstable-2026-01-24";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "mactag.yazi";
|
||||
version = "26.1.22-unstable-2026-04-10";
|
||||
version = "0-unstable-2026-04-10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "mediainfo.yazi";
|
||||
version = "26.1.22-unstable-2026-04-10";
|
||||
version = "0-unstable-2026-04-10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "boydaihungst";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "mount.yazi";
|
||||
version = "25.12.29-unstable-2026-04-09";
|
||||
version = "0-unstable-2026-04-09";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "office.yazi";
|
||||
version = "0-unstable-2026-04-22";
|
||||
version = "0-unstable-2025-09-20";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "macydnah";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "piper.yazi";
|
||||
version = "26.1.22-unstable-2026-01-24";
|
||||
version = "0-unstable-2026-01-24";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "relative-motions.yazi";
|
||||
version = "25.5.28-unstable-2025-07-09";
|
||||
version = "0-unstable-2025-07-09";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "dedukun";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "restore.yazi";
|
||||
version = "25.5.31-unstable-2026-04-04";
|
||||
version = "0-unstable-2026-04-04";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "boydaihungst";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "smart-enter.yazi";
|
||||
version = "25.5.31-unstable-2025-06-18";
|
||||
version = "0-unstable-2025-06-18";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "smart-filter.yazi";
|
||||
version = "25.12.29-unstable-2025-12-29";
|
||||
version = "0-unstable-2025-12-29";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "smart-paste.yazi";
|
||||
version = "25.5.31-unstable-2025-06-18";
|
||||
version = "0-unstable-2025-06-18";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
mkYaziPlugin {
|
||||
pname = "split-tabs.yazi";
|
||||
version = "0-unstable-2026-04-13";
|
||||
version = "0-unstable-2026-05-13";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "terrakok";
|
||||
repo = "split-tabs.yazi";
|
||||
rev = "6c0931840d764bffa0c38677b6a84e69928e283f";
|
||||
hash = "sha256-FqeXVVFk4+aXn8d+LLs8idRBkLLzRPeVol6vMCh6mQ4=";
|
||||
rev = "ca95efc94a3a62e6e58c741f60801c1a0ddba1a6";
|
||||
hash = "sha256-ic09opWZcoJ874bU2HN+5Y9mbnZEnvds+abqRQYuiYE=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "sshfs.yazi";
|
||||
version = "2.0.0-unstable-2026-04-15";
|
||||
version = "2.1.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "uhs-robert";
|
||||
repo = "sshfs.yazi";
|
||||
rev = "7ba17a8c8498fca9f0a9c437704e74b56d96ed96";
|
||||
hash = "sha256-TS3/xl8jbbCoF1LzPYvmG9BRqvlzPg4EZRErlL7S2/M=";
|
||||
tag = "v2.1.0";
|
||||
hash = "sha256-02LzKNptzs6o+YPGJRyYCly/Xqzi/5mvVBS+b28nY6U=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "starship.yazi";
|
||||
version = "25.4.8-unstable-2026-03-22";
|
||||
version = "0-unstable-2026-03-22";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Rolv-Apneseth";
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "sudo.yazi";
|
||||
version = "0-unstable-2025-11-05";
|
||||
version = "0-unstable-2026-05-07";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "TD-Sky";
|
||||
repo = "sudo.yazi";
|
||||
rev = "86205aa8044f10b02471be1087f3381bbadc967e";
|
||||
hash = "sha256-mpQLij+Sg88RarCC+0u7JfZ2EqcX4gB7jvy8bfBt90w=";
|
||||
rev = "afd61cedbcd13c549c552766755645069561d28c";
|
||||
hash = "sha256-5wa4fdYo7wOXOzdrigWMtADZIL/7alG8Jw7r8iWz9yA=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "toggle-pane.yazi";
|
||||
version = "25.5.31-unstable-2025-06-18";
|
||||
version = "0-unstable-2026-05-07";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
repo = "plugins";
|
||||
rev = "86d28e4fb4f25f36cc501b8cb0badb37a6b14263";
|
||||
hash = "sha256-m/gJTDm0cVkIdcQ1ZJliPqBhNKoCW1FciLkuq7D1mxo=";
|
||||
rev = "4ffa48f33465c22cce48c5d506295a3eb27c1979";
|
||||
hash = "sha256-wr5QL493A175dRjYSyYpMMJax1RKWaZ3jAdFdL3XXTw=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p python3 python3Packages.requests python3Packages.packaging nix curl git argparse
|
||||
#!nix-shell -i python3 -p python3 python3Packages.requests python3Packages.packaging python3Packages.nixpkgs-plugin-update nix curl git argparse
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
from nixpkgs_plugin_update import make_unstable_version, normalize_release_version
|
||||
from packaging import version
|
||||
from packaging.version import InvalidVersion
|
||||
|
||||
|
||||
@dataclass
|
||||
class UpdateCandidate:
|
||||
"""An upstream revision that might be used to update a plugin."""
|
||||
|
||||
rev: str
|
||||
commit: str | None
|
||||
date: str
|
||||
version: str
|
||||
kind: str
|
||||
|
||||
|
||||
def run_command(cmd: str, capture_output: bool = True) -> str:
|
||||
@@ -65,18 +81,42 @@ def get_default_branch(owner: str, repo: str, headers: dict[str, str]) -> str:
|
||||
print("Falling back to 'main' as default branch")
|
||||
return "main"
|
||||
|
||||
def fetch_plugin_content(owner: str, repo: str, plugin_pname: str, headers: dict[str, str]) -> str:
|
||||
"""Fetch the plugin's main.lua content from GitHub"""
|
||||
default_branch = get_default_branch(owner, repo, headers)
|
||||
plugin_path = f"{plugin_pname}/" if owner == "yazi-rs" else ""
|
||||
main_lua_url = f"https://raw.githubusercontent.com/{owner}/{repo}/{default_branch}/{plugin_path}main.lua"
|
||||
|
||||
def github_get(
|
||||
owner: str,
|
||||
repo: str,
|
||||
path: str,
|
||||
headers: dict[str, str],
|
||||
params: dict[str, str | int] | None = None,
|
||||
allow_404: bool = False,
|
||||
) -> dict | list | None:
|
||||
"""Fetch JSON from the GitHub API."""
|
||||
api_url = f"https://api.github.com/repos/{owner}/{repo}/{path}"
|
||||
|
||||
try:
|
||||
response = requests.get(main_lua_url, headers=headers)
|
||||
response = requests.get(api_url, headers=headers, params=params)
|
||||
if allow_404 and response.status_code == 404:
|
||||
return None
|
||||
response.raise_for_status()
|
||||
return response.text
|
||||
return response.json()
|
||||
except requests.RequestException as e:
|
||||
raise RuntimeError(f"Error fetching plugin content: {e}")
|
||||
raise RuntimeError(f"Error fetching {api_url}: {e}")
|
||||
|
||||
|
||||
def fetch_plugin_content(
|
||||
owner: str,
|
||||
repo: str,
|
||||
plugin_pname: str,
|
||||
ref: str,
|
||||
headers: dict[str, str],
|
||||
) -> str:
|
||||
"""Fetch the plugin's main.lua content from GitHub"""
|
||||
plugin_path = f"{plugin_pname}/" if owner == "yazi-rs" else ""
|
||||
content_data = github_get(owner, repo, f"contents/{plugin_path}main.lua", headers, {"ref": ref})
|
||||
if not isinstance(content_data, dict) or "content" not in content_data:
|
||||
raise RuntimeError(f"Could not fetch main.lua at {ref}")
|
||||
|
||||
return base64.b64decode(content_data["content"]).decode("utf-8")
|
||||
|
||||
|
||||
def check_version_compatibility(plugin_content: str, plugin_name: str, yazi_version: str) -> str:
|
||||
@@ -95,40 +135,241 @@ def check_version_compatibility(plugin_content: str, plugin_name: str, yazi_vers
|
||||
return required_version
|
||||
|
||||
|
||||
def get_latest_commit(owner: str, repo: str, plugin_pname: str, headers: dict[str, str]) -> tuple[str, str]:
|
||||
"""Get the latest commit hash and date for the plugin"""
|
||||
def candidate_sort_key(candidate: UpdateCandidate) -> tuple[int, version.Version | str]:
|
||||
"""Sort candidates by parsed version when possible, then by text."""
|
||||
try:
|
||||
return (1, version.parse(candidate.version))
|
||||
except InvalidVersion:
|
||||
return (0, candidate.version)
|
||||
|
||||
|
||||
def normalize_candidate(tag: str | None, kind: str) -> UpdateCandidate | None:
|
||||
"""Create an unresolved release/tag candidate from a GitHub tag."""
|
||||
candidate_version = normalize_release_version(tag) if tag else None
|
||||
if candidate_version is None:
|
||||
return None
|
||||
|
||||
return UpdateCandidate(
|
||||
rev=tag,
|
||||
commit=None,
|
||||
date="unknown",
|
||||
version=candidate_version,
|
||||
kind=kind,
|
||||
)
|
||||
|
||||
|
||||
def resolve_candidate(owner: str, repo: str, candidate: UpdateCandidate, headers: dict[str, str]) -> UpdateCandidate:
|
||||
"""Resolve a release/tag candidate to the commit it points at."""
|
||||
if candidate.commit is not None:
|
||||
return candidate
|
||||
|
||||
commit_data = github_get(owner, repo, f"commits/{candidate.rev}", headers)
|
||||
if not isinstance(commit_data, dict):
|
||||
raise RuntimeError(f"Could not resolve {candidate.rev}")
|
||||
|
||||
return UpdateCandidate(
|
||||
rev=candidate.rev,
|
||||
commit=commit_data["sha"],
|
||||
date=commit_data["commit"]["committer"]["date"].split("T")[0],
|
||||
version=candidate.version,
|
||||
kind=candidate.kind,
|
||||
)
|
||||
|
||||
|
||||
def get_commit_candidates(owner: str, repo: str, plugin_pname: str, headers: dict[str, str]) -> list[UpdateCandidate]:
|
||||
"""Get recent default branch commit candidates for a plugin."""
|
||||
default_branch = get_default_branch(owner, repo, headers)
|
||||
|
||||
if owner == "yazi-rs":
|
||||
# For official plugins, get commit info for the specific plugin file
|
||||
api_url = f"https://api.github.com/repos/{owner}/{repo}/commits?path={plugin_pname}/main.lua&per_page=1"
|
||||
commits_data = github_get(
|
||||
owner,
|
||||
repo,
|
||||
"commits",
|
||||
headers,
|
||||
{"path": f"{plugin_pname}/main.lua", "per_page": 100},
|
||||
)
|
||||
if not isinstance(commits_data, list) or not commits_data:
|
||||
raise RuntimeError(f"Could not get recent commits for {plugin_pname}")
|
||||
else:
|
||||
# For third-party plugins, get latest commit on default branch
|
||||
api_url = f"https://api.github.com/repos/{owner}/{repo}/commits/{default_branch}"
|
||||
commits_data = github_get(
|
||||
owner,
|
||||
repo,
|
||||
"commits",
|
||||
headers,
|
||||
{"sha": default_branch, "per_page": 100},
|
||||
)
|
||||
if not isinstance(commits_data, list) or not commits_data:
|
||||
raise RuntimeError(f"Could not get recent commits for {owner}/{repo}")
|
||||
|
||||
try:
|
||||
response = requests.get(api_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
commit_data = response.json()
|
||||
except requests.RequestException as e:
|
||||
raise RuntimeError(f"Error fetching commit data: {e}")
|
||||
|
||||
if owner == "yazi-rs":
|
||||
latest_commit = commit_data[0]["sha"]
|
||||
commit_date = commit_data[0]["commit"]["committer"]["date"].split("T")[0]
|
||||
else:
|
||||
latest_commit = commit_data["sha"]
|
||||
candidates = []
|
||||
for commit_data in commits_data:
|
||||
commit = commit_data["sha"]
|
||||
commit_date = commit_data["commit"]["committer"]["date"].split("T")[0]
|
||||
commit_datetime = datetime.strptime(commit_date, "%Y-%m-%d")
|
||||
|
||||
if not latest_commit:
|
||||
raise RuntimeError("Could not get latest commit hash")
|
||||
candidates.append(
|
||||
UpdateCandidate(
|
||||
rev=commit,
|
||||
commit=commit,
|
||||
date=commit_date,
|
||||
version=make_unstable_version(commit_datetime, None),
|
||||
kind="commit",
|
||||
)
|
||||
)
|
||||
|
||||
return latest_commit, commit_date
|
||||
return candidates
|
||||
|
||||
|
||||
def calculate_sri_hash(owner: str, repo: str, latest_commit: str) -> str:
|
||||
def get_release_candidates(owner: str, repo: str, headers: dict[str, str]) -> list[UpdateCandidate]:
|
||||
"""Get non-prerelease GitHub release candidates without resolving tags."""
|
||||
releases = github_get(owner, repo, "releases", headers, {"per_page": 100})
|
||||
if not isinstance(releases, list):
|
||||
return []
|
||||
|
||||
candidates = []
|
||||
for release in releases:
|
||||
if release.get("draft") or release.get("prerelease"):
|
||||
continue
|
||||
|
||||
candidate = normalize_candidate(release.get("tag_name"), "release")
|
||||
if candidate is not None:
|
||||
candidates.append(candidate)
|
||||
|
||||
candidates.sort(key=candidate_sort_key, reverse=True)
|
||||
return candidates
|
||||
|
||||
|
||||
def get_tag_candidates(owner: str, repo: str, headers: dict[str, str]) -> list[UpdateCandidate]:
|
||||
"""Get GitHub tag candidates without resolving tags."""
|
||||
tags = github_get(owner, repo, "tags", headers, {"per_page": 100})
|
||||
if not isinstance(tags, list):
|
||||
return []
|
||||
|
||||
candidates = []
|
||||
for tag in tags:
|
||||
candidate = normalize_candidate(tag.get("name"), "tag")
|
||||
if candidate is not None:
|
||||
candidates.append(candidate)
|
||||
|
||||
candidates.sort(key=candidate_sort_key, reverse=True)
|
||||
return candidates
|
||||
|
||||
|
||||
def get_update_candidates(owner: str, repo: str, plugin_pname: str, headers: dict[str, str]) -> list[UpdateCandidate]:
|
||||
"""Get update candidates, preferring releases, then tags, then commits."""
|
||||
release_candidates = get_release_candidates(owner, repo, headers)
|
||||
if release_candidates:
|
||||
return release_candidates
|
||||
|
||||
tag_candidates = get_tag_candidates(owner, repo, headers)
|
||||
if tag_candidates:
|
||||
return tag_candidates
|
||||
|
||||
return get_commit_candidates(owner, repo, plugin_pname, headers)
|
||||
|
||||
|
||||
def compare_to_current(
|
||||
owner: str,
|
||||
repo: str,
|
||||
old_commit: str,
|
||||
candidate: UpdateCandidate,
|
||||
headers: dict[str, str],
|
||||
) -> str:
|
||||
"""Compare a candidate to the packaged commit."""
|
||||
if old_commit == "unknown":
|
||||
print("Current commit is unknown, skipping to avoid a possible regression")
|
||||
return "unknown"
|
||||
|
||||
if candidate.commit is None:
|
||||
raise RuntimeError(f"Candidate {candidate.rev} is unresolved")
|
||||
|
||||
if old_commit == candidate.commit or old_commit == candidate.rev:
|
||||
return "identical"
|
||||
|
||||
compare_data = github_get(owner, repo, f"compare/{old_commit}...{candidate.commit}", headers, allow_404=True)
|
||||
if not isinstance(compare_data, dict):
|
||||
print(f"Could not compare {old_commit}...{candidate.commit}, skipping to avoid a possible regression")
|
||||
return "unknown"
|
||||
|
||||
return str(compare_data.get("status"))
|
||||
|
||||
|
||||
def is_yazi_compatible(
|
||||
owner: str,
|
||||
repo: str,
|
||||
plugin_name: str,
|
||||
plugin_pname: str,
|
||||
candidate: UpdateCandidate,
|
||||
yazi_version: str,
|
||||
headers: dict[str, str],
|
||||
) -> bool:
|
||||
"""Check if a candidate supports nixpkgs' Yazi version."""
|
||||
try:
|
||||
plugin_content = fetch_plugin_content(owner, repo, plugin_pname, candidate.rev, headers)
|
||||
check_version_compatibility(plugin_content, plugin_name, yazi_version)
|
||||
return True
|
||||
except RuntimeError as e:
|
||||
print(f"Skipping {candidate.rev}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def select_compatible_candidate(
|
||||
owner: str,
|
||||
repo: str,
|
||||
plugin_name: str,
|
||||
plugin_pname: str,
|
||||
old_ref_attr: str,
|
||||
old_ref: str,
|
||||
old_commit: str,
|
||||
old_version: str,
|
||||
yazi_version: str,
|
||||
headers: dict[str, str],
|
||||
) -> UpdateCandidate | None:
|
||||
"""Select the newest compatible candidate that moves the package forward."""
|
||||
candidates = get_update_candidates(owner, repo, plugin_pname, headers)
|
||||
|
||||
for unresolved_candidate in candidates:
|
||||
try:
|
||||
candidate = resolve_candidate(owner, repo, unresolved_candidate, headers)
|
||||
except RuntimeError as e:
|
||||
print(f"Skipping {unresolved_candidate.rev}: {e}")
|
||||
if unresolved_candidate.kind in ("release", "tag"):
|
||||
break
|
||||
continue
|
||||
|
||||
print(f"Checking {plugin_name} {candidate.kind} {candidate.rev} ({candidate.date})")
|
||||
|
||||
compare_status = compare_to_current(owner, repo, old_commit, candidate, headers)
|
||||
if compare_status == "identical":
|
||||
candidate_ref_attr = "rev" if candidate.kind == "commit" else "tag"
|
||||
source_ref_changed = old_ref_attr != candidate_ref_attr or old_ref != candidate.rev
|
||||
if old_version != candidate.version or source_ref_changed:
|
||||
if not is_yazi_compatible(owner, repo, plugin_name, plugin_pname, candidate, yazi_version, headers):
|
||||
break
|
||||
|
||||
return candidate
|
||||
|
||||
print(f"{plugin_name} is already at {candidate.rev}; older candidates will not be used")
|
||||
break
|
||||
|
||||
if compare_status != "ahead":
|
||||
print(f"Skipping {candidate.rev}: compare status is {compare_status}, not ahead")
|
||||
if candidate.kind in ("release", "tag"):
|
||||
print(f"{candidate.rev} is not newer than the packaged revision; older {candidate.kind}s will not be used")
|
||||
break
|
||||
continue
|
||||
|
||||
if not is_yazi_compatible(owner, repo, plugin_name, plugin_pname, candidate, yazi_version, headers):
|
||||
continue
|
||||
|
||||
return candidate
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def calculate_sri_hash(owner: str, repo: str, rev: str) -> str:
|
||||
"""Calculate the SRI hash for the plugin source"""
|
||||
prefetch_url = f"https://github.com/{owner}/{repo}/archive/{latest_commit}.tar.gz"
|
||||
prefetch_url = f"https://github.com/{owner}/{repo}/archive/{rev}.tar.gz"
|
||||
|
||||
try:
|
||||
new_hash = run_command(f"nix-prefetch-url --unpack --type sha256 {prefetch_url} 2>/dev/null")
|
||||
@@ -167,16 +408,39 @@ def write_nix_file(file_path: str, content: str) -> None:
|
||||
raise RuntimeError(f"Error writing to file {file_path}: {e}")
|
||||
|
||||
|
||||
def update_nix_file(default_nix_path: str, latest_commit: str, new_version: str, new_hash: str) -> None:
|
||||
def get_source_ref(nix_content: str) -> tuple[str, str]:
|
||||
"""Get the source ref attribute from a Nix file."""
|
||||
source_ref_match = re.search(r'\b(rev|tag) = "([^"]*)"', nix_content)
|
||||
if source_ref_match is None:
|
||||
raise RuntimeError("Could not find rev or tag attribute")
|
||||
|
||||
return source_ref_match.group(1), source_ref_match.group(2)
|
||||
|
||||
|
||||
def resolve_ref_commit(owner: str, repo: str, ref: str, headers: dict[str, str]) -> str:
|
||||
"""Resolve a GitHub ref to its commit."""
|
||||
commit_data = github_get(owner, repo, f"commits/{ref}", headers)
|
||||
if not isinstance(commit_data, dict):
|
||||
raise RuntimeError(f"Could not resolve {ref}")
|
||||
|
||||
return commit_data["sha"]
|
||||
|
||||
|
||||
def update_nix_file(default_nix_path: str, candidate: UpdateCandidate, new_hash: str) -> None:
|
||||
"""Update the default.nix file with new version, revision and hash"""
|
||||
default_nix_content = read_nix_file(default_nix_path)
|
||||
|
||||
default_nix_content = re.sub(r'rev = "[^"]*"', f'rev = "{latest_commit}"', default_nix_content)
|
||||
source_ref_attr = "rev" if candidate.kind == "commit" else "tag"
|
||||
default_nix_content = re.sub(
|
||||
r'\b(rev|tag) = "[^"]*"',
|
||||
f'{source_ref_attr} = "{candidate.rev}"',
|
||||
default_nix_content,
|
||||
)
|
||||
|
||||
if 'version = "' in default_nix_content:
|
||||
default_nix_content = re.sub(r'version = "[^"]*"', f'version = "{new_version}"', default_nix_content)
|
||||
default_nix_content = re.sub(r'version = "[^"]*"', f'version = "{candidate.version}"', default_nix_content)
|
||||
else:
|
||||
default_nix_content = re.sub(r'(pname = "[^"]*";)', f'\\1\n version = "{new_version}";', default_nix_content)
|
||||
default_nix_content = re.sub(r'(pname = "[^"]*";)', f'\\1\n version = "{candidate.version}";', default_nix_content)
|
||||
|
||||
if 'hash = "' in default_nix_content:
|
||||
default_nix_content = re.sub(r'hash = "[^"]*"', f'hash = "{new_hash}"', default_nix_content)
|
||||
@@ -202,6 +466,11 @@ def get_all_plugins(nixpkgs_dir: str) -> list[dict[str, str]]:
|
||||
|
||||
excluded_attrs = ["mkYaziPlugin", "override", "overrideDerivation", "overrideAttrs", "recurseForDerivations"]
|
||||
plugin_names = [name for name in plugin_names if name not in excluded_attrs]
|
||||
plugin_names = [
|
||||
name
|
||||
for name in plugin_names
|
||||
if Path(nixpkgs_dir, "pkgs/by-name/ya/yazi/plugins", name, "default.nix").exists()
|
||||
]
|
||||
|
||||
plugins = []
|
||||
for name in plugin_names:
|
||||
@@ -247,8 +516,7 @@ def update_single_plugin(nixpkgs_dir: str, plugin_name: str, plugin_pname: str)
|
||||
nix_content = read_nix_file(default_nix_path)
|
||||
old_version_match = re.search(r'version = "([^"]*)"', nix_content)
|
||||
old_version = old_version_match.group(1) if old_version_match else "unknown"
|
||||
old_commit_match = re.search(r'rev = "([^"]*)"', nix_content)
|
||||
old_commit = old_commit_match.group(1) if old_commit_match else "unknown"
|
||||
old_ref_attr, old_ref = get_source_ref(nix_content)
|
||||
|
||||
plugin_info = get_plugin_info(nixpkgs_dir, plugin_name)
|
||||
owner = plugin_info["owner"]
|
||||
@@ -257,34 +525,43 @@ def update_single_plugin(nixpkgs_dir: str, plugin_name: str, plugin_pname: str)
|
||||
yazi_version = get_yazi_version(nixpkgs_dir)
|
||||
|
||||
headers = get_github_headers()
|
||||
try:
|
||||
old_commit = old_ref if old_ref_attr == "rev" else resolve_ref_commit(owner, repo, old_ref, headers)
|
||||
except RuntimeError as e:
|
||||
print(f"Could not resolve current {old_ref_attr} {old_ref}: {e}")
|
||||
old_commit = "unknown"
|
||||
|
||||
plugin_content = fetch_plugin_content(owner, repo, plugin_pname, headers)
|
||||
required_version = check_version_compatibility(plugin_content, plugin_name, yazi_version)
|
||||
|
||||
latest_commit, commit_date = get_latest_commit(owner, repo, plugin_pname, headers)
|
||||
print(f"Checking {plugin_name} latest commit {latest_commit} ({commit_date})")
|
||||
|
||||
if latest_commit == old_commit:
|
||||
print(f"No changes for {plugin_name}, already at latest commit {latest_commit}")
|
||||
candidate = select_compatible_candidate(
|
||||
owner,
|
||||
repo,
|
||||
plugin_name,
|
||||
plugin_pname,
|
||||
old_ref_attr,
|
||||
old_ref,
|
||||
old_commit,
|
||||
old_version,
|
||||
yazi_version,
|
||||
headers,
|
||||
)
|
||||
if candidate is None:
|
||||
print(f"No forward compatible update found for {plugin_name}")
|
||||
return None
|
||||
|
||||
print(f"Updating {plugin_name} from commit {old_commit} to {latest_commit}")
|
||||
print(f"Updating {plugin_name} from {old_commit} to {candidate.rev}")
|
||||
|
||||
new_version = f"{required_version}-unstable-{commit_date}"
|
||||
|
||||
new_hash = calculate_sri_hash(owner, repo, latest_commit)
|
||||
new_hash = calculate_sri_hash(owner, repo, candidate.rev)
|
||||
print(f"Generated SRI hash: {new_hash}")
|
||||
|
||||
update_nix_file(default_nix_path, latest_commit, new_version, new_hash)
|
||||
update_nix_file(default_nix_path, candidate, new_hash)
|
||||
|
||||
print(f"Successfully updated {plugin_name} from {old_version} to {new_version}")
|
||||
print(f"Successfully updated {plugin_name} from {old_version} to {candidate.version}")
|
||||
|
||||
return {
|
||||
"name": plugin_name,
|
||||
"old_version": old_version,
|
||||
"new_version": new_version,
|
||||
"new_version": candidate.version,
|
||||
"old_commit": old_commit,
|
||||
"new_commit": latest_commit,
|
||||
"new_commit": candidate.commit,
|
||||
"owner": owner,
|
||||
"repo": repo,
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "vcs-files.yazi";
|
||||
version = "26.1.22-unstable-2026-04-10";
|
||||
version = "0-unstable-2026-04-10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "yafg.yazi";
|
||||
version = "0-unstable-2026-01-10";
|
||||
version = "0-unstable-2026-05-06";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "XYenon";
|
||||
repo = "yafg.yazi";
|
||||
rev = "dd03b133d6cd1ff92368360558da193517169f9e";
|
||||
hash = "sha256-xTZ+6KRr85A4QpPWAE9QN1AnUVnCw/tvRvsWOmmayao=";
|
||||
rev = "e6ba85125bfa4e3a60ef28b70949299712103b2a";
|
||||
hash = "sha256-IKQscTTirtfbsXKzCmaokPDrQZqXa4MSY2+6DbEQluU=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "yatline.yazi";
|
||||
version = "25.12.29-unstable-2026-01-27";
|
||||
version = "0.5.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "imsi32";
|
||||
repo = "yatline.yazi";
|
||||
rev = "c5d4b487d6277dd68ea9d3c6537641bf4ae9cf8e";
|
||||
tag = "v0.5.0";
|
||||
hash = "sha256-HjTRAfUHs6vlEWKruQWeA2wT/Mcd+WEHM90egFTYcWQ=";
|
||||
};
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ buildPythonPackage rec {
|
||||
patches = [
|
||||
# Fix time-of-day-dependent failure in series_time validation.
|
||||
(fetchpatch2 {
|
||||
url = "https://github.com/ImagingDataCommons/highdicom/commit/e9e3f2514a74b0d4be736cff222c934ef66d67ff.patch";
|
||||
hash = "sha256-48dJAimxXYG0FQouquY5TLXi+3HarS8yx9HoLXiFymM=";
|
||||
url = "https://github.com/ImagingDataCommons/highdicom/commit/e9e3f2514a74b0d4be736cff222c934ef66d67ff.patch?full_index=1";
|
||||
hash = "sha256-1h9xmcezxuvHw54t4kLahDB62d0XHzEyrmHmPf6NW7M=";
|
||||
})
|
||||
];
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
pytestCheckHook,
|
||||
fetchFromGitHub,
|
||||
fetchpatch,
|
||||
fetchpatch2,
|
||||
replaceVars,
|
||||
exiftool,
|
||||
ffmpeg,
|
||||
@@ -55,6 +56,16 @@ buildPythonPackage rec {
|
||||
url = "https://github.com/jvoisin/mat2/commit/00b4f110711754496932c59d5af3c0b2ed694484.patch";
|
||||
hash = "sha256-5h/nM1dK8HmYtoIBVGOvUegMFBpGxcfpn5O6QrjLi9M=";
|
||||
})
|
||||
# Loosen test_climat2 assertions split across terminal-width boundaries.
|
||||
(fetchpatch2 {
|
||||
url = "https://github.com/jvoisin/mat2/commit/690e01d475117a4e0c85f26154b26ef332f036be.patch?full_index=1";
|
||||
hash = "sha256-pDbY3E6BPp20orDOx7zxhCdAB+nAdpddTYjPYHStVLc=";
|
||||
})
|
||||
# Fix test_climat2 under Python 3.14+ argparse usage formatting.
|
||||
(fetchpatch2 {
|
||||
url = "https://github.com/jvoisin/mat2/commit/05f34a17695be65b1ad9782911f87e000de8fc8b.patch?full_index=1";
|
||||
hash = "sha256-rIaXocT+LKM2De5iBPIPoBdFbdd17TJJPyFrPzNAJF0=";
|
||||
})
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
}:
|
||||
mkKdeDerivation rec {
|
||||
pname = "plasma-wayland-protocols";
|
||||
version = "1.20.0";
|
||||
version = "1.21.0";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://kde/stable/plasma-wayland-protocols/plasma-wayland-protocols-${version}.tar.xz";
|
||||
hash = "sha256-mBi7FGIhHOWYLmcKvw2WTrEf4dDAKhwmCE2zBpWnnWo=";
|
||||
hash = "sha256-aYp7KLcRJwMU45biSK6GCHz+rtATcgCQY5lb5uHchbo=";
|
||||
};
|
||||
|
||||
meta.license = with lib.licenses; [
|
||||
|
||||
@@ -25,18 +25,18 @@
|
||||
"lts": true
|
||||
},
|
||||
"6.12": {
|
||||
"version": "6.12.87",
|
||||
"hash": "sha256:0c4qidff0qs2x0mvba83cw3ksaz2af3xwabvc839xvsc9djaf4nc",
|
||||
"version": "6.12.88",
|
||||
"hash": "sha256:1s2x66j46gxw17j8hh5iws0l00aivmphp3mn8vgwbn8sj44gacjb",
|
||||
"lts": true
|
||||
},
|
||||
"6.18": {
|
||||
"version": "6.18.29",
|
||||
"hash": "sha256:0g584ak8p9nqxysn8d1qzxbp1asfd39hqy9np35gri9v3xdsfgn3",
|
||||
"version": "6.18.30",
|
||||
"hash": "sha256:1m5kvzky4g2jc8b09np8can0lasg1lwjfgdj41s3ymxgqdp8icx8",
|
||||
"lts": true
|
||||
},
|
||||
"7.0": {
|
||||
"version": "7.0.6",
|
||||
"hash": "sha256:08vm18wx6399phzgr3wz94yga3ab4fyca79445ygvbspm904996b",
|
||||
"version": "7.0.7",
|
||||
"hash": "sha256:1x2xnb7gpj0inxdc317zi71i0d98b7wq64s0yzk2vzxalf3gxqf8",
|
||||
"lts": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
lib,
|
||||
mkMesonExecutable,
|
||||
stdenv,
|
||||
|
||||
nix-store,
|
||||
nix-expr,
|
||||
@@ -12,6 +13,11 @@
|
||||
# Configuration Options
|
||||
|
||||
version,
|
||||
|
||||
# Whether to link against mimalloc for malloc override.
|
||||
# Significantly improves evaluation performance on allocation-heavy
|
||||
# workloads (~10-15% on large evaluations).
|
||||
withMimalloc ? !stdenv.hostPlatform.isWindows,
|
||||
}:
|
||||
|
||||
mkMesonExecutable (finalAttrs: {
|
||||
@@ -25,10 +31,11 @@ mkMesonExecutable (finalAttrs: {
|
||||
nix-expr
|
||||
nix-main
|
||||
nix-cmd
|
||||
mimalloc
|
||||
];
|
||||
]
|
||||
++ lib.optional ((lib.versionAtLeast version "2.35pre") && withMimalloc) mimalloc;
|
||||
|
||||
mesonFlags = [
|
||||
mesonFlags = lib.optionals (lib.versionAtLeast version "2.35pre") [
|
||||
(lib.mesonEnable "mimalloc" withMimalloc)
|
||||
];
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -56,6 +56,7 @@ let
|
||||
"communicator"
|
||||
"dolphin-plugins"
|
||||
"eventviews"
|
||||
"extra-cmake-modules"
|
||||
"flatpak-kcm"
|
||||
"ghostwriter"
|
||||
"grantleetheme"
|
||||
|
||||
Reference in New Issue
Block a user