Merge branch 'staging-next' into staging
Conflicts: pkgs/development/libraries/log4cplus/default.nix
This commit is contained in:
commit
07a8ae0c5a
6
.github/CODEOWNERS
vendored
6
.github/CODEOWNERS
vendored
|
@ -39,7 +39,7 @@
|
||||||
/pkgs/top-level/stage.nix @nbp @Ericson2314 @matthewbauer
|
/pkgs/top-level/stage.nix @nbp @Ericson2314 @matthewbauer
|
||||||
/pkgs/top-level/splice.nix @Ericson2314 @matthewbauer
|
/pkgs/top-level/splice.nix @Ericson2314 @matthewbauer
|
||||||
/pkgs/top-level/release-cross.nix @Ericson2314 @matthewbauer
|
/pkgs/top-level/release-cross.nix @Ericson2314 @matthewbauer
|
||||||
/pkgs/stdenv/generic @Ericson2314 @matthewbauer
|
/pkgs/stdenv/generic @Ericson2314 @matthewbauer @cab404
|
||||||
/pkgs/stdenv/cross @Ericson2314 @matthewbauer
|
/pkgs/stdenv/cross @Ericson2314 @matthewbauer
|
||||||
/pkgs/build-support/cc-wrapper @Ericson2314 @orivej
|
/pkgs/build-support/cc-wrapper @Ericson2314 @orivej
|
||||||
/pkgs/build-support/bintools-wrapper @Ericson2314 @orivej
|
/pkgs/build-support/bintools-wrapper @Ericson2314 @orivej
|
||||||
|
@ -219,9 +219,9 @@
|
||||||
# Podman, CRI-O modules and related
|
# Podman, CRI-O modules and related
|
||||||
/nixos/modules/virtualisation/containers.nix @NixOS/podman @zowoq @adisbladis
|
/nixos/modules/virtualisation/containers.nix @NixOS/podman @zowoq @adisbladis
|
||||||
/nixos/modules/virtualisation/cri-o.nix @NixOS/podman @zowoq @adisbladis
|
/nixos/modules/virtualisation/cri-o.nix @NixOS/podman @zowoq @adisbladis
|
||||||
/nixos/modules/virtualisation/podman.nix @NixOS/podman @zowoq @adisbladis
|
/nixos/modules/virtualisation/podman @NixOS/podman @zowoq @adisbladis
|
||||||
/nixos/tests/cri-o.nix @NixOS/podman @zowoq @adisbladis
|
/nixos/tests/cri-o.nix @NixOS/podman @zowoq @adisbladis
|
||||||
/nixos/tests/podman.nix @NixOS/podman @zowoq @adisbladis
|
/nixos/tests/podman @NixOS/podman @zowoq @adisbladis
|
||||||
|
|
||||||
# Docker tools
|
# Docker tools
|
||||||
/pkgs/build-support/docker @roberth @utdemir
|
/pkgs/build-support/docker @roberth @utdemir
|
||||||
|
|
|
@ -1633,3 +1633,25 @@ would be:
|
||||||
```ShellSession
|
```ShellSession
|
||||||
$ maintainers/scripts/update-python-libraries --target minor --commit --use-pkgs-prefix pkgs/development/python-modules/**/default.nix
|
$ maintainers/scripts/update-python-libraries --target minor --commit --use-pkgs-prefix pkgs/development/python-modules/**/default.nix
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## CPython Update Schedule
|
||||||
|
|
||||||
|
With [PEP 602](https://www.python.org/dev/peps/pep-0602/), CPython now
|
||||||
|
follows a yearly release cadence. In nixpkgs, all supported interpreters
|
||||||
|
are made available, but only the most recent two
|
||||||
|
interpreters package sets are built; this is a compromise between being
|
||||||
|
the latest interpreter, and what the majority of the Python packages support.
|
||||||
|
|
||||||
|
New CPython interpreters are released in October. Generally, it takes some
|
||||||
|
time for the majority of active Python projects to support the latest stable
|
||||||
|
interpreter. To help ease the migration for Nixpkgs users
|
||||||
|
between Python interpreters the schedule below will be used:
|
||||||
|
|
||||||
|
| When | Event |
|
||||||
|
| --- | --- |
|
||||||
|
| After YY.11 Release | Bump CPython package set window. The latest and previous latest stable should now be built. |
|
||||||
|
| After YY.05 Release | Bump default CPython interpreter to latest stable. |
|
||||||
|
|
||||||
|
In practice, this means that the Python community will have had a stable interpreter
|
||||||
|
for ~2 months before attempting to update the package set. And this will
|
||||||
|
allow for ~7 months for Python applications to support the latest interpreter.
|
||||||
|
|
|
@ -201,6 +201,19 @@ $ nix-shell --run 'ruby -rpg -e "puts PG.library_version"'
|
||||||
|
|
||||||
Of course for this use-case one could also use overlays since the configuration for `pg` depends on the `postgresql` alias, but for demonstration purposes this has to suffice.
|
Of course for this use-case one could also use overlays since the configuration for `pg` depends on the `postgresql` alias, but for demonstration purposes this has to suffice.
|
||||||
|
|
||||||
|
### Platform-specific gems
|
||||||
|
|
||||||
|
Right now, bundix has some issues with pre-built, platform-specific gems: [bundix PR #68](https://github.com/nix-community/bundix/pull/68).
|
||||||
|
Until this is solved, you can tell bundler to not use platform-specific gems and instead build them from source each time:
|
||||||
|
- globally (will be set in `~/.config/.bundle/config`):
|
||||||
|
```shell
|
||||||
|
$ bundle config set force_ruby_platform true
|
||||||
|
```
|
||||||
|
- locally (will be set in `<project-root>/.bundle/config`):
|
||||||
|
```shell
|
||||||
|
$ bundle config set --local force_ruby_platform true
|
||||||
|
```
|
||||||
|
|
||||||
### Adding a gem to the default gemset {#adding-a-gem-to-the-default-gemset}
|
### Adding a gem to the default gemset {#adding-a-gem-to-the-default-gemset}
|
||||||
|
|
||||||
Now that you know how to get a working Ruby environment with Nix, it's time to go forward and start actually developing with Ruby. We will first have a look at how Ruby gems are packaged on Nix. Then, we will look at how you can use development mode with your code.
|
Now that you know how to get a working Ruby environment with Nix, it's time to go forward and start actually developing with Ruby. We will first have a look at how Ruby gems are packaged on Nix. Then, we will look at how you can use development mode with your code.
|
||||||
|
|
|
@ -796,7 +796,7 @@ The standard environment provides a number of useful functions.
|
||||||
|
|
||||||
### `makeWrapper` \<executable\> \<wrapperfile\> \<args\> {#fun-makeWrapper}
|
### `makeWrapper` \<executable\> \<wrapperfile\> \<args\> {#fun-makeWrapper}
|
||||||
|
|
||||||
Constructs a wrapper for a program with various possible arguments. For example:
|
Constructs a wrapper for a program with various possible arguments. It is defined as part of 2 setup-hooks named `makeWrapper` and `makeBinaryWrapper` that implement the same bash functions. Hence, to use it you have to add `makeWrapper` to your `nativeBuildInputs`. Here's an example usage:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# adds `FOOBAR=baz` to `$out/bin/foo`’s environment
|
# adds `FOOBAR=baz` to `$out/bin/foo`’s environment
|
||||||
|
@ -808,9 +808,11 @@ makeWrapper $out/bin/foo $wrapperfile --set FOOBAR baz
|
||||||
makeWrapper $out/bin/foo $wrapperfile --prefix PATH : ${lib.makeBinPath [ hello git ]}
|
makeWrapper $out/bin/foo $wrapperfile --prefix PATH : ${lib.makeBinPath [ hello git ]}
|
||||||
```
|
```
|
||||||
|
|
||||||
There’s many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh`.
|
There’s many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh` for the `makeWrapper` implementation and in `nixpkgs/pkgs/build-support/setup-hooks/make-binary-wrapper.sh` for the `makeBinaryWrapper` implementation.
|
||||||
|
|
||||||
`wrapProgram` is a convenience function you probably want to use most of the time.
|
`wrapProgram` is a convenience function you probably want to use most of the time, implemented by both `makeWrapper` and `makeBinaryWrapper`.
|
||||||
|
|
||||||
|
Using the `makeBinaryWrapper` implementation is usually preferred, as it creates a tiny _compiled_ wrapper executable, that can be used as a shebang interpreter. This is needed mostly on Darwin, where shebangs cannot point to scripts, [due to a limitation with the `execve`-syscall](https://stackoverflow.com/questions/67100831/macos-shebang-with-absolute-path-not-working). Compiled wrappers generated by `makeBinaryWrapper` can be inspected with `less <path-to-wrapper>` - by scrolling past the binary data you should be able to see the shell command that generated the executable and there see the environment variables that were injected into the wrapper.
|
||||||
|
|
||||||
### `substitute` \<infile\> \<outfile\> \<subs\> {#fun-substitute}
|
### `substitute` \<infile\> \<outfile\> \<subs\> {#fun-substitute}
|
||||||
|
|
||||||
|
@ -885,9 +887,9 @@ someVar=$(stripHash $name)
|
||||||
|
|
||||||
### `wrapProgram` \<executable\> \<makeWrapperArgs\> {#fun-wrapProgram}
|
### `wrapProgram` \<executable\> \<makeWrapperArgs\> {#fun-wrapProgram}
|
||||||
|
|
||||||
Convenience function for `makeWrapper` that automatically creates a sane wrapper file. It takes all the same arguments as `makeWrapper`, except for `--argv0`.
|
Convenience function for `makeWrapper` that replaces `<\executable\>` with a wrapper that executes the original program. It takes all the same arguments as `makeWrapper`, except for `--inherit-argv0` (used by the `makeBinaryWrapper` implementation) and `--argv0` (used by both `makeWrapper` and `makeBinaryWrapper` wrapper implementations).
|
||||||
|
|
||||||
It cannot be applied multiple times, since it will overwrite the wrapper file.
|
If you will apply it multiple times, it will overwrite the wrapper file and you will end up with double wrapping, which should be avoided.
|
||||||
|
|
||||||
## Package setup hooks {#ssec-setup-hooks}
|
## Package setup hooks {#ssec-setup-hooks}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,8 @@ let
|
||||||
"riscv32-netbsd" "riscv64-netbsd" "x86_64-netbsd"
|
"riscv32-netbsd" "riscv64-netbsd" "x86_64-netbsd"
|
||||||
|
|
||||||
# none
|
# none
|
||||||
"aarch64-none" "arm-none" "armv6l-none" "avr-none" "i686-none"
|
"aarch64_be-none" "aarch64-none" "arm-none" "armv6l-none" "avr-none" "i686-none"
|
||||||
"msp430-none" "or1k-none" "m68k-none" "powerpc-none"
|
"msp430-none" "or1k-none" "m68k-none" "powerpc-none" "powerpcle-none"
|
||||||
"riscv32-none" "riscv64-none" "s390-none" "s390x-none" "vc4-none"
|
"riscv32-none" "riscv64-none" "s390-none" "s390x-none" "vc4-none"
|
||||||
"x86_64-none"
|
"x86_64-none"
|
||||||
|
|
||||||
|
|
|
@ -290,6 +290,7 @@ rec {
|
||||||
libc = "nblibc";
|
libc = "nblibc";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# this is broken and never worked fully
|
||||||
x86_64-netbsd-llvm = {
|
x86_64-netbsd-llvm = {
|
||||||
config = "x86_64-unknown-netbsd";
|
config = "x86_64-unknown-netbsd";
|
||||||
libc = "nblibc";
|
libc = "nblibc";
|
||||||
|
|
|
@ -1414,6 +1414,12 @@
|
||||||
githubId = 251106;
|
githubId = 251106;
|
||||||
name = "Daniel Bergey";
|
name = "Daniel Bergey";
|
||||||
};
|
};
|
||||||
|
bergkvist = {
|
||||||
|
email = "tobias@bergkv.ist";
|
||||||
|
github = "bergkvist";
|
||||||
|
githubId = 410028;
|
||||||
|
name = "Tobias Bergkvist";
|
||||||
|
};
|
||||||
betaboon = {
|
betaboon = {
|
||||||
email = "betaboon@0x80.ninja";
|
email = "betaboon@0x80.ninja";
|
||||||
github = "betaboon";
|
github = "betaboon";
|
||||||
|
@ -3689,6 +3695,7 @@
|
||||||
};
|
};
|
||||||
evils = {
|
evils = {
|
||||||
email = "evils.devils@protonmail.com";
|
email = "evils.devils@protonmail.com";
|
||||||
|
matrix = "@evils:nixos.dev";
|
||||||
github = "evils";
|
github = "evils";
|
||||||
githubId = 30512529;
|
githubId = 30512529;
|
||||||
name = "Evils";
|
name = "Evils";
|
||||||
|
@ -13389,4 +13396,10 @@
|
||||||
github = "vdot0x23";
|
github = "vdot0x23";
|
||||||
githubId = 40716069;
|
githubId = 40716069;
|
||||||
};
|
};
|
||||||
|
jpagex = {
|
||||||
|
name = "Jérémy Pagé";
|
||||||
|
email = "contact@jeremypage.me";
|
||||||
|
github = "jpagex";
|
||||||
|
githubId = 635768;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,7 +385,7 @@ def check_results(
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def parse_plugin_line(line: str) -> PluginDesc:
|
def parse_plugin_line(line: str) -> PluginDesc:
|
||||||
branch = "master"
|
branch = "HEAD"
|
||||||
alias = None
|
alias = None
|
||||||
name, repo = line.split("/")
|
name, repo = line.split("/")
|
||||||
if " as " in repo:
|
if " as " in repo:
|
||||||
|
|
|
@ -259,4 +259,11 @@ with lib.maintainers; {
|
||||||
];
|
];
|
||||||
scope = "coqui-ai TTS (formerly Mozilla TTS) and leaf packages";
|
scope = "coqui-ai TTS (formerly Mozilla TTS) and leaf packages";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
xfce = {
|
||||||
|
members = [
|
||||||
|
romildo
|
||||||
|
];
|
||||||
|
scope = "Maintain Xfce desktop environment and related packages.";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ let
|
||||||
in rec {
|
in rec {
|
||||||
inherit generatedSources;
|
inherit generatedSources;
|
||||||
|
|
||||||
inherit (optionsDoc) optionsJSON optionsXML optionsDocBook;
|
inherit (optionsDoc) optionsJSON optionsDocBook;
|
||||||
|
|
||||||
# Generate the NixOS manual.
|
# Generate the NixOS manual.
|
||||||
manualHTML = runCommand "nixos-manual-html"
|
manualHTML = runCommand "nixos-manual-html"
|
||||||
|
|
|
@ -53,12 +53,12 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
withWarnings = x:
|
withWarnings = x:
|
||||||
lib.warnIf (evalConfigArgs?args) "The extraArgs argument to eval-config.nix is deprecated. Please set config._module.args instead."
|
lib.warnIf (evalConfigArgs?extraArgs) "The extraArgs argument to eval-config.nix is deprecated. Please set config._module.args instead."
|
||||||
lib.warnIf (evalConfigArgs?check) "The check argument to eval-config.nix is deprecated. Please set config._module.check instead."
|
lib.warnIf (evalConfigArgs?check) "The check argument to eval-config.nix is deprecated. Please set config._module.check instead."
|
||||||
x;
|
x;
|
||||||
|
|
||||||
legacyModules =
|
legacyModules =
|
||||||
lib.optional (evalConfigArgs?args) {
|
lib.optional (evalConfigArgs?extraArgs) {
|
||||||
config = {
|
config = {
|
||||||
_module.args = extraArgs;
|
_module.args = extraArgs;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,18 +24,25 @@
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
# Replace functions by the string <function>
|
# Make a value safe for JSON. Functions are replaced by the string "<function>",
|
||||||
substFunction = x:
|
# derivations are replaced with an attrset
|
||||||
if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
|
# { _type = "derivation"; name = <name of that derivation>; }.
|
||||||
else if builtins.isList x then map substFunction x
|
# We need to handle derivations specially because consumers want to know about them,
|
||||||
|
# but we can't easily use the type,name subset of keys (since type is often used as
|
||||||
|
# a module option and might cause confusion). Use _type,name instead to the same
|
||||||
|
# effect, since _type is already used by the module system.
|
||||||
|
substSpecial = x:
|
||||||
|
if lib.isDerivation x then { _type = "derivation"; name = x.name; }
|
||||||
|
else if builtins.isAttrs x then lib.mapAttrs (name: substSpecial) x
|
||||||
|
else if builtins.isList x then map substSpecial x
|
||||||
else if lib.isFunction x then "<function>"
|
else if lib.isFunction x then "<function>"
|
||||||
else x;
|
else x;
|
||||||
|
|
||||||
optionsListDesc = lib.flip map optionsListVisible
|
optionsList = lib.flip map optionsListVisible
|
||||||
(opt: transformOptions opt
|
(opt: transformOptions opt
|
||||||
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
|
// lib.optionalAttrs (opt ? example) { example = substSpecial opt.example; }
|
||||||
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
|
// lib.optionalAttrs (opt ? default) { default = substSpecial opt.default; }
|
||||||
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
|
// lib.optionalAttrs (opt ? type) { type = substSpecial opt.type; }
|
||||||
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages opt.name; }
|
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages opt.name; }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -69,96 +76,25 @@ let
|
||||||
+ "</listitem>";
|
+ "</listitem>";
|
||||||
in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
|
in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
|
||||||
|
|
||||||
# Custom "less" that pushes up all the things ending in ".enable*"
|
|
||||||
# and ".package*"
|
|
||||||
optionLess = a: b:
|
|
||||||
let
|
|
||||||
ise = lib.hasPrefix "enable";
|
|
||||||
isp = lib.hasPrefix "package";
|
|
||||||
cmp = lib.splitByAndCompare ise lib.compare
|
|
||||||
(lib.splitByAndCompare isp lib.compare lib.compare);
|
|
||||||
in lib.compareLists cmp a.loc b.loc < 0;
|
|
||||||
|
|
||||||
# Remove invisible and internal options.
|
# Remove invisible and internal options.
|
||||||
optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
|
optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
|
||||||
|
|
||||||
# Customly sort option list for the man page.
|
|
||||||
# Always ensure that the sort order matches sortXML.py!
|
|
||||||
optionsList = lib.sort optionLess optionsListDesc;
|
|
||||||
|
|
||||||
# Convert the list of options into an XML file.
|
|
||||||
# This file is *not* sorted sorted to save on eval time, since the docbook XML
|
|
||||||
# and the manpage depend on it and thus we evaluate this on every system rebuild.
|
|
||||||
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsListDesc);
|
|
||||||
|
|
||||||
optionsNix = builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList);
|
optionsNix = builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList);
|
||||||
|
|
||||||
# TODO: declarations: link to github
|
in rec {
|
||||||
singleAsciiDoc = name: value: ''
|
|
||||||
== ${name}
|
|
||||||
|
|
||||||
${value.description}
|
|
||||||
|
|
||||||
[discrete]
|
|
||||||
=== details
|
|
||||||
|
|
||||||
Type:: ${value.type}
|
|
||||||
${ if lib.hasAttr "default" value
|
|
||||||
then ''
|
|
||||||
Default::
|
|
||||||
+
|
|
||||||
----
|
|
||||||
${builtins.toJSON value.default}
|
|
||||||
----
|
|
||||||
''
|
|
||||||
else "No Default:: {blank}"
|
|
||||||
}
|
|
||||||
${ if value.readOnly
|
|
||||||
then "Read Only:: {blank}"
|
|
||||||
else ""
|
|
||||||
}
|
|
||||||
${ if lib.hasAttr "example" value
|
|
||||||
then ''
|
|
||||||
Example::
|
|
||||||
+
|
|
||||||
----
|
|
||||||
${builtins.toJSON value.example}
|
|
||||||
----
|
|
||||||
''
|
|
||||||
else "No Example:: {blank}"
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
singleMDDoc = name: value: ''
|
|
||||||
## ${lib.escape [ "<" ">" ] name}
|
|
||||||
${value.description}
|
|
||||||
|
|
||||||
${lib.optionalString (value ? type) ''
|
|
||||||
*_Type_*:
|
|
||||||
${value.type}
|
|
||||||
''}
|
|
||||||
|
|
||||||
${lib.optionalString (value ? default) ''
|
|
||||||
*_Default_*
|
|
||||||
```
|
|
||||||
${builtins.toJSON value.default}
|
|
||||||
```
|
|
||||||
''}
|
|
||||||
|
|
||||||
${lib.optionalString (value ? example) ''
|
|
||||||
*_Example_*
|
|
||||||
```
|
|
||||||
${builtins.toJSON value.example}
|
|
||||||
```
|
|
||||||
''}
|
|
||||||
'';
|
|
||||||
|
|
||||||
in {
|
|
||||||
inherit optionsNix;
|
inherit optionsNix;
|
||||||
|
|
||||||
optionsAsciiDoc = lib.concatStringsSep "\n" (lib.mapAttrsToList singleAsciiDoc optionsNix);
|
optionsAsciiDoc = pkgs.runCommand "options.adoc" {} ''
|
||||||
|
${pkgs.python3Minimal}/bin/python ${./generateAsciiDoc.py} \
|
||||||
|
< ${optionsJSON}/share/doc/nixos/options.json \
|
||||||
|
> $out
|
||||||
|
'';
|
||||||
|
|
||||||
optionsMDDoc = lib.concatStringsSep "\n" (lib.mapAttrsToList singleMDDoc optionsNix);
|
optionsCommonMark = pkgs.runCommand "options.md" {} ''
|
||||||
|
${pkgs.python3Minimal}/bin/python ${./generateCommonMark.py} \
|
||||||
|
< ${optionsJSON}/share/doc/nixos/options.json \
|
||||||
|
> $out
|
||||||
|
'';
|
||||||
|
|
||||||
optionsJSON = pkgs.runCommand "options.json"
|
optionsJSON = pkgs.runCommand "options.json"
|
||||||
{ meta.description = "List of NixOS options in JSON format";
|
{ meta.description = "List of NixOS options in JSON format";
|
||||||
|
@ -176,7 +112,18 @@ in {
|
||||||
mkdir -p $out/nix-support
|
mkdir -p $out/nix-support
|
||||||
echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
|
echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
|
||||||
echo "file json-br $dst/options.json.br" >> $out/nix-support/hydra-build-products
|
echo "file json-br $dst/options.json.br" >> $out/nix-support/hydra-build-products
|
||||||
''; # */
|
'';
|
||||||
|
|
||||||
|
# Convert options.json into an XML file.
|
||||||
|
# The actual generation of the xml file is done in nix purely for the convenience
|
||||||
|
# of not having to generate the xml some other way
|
||||||
|
optionsXML = pkgs.runCommand "options.xml" {} ''
|
||||||
|
${pkgs.nix}/bin/nix-instantiate \
|
||||||
|
--store dummy:// \
|
||||||
|
--eval --xml --strict ${./optionsJSONtoXML.nix} \
|
||||||
|
--argstr file ${optionsJSON}/share/doc/nixos/options.json \
|
||||||
|
> "$out"
|
||||||
|
'';
|
||||||
|
|
||||||
optionsDocBook = pkgs.runCommand "options-docbook.xml" {} ''
|
optionsDocBook = pkgs.runCommand "options-docbook.xml" {} ''
|
||||||
optionsXML=${optionsXML}
|
optionsXML=${optionsXML}
|
||||||
|
|
37
nixos/lib/make-options-doc/generateAsciiDoc.py
Normal file
37
nixos/lib/make-options-doc/generateAsciiDoc.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
options = json.load(sys.stdin)
|
||||||
|
# TODO: declarations: link to github
|
||||||
|
for (name, value) in options.items():
|
||||||
|
print(f'== {name}')
|
||||||
|
print()
|
||||||
|
print(value['description'])
|
||||||
|
print()
|
||||||
|
print('[discrete]')
|
||||||
|
print('=== details')
|
||||||
|
print()
|
||||||
|
print(f'Type:: {value["type"]}')
|
||||||
|
if 'default' in value:
|
||||||
|
print('Default::')
|
||||||
|
print('+')
|
||||||
|
print('----')
|
||||||
|
print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
|
||||||
|
print('----')
|
||||||
|
print()
|
||||||
|
else:
|
||||||
|
print('No Default:: {blank}')
|
||||||
|
if value['readOnly']:
|
||||||
|
print('Read Only:: {blank}')
|
||||||
|
else:
|
||||||
|
print()
|
||||||
|
if 'example' in value:
|
||||||
|
print('Example::')
|
||||||
|
print('+')
|
||||||
|
print('----')
|
||||||
|
print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
|
||||||
|
print('----')
|
||||||
|
print()
|
||||||
|
else:
|
||||||
|
print('No Example:: {blank}')
|
||||||
|
print()
|
27
nixos/lib/make-options-doc/generateCommonMark.py
Normal file
27
nixos/lib/make-options-doc/generateCommonMark.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
options = json.load(sys.stdin)
|
||||||
|
for (name, value) in options.items():
|
||||||
|
print('##', name.replace('<', '\\<').replace('>', '\\>'))
|
||||||
|
print(value['description'])
|
||||||
|
print()
|
||||||
|
if 'type' in value:
|
||||||
|
print('*_Type_*:')
|
||||||
|
print(value['type'])
|
||||||
|
print()
|
||||||
|
print()
|
||||||
|
if 'default' in value:
|
||||||
|
print('*_Default_*')
|
||||||
|
print('```')
|
||||||
|
print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
|
||||||
|
print('```')
|
||||||
|
print()
|
||||||
|
print()
|
||||||
|
if 'example' in value:
|
||||||
|
print('*_Example_*')
|
||||||
|
print('```')
|
||||||
|
print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
|
||||||
|
print('```')
|
||||||
|
print()
|
||||||
|
print()
|
|
@ -189,7 +189,7 @@
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
<xsl:template match="derivation">
|
<xsl:template match="attrs[attr[@name = '_type' and string[@value = 'derivation']]]">
|
||||||
<replaceable>(build of <xsl:value-of select="attr[@name = 'name']/string/@value" />)</replaceable>
|
<replaceable>(build of <xsl:value-of select="attr[@name = 'name']/string/@value" />)</replaceable>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
6
nixos/lib/make-options-doc/optionsJSONtoXML.nix
Normal file
6
nixos/lib/make-options-doc/optionsJSONtoXML.nix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{ file }:
|
||||||
|
|
||||||
|
builtins.attrValues
|
||||||
|
(builtins.mapAttrs
|
||||||
|
(name: def: def // { inherit name; })
|
||||||
|
(builtins.fromJSON (builtins.readFile file)))
|
|
@ -19,7 +19,6 @@ def sortKey(opt):
|
||||||
for p in opt.findall('attr[@name="loc"]/list/string')
|
for p in opt.findall('attr[@name="loc"]/list/string')
|
||||||
]
|
]
|
||||||
|
|
||||||
# always ensure that the sort order matches the order used in the nix expression!
|
|
||||||
options.sort(key=sortKey)
|
options.sort(key=sortKey)
|
||||||
|
|
||||||
doc = ET.Element("expr")
|
doc = ET.Element("expr")
|
||||||
|
|
|
@ -21,8 +21,15 @@ stdenv.mkDerivation {
|
||||||
# for nix-store --load-db.
|
# for nix-store --load-db.
|
||||||
cp $closureInfo/registration nix-path-registration
|
cp $closureInfo/registration nix-path-registration
|
||||||
|
|
||||||
|
# 64 cores on i686 does not work
|
||||||
|
# fails with FATAL ERROR: mangle2:: xz compress failed with error code 5
|
||||||
|
if ((NIX_BUILD_CORES > 48)); then
|
||||||
|
NIX_BUILD_CORES=48
|
||||||
|
fi
|
||||||
|
|
||||||
# Generate the squashfs image.
|
# Generate the squashfs image.
|
||||||
mksquashfs nix-path-registration $(cat $closureInfo/store-paths) $out \
|
mksquashfs nix-path-registration $(cat $closureInfo/store-paths) $out \
|
||||||
-no-hardlinks -keep-as-directory -all-root -b 1048576 -comp ${comp}
|
-no-hardlinks -keep-as-directory -all-root -b 1048576 -comp ${comp} \
|
||||||
|
-processors $NIX_BUILD_CORES
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{ config, lib }:
|
{ lib, systemdUtils }:
|
||||||
|
|
||||||
|
with systemdUtils.lib;
|
||||||
with lib;
|
with lib;
|
||||||
with import ./systemd-lib.nix { inherit config lib pkgs; };
|
|
||||||
|
|
||||||
let
|
let
|
||||||
checkService = checkUnitConfig "Service" [
|
checkService = checkUnitConfig "Service" [
|
32
nixos/lib/test-driver/default.nix
Normal file
32
nixos/lib/test-driver/default.nix
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{ lib
|
||||||
|
, python3Packages
|
||||||
|
, enableOCR ? false
|
||||||
|
, qemu_pkg ? qemu_test
|
||||||
|
, coreutils
|
||||||
|
, imagemagick_light
|
||||||
|
, libtiff
|
||||||
|
, netpbm
|
||||||
|
, qemu_test
|
||||||
|
, socat
|
||||||
|
, tesseract4
|
||||||
|
, vde2
|
||||||
|
}:
|
||||||
|
|
||||||
|
python3Packages.buildPythonApplication rec {
|
||||||
|
pname = "nixos-test-driver";
|
||||||
|
version = "1.0";
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
propagatedBuildInputs = [ coreutils netpbm python3Packages.colorama python3Packages.ptpython qemu_pkg socat vde2 ]
|
||||||
|
++ (lib.optionals enableOCR [ imagemagick_light tesseract4 ]);
|
||||||
|
|
||||||
|
doCheck = true;
|
||||||
|
checkInputs = with python3Packages; [ mypy pylint black ];
|
||||||
|
checkPhase = ''
|
||||||
|
mypy --disallow-untyped-defs \
|
||||||
|
--no-implicit-optional \
|
||||||
|
--ignore-missing-imports ${src}/test_driver
|
||||||
|
pylint --errors-only ${src}/test_driver
|
||||||
|
black --check --diff ${src}/test_driver
|
||||||
|
'';
|
||||||
|
}
|
13
nixos/lib/test-driver/setup.py
Normal file
13
nixos/lib/test-driver/setup.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="nixos-test-driver",
|
||||||
|
version='1.0',
|
||||||
|
packages=find_packages(),
|
||||||
|
entry_points={
|
||||||
|
"console_scripts": [
|
||||||
|
"nixos-test-driver=test_driver:main",
|
||||||
|
"generate-driver-symbols=test_driver:generate_driver_symbols"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
100
nixos/lib/test-driver/test_driver/__init__.py
Executable file
100
nixos/lib/test-driver/test_driver/__init__.py
Executable file
|
@ -0,0 +1,100 @@
|
||||||
|
from pathlib import Path
|
||||||
|
import argparse
|
||||||
|
import ptpython.repl
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
from test_driver.logger import rootlog
|
||||||
|
from test_driver.driver import Driver
|
||||||
|
|
||||||
|
|
||||||
|
class EnvDefault(argparse.Action):
|
||||||
|
"""An argpars Action that takes values from the specified
|
||||||
|
environment variable as the flags default value.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, envvar, required=False, default=None, nargs=None, **kwargs): # type: ignore
|
||||||
|
if not default and envvar:
|
||||||
|
if envvar in os.environ:
|
||||||
|
if nargs is not None and (nargs.isdigit() or nargs in ["*", "+"]):
|
||||||
|
default = os.environ[envvar].split()
|
||||||
|
else:
|
||||||
|
default = os.environ[envvar]
|
||||||
|
kwargs["help"] = (
|
||||||
|
kwargs["help"] + f" (default from environment: {default})"
|
||||||
|
)
|
||||||
|
if required and default:
|
||||||
|
required = False
|
||||||
|
super(EnvDefault, self).__init__(
|
||||||
|
default=default, required=required, nargs=nargs, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def __call__(self, parser, namespace, values, option_string=None): # type: ignore
|
||||||
|
setattr(namespace, self.dest, values)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
arg_parser = argparse.ArgumentParser(prog="nixos-test-driver")
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"-K",
|
||||||
|
"--keep-vm-state",
|
||||||
|
help="re-use a VM state coming from a previous run",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"-I",
|
||||||
|
"--interactive",
|
||||||
|
help="drop into a python repl and run the tests interactively",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--start-scripts",
|
||||||
|
metavar="START-SCRIPT",
|
||||||
|
action=EnvDefault,
|
||||||
|
envvar="startScripts",
|
||||||
|
nargs="*",
|
||||||
|
help="start scripts for participating virtual machines",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--vlans",
|
||||||
|
metavar="VLAN",
|
||||||
|
action=EnvDefault,
|
||||||
|
envvar="vlans",
|
||||||
|
nargs="*",
|
||||||
|
help="vlans to span by the driver",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"testscript",
|
||||||
|
action=EnvDefault,
|
||||||
|
envvar="testScript",
|
||||||
|
help="the test script to run",
|
||||||
|
type=Path,
|
||||||
|
)
|
||||||
|
|
||||||
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
|
if not args.keep_vm_state:
|
||||||
|
rootlog.info("Machine state will be reset. To keep it, pass --keep-vm-state")
|
||||||
|
|
||||||
|
with Driver(
|
||||||
|
args.start_scripts, args.vlans, args.testscript.read_text(), args.keep_vm_state
|
||||||
|
) as driver:
|
||||||
|
if args.interactive:
|
||||||
|
ptpython.repl.embed(driver.test_symbols(), {})
|
||||||
|
else:
|
||||||
|
tic = time.time()
|
||||||
|
driver.run_tests()
|
||||||
|
toc = time.time()
|
||||||
|
rootlog.info(f"test script finished in {(toc-tic):.2f}s")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_driver_symbols() -> None:
|
||||||
|
"""
|
||||||
|
This generates a file with symbols of the test-driver code that can be used
|
||||||
|
in user's test scripts. That list is then used by pyflakes to lint those
|
||||||
|
scripts.
|
||||||
|
"""
|
||||||
|
d = Driver([], [], "")
|
||||||
|
test_symbols = d.test_symbols()
|
||||||
|
with open("driver-symbols", "w") as fp:
|
||||||
|
fp.write(",".join(test_symbols.keys()))
|
161
nixos/lib/test-driver/test_driver/driver.py
Normal file
161
nixos/lib/test-driver/test_driver/driver.py
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, Iterator, List
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
from test_driver.logger import rootlog
|
||||||
|
from test_driver.machine import Machine, NixStartScript, retry
|
||||||
|
from test_driver.vlan import VLan
|
||||||
|
|
||||||
|
|
||||||
|
class Driver:
|
||||||
|
"""A handle to the driver that sets up the environment
|
||||||
|
and runs the tests"""
|
||||||
|
|
||||||
|
tests: str
|
||||||
|
vlans: List[VLan]
|
||||||
|
machines: List[Machine]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
start_scripts: List[str],
|
||||||
|
vlans: List[int],
|
||||||
|
tests: str,
|
||||||
|
keep_vm_state: bool = False,
|
||||||
|
):
|
||||||
|
self.tests = tests
|
||||||
|
|
||||||
|
tmp_dir = Path(os.environ.get("TMPDIR", tempfile.gettempdir()))
|
||||||
|
tmp_dir.mkdir(mode=0o700, exist_ok=True)
|
||||||
|
|
||||||
|
with rootlog.nested("start all VLans"):
|
||||||
|
self.vlans = [VLan(nr, tmp_dir) for nr in vlans]
|
||||||
|
|
||||||
|
def cmd(scripts: List[str]) -> Iterator[NixStartScript]:
|
||||||
|
for s in scripts:
|
||||||
|
yield NixStartScript(s)
|
||||||
|
|
||||||
|
self.machines = [
|
||||||
|
Machine(
|
||||||
|
start_command=cmd,
|
||||||
|
keep_vm_state=keep_vm_state,
|
||||||
|
name=cmd.machine_name,
|
||||||
|
tmp_dir=tmp_dir,
|
||||||
|
)
|
||||||
|
for cmd in cmd(start_scripts)
|
||||||
|
]
|
||||||
|
|
||||||
|
def __enter__(self) -> "Driver":
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, *_: Any) -> None:
|
||||||
|
with rootlog.nested("cleanup"):
|
||||||
|
for machine in self.machines:
|
||||||
|
machine.release()
|
||||||
|
|
||||||
|
def subtest(self, name: str) -> Iterator[None]:
|
||||||
|
"""Group logs under a given test name"""
|
||||||
|
with rootlog.nested(name):
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
rootlog.error(f'Test "{name}" failed with error: "{e}"')
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def test_symbols(self) -> Dict[str, Any]:
|
||||||
|
@contextmanager
|
||||||
|
def subtest(name: str) -> Iterator[None]:
|
||||||
|
return self.subtest(name)
|
||||||
|
|
||||||
|
general_symbols = dict(
|
||||||
|
start_all=self.start_all,
|
||||||
|
test_script=self.test_script,
|
||||||
|
machines=self.machines,
|
||||||
|
vlans=self.vlans,
|
||||||
|
driver=self,
|
||||||
|
log=rootlog,
|
||||||
|
os=os,
|
||||||
|
create_machine=self.create_machine,
|
||||||
|
subtest=subtest,
|
||||||
|
run_tests=self.run_tests,
|
||||||
|
join_all=self.join_all,
|
||||||
|
retry=retry,
|
||||||
|
serial_stdout_off=self.serial_stdout_off,
|
||||||
|
serial_stdout_on=self.serial_stdout_on,
|
||||||
|
Machine=Machine, # for typing
|
||||||
|
)
|
||||||
|
machine_symbols = {m.name: m for m in self.machines}
|
||||||
|
# If there's exactly one machine, make it available under the name
|
||||||
|
# "machine", even if it's not called that.
|
||||||
|
if len(self.machines) == 1:
|
||||||
|
(machine_symbols["machine"],) = self.machines
|
||||||
|
vlan_symbols = {
|
||||||
|
f"vlan{v.nr}": self.vlans[idx] for idx, v in enumerate(self.vlans)
|
||||||
|
}
|
||||||
|
print(
|
||||||
|
"additionally exposed symbols:\n "
|
||||||
|
+ ", ".join(map(lambda m: m.name, self.machines))
|
||||||
|
+ ",\n "
|
||||||
|
+ ", ".join(map(lambda v: f"vlan{v.nr}", self.vlans))
|
||||||
|
+ ",\n "
|
||||||
|
+ ", ".join(list(general_symbols.keys()))
|
||||||
|
)
|
||||||
|
return {**general_symbols, **machine_symbols, **vlan_symbols}
|
||||||
|
|
||||||
|
def test_script(self) -> None:
|
||||||
|
"""Run the test script"""
|
||||||
|
with rootlog.nested("run the VM test script"):
|
||||||
|
symbols = self.test_symbols() # call eagerly
|
||||||
|
exec(self.tests, symbols, None)
|
||||||
|
|
||||||
|
def run_tests(self) -> None:
|
||||||
|
"""Run the test script (for non-interactive test runs)"""
|
||||||
|
self.test_script()
|
||||||
|
# TODO: Collect coverage data
|
||||||
|
for machine in self.machines:
|
||||||
|
if machine.is_up():
|
||||||
|
machine.execute("sync")
|
||||||
|
|
||||||
|
def start_all(self) -> None:
|
||||||
|
"""Start all machines"""
|
||||||
|
with rootlog.nested("start all VMs"):
|
||||||
|
for machine in self.machines:
|
||||||
|
machine.start()
|
||||||
|
|
||||||
|
def join_all(self) -> None:
|
||||||
|
"""Wait for all machines to shut down"""
|
||||||
|
with rootlog.nested("wait for all VMs to finish"):
|
||||||
|
for machine in self.machines:
|
||||||
|
machine.wait_for_shutdown()
|
||||||
|
|
||||||
|
def create_machine(self, args: Dict[str, Any]) -> Machine:
|
||||||
|
rootlog.warning(
|
||||||
|
"Using legacy create_machine(), please instantiate the"
|
||||||
|
"Machine class directly, instead"
|
||||||
|
)
|
||||||
|
tmp_dir = Path(os.environ.get("TMPDIR", tempfile.gettempdir()))
|
||||||
|
tmp_dir.mkdir(mode=0o700, exist_ok=True)
|
||||||
|
|
||||||
|
if args.get("startCommand"):
|
||||||
|
start_command: str = args.get("startCommand", "")
|
||||||
|
cmd = NixStartScript(start_command)
|
||||||
|
name = args.get("name", cmd.machine_name)
|
||||||
|
else:
|
||||||
|
cmd = Machine.create_startcommand(args) # type: ignore
|
||||||
|
name = args.get("name", "machine")
|
||||||
|
|
||||||
|
return Machine(
|
||||||
|
tmp_dir=tmp_dir,
|
||||||
|
start_command=cmd,
|
||||||
|
name=name,
|
||||||
|
keep_vm_state=args.get("keep_vm_state", False),
|
||||||
|
allow_reboot=args.get("allow_reboot", False),
|
||||||
|
)
|
||||||
|
|
||||||
|
def serial_stdout_on(self) -> None:
|
||||||
|
rootlog._print_serial_logs = True
|
||||||
|
|
||||||
|
def serial_stdout_off(self) -> None:
|
||||||
|
rootlog._print_serial_logs = False
|
101
nixos/lib/test-driver/test_driver/logger.py
Normal file
101
nixos/lib/test-driver/test_driver/logger.py
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
from colorama import Style
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from typing import Any, Dict, Iterator
|
||||||
|
from queue import Queue, Empty
|
||||||
|
from xml.sax.saxutils import XMLGenerator
|
||||||
|
import codecs
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import unicodedata
|
||||||
|
|
||||||
|
|
||||||
|
class Logger:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.logfile = os.environ.get("LOGFILE", "/dev/null")
|
||||||
|
self.logfile_handle = codecs.open(self.logfile, "wb")
|
||||||
|
self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
|
||||||
|
self.queue: "Queue[Dict[str, str]]" = Queue()
|
||||||
|
|
||||||
|
self.xml.startDocument()
|
||||||
|
self.xml.startElement("logfile", attrs={})
|
||||||
|
|
||||||
|
self._print_serial_logs = True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _eprint(*args: object, **kwargs: Any) -> None:
|
||||||
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
self.xml.endElement("logfile")
|
||||||
|
self.xml.endDocument()
|
||||||
|
self.logfile_handle.close()
|
||||||
|
|
||||||
|
def sanitise(self, message: str) -> str:
|
||||||
|
return "".join(ch for ch in message if unicodedata.category(ch)[0] != "C")
|
||||||
|
|
||||||
|
def maybe_prefix(self, message: str, attributes: Dict[str, str]) -> str:
|
||||||
|
if "machine" in attributes:
|
||||||
|
return "{}: {}".format(attributes["machine"], message)
|
||||||
|
return message
|
||||||
|
|
||||||
|
def log_line(self, message: str, attributes: Dict[str, str]) -> None:
|
||||||
|
self.xml.startElement("line", attributes)
|
||||||
|
self.xml.characters(message)
|
||||||
|
self.xml.endElement("line")
|
||||||
|
|
||||||
|
def info(self, *args, **kwargs) -> None: # type: ignore
|
||||||
|
self.log(*args, **kwargs)
|
||||||
|
|
||||||
|
def warning(self, *args, **kwargs) -> None: # type: ignore
|
||||||
|
self.log(*args, **kwargs)
|
||||||
|
|
||||||
|
def error(self, *args, **kwargs) -> None: # type: ignore
|
||||||
|
self.log(*args, **kwargs)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
|
||||||
|
self._eprint(self.maybe_prefix(message, attributes))
|
||||||
|
self.drain_log_queue()
|
||||||
|
self.log_line(message, attributes)
|
||||||
|
|
||||||
|
def log_serial(self, message: str, machine: str) -> None:
|
||||||
|
self.enqueue({"msg": message, "machine": machine, "type": "serial"})
|
||||||
|
if self._print_serial_logs:
|
||||||
|
self._eprint(
|
||||||
|
Style.DIM + "{} # {}".format(machine, message) + Style.RESET_ALL
|
||||||
|
)
|
||||||
|
|
||||||
|
def enqueue(self, item: Dict[str, str]) -> None:
|
||||||
|
self.queue.put(item)
|
||||||
|
|
||||||
|
def drain_log_queue(self) -> None:
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
item = self.queue.get_nowait()
|
||||||
|
msg = self.sanitise(item["msg"])
|
||||||
|
del item["msg"]
|
||||||
|
self.log_line(msg, item)
|
||||||
|
except Empty:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
|
||||||
|
self._eprint(self.maybe_prefix(message, attributes))
|
||||||
|
|
||||||
|
self.xml.startElement("nest", attrs={})
|
||||||
|
self.xml.startElement("head", attributes)
|
||||||
|
self.xml.characters(message)
|
||||||
|
self.xml.endElement("head")
|
||||||
|
|
||||||
|
tic = time.time()
|
||||||
|
self.drain_log_queue()
|
||||||
|
yield
|
||||||
|
self.drain_log_queue()
|
||||||
|
toc = time.time()
|
||||||
|
self.log("(finished: {}, in {:.2f} seconds)".format(message, toc - tic))
|
||||||
|
|
||||||
|
self.xml.endElement("nest")
|
||||||
|
|
||||||
|
|
||||||
|
rootlog = Logger()
|
424
nixos/lib/test-driver/test-driver.py → nixos/lib/test-driver/test_driver/machine.py
Executable file → Normal file
424
nixos/lib/test-driver/test-driver.py → nixos/lib/test-driver/test_driver/machine.py
Executable file → Normal file
|
@ -1,19 +1,11 @@
|
||||||
#! /somewhere/python3
|
from contextlib import _GeneratorContextManager
|
||||||
from contextlib import contextmanager, _GeneratorContextManager
|
|
||||||
from queue import Queue, Empty
|
|
||||||
from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List, Iterable
|
|
||||||
from xml.sax.saxutils import XMLGenerator
|
|
||||||
from colorama import Style
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import queue
|
from queue import Queue
|
||||||
import io
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
|
||||||
import threading
|
|
||||||
import argparse
|
|
||||||
import base64
|
import base64
|
||||||
import codecs
|
import io
|
||||||
import os
|
import os
|
||||||
import ptpython.repl
|
import queue
|
||||||
import pty
|
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -21,8 +13,10 @@ import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
import unicodedata
|
|
||||||
|
from test_driver.logger import rootlog
|
||||||
|
|
||||||
CHAR_TO_KEY = {
|
CHAR_TO_KEY = {
|
||||||
"A": "shift-a",
|
"A": "shift-a",
|
||||||
|
@ -88,115 +82,10 @@ CHAR_TO_KEY = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Logger:
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self.logfile = os.environ.get("LOGFILE", "/dev/null")
|
|
||||||
self.logfile_handle = codecs.open(self.logfile, "wb")
|
|
||||||
self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
|
|
||||||
self.queue: "Queue[Dict[str, str]]" = Queue()
|
|
||||||
|
|
||||||
self.xml.startDocument()
|
|
||||||
self.xml.startElement("logfile", attrs={})
|
|
||||||
|
|
||||||
self._print_serial_logs = True
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _eprint(*args: object, **kwargs: Any) -> None:
|
|
||||||
print(*args, file=sys.stderr, **kwargs)
|
|
||||||
|
|
||||||
def close(self) -> None:
|
|
||||||
self.xml.endElement("logfile")
|
|
||||||
self.xml.endDocument()
|
|
||||||
self.logfile_handle.close()
|
|
||||||
|
|
||||||
def sanitise(self, message: str) -> str:
|
|
||||||
return "".join(ch for ch in message if unicodedata.category(ch)[0] != "C")
|
|
||||||
|
|
||||||
def maybe_prefix(self, message: str, attributes: Dict[str, str]) -> str:
|
|
||||||
if "machine" in attributes:
|
|
||||||
return "{}: {}".format(attributes["machine"], message)
|
|
||||||
return message
|
|
||||||
|
|
||||||
def log_line(self, message: str, attributes: Dict[str, str]) -> None:
|
|
||||||
self.xml.startElement("line", attributes)
|
|
||||||
self.xml.characters(message)
|
|
||||||
self.xml.endElement("line")
|
|
||||||
|
|
||||||
def info(self, *args, **kwargs) -> None: # type: ignore
|
|
||||||
self.log(*args, **kwargs)
|
|
||||||
|
|
||||||
def warning(self, *args, **kwargs) -> None: # type: ignore
|
|
||||||
self.log(*args, **kwargs)
|
|
||||||
|
|
||||||
def error(self, *args, **kwargs) -> None: # type: ignore
|
|
||||||
self.log(*args, **kwargs)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
|
|
||||||
self._eprint(self.maybe_prefix(message, attributes))
|
|
||||||
self.drain_log_queue()
|
|
||||||
self.log_line(message, attributes)
|
|
||||||
|
|
||||||
def log_serial(self, message: str, machine: str) -> None:
|
|
||||||
self.enqueue({"msg": message, "machine": machine, "type": "serial"})
|
|
||||||
if self._print_serial_logs:
|
|
||||||
self._eprint(
|
|
||||||
Style.DIM + "{} # {}".format(machine, message) + Style.RESET_ALL
|
|
||||||
)
|
|
||||||
|
|
||||||
def enqueue(self, item: Dict[str, str]) -> None:
|
|
||||||
self.queue.put(item)
|
|
||||||
|
|
||||||
def drain_log_queue(self) -> None:
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
item = self.queue.get_nowait()
|
|
||||||
msg = self.sanitise(item["msg"])
|
|
||||||
del item["msg"]
|
|
||||||
self.log_line(msg, item)
|
|
||||||
except Empty:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
|
|
||||||
self._eprint(self.maybe_prefix(message, attributes))
|
|
||||||
|
|
||||||
self.xml.startElement("nest", attrs={})
|
|
||||||
self.xml.startElement("head", attributes)
|
|
||||||
self.xml.characters(message)
|
|
||||||
self.xml.endElement("head")
|
|
||||||
|
|
||||||
tic = time.time()
|
|
||||||
self.drain_log_queue()
|
|
||||||
yield
|
|
||||||
self.drain_log_queue()
|
|
||||||
toc = time.time()
|
|
||||||
self.log("(finished: {}, in {:.2f} seconds)".format(message, toc - tic))
|
|
||||||
|
|
||||||
self.xml.endElement("nest")
|
|
||||||
|
|
||||||
|
|
||||||
rootlog = Logger()
|
|
||||||
|
|
||||||
|
|
||||||
def make_command(args: list) -> str:
|
def make_command(args: list) -> str:
|
||||||
return " ".join(map(shlex.quote, (map(str, args))))
|
return " ".join(map(shlex.quote, (map(str, args))))
|
||||||
|
|
||||||
|
|
||||||
def retry(fn: Callable, timeout: int = 900) -> None:
|
|
||||||
"""Call the given function repeatedly, with 1 second intervals,
|
|
||||||
until it returns True or a timeout is reached.
|
|
||||||
"""
|
|
||||||
|
|
||||||
for _ in range(timeout):
|
|
||||||
if fn(False):
|
|
||||||
return
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
if not fn(True):
|
|
||||||
raise Exception(f"action timed out after {timeout} seconds")
|
|
||||||
|
|
||||||
|
|
||||||
def _perform_ocr_on_screenshot(
|
def _perform_ocr_on_screenshot(
|
||||||
screenshot_path: str, model_ids: Iterable[int]
|
screenshot_path: str, model_ids: Iterable[int]
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
|
@ -228,6 +117,20 @@ def _perform_ocr_on_screenshot(
|
||||||
return model_results
|
return model_results
|
||||||
|
|
||||||
|
|
||||||
|
def retry(fn: Callable, timeout: int = 900) -> None:
|
||||||
|
"""Call the given function repeatedly, with 1 second intervals,
|
||||||
|
until it returns True or a timeout is reached.
|
||||||
|
"""
|
||||||
|
|
||||||
|
for _ in range(timeout):
|
||||||
|
if fn(False):
|
||||||
|
return
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
if not fn(True):
|
||||||
|
raise Exception(f"action timed out after {timeout} seconds")
|
||||||
|
|
||||||
|
|
||||||
class StartCommand:
|
class StartCommand:
|
||||||
"""The Base Start Command knows how to append the necesary
|
"""The Base Start Command knows how to append the necesary
|
||||||
runtime qemu options as determined by a particular test driver
|
runtime qemu options as determined by a particular test driver
|
||||||
|
@ -1066,286 +969,3 @@ class Machine:
|
||||||
self.shell.close()
|
self.shell.close()
|
||||||
self.monitor.close()
|
self.monitor.close()
|
||||||
self.serial_thread.join()
|
self.serial_thread.join()
|
||||||
|
|
||||||
|
|
||||||
class VLan:
|
|
||||||
"""This class handles a VLAN that the run-vm scripts identify via its
|
|
||||||
number handles. The network's lifetime equals the object's lifetime.
|
|
||||||
"""
|
|
||||||
|
|
||||||
nr: int
|
|
||||||
socket_dir: Path
|
|
||||||
|
|
||||||
process: subprocess.Popen
|
|
||||||
pid: int
|
|
||||||
fd: io.TextIOBase
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return f"<Vlan Nr. {self.nr}>"
|
|
||||||
|
|
||||||
def __init__(self, nr: int, tmp_dir: Path):
|
|
||||||
self.nr = nr
|
|
||||||
self.socket_dir = tmp_dir / f"vde{self.nr}.ctl"
|
|
||||||
|
|
||||||
# TODO: don't side-effect environment here
|
|
||||||
os.environ[f"QEMU_VDE_SOCKET_{self.nr}"] = str(self.socket_dir)
|
|
||||||
|
|
||||||
rootlog.info("start vlan")
|
|
||||||
pty_master, pty_slave = pty.openpty()
|
|
||||||
|
|
||||||
self.process = subprocess.Popen(
|
|
||||||
["vde_switch", "-s", self.socket_dir, "--dirmode", "0700"],
|
|
||||||
stdin=pty_slave,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
shell=False,
|
|
||||||
)
|
|
||||||
self.pid = self.process.pid
|
|
||||||
self.fd = os.fdopen(pty_master, "w")
|
|
||||||
self.fd.write("version\n")
|
|
||||||
|
|
||||||
# TODO: perl version checks if this can be read from
|
|
||||||
# an if not, dies. we could hang here forever. Fix it.
|
|
||||||
assert self.process.stdout is not None
|
|
||||||
self.process.stdout.readline()
|
|
||||||
if not (self.socket_dir / "ctl").exists():
|
|
||||||
rootlog.error("cannot start vde_switch")
|
|
||||||
|
|
||||||
rootlog.info(f"running vlan (pid {self.pid})")
|
|
||||||
|
|
||||||
def __del__(self) -> None:
|
|
||||||
rootlog.info(f"kill vlan (pid {self.pid})")
|
|
||||||
self.fd.close()
|
|
||||||
self.process.terminate()
|
|
||||||
|
|
||||||
|
|
||||||
class Driver:
|
|
||||||
"""A handle to the driver that sets up the environment
|
|
||||||
and runs the tests"""
|
|
||||||
|
|
||||||
tests: str
|
|
||||||
vlans: List[VLan]
|
|
||||||
machines: List[Machine]
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
start_scripts: List[str],
|
|
||||||
vlans: List[int],
|
|
||||||
tests: str,
|
|
||||||
keep_vm_state: bool = False,
|
|
||||||
):
|
|
||||||
self.tests = tests
|
|
||||||
|
|
||||||
tmp_dir = Path(os.environ.get("TMPDIR", tempfile.gettempdir()))
|
|
||||||
tmp_dir.mkdir(mode=0o700, exist_ok=True)
|
|
||||||
|
|
||||||
with rootlog.nested("start all VLans"):
|
|
||||||
self.vlans = [VLan(nr, tmp_dir) for nr in vlans]
|
|
||||||
|
|
||||||
def cmd(scripts: List[str]) -> Iterator[NixStartScript]:
|
|
||||||
for s in scripts:
|
|
||||||
yield NixStartScript(s)
|
|
||||||
|
|
||||||
self.machines = [
|
|
||||||
Machine(
|
|
||||||
start_command=cmd,
|
|
||||||
keep_vm_state=keep_vm_state,
|
|
||||||
name=cmd.machine_name,
|
|
||||||
tmp_dir=tmp_dir,
|
|
||||||
)
|
|
||||||
for cmd in cmd(start_scripts)
|
|
||||||
]
|
|
||||||
|
|
||||||
def __enter__(self) -> "Driver":
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, *_: Any) -> None:
|
|
||||||
with rootlog.nested("cleanup"):
|
|
||||||
for machine in self.machines:
|
|
||||||
machine.release()
|
|
||||||
|
|
||||||
def subtest(self, name: str) -> Iterator[None]:
|
|
||||||
"""Group logs under a given test name"""
|
|
||||||
with rootlog.nested(name):
|
|
||||||
try:
|
|
||||||
yield
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
rootlog.error(f'Test "{name}" failed with error: "{e}"')
|
|
||||||
raise e
|
|
||||||
|
|
||||||
def test_symbols(self) -> Dict[str, Any]:
|
|
||||||
@contextmanager
|
|
||||||
def subtest(name: str) -> Iterator[None]:
|
|
||||||
return self.subtest(name)
|
|
||||||
|
|
||||||
general_symbols = dict(
|
|
||||||
start_all=self.start_all,
|
|
||||||
test_script=self.test_script,
|
|
||||||
machines=self.machines,
|
|
||||||
vlans=self.vlans,
|
|
||||||
driver=self,
|
|
||||||
log=rootlog,
|
|
||||||
os=os,
|
|
||||||
create_machine=self.create_machine,
|
|
||||||
subtest=subtest,
|
|
||||||
run_tests=self.run_tests,
|
|
||||||
join_all=self.join_all,
|
|
||||||
retry=retry,
|
|
||||||
serial_stdout_off=self.serial_stdout_off,
|
|
||||||
serial_stdout_on=self.serial_stdout_on,
|
|
||||||
Machine=Machine, # for typing
|
|
||||||
)
|
|
||||||
machine_symbols = {m.name: m for m in self.machines}
|
|
||||||
# If there's exactly one machine, make it available under the name
|
|
||||||
# "machine", even if it's not called that.
|
|
||||||
if len(self.machines) == 1:
|
|
||||||
(machine_symbols["machine"],) = self.machines
|
|
||||||
vlan_symbols = {
|
|
||||||
f"vlan{v.nr}": self.vlans[idx] for idx, v in enumerate(self.vlans)
|
|
||||||
}
|
|
||||||
print(
|
|
||||||
"additionally exposed symbols:\n "
|
|
||||||
+ ", ".join(map(lambda m: m.name, self.machines))
|
|
||||||
+ ",\n "
|
|
||||||
+ ", ".join(map(lambda v: f"vlan{v.nr}", self.vlans))
|
|
||||||
+ ",\n "
|
|
||||||
+ ", ".join(list(general_symbols.keys()))
|
|
||||||
)
|
|
||||||
return {**general_symbols, **machine_symbols, **vlan_symbols}
|
|
||||||
|
|
||||||
def test_script(self) -> None:
|
|
||||||
"""Run the test script"""
|
|
||||||
with rootlog.nested("run the VM test script"):
|
|
||||||
symbols = self.test_symbols() # call eagerly
|
|
||||||
exec(self.tests, symbols, None)
|
|
||||||
|
|
||||||
def run_tests(self) -> None:
|
|
||||||
"""Run the test script (for non-interactive test runs)"""
|
|
||||||
self.test_script()
|
|
||||||
# TODO: Collect coverage data
|
|
||||||
for machine in self.machines:
|
|
||||||
if machine.is_up():
|
|
||||||
machine.execute("sync")
|
|
||||||
|
|
||||||
def start_all(self) -> None:
|
|
||||||
"""Start all machines"""
|
|
||||||
with rootlog.nested("start all VMs"):
|
|
||||||
for machine in self.machines:
|
|
||||||
machine.start()
|
|
||||||
|
|
||||||
def join_all(self) -> None:
|
|
||||||
"""Wait for all machines to shut down"""
|
|
||||||
with rootlog.nested("wait for all VMs to finish"):
|
|
||||||
for machine in self.machines:
|
|
||||||
machine.wait_for_shutdown()
|
|
||||||
|
|
||||||
def create_machine(self, args: Dict[str, Any]) -> Machine:
|
|
||||||
rootlog.warning(
|
|
||||||
"Using legacy create_machine(), please instantiate the"
|
|
||||||
"Machine class directly, instead"
|
|
||||||
)
|
|
||||||
tmp_dir = Path(os.environ.get("TMPDIR", tempfile.gettempdir()))
|
|
||||||
tmp_dir.mkdir(mode=0o700, exist_ok=True)
|
|
||||||
|
|
||||||
if args.get("startCommand"):
|
|
||||||
start_command: str = args.get("startCommand", "")
|
|
||||||
cmd = NixStartScript(start_command)
|
|
||||||
name = args.get("name", cmd.machine_name)
|
|
||||||
else:
|
|
||||||
cmd = Machine.create_startcommand(args) # type: ignore
|
|
||||||
name = args.get("name", "machine")
|
|
||||||
|
|
||||||
return Machine(
|
|
||||||
tmp_dir=tmp_dir,
|
|
||||||
start_command=cmd,
|
|
||||||
name=name,
|
|
||||||
keep_vm_state=args.get("keep_vm_state", False),
|
|
||||||
allow_reboot=args.get("allow_reboot", False),
|
|
||||||
)
|
|
||||||
|
|
||||||
def serial_stdout_on(self) -> None:
|
|
||||||
rootlog._print_serial_logs = True
|
|
||||||
|
|
||||||
def serial_stdout_off(self) -> None:
|
|
||||||
rootlog._print_serial_logs = False
|
|
||||||
|
|
||||||
|
|
||||||
class EnvDefault(argparse.Action):
|
|
||||||
"""An argpars Action that takes values from the specified
|
|
||||||
environment variable as the flags default value.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, envvar, required=False, default=None, nargs=None, **kwargs): # type: ignore
|
|
||||||
if not default and envvar:
|
|
||||||
if envvar in os.environ:
|
|
||||||
if nargs is not None and (nargs.isdigit() or nargs in ["*", "+"]):
|
|
||||||
default = os.environ[envvar].split()
|
|
||||||
else:
|
|
||||||
default = os.environ[envvar]
|
|
||||||
kwargs["help"] = (
|
|
||||||
kwargs["help"] + f" (default from environment: {default})"
|
|
||||||
)
|
|
||||||
if required and default:
|
|
||||||
required = False
|
|
||||||
super(EnvDefault, self).__init__(
|
|
||||||
default=default, required=required, nargs=nargs, **kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
def __call__(self, parser, namespace, values, option_string=None): # type: ignore
|
|
||||||
setattr(namespace, self.dest, values)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
arg_parser = argparse.ArgumentParser(prog="nixos-test-driver")
|
|
||||||
arg_parser.add_argument(
|
|
||||||
"-K",
|
|
||||||
"--keep-vm-state",
|
|
||||||
help="re-use a VM state coming from a previous run",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
arg_parser.add_argument(
|
|
||||||
"-I",
|
|
||||||
"--interactive",
|
|
||||||
help="drop into a python repl and run the tests interactively",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
arg_parser.add_argument(
|
|
||||||
"--start-scripts",
|
|
||||||
metavar="START-SCRIPT",
|
|
||||||
action=EnvDefault,
|
|
||||||
envvar="startScripts",
|
|
||||||
nargs="*",
|
|
||||||
help="start scripts for participating virtual machines",
|
|
||||||
)
|
|
||||||
arg_parser.add_argument(
|
|
||||||
"--vlans",
|
|
||||||
metavar="VLAN",
|
|
||||||
action=EnvDefault,
|
|
||||||
envvar="vlans",
|
|
||||||
nargs="*",
|
|
||||||
help="vlans to span by the driver",
|
|
||||||
)
|
|
||||||
arg_parser.add_argument(
|
|
||||||
"testscript",
|
|
||||||
action=EnvDefault,
|
|
||||||
envvar="testScript",
|
|
||||||
help="the test script to run",
|
|
||||||
type=Path,
|
|
||||||
)
|
|
||||||
|
|
||||||
args = arg_parser.parse_args()
|
|
||||||
|
|
||||||
if not args.keep_vm_state:
|
|
||||||
rootlog.info("Machine state will be reset. To keep it, pass --keep-vm-state")
|
|
||||||
|
|
||||||
with Driver(
|
|
||||||
args.start_scripts, args.vlans, args.testscript.read_text(), args.keep_vm_state
|
|
||||||
) as driver:
|
|
||||||
if args.interactive:
|
|
||||||
ptpython.repl.embed(driver.test_symbols(), {})
|
|
||||||
else:
|
|
||||||
tic = time.time()
|
|
||||||
driver.run_tests()
|
|
||||||
toc = time.time()
|
|
||||||
rootlog.info(f"test script finished in {(toc-tic):.2f}s")
|
|
58
nixos/lib/test-driver/test_driver/vlan.py
Normal file
58
nixos/lib/test-driver/test_driver/vlan.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
from pathlib import Path
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import pty
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from test_driver.logger import rootlog
|
||||||
|
|
||||||
|
|
||||||
|
class VLan:
|
||||||
|
"""This class handles a VLAN that the run-vm scripts identify via its
|
||||||
|
number handles. The network's lifetime equals the object's lifetime.
|
||||||
|
"""
|
||||||
|
|
||||||
|
nr: int
|
||||||
|
socket_dir: Path
|
||||||
|
|
||||||
|
process: subprocess.Popen
|
||||||
|
pid: int
|
||||||
|
fd: io.TextIOBase
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"<Vlan Nr. {self.nr}>"
|
||||||
|
|
||||||
|
def __init__(self, nr: int, tmp_dir: Path):
|
||||||
|
self.nr = nr
|
||||||
|
self.socket_dir = tmp_dir / f"vde{self.nr}.ctl"
|
||||||
|
|
||||||
|
# TODO: don't side-effect environment here
|
||||||
|
os.environ[f"QEMU_VDE_SOCKET_{self.nr}"] = str(self.socket_dir)
|
||||||
|
|
||||||
|
rootlog.info("start vlan")
|
||||||
|
pty_master, pty_slave = pty.openpty()
|
||||||
|
|
||||||
|
self.process = subprocess.Popen(
|
||||||
|
["vde_switch", "-s", self.socket_dir, "--dirmode", "0700"],
|
||||||
|
stdin=pty_slave,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
shell=False,
|
||||||
|
)
|
||||||
|
self.pid = self.process.pid
|
||||||
|
self.fd = os.fdopen(pty_master, "w")
|
||||||
|
self.fd.write("version\n")
|
||||||
|
|
||||||
|
# TODO: perl version checks if this can be read from
|
||||||
|
# an if not, dies. we could hang here forever. Fix it.
|
||||||
|
assert self.process.stdout is not None
|
||||||
|
self.process.stdout.readline()
|
||||||
|
if not (self.socket_dir / "ctl").exists():
|
||||||
|
rootlog.error("cannot start vde_switch")
|
||||||
|
|
||||||
|
rootlog.info(f"running vlan (pid {self.pid})")
|
||||||
|
|
||||||
|
def __del__(self) -> None:
|
||||||
|
rootlog.info(f"kill vlan (pid {self.pid})")
|
||||||
|
self.fd.close()
|
||||||
|
self.process.terminate()
|
|
@ -16,65 +16,6 @@ rec {
|
||||||
|
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
|
||||||
# Reifies and correctly wraps the python test driver for
|
|
||||||
# the respective qemu version and with or without ocr support
|
|
||||||
pythonTestDriver = {
|
|
||||||
qemu_pkg ? pkgs.qemu_test
|
|
||||||
, enableOCR ? false
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
name = "nixos-test-driver";
|
|
||||||
testDriverScript = ./test-driver/test-driver.py;
|
|
||||||
ocrProg = tesseract4.override { enableLanguages = [ "eng" ]; };
|
|
||||||
imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
|
|
||||||
in stdenv.mkDerivation {
|
|
||||||
inherit name;
|
|
||||||
|
|
||||||
nativeBuildInputs = [ makeWrapper ];
|
|
||||||
buildInputs = [ (python3.withPackages (p: [ p.ptpython p.colorama ])) ];
|
|
||||||
checkInputs = with python3Packages; [ pylint black mypy ];
|
|
||||||
|
|
||||||
dontUnpack = true;
|
|
||||||
|
|
||||||
preferLocalBuild = true;
|
|
||||||
|
|
||||||
buildPhase = ''
|
|
||||||
python <<EOF
|
|
||||||
from pydoc import importfile
|
|
||||||
with open('driver-symbols', 'w') as fp:
|
|
||||||
t = importfile('${testDriverScript}')
|
|
||||||
d = t.Driver([],[],"")
|
|
||||||
test_symbols = d.test_symbols()
|
|
||||||
fp.write(','.join(test_symbols.keys()))
|
|
||||||
EOF
|
|
||||||
'';
|
|
||||||
|
|
||||||
doCheck = true;
|
|
||||||
checkPhase = ''
|
|
||||||
mypy --disallow-untyped-defs \
|
|
||||||
--no-implicit-optional \
|
|
||||||
--ignore-missing-imports ${testDriverScript}
|
|
||||||
pylint --errors-only ${testDriverScript}
|
|
||||||
black --check --diff ${testDriverScript}
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase =
|
|
||||||
''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
cp ${testDriverScript} $out/bin/nixos-test-driver
|
|
||||||
chmod u+x $out/bin/nixos-test-driver
|
|
||||||
# TODO: copy user script part into this file (append)
|
|
||||||
|
|
||||||
wrapProgram $out/bin/nixos-test-driver \
|
|
||||||
--argv0 ${name} \
|
|
||||||
--prefix PATH : "${lib.makeBinPath [ qemu_pkg vde2 netpbm coreutils socat ]}" \
|
|
||||||
${lib.optionalString enableOCR
|
|
||||||
"--prefix PATH : '${ocrProg}/bin:${imagemagick_tiff}/bin'"} \
|
|
||||||
|
|
||||||
install -m 0644 -vD driver-symbols $out/nix-support/driver-symbols
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Run an automated test suite in the given virtual network.
|
# Run an automated test suite in the given virtual network.
|
||||||
runTests = { driver, pos }:
|
runTests = { driver, pos }:
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
|
@ -112,8 +53,15 @@ rec {
|
||||||
, passthru ? {}
|
, passthru ? {}
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
# FIXME: get this pkg from the module system
|
# Reifies and correctly wraps the python test driver for
|
||||||
testDriver = pythonTestDriver { inherit qemu_pkg enableOCR;};
|
# the respective qemu version and with or without ocr support
|
||||||
|
testDriver = pkgs.callPackage ./test-driver {
|
||||||
|
inherit enableOCR;
|
||||||
|
qemu_pkg = qemu_test;
|
||||||
|
imagemagick_light = imagemagick_light.override { inherit libtiff; };
|
||||||
|
tesseract4 = tesseract4.override { enableLanguages = [ "eng" ]; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
testDriverName =
|
testDriverName =
|
||||||
let
|
let
|
||||||
|
@ -178,10 +126,11 @@ rec {
|
||||||
echo -n "$testScript" > $out/test-script
|
echo -n "$testScript" > $out/test-script
|
||||||
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver
|
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver
|
||||||
|
|
||||||
|
${testDriver}/bin/generate-driver-symbols
|
||||||
${lib.optionalString (!skipLint) ''
|
${lib.optionalString (!skipLint) ''
|
||||||
PYFLAKES_BUILTINS="$(
|
PYFLAKES_BUILTINS="$(
|
||||||
echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)},
|
echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)},
|
||||||
< ${lib.escapeShellArg "${testDriver}/nix-support/driver-symbols"}
|
< ${lib.escapeShellArg "driver-symbols"}
|
||||||
)" ${python3Packages.pyflakes}/bin/pyflakes $out/test-script
|
)" ${python3Packages.pyflakes}/bin/pyflakes $out/test-script
|
||||||
''}
|
''}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pkgs: with pkgs.lib;
|
{ lib, config, pkgs }: with lib;
|
||||||
|
|
||||||
rec {
|
rec {
|
||||||
|
|
||||||
|
@ -165,4 +165,9 @@ rec {
|
||||||
${builtins.toJSON set}
|
${builtins.toJSON set}
|
||||||
EOF
|
EOF
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
systemdUtils = {
|
||||||
|
lib = import ./systemd-lib.nix { inherit lib config pkgs; };
|
||||||
|
unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
37
nixos/modules/hardware/gpgsmartcards.nix
Normal file
37
nixos/modules/hardware/gpgsmartcards.nix
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
# gnupg's manual describes how to setup ccid udev rules:
|
||||||
|
# https://www.gnupg.org/howtos/card-howto/en/ch02s03.html
|
||||||
|
# gnupg folks advised me (https://dev.gnupg.org/T5409) to look at debian's rules:
|
||||||
|
# https://salsa.debian.org/debian/gnupg2/-/blob/debian/main/debian/scdaemon.udev
|
||||||
|
|
||||||
|
# the latest rev of the entire debian gnupg2 repo as of 2021-04-28
|
||||||
|
# the scdaemon.udev file was last commited on 2021-01-05 (7817a03):
|
||||||
|
scdaemonUdevRev = "01898735a015541e3ffb43c7245ac1e612f40836";
|
||||||
|
|
||||||
|
scdaemonRules = pkgs.fetchurl {
|
||||||
|
url = "https://salsa.debian.org/debian/gnupg2/-/raw/${scdaemonUdevRev}/debian/scdaemon.udev";
|
||||||
|
sha256 = "08v0vp6950bz7galvc92zdss89y9vcwbinmbfcdldy8x72w6rqr3";
|
||||||
|
};
|
||||||
|
|
||||||
|
# per debian's udev deb hook (https://man7.org/linux/man-pages/man1/dh_installudev.1.html)
|
||||||
|
destination = "60-scdaemon.rules";
|
||||||
|
|
||||||
|
scdaemonUdevRulesPkg = pkgs.runCommandNoCC "scdaemon-udev-rules" {} ''
|
||||||
|
loc="$out/lib/udev/rules.d/"
|
||||||
|
mkdir -p "''${loc}"
|
||||||
|
cp "${scdaemonRules}" "''${loc}/${destination}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
cfg = config.hardware.gpgSmartcards;
|
||||||
|
in {
|
||||||
|
options.hardware.gpgSmartcards = {
|
||||||
|
enable = mkEnableOption "udev rules for gnupg smart cards";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
services.udev.packages = [ scdaemonUdevRulesPkg ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ let
|
||||||
cfg = config.hardware.keyboard.zsa;
|
cfg = config.hardware.keyboard.zsa;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# TODO: make group configurable like in https://github.com/NixOS/nixpkgs/blob/0b2b4b8c4e729535a61db56468809c5c2d3d175c/pkgs/tools/security/nitrokey-app/udev-rules.nix ?
|
|
||||||
options.hardware.keyboard.zsa = {
|
options.hardware.keyboard.zsa = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
@ -14,7 +13,6 @@ in
|
||||||
Enables udev rules for keyboards from ZSA like the ErgoDox EZ, Planck EZ and Moonlander Mark I.
|
Enables udev rules for keyboards from ZSA like the ErgoDox EZ, Planck EZ and Moonlander Mark I.
|
||||||
You need it when you want to flash a new configuration on the keyboard
|
You need it when you want to flash a new configuration on the keyboard
|
||||||
or use their live training in the browser.
|
or use their live training in the browser.
|
||||||
Access to the keyboard is granted to users in the "plugdev" group.
|
|
||||||
You may want to install the wally-cli package.
|
You may want to install the wally-cli package.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -22,6 +20,5 @@ in
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services.udev.packages = [ pkgs.zsa-udev-rules ];
|
services.udev.packages = [ pkgs.zsa-udev-rules ];
|
||||||
users.groups.plugdev = {};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ in
|
||||||
|
|
||||||
config = mkOption {
|
config = mkOption {
|
||||||
default = null;
|
default = null;
|
||||||
|
type = types.nullOr types.path;
|
||||||
description = ''
|
description = ''
|
||||||
Path to the configuration file which maps the memory, IRQs
|
Path to the configuration file which maps the memory, IRQs
|
||||||
and ports used by the PCMCIA hardware.
|
and ports used by the PCMCIA hardware.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{ pkgs, ... }:
|
{ lib, config, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
_module.args = {
|
_module.args = {
|
||||||
utils = import ../../lib/utils.nix pkgs;
|
utils = import ../../lib/utils.nix { inherit lib config pkgs; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
./hardware/device-tree.nix
|
./hardware/device-tree.nix
|
||||||
./hardware/gkraken.nix
|
./hardware/gkraken.nix
|
||||||
./hardware/flirc.nix
|
./hardware/flirc.nix
|
||||||
|
./hardware/gpgsmartcards.nix
|
||||||
./hardware/i2c.nix
|
./hardware/i2c.nix
|
||||||
./hardware/sensor/hddtemp.nix
|
./hardware/sensor/hddtemp.nix
|
||||||
./hardware/sensor/iio.nix
|
./hardware/sensor/iio.nix
|
||||||
|
@ -1192,8 +1193,7 @@
|
||||||
./virtualisation/kvmgt.nix
|
./virtualisation/kvmgt.nix
|
||||||
./virtualisation/openvswitch.nix
|
./virtualisation/openvswitch.nix
|
||||||
./virtualisation/parallels-guest.nix
|
./virtualisation/parallels-guest.nix
|
||||||
./virtualisation/podman.nix
|
./virtualisation/podman/default.nix
|
||||||
./virtualisation/podman-network-socket-ghostunnel.nix
|
|
||||||
./virtualisation/qemu-guest-agent.nix
|
./virtualisation/qemu-guest-agent.nix
|
||||||
./virtualisation/railcar.nix
|
./virtualisation/railcar.nix
|
||||||
./virtualisation/spice-usb-redirection.nix
|
./virtualisation/spice-usb-redirection.nix
|
||||||
|
|
|
@ -60,7 +60,7 @@ in
|
||||||
environment.systemPackages = [ pkgs.dconf ];
|
environment.systemPackages = [ pkgs.dconf ];
|
||||||
|
|
||||||
# Needed for unwrapped applications
|
# Needed for unwrapped applications
|
||||||
environment.sessionVariables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.dconf.lib}/lib/gio/modules" ];
|
environment.variables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.dconf.lib}/lib/gio/modules" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,9 +295,14 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
limits = mkOption {
|
limits = mkOption {
|
||||||
|
default = [];
|
||||||
|
type = limitsType;
|
||||||
description = ''
|
description = ''
|
||||||
Attribute set describing resource limits. Defaults to the
|
Attribute set describing resource limits. Defaults to the
|
||||||
value of <option>security.pam.loginLimits</option>.
|
value of <option>security.pam.loginLimits</option>.
|
||||||
|
The meaning of the values is explained in <citerefentry>
|
||||||
|
<refentrytitle>limits.conf</refentrytitle><manvolnum>5</manvolnum>
|
||||||
|
</citerefentry>.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -648,6 +653,51 @@ let
|
||||||
"${domain} ${type} ${item} ${toString value}\n")
|
"${domain} ${type} ${item} ${toString value}\n")
|
||||||
limits);
|
limits);
|
||||||
|
|
||||||
|
limitsType = with lib.types; listOf (submodule ({ ... }: {
|
||||||
|
options = {
|
||||||
|
domain = mkOption {
|
||||||
|
description = "Username, groupname, or wildcard this limit applies to";
|
||||||
|
example = "@wheel";
|
||||||
|
type = str;
|
||||||
|
};
|
||||||
|
|
||||||
|
type = mkOption {
|
||||||
|
description = "Type of this limit";
|
||||||
|
type = enum [ "-" "hard" "soft" ];
|
||||||
|
default = "-";
|
||||||
|
};
|
||||||
|
|
||||||
|
item = mkOption {
|
||||||
|
description = "Item this limit applies to";
|
||||||
|
type = enum [
|
||||||
|
"core"
|
||||||
|
"data"
|
||||||
|
"fsize"
|
||||||
|
"memlock"
|
||||||
|
"nofile"
|
||||||
|
"rss"
|
||||||
|
"stack"
|
||||||
|
"cpu"
|
||||||
|
"nproc"
|
||||||
|
"as"
|
||||||
|
"maxlogins"
|
||||||
|
"maxsyslogins"
|
||||||
|
"priority"
|
||||||
|
"locks"
|
||||||
|
"sigpending"
|
||||||
|
"msgqueue"
|
||||||
|
"nice"
|
||||||
|
"rtprio"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
value = mkOption {
|
||||||
|
description = "Value of this limit";
|
||||||
|
type = oneOf [ str int ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
motd = pkgs.writeText "motd" config.users.motd;
|
motd = pkgs.writeText "motd" config.users.motd;
|
||||||
|
|
||||||
makePAMService = name: service:
|
makePAMService = name: service:
|
||||||
|
@ -669,6 +719,7 @@ in
|
||||||
|
|
||||||
security.pam.loginLimits = mkOption {
|
security.pam.loginLimits = mkOption {
|
||||||
default = [];
|
default = [];
|
||||||
|
type = limitsType;
|
||||||
example =
|
example =
|
||||||
[ { domain = "ftp";
|
[ { domain = "ftp";
|
||||||
type = "hard";
|
type = "hard";
|
||||||
|
@ -688,7 +739,8 @@ in
|
||||||
<varname>domain</varname>, <varname>type</varname>,
|
<varname>domain</varname>, <varname>type</varname>,
|
||||||
<varname>item</varname>, and <varname>value</varname>
|
<varname>item</varname>, and <varname>value</varname>
|
||||||
attribute. The syntax and semantics of these attributes
|
attribute. The syntax and semantics of these attributes
|
||||||
must be that described in the limits.conf(5) man page.
|
must be that described in <citerefentry><refentrytitle>limits.conf</refentrytitle>
|
||||||
|
<manvolnum>5</manvolnum></citerefentry>.
|
||||||
|
|
||||||
Note that these limits do not apply to systemd services,
|
Note that these limits do not apply to systemd services,
|
||||||
whose limits can be changed via <option>systemd.extraConfig</option>
|
whose limits can be changed via <option>systemd.extraConfig</option>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, utils, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
toplevelConfig = config;
|
toplevelConfig = config;
|
||||||
inherit (lib) types;
|
inherit (lib) types;
|
||||||
inherit (import ../system/boot/systemd-lib.nix {
|
inherit (utils.systemdUtils.lib) mkPathSafeName;
|
||||||
inherit config pkgs lib;
|
|
||||||
}) mkPathSafeName;
|
|
||||||
in {
|
in {
|
||||||
options.systemd.services = lib.mkOption {
|
options.systemd.services = lib.mkOption {
|
||||||
type = types.attrsOf (types.submodule ({ name, config, ... }: {
|
type = types.attrsOf (types.submodule ({ name, config, ... }: {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, utils, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
# Type for a valid systemd unit option. Needed for correctly passing "timerConfig" to "systemd.timers"
|
# Type for a valid systemd unit option. Needed for correctly passing "timerConfig" to "systemd.timers"
|
||||||
unitOption = (import ../../system/boot/systemd-unit-options.nix { inherit config lib; }).unitOption;
|
inherit (utils.systemdUtils.unitOptions) unitOption;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.restic.backups = mkOption {
|
options.services.restic.backups = mkOption {
|
||||||
|
|
|
@ -38,7 +38,7 @@ with lib;
|
||||||
|
|
||||||
systemd.packages = [ pkgs.glib-networking ];
|
systemd.packages = [ pkgs.glib-networking ];
|
||||||
|
|
||||||
environment.sessionVariables.GIO_EXTRA_MODULES = [ "${pkgs.glib-networking.out}/lib/gio/modules" ];
|
environment.variables.GIO_EXTRA_MODULES = [ "${pkgs.glib-networking.out}/lib/gio/modules" ];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ in
|
||||||
services.udev.packages = [ pkgs.libmtp.bin ];
|
services.udev.packages = [ pkgs.libmtp.bin ];
|
||||||
|
|
||||||
# Needed for unwrapped applications
|
# Needed for unwrapped applications
|
||||||
environment.sessionVariables.GIO_EXTRA_MODULES = [ "${cfg.package}/lib/gio/modules" ];
|
environment.variables.GIO_EXTRA_MODULES = [ "${cfg.package}/lib/gio/modules" ];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ in {
|
||||||
|
|
||||||
haskellPackages = mkOption {
|
haskellPackages = mkOption {
|
||||||
description = "Which haskell package set to use.";
|
description = "Which haskell package set to use.";
|
||||||
|
type = types.attrs;
|
||||||
default = pkgs.haskellPackages;
|
default = pkgs.haskellPackages;
|
||||||
defaultText = literalExpression "pkgs.haskellPackages";
|
defaultText = literalExpression "pkgs.haskellPackages";
|
||||||
};
|
};
|
||||||
|
|
|
@ -137,7 +137,6 @@ in
|
||||||
description = "the RAS logging daemon";
|
description = "the RAS logging daemon";
|
||||||
documentation = [ "man:rasdaemon(1)" ];
|
documentation = [ "man:rasdaemon(1)" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "syslog.target" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
StateDirectory = optionalString (cfg.record) "rasdaemon";
|
StateDirectory = optionalString (cfg.record) "rasdaemon";
|
||||||
|
|
|
@ -104,31 +104,37 @@ in
|
||||||
properties = mkOption {
|
properties = mkOption {
|
||||||
description = "An attribute set in which each attribute represents a machine property. Optionally, these values can be shell substitutions.";
|
description = "An attribute set in which each attribute represents a machine property. Optionally, these values can be shell substitutions.";
|
||||||
default = {};
|
default = {};
|
||||||
|
type = types.attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
containers = mkOption {
|
containers = mkOption {
|
||||||
description = "An attribute set in which each key represents a container and each value an attribute set providing its configuration properties";
|
description = "An attribute set in which each key represents a container and each value an attribute set providing its configuration properties";
|
||||||
default = {};
|
default = {};
|
||||||
|
type = types.attrsOf types.attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
components = mkOption {
|
components = mkOption {
|
||||||
description = "An atttribute set in which each key represents a container and each value an attribute set in which each key represents a component and each value a derivation constructing its initial state";
|
description = "An atttribute set in which each key represents a container and each value an attribute set in which each key represents a component and each value a derivation constructing its initial state";
|
||||||
default = {};
|
default = {};
|
||||||
|
type = types.attrsOf types.attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
extraContainerProperties = mkOption {
|
extraContainerProperties = mkOption {
|
||||||
description = "An attribute set providing additional container settings in addition to the default properties";
|
description = "An attribute set providing additional container settings in addition to the default properties";
|
||||||
default = {};
|
default = {};
|
||||||
|
type = types.attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
extraContainerPaths = mkOption {
|
extraContainerPaths = mkOption {
|
||||||
description = "A list of paths containing additional container configurations that are added to the search folders";
|
description = "A list of paths containing additional container configurations that are added to the search folders";
|
||||||
default = [];
|
default = [];
|
||||||
|
type = types.listOf types.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
extraModulePaths = mkOption {
|
extraModulePaths = mkOption {
|
||||||
description = "A list of paths containing additional modules that are added to the search folders";
|
description = "A list of paths containing additional modules that are added to the search folders";
|
||||||
default = [];
|
default = [];
|
||||||
|
type = types.listOf types.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
enableLegacyModules = mkOption {
|
enableLegacyModules = mkOption {
|
||||||
|
|
|
@ -192,15 +192,28 @@ in
|
||||||
example = "batch";
|
example = "batch";
|
||||||
description = ''
|
description = ''
|
||||||
Nix daemon process CPU scheduling policy. This policy propagates to
|
Nix daemon process CPU scheduling policy. This policy propagates to
|
||||||
build processes. other is the default scheduling policy for regular
|
build processes. <literal>other</literal> is the default scheduling
|
||||||
tasks. The batch policy is similar to other, but optimised for
|
policy for regular tasks. The <literal>batch</literal> policy is
|
||||||
non-interactive tasks. idle is for extremely low-priority tasks
|
similar to <literal>other</literal>, but optimised for
|
||||||
that should only be run when no other task requires CPU time.
|
non-interactive tasks. <literal>idle</literal> is for extremely
|
||||||
|
low-priority tasks that should only be run when no other task
|
||||||
|
requires CPU time.
|
||||||
|
|
||||||
Please note that while using the idle policy may greatly improve
|
Please note that while using the <literal>idle</literal> policy may
|
||||||
responsiveness of a system performing expensive builds, it may also
|
greatly improve responsiveness of a system performing expensive
|
||||||
slow down and potentially starve crucial configuration updates
|
builds, it may also slow down and potentially starve crucial
|
||||||
during load.
|
configuration updates during load.
|
||||||
|
|
||||||
|
<literal>idle</literal> may therefore be a sensible policy for
|
||||||
|
systems that experience only intermittent phases of high CPU load,
|
||||||
|
such as desktop or portable computers used interactively. Other
|
||||||
|
systems should use the <literal>other</literal> or
|
||||||
|
<literal>batch</literal> policy instead.
|
||||||
|
|
||||||
|
For more fine-grained resource control, please refer to
|
||||||
|
<citerefentry><refentrytitle>systemd.resource-control
|
||||||
|
</refentrytitle><manvolnum>5</manvolnum></citerefentry> and adjust
|
||||||
|
<option>systemd.services.nix-daemon</option> directly.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,13 +223,20 @@ in
|
||||||
example = "idle";
|
example = "idle";
|
||||||
description = ''
|
description = ''
|
||||||
Nix daemon process I/O scheduling class. This class propagates to
|
Nix daemon process I/O scheduling class. This class propagates to
|
||||||
build processes. best-effort is the default class for regular tasks.
|
build processes. <literal>best-effort</literal> is the default
|
||||||
The idle class is for extremely low-priority tasks that should only
|
class for regular tasks. The <literal>idle</literal> class is for
|
||||||
perform I/O when no other task does.
|
extremely low-priority tasks that should only perform I/O when no
|
||||||
|
other task does.
|
||||||
|
|
||||||
Please note that while using the idle scheduling class can improve
|
Please note that while using the <literal>idle</literal> scheduling
|
||||||
responsiveness of a system performing expensive builds, it might also
|
class can improve responsiveness of a system performing expensive
|
||||||
slow down or starve crucial configuration updates during load.
|
builds, it might also slow down or starve crucial configuration
|
||||||
|
updates during load.
|
||||||
|
|
||||||
|
<literal>idle</literal> may therefore be a sensible class for
|
||||||
|
systems that experience only intermittent phases of high I/O load,
|
||||||
|
such as desktop or portable computers used interactively. Other
|
||||||
|
systems should use the <literal>best-effort</literal> class.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,8 @@ in
|
||||||
"-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "videobridge";
|
"-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "videobridge";
|
||||||
"-Djava.util.logging.config.file" = "/etc/jitsi/videobridge/logging.properties";
|
"-Djava.util.logging.config.file" = "/etc/jitsi/videobridge/logging.properties";
|
||||||
"-Dconfig.file" = pkgs.writeText "jvb.conf" (toHOCON jvbConfig);
|
"-Dconfig.file" = pkgs.writeText "jvb.conf" (toHOCON jvbConfig);
|
||||||
|
# Mitigate CVE-2021-44228
|
||||||
|
"-Dlog4j2.formatMsgNoLookups" = true;
|
||||||
} // (mapAttrs' (k: v: nameValuePair "-D${k}" v) cfg.extraProperties);
|
} // (mapAttrs' (k: v: nameValuePair "-D${k}" v) cfg.extraProperties);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,6 +97,11 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
confDir = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = confDir;
|
||||||
|
description = "The location of the config files for xrdp.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -149,7 +154,7 @@ in
|
||||||
User = "xrdp";
|
User = "xrdp";
|
||||||
Group = "xrdp";
|
Group = "xrdp";
|
||||||
PermissionsStartOnly = true;
|
PermissionsStartOnly = true;
|
||||||
ExecStart = "${cfg.package}/bin/xrdp --nodaemon --port ${toString cfg.port} --config ${confDir}/xrdp.ini";
|
ExecStart = "${cfg.package}/bin/xrdp --nodaemon --port ${toString cfg.port} --config ${cfg.confDir}/xrdp.ini";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,7 +164,7 @@ in
|
||||||
description = "xrdp session manager";
|
description = "xrdp session manager";
|
||||||
restartIfChanged = false; # do not restart on "nixos-rebuild switch". like "display-manager", it can have many interactive programs as children
|
restartIfChanged = false; # do not restart on "nixos-rebuild switch". like "display-manager", it can have many interactive programs as children
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${cfg.package}/bin/xrdp-sesman --nodaemon --config ${confDir}/sesman.ini";
|
ExecStart = "${cfg.package}/bin/xrdp-sesman --nodaemon --config ${cfg.confDir}/sesman.ini";
|
||||||
ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
|
ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -621,12 +621,13 @@ in
|
||||||
|
|
||||||
max_user_api_reqs_per_minute = 20;
|
max_user_api_reqs_per_minute = 20;
|
||||||
max_user_api_reqs_per_day = 2880;
|
max_user_api_reqs_per_day = 2880;
|
||||||
max_admin_api_reqs_per_key_per_minute = 60;
|
max_admin_api_reqs_per_minute = 60;
|
||||||
max_reqs_per_ip_per_minute = 200;
|
max_reqs_per_ip_per_minute = 200;
|
||||||
max_reqs_per_ip_per_10_seconds = 50;
|
max_reqs_per_ip_per_10_seconds = 50;
|
||||||
max_asset_reqs_per_ip_per_10_seconds = 200;
|
max_asset_reqs_per_ip_per_10_seconds = 200;
|
||||||
max_reqs_per_ip_mode = "block";
|
max_reqs_per_ip_mode = "block";
|
||||||
max_reqs_rate_limit_on_private = false;
|
max_reqs_rate_limit_on_private = false;
|
||||||
|
skip_per_ip_rate_limit_trust_level = 1;
|
||||||
force_anonymous_min_queue_seconds = 1;
|
force_anonymous_min_queue_seconds = 1;
|
||||||
force_anonymous_min_per_10_seconds = 3;
|
force_anonymous_min_per_10_seconds = 3;
|
||||||
background_requests_max_queue_length = 0.5;
|
background_requests_max_queue_length = 0.5;
|
||||||
|
@ -646,6 +647,9 @@ in
|
||||||
enable_email_sync_demon = false;
|
enable_email_sync_demon = false;
|
||||||
max_digests_enqueued_per_30_mins_per_site = 10000;
|
max_digests_enqueued_per_30_mins_per_site = 10000;
|
||||||
cluster_name = null;
|
cluster_name = null;
|
||||||
|
multisite_config_path = "config/multisite.yml";
|
||||||
|
enable_long_polling = null;
|
||||||
|
long_polling_interval = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.redis.enable = lib.mkDefault (cfg.redis.host == "localhost");
|
services.redis.enable = lib.mkDefault (cfg.redis.host == "localhost");
|
||||||
|
@ -825,7 +829,7 @@ in
|
||||||
|
|
||||||
appendHttpConfig = ''
|
appendHttpConfig = ''
|
||||||
# inactive means we keep stuff around for 1440m minutes regardless of last access (1 week)
|
# inactive means we keep stuff around for 1440m minutes regardless of last access (1 week)
|
||||||
# levels means it is a 2 deep heirarchy cause we can have lots of files
|
# levels means it is a 2 deep hierarchy cause we can have lots of files
|
||||||
# max_size limits the size of the cache
|
# max_size limits the size of the cache
|
||||||
proxy_cache_path /var/cache/nginx inactive=1440m levels=1:2 keys_zone=discourse:10m max_size=600m;
|
proxy_cache_path /var/cache/nginx inactive=1440m levels=1:2 keys_zone=discourse:10m max_size=600m;
|
||||||
|
|
||||||
|
@ -837,7 +841,7 @@ in
|
||||||
inherit (cfg) sslCertificate sslCertificateKey enableACME;
|
inherit (cfg) sslCertificate sslCertificateKey enableACME;
|
||||||
forceSSL = lib.mkDefault tlsEnabled;
|
forceSSL = lib.mkDefault tlsEnabled;
|
||||||
|
|
||||||
root = "/run/discourse/public";
|
root = "${cfg.package}/share/discourse/public";
|
||||||
|
|
||||||
locations =
|
locations =
|
||||||
let
|
let
|
||||||
|
@ -889,7 +893,7 @@ in
|
||||||
"~ ^/uploads/" = proxy {
|
"~ ^/uploads/" = proxy {
|
||||||
extraConfig = cache_1y + ''
|
extraConfig = cache_1y + ''
|
||||||
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
|
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
|
||||||
proxy_set_header X-Accel-Mapping /run/discourse/public/=/downloads/;
|
proxy_set_header X-Accel-Mapping ${cfg.package}/share/discourse/public/=/downloads/;
|
||||||
|
|
||||||
# custom CSS
|
# custom CSS
|
||||||
location ~ /stylesheet-cache/ {
|
location ~ /stylesheet-cache/ {
|
||||||
|
@ -911,7 +915,7 @@ in
|
||||||
"~ ^/admin/backups/" = proxy {
|
"~ ^/admin/backups/" = proxy {
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
|
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
|
||||||
proxy_set_header X-Accel-Mapping /run/discourse/public/=/downloads/;
|
proxy_set_header X-Accel-Mapping ${cfg.package}/share/discourse/public/=/downloads/;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
"~ ^/(svg-sprite/|letter_avatar/|letter_avatar_proxy/|user_avatar|highlight-js|stylesheets|theme-javascripts|favicon/proxied|service-worker)" = proxy {
|
"~ ^/(svg-sprite/|letter_avatar/|letter_avatar_proxy/|user_avatar|highlight-js|stylesheets|theme-javascripts|favicon/proxied|service-worker)" = proxy {
|
||||||
|
@ -938,7 +942,7 @@ in
|
||||||
};
|
};
|
||||||
"/downloads/".extraConfig = ''
|
"/downloads/".extraConfig = ''
|
||||||
internal;
|
internal;
|
||||||
alias /run/discourse/public/;
|
alias ${cfg.package}/share/discourse/public/;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -297,7 +297,7 @@ services.discourse = {
|
||||||
the script:
|
the script:
|
||||||
<programlisting language="bash">
|
<programlisting language="bash">
|
||||||
./update.py update-plugins
|
./update.py update-plugins
|
||||||
</programlisting>.
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -308,6 +308,9 @@ in
|
||||||
inherit user;
|
inherit user;
|
||||||
group = webserver.group;
|
group = webserver.group;
|
||||||
|
|
||||||
|
# Not yet compatible with php 8 https://www.dokuwiki.org/requirements
|
||||||
|
# https://github.com/splitbrain/dokuwiki/issues/3545
|
||||||
|
phpPackage = pkgs.php74;
|
||||||
phpEnv = {
|
phpEnv = {
|
||||||
DOKUWIKI_LOCAL_CONFIG = "${dokuwikiLocalConfig hostName cfg}";
|
DOKUWIKI_LOCAL_CONFIG = "${dokuwikiLocalConfig hostName cfg}";
|
||||||
DOKUWIKI_PLUGINS_LOCAL_CONFIG = "${dokuwikiPluginsLocalConfig hostName cfg}";
|
DOKUWIKI_PLUGINS_LOCAL_CONFIG = "${dokuwikiPluginsLocalConfig hostName cfg}";
|
||||||
|
@ -446,5 +449,6 @@ in
|
||||||
meta.maintainers = with maintainers; [
|
meta.maintainers = with maintainers; [
|
||||||
_1000101
|
_1000101
|
||||||
onny
|
onny
|
||||||
|
dandellion
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ in
|
||||||
{
|
{
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
maintainers = with maintainers; [ ];
|
maintainers = teams.xfce.members;
|
||||||
};
|
};
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
|
|
|
@ -39,10 +39,12 @@ in {
|
||||||
options = {
|
options = {
|
||||||
services.xserver.windowManager.xmonad = {
|
services.xserver.windowManager.xmonad = {
|
||||||
enable = mkEnableOption "xmonad";
|
enable = mkEnableOption "xmonad";
|
||||||
|
|
||||||
haskellPackages = mkOption {
|
haskellPackages = mkOption {
|
||||||
default = pkgs.haskellPackages;
|
default = pkgs.haskellPackages;
|
||||||
defaultText = literalExpression "pkgs.haskellPackages";
|
defaultText = literalExpression "pkgs.haskellPackages";
|
||||||
example = literalExpression "pkgs.haskell.packages.ghc784";
|
example = literalExpression "pkgs.haskell.packages.ghc784";
|
||||||
|
type = types.attrs;
|
||||||
description = ''
|
description = ''
|
||||||
haskellPackages used to build Xmonad and other packages.
|
haskellPackages used to build Xmonad and other packages.
|
||||||
This can be used to change the GHC version used to build
|
This can be used to change the GHC version used to build
|
||||||
|
|
|
@ -351,8 +351,14 @@ foreach my $device (keys %$prevSwaps) {
|
||||||
|
|
||||||
# Should we have systemd re-exec itself?
|
# Should we have systemd re-exec itself?
|
||||||
my $prevSystemd = abs_path("/proc/1/exe") // "/unknown";
|
my $prevSystemd = abs_path("/proc/1/exe") // "/unknown";
|
||||||
|
my $prevSystemdSystemConfig = abs_path("/etc/systemd/system.conf") // "/unknown";
|
||||||
my $newSystemd = abs_path("@systemd@/lib/systemd/systemd") or die;
|
my $newSystemd = abs_path("@systemd@/lib/systemd/systemd") or die;
|
||||||
|
my $newSystemdSystemConfig = abs_path("$out/etc/systemd/system.conf") // "/unknown";
|
||||||
|
|
||||||
my $restartSystemd = $prevSystemd ne $newSystemd;
|
my $restartSystemd = $prevSystemd ne $newSystemd;
|
||||||
|
if ($prevSystemdSystemConfig ne $newSystemdSystemConfig) {
|
||||||
|
$restartSystemd = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub filterUnits {
|
sub filterUnits {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, utils, ... }:
|
||||||
|
|
||||||
|
with utils.systemdUtils.unitOptions;
|
||||||
|
with utils.systemdUtils.lib;
|
||||||
with lib;
|
with lib;
|
||||||
with import ./systemd-unit-options.nix { inherit config lib; };
|
|
||||||
with import ./systemd-lib.nix { inherit config lib pkgs; };
|
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
|
@ -823,6 +823,16 @@ let
|
||||||
(assertValueOneOf "OnLink" boolValues)
|
(assertValueOneOf "OnLink" boolValues)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
sectionDHCPServerStaticLease = checkUnitConfig "DHCPServerStaticLease" [
|
||||||
|
(assertOnlyFields [
|
||||||
|
"MACAddress"
|
||||||
|
"Address"
|
||||||
|
])
|
||||||
|
(assertHasField "MACAddress")
|
||||||
|
(assertHasField "Address")
|
||||||
|
(assertMacAddress "MACAddress")
|
||||||
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1163,6 +1173,25 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dhcpServerStaticLeaseOptions = {
|
||||||
|
options = {
|
||||||
|
dhcpServerStaticLeaseConfig = mkOption {
|
||||||
|
default = {};
|
||||||
|
example = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; };
|
||||||
|
type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPServerStaticLease;
|
||||||
|
description = ''
|
||||||
|
Each attribute in this set specifies an option in the
|
||||||
|
<literal>[DHCPServerStaticLease]</literal> section of the unit. See
|
||||||
|
<citerefentry><refentrytitle>systemd.network</refentrytitle>
|
||||||
|
<manvolnum>5</manvolnum></citerefentry> for details.
|
||||||
|
|
||||||
|
Make sure to configure the corresponding client interface to use
|
||||||
|
<literal>ClientIdentifier=mac</literal>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
networkOptions = commonNetworkOptions // {
|
networkOptions = commonNetworkOptions // {
|
||||||
|
|
||||||
linkConfig = mkOption {
|
linkConfig = mkOption {
|
||||||
|
@ -1275,6 +1304,17 @@ let
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dhcpServerStaticLeases = mkOption {
|
||||||
|
default = [];
|
||||||
|
example = [ { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; } ];
|
||||||
|
type = with types; listOf (submodule dhcpServerStaticLeaseOptions);
|
||||||
|
description = ''
|
||||||
|
A list of DHCPServerStaticLease sections to be added to the unit. See
|
||||||
|
<citerefentry><refentrytitle>systemd.network</refentrytitle>
|
||||||
|
<manvolnum>5</manvolnum></citerefentry> for details.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
ipv6Prefixes = mkOption {
|
ipv6Prefixes = mkOption {
|
||||||
default = [];
|
default = [];
|
||||||
example = [ { AddressAutoconfiguration = true; OnLink = true; } ];
|
example = [ { AddressAutoconfiguration = true; OnLink = true; } ];
|
||||||
|
@ -1646,6 +1686,10 @@ let
|
||||||
[IPv6Prefix]
|
[IPv6Prefix]
|
||||||
${attrsToSection x.ipv6PrefixConfig}
|
${attrsToSection x.ipv6PrefixConfig}
|
||||||
'')
|
'')
|
||||||
|
+ flip concatMapStrings def.dhcpServerStaticLeases (x: ''
|
||||||
|
[DHCPServerStaticLease]
|
||||||
|
${attrsToSection x.dhcpServerStaticLeaseConfig}
|
||||||
|
'')
|
||||||
+ def.extraConfig;
|
+ def.extraConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,18 @@ specialMount() {
|
||||||
}
|
}
|
||||||
source @earlyMountScript@
|
source @earlyMountScript@
|
||||||
|
|
||||||
|
# Copy initrd secrets from /.initrd-secrets to their actual destinations
|
||||||
|
if [ -d "/.initrd-secrets" ]; then
|
||||||
|
#
|
||||||
|
# Secrets are named by their full destination pathname and stored
|
||||||
|
# under /.initrd-secrets/
|
||||||
|
#
|
||||||
|
for secret in $(cd "/.initrd-secrets"; find . -type f); do
|
||||||
|
mkdir -p $(dirname "/$secret")
|
||||||
|
cp "/.initrd-secrets/$secret" "$secret"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
# Log the script output to /dev/kmsg or /run/log/stage-1-init.log.
|
# Log the script output to /dev/kmsg or /run/log/stage-1-init.log.
|
||||||
mkdir -p /tmp
|
mkdir -p /tmp
|
||||||
mkfifo /tmp/stage-1-init.log.fifo
|
mkfifo /tmp/stage-1-init.log.fifo
|
||||||
|
|
|
@ -411,8 +411,8 @@ let
|
||||||
${lib.concatStringsSep "\n" (mapAttrsToList (dest: source:
|
${lib.concatStringsSep "\n" (mapAttrsToList (dest: source:
|
||||||
let source' = if source == null then dest else toString source; in
|
let source' = if source == null then dest else toString source; in
|
||||||
''
|
''
|
||||||
mkdir -p $(dirname "$tmp/${dest}")
|
mkdir -p $(dirname "$tmp/.initrd-secrets/${dest}")
|
||||||
cp -a ${source'} "$tmp/${dest}"
|
cp -a ${source'} "$tmp/.initrd-secrets/${dest}"
|
||||||
''
|
''
|
||||||
) config.boot.initrd.secrets)
|
) config.boot.initrd.secrets)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, lib , pkgs, ...}:
|
{ config, lib, pkgs, utils, ...}:
|
||||||
|
|
||||||
|
with utils.systemdUtils.unitOptions;
|
||||||
|
with utils.systemdUtils.lib;
|
||||||
with lib;
|
with lib;
|
||||||
with import ./systemd-unit-options.nix { inherit config lib; };
|
|
||||||
with import ./systemd-lib.nix { inherit config lib pkgs; };
|
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.systemd.nspawn;
|
cfg = config.systemd.nspawn;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{ config, lib, pkgs, utils, ... }:
|
{ config, lib, pkgs, utils, ... }:
|
||||||
|
|
||||||
with utils;
|
with utils;
|
||||||
|
with systemdUtils.unitOptions;
|
||||||
|
with systemdUtils.lib;
|
||||||
with lib;
|
with lib;
|
||||||
with import ./systemd-unit-options.nix { inherit config lib; };
|
|
||||||
with import ./systemd-lib.nix { inherit config lib pkgs; };
|
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ in
|
||||||
SystemCallArchitectures = "native";
|
SystemCallArchitectures = "native";
|
||||||
SystemCallFilter = "@system-service";
|
SystemCallFilter = "@system-service";
|
||||||
SystemCallErrorNumber = "EPERM";
|
SystemCallErrorNumber = "EPERM";
|
||||||
CapabilityBoundingSet = "CAP_DAC_OVERRIDE" ++
|
CapabilityBoundingSet = "CAP_DAC_OVERRIDE" +
|
||||||
lib.optionalString cfg.touchBeforeSync " CAP_FOWNER";
|
lib.optionalString cfg.touchBeforeSync " CAP_FOWNER";
|
||||||
|
|
||||||
ProtectSystem = "strict";
|
ProtectSystem = "strict";
|
||||||
|
|
|
@ -39,8 +39,8 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./podman-dnsname.nix
|
./dnsname.nix
|
||||||
./podman-network-socket.nix
|
./network-socket.nix
|
||||||
(lib.mkRenamedOptionModule [ "virtualisation" "podman" "libpod" ] [ "virtualisation" "containers" "containersConf" ])
|
(lib.mkRenamedOptionModule [ "virtualisation" "podman" "libpod" ] [ "virtualisation" "containers" "containersConf" ])
|
||||||
];
|
];
|
||||||
|
|
|
@ -9,6 +9,10 @@ let
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
imports = [
|
||||||
|
./network-socket-ghostunnel.nix
|
||||||
|
];
|
||||||
|
|
||||||
options.virtualisation.podman.networkSocket = {
|
options.virtualisation.podman.networkSocket = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
|
@ -835,6 +835,7 @@ in
|
||||||
|
|
||||||
# FIXME: Consolidate this one day.
|
# FIXME: Consolidate this one day.
|
||||||
virtualisation.qemu.options = mkMerge [
|
virtualisation.qemu.options = mkMerge [
|
||||||
|
[ "-device virtio-keyboard" ]
|
||||||
(mkIf pkgs.stdenv.hostPlatform.isx86 [
|
(mkIf pkgs.stdenv.hostPlatform.isx86 [
|
||||||
"-usb" "-device usb-tablet,bus=usb-bus.0"
|
"-usb" "-device usb-tablet,bus=usb-bus.0"
|
||||||
])
|
])
|
||||||
|
|
|
@ -369,9 +369,9 @@ in
|
||||||
plikd = handleTest ./plikd.nix {};
|
plikd = handleTest ./plikd.nix {};
|
||||||
plotinus = handleTest ./plotinus.nix {};
|
plotinus = handleTest ./plotinus.nix {};
|
||||||
podgrab = handleTest ./podgrab.nix {};
|
podgrab = handleTest ./podgrab.nix {};
|
||||||
podman = handleTestOn ["x86_64-linux"] ./podman.nix {};
|
podman = handleTestOn ["x86_64-linux"] ./podman/default.nix {};
|
||||||
podman-dnsname = handleTestOn ["x86_64-linux"] ./podman-dnsname.nix {};
|
podman-dnsname = handleTestOn ["x86_64-linux"] ./podman/dnsname.nix {};
|
||||||
podman-tls-ghostunnel = handleTestOn ["x86_64-linux"] ./podman-tls-ghostunnel.nix {};
|
podman-tls-ghostunnel = handleTestOn ["x86_64-linux"] ./podman/tls-ghostunnel.nix {};
|
||||||
pomerium = handleTestOn ["x86_64-linux"] ./pomerium.nix {};
|
pomerium = handleTestOn ["x86_64-linux"] ./pomerium.nix {};
|
||||||
postfix = handleTest ./postfix.nix {};
|
postfix = handleTest ./postfix.nix {};
|
||||||
postfix-raise-smtpd-tls-security-level = handleTest ./postfix-raise-smtpd-tls-security-level.nix {};
|
postfix-raise-smtpd-tls-security-level = handleTest ./postfix-raise-smtpd-tls-security-level.nix {};
|
||||||
|
@ -454,6 +454,7 @@ in
|
||||||
systemd-journal = handleTest ./systemd-journal.nix {};
|
systemd-journal = handleTest ./systemd-journal.nix {};
|
||||||
systemd-networkd = handleTest ./systemd-networkd.nix {};
|
systemd-networkd = handleTest ./systemd-networkd.nix {};
|
||||||
systemd-networkd-dhcpserver = handleTest ./systemd-networkd-dhcpserver.nix {};
|
systemd-networkd-dhcpserver = handleTest ./systemd-networkd-dhcpserver.nix {};
|
||||||
|
systemd-networkd-dhcpserver-static-leases = handleTest ./systemd-networkd-dhcpserver-static-leases.nix {};
|
||||||
systemd-networkd-ipv6-prefix-delegation = handleTest ./systemd-networkd-ipv6-prefix-delegation.nix {};
|
systemd-networkd-ipv6-prefix-delegation = handleTest ./systemd-networkd-ipv6-prefix-delegation.nix {};
|
||||||
systemd-networkd-vrf = handleTest ./systemd-networkd-vrf.nix {};
|
systemd-networkd-vrf = handleTest ./systemd-networkd-vrf.nix {};
|
||||||
systemd-nspawn = handleTest ./systemd-nspawn.nix {};
|
systemd-nspawn = handleTest ./systemd-nspawn.nix {};
|
||||||
|
|
|
@ -23,6 +23,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
import re
|
||||||
# sane loads libsane-brother5.so.1 successfully, and scanimage doesn't die
|
# sane loads libsane-brother5.so.1 successfully, and scanimage doesn't die
|
||||||
strace = machine.succeed('strace scanimage -L 2>&1').split("\n")
|
strace = machine.succeed('strace scanimage -L 2>&1').split("\n")
|
||||||
regexp = 'openat\(.*libsane-brother5.so.1", O_RDONLY|O_CLOEXEC\) = \d\d*$'
|
regexp = 'openat\(.*libsane-brother5.so.1", O_RDONLY|O_CLOEXEC\) = \d\d*$'
|
||||||
|
|
|
@ -13,7 +13,12 @@ let
|
||||||
|
|
||||||
machine = { ... }: {
|
machine = { ... }: {
|
||||||
virtualisation.useBootLoader = true;
|
virtualisation.useBootLoader = true;
|
||||||
boot.initrd.secrets."/test" = secretInStore;
|
boot.initrd.secrets = {
|
||||||
|
"/test" = secretInStore;
|
||||||
|
|
||||||
|
# This should *not* need to be copied in postMountCommands
|
||||||
|
"/run/keys/test" = secretInStore;
|
||||||
|
};
|
||||||
boot.initrd.postMountCommands = ''
|
boot.initrd.postMountCommands = ''
|
||||||
cp /test /mnt-root/secret-from-initramfs
|
cp /test /mnt-root/secret-from-initramfs
|
||||||
'';
|
'';
|
||||||
|
@ -26,7 +31,8 @@ let
|
||||||
start_all()
|
start_all()
|
||||||
machine.wait_for_unit("multi-user.target")
|
machine.wait_for_unit("multi-user.target")
|
||||||
machine.succeed(
|
machine.succeed(
|
||||||
"cmp ${secretInStore} /secret-from-initramfs"
|
"cmp ${secretInStore} /secret-from-initramfs",
|
||||||
|
"cmp ${secretInStore} /run/keys/test",
|
||||||
)
|
)
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,12 +53,12 @@ let
|
||||||
};
|
};
|
||||||
# /etc/nixos/configuration.nix for the vm
|
# /etc/nixos/configuration.nix for the vm
|
||||||
configFile = pkgs.writeText "configuration.nix" ''
|
configFile = pkgs.writeText "configuration.nix" ''
|
||||||
{config, pkgs, ...}: ({
|
{config, pkgs, lib, ...}: ({
|
||||||
imports =
|
imports =
|
||||||
[ ./hardware-configuration.nix
|
[ ./hardware-configuration.nix
|
||||||
<nixpkgs/nixos/modules/testing/test-instrumentation.nix>
|
<nixpkgs/nixos/modules/testing/test-instrumentation.nix>
|
||||||
];
|
];
|
||||||
} // pkgs.lib.importJSON ${
|
} // lib.importJSON ${
|
||||||
pkgs.writeText "simpleConfig.json" (builtins.toJSON simpleConfig)
|
pkgs.writeText "simpleConfig.json" (builtins.toJSON simpleConfig)
|
||||||
})
|
})
|
||||||
'';
|
'';
|
||||||
|
@ -114,7 +114,7 @@ in {
|
||||||
"${configFile}",
|
"${configFile}",
|
||||||
"/etc/nixos/configuration.nix",
|
"/etc/nixos/configuration.nix",
|
||||||
)
|
)
|
||||||
machine.succeed("nixos-rebuild boot >&2")
|
machine.succeed("nixos-rebuild boot --show-trace >&2")
|
||||||
|
|
||||||
machine.succeed("egrep 'menuentry.*debian' /boot/grub/grub.cfg")
|
machine.succeed("egrep 'menuentry.*debian' /boot/grub/grub.cfg")
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This test runs podman and checks if simple container starts
|
# This test runs podman and checks if simple container starts
|
||||||
|
|
||||||
import ./make-test-python.nix (
|
import ../make-test-python.nix (
|
||||||
{ pkgs, lib, ... }: {
|
{ pkgs, lib, ... }: {
|
||||||
name = "podman";
|
name = "podman";
|
||||||
meta = {
|
meta = {
|
||||||
|
@ -48,7 +48,7 @@ import ./make-test-python.nix (
|
||||||
start_all()
|
start_all()
|
||||||
|
|
||||||
with subtest("Run container as root with runc"):
|
with subtest("Run container as root with runc"):
|
||||||
podman.succeed("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg")
|
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
"podman run --runtime=runc -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
"podman run --runtime=runc -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
||||||
)
|
)
|
||||||
|
@ -57,7 +57,7 @@ import ./make-test-python.nix (
|
||||||
podman.succeed("podman rm sleeping")
|
podman.succeed("podman rm sleeping")
|
||||||
|
|
||||||
with subtest("Run container as root with crun"):
|
with subtest("Run container as root with crun"):
|
||||||
podman.succeed("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg")
|
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
"podman run --runtime=crun -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
"podman run --runtime=crun -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
||||||
)
|
)
|
||||||
|
@ -66,7 +66,7 @@ import ./make-test-python.nix (
|
||||||
podman.succeed("podman rm sleeping")
|
podman.succeed("podman rm sleeping")
|
||||||
|
|
||||||
with subtest("Run container as root with the default backend"):
|
with subtest("Run container as root with the default backend"):
|
||||||
podman.succeed("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg")
|
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
"podman run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
"podman run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
||||||
)
|
)
|
||||||
|
@ -78,7 +78,7 @@ import ./make-test-python.nix (
|
||||||
podman.succeed("loginctl enable-linger alice")
|
podman.succeed("loginctl enable-linger alice")
|
||||||
|
|
||||||
with subtest("Run container rootless with runc"):
|
with subtest("Run container rootless with runc"):
|
||||||
podman.succeed(su_cmd("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg"))
|
podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
su_cmd(
|
su_cmd(
|
||||||
"podman run --runtime=runc -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
"podman run --runtime=runc -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
||||||
|
@ -89,7 +89,7 @@ import ./make-test-python.nix (
|
||||||
podman.succeed(su_cmd("podman rm sleeping"))
|
podman.succeed(su_cmd("podman rm sleeping"))
|
||||||
|
|
||||||
with subtest("Run container rootless with crun"):
|
with subtest("Run container rootless with crun"):
|
||||||
podman.succeed(su_cmd("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg"))
|
podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
su_cmd(
|
su_cmd(
|
||||||
"podman run --runtime=crun -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
"podman run --runtime=crun -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
||||||
|
@ -100,7 +100,7 @@ import ./make-test-python.nix (
|
||||||
podman.succeed(su_cmd("podman rm sleeping"))
|
podman.succeed(su_cmd("podman rm sleeping"))
|
||||||
|
|
||||||
with subtest("Run container rootless with the default backend"):
|
with subtest("Run container rootless with the default backend"):
|
||||||
podman.succeed(su_cmd("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg"))
|
podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
su_cmd(
|
su_cmd(
|
||||||
"podman run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
"podman run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
||||||
|
@ -112,7 +112,7 @@ import ./make-test-python.nix (
|
||||||
|
|
||||||
with subtest("Run container with init"):
|
with subtest("Run container with init"):
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
"tar cvf busybox.tar -C ${pkgs.pkgsStatic.busybox} . && podman import busybox.tar busybox"
|
"tar cv -C ${pkgs.pkgsStatic.busybox} . | podman import - busybox"
|
||||||
)
|
)
|
||||||
pid = podman.succeed("podman run --rm busybox readlink /proc/self").strip()
|
pid = podman.succeed("podman run --rm busybox readlink /proc/self").strip()
|
||||||
assert pid == "1"
|
assert pid == "1"
|
||||||
|
@ -124,7 +124,7 @@ import ./make-test-python.nix (
|
||||||
|
|
||||||
with subtest("Run container via docker cli"):
|
with subtest("Run container via docker cli"):
|
||||||
podman.succeed("docker network create default")
|
podman.succeed("docker network create default")
|
||||||
podman.succeed("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg")
|
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
"docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
"docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
||||||
)
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test-python.nix (
|
import ../make-test-python.nix (
|
||||||
{ pkgs, lib, ... }:
|
{ pkgs, lib, ... }:
|
||||||
let
|
let
|
||||||
inherit (pkgs) writeTextDir python3 curl;
|
inherit (pkgs) writeTextDir python3 curl;
|
||||||
|
@ -21,7 +21,7 @@ import ./make-test-python.nix (
|
||||||
podman.wait_for_unit("sockets.target")
|
podman.wait_for_unit("sockets.target")
|
||||||
|
|
||||||
with subtest("DNS works"): # also tests inter-container tcp routing
|
with subtest("DNS works"): # also tests inter-container tcp routing
|
||||||
podman.succeed("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg")
|
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
|
||||||
podman.succeed(
|
podman.succeed(
|
||||||
"podman run -d --name=webserver -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${webroot} scratchimg ${python3}/bin/python -m http.server 8000"
|
"podman run -d --name=webserver -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${webroot} scratchimg ${python3}/bin/python -m http.server 8000"
|
||||||
)
|
)
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
This test runs podman as a backend for the Docker CLI.
|
This test runs podman as a backend for the Docker CLI.
|
||||||
*/
|
*/
|
||||||
import ./make-test-python.nix (
|
import ../make-test-python.nix (
|
||||||
{ pkgs, lib, ... }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
let gen-ca = pkgs.writeScript "gen-ca" ''
|
let gen-ca = pkgs.writeScript "gen-ca" ''
|
||||||
|
@ -126,7 +126,7 @@ import ./make-test-python.nix (
|
||||||
client.succeed("docker version")
|
client.succeed("docker version")
|
||||||
|
|
||||||
# via socket would be nicer
|
# via socket would be nicer
|
||||||
podman.succeed("tar cvf scratchimg.tar --files-from /dev/null && podman import scratchimg.tar scratchimg")
|
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
|
||||||
|
|
||||||
client.succeed(
|
client.succeed(
|
||||||
"docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
"docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
81
nixos/tests/systemd-networkd-dhcpserver-static-leases.nix
Normal file
81
nixos/tests/systemd-networkd-dhcpserver-static-leases.nix
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
# In contrast to systemd-networkd-dhcpserver, this test configures
|
||||||
|
# the router with a static DHCP lease for the client's MAC address.
|
||||||
|
import ./make-test-python.nix ({ lib, ... }: {
|
||||||
|
name = "systemd-networkd-dhcpserver-static-leases";
|
||||||
|
meta = with lib.maintainers; {
|
||||||
|
maintainers = [ veehaitch tomfitzhenry ];
|
||||||
|
};
|
||||||
|
nodes = {
|
||||||
|
router = {
|
||||||
|
virtualisation.vlans = [ 1 ];
|
||||||
|
systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug";
|
||||||
|
networking = {
|
||||||
|
useNetworkd = true;
|
||||||
|
useDHCP = false;
|
||||||
|
firewall.enable = false;
|
||||||
|
};
|
||||||
|
systemd.network = {
|
||||||
|
networks = {
|
||||||
|
# systemd-networkd will load the first network unit file
|
||||||
|
# that matches, ordered lexiographically by filename.
|
||||||
|
# /etc/systemd/network/{40-eth1,99-main}.network already
|
||||||
|
# exists. This network unit must be loaded for the test,
|
||||||
|
# however, hence why this network is named such.
|
||||||
|
"01-eth1" = {
|
||||||
|
name = "eth1";
|
||||||
|
networkConfig = {
|
||||||
|
DHCPServer = true;
|
||||||
|
Address = "10.0.0.1/24";
|
||||||
|
};
|
||||||
|
dhcpServerStaticLeases = [{
|
||||||
|
dhcpServerStaticLeaseConfig = {
|
||||||
|
MACAddress = "02:de:ad:be:ef:01";
|
||||||
|
Address = "10.0.0.10";
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
client = {
|
||||||
|
virtualisation.vlans = [ 1 ];
|
||||||
|
systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug";
|
||||||
|
networking = {
|
||||||
|
useNetworkd = true;
|
||||||
|
useDHCP = false;
|
||||||
|
firewall.enable = false;
|
||||||
|
interfaces.eth1 = {
|
||||||
|
useDHCP = true;
|
||||||
|
macAddress = "02:de:ad:be:ef:01";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# This setting is important to have the router assign the
|
||||||
|
# configured lease based on the client's MAC address. Also see:
|
||||||
|
# https://github.com/systemd/systemd/issues/21368#issuecomment-982193546
|
||||||
|
systemd.network.networks."40-eth1".dhcpV4Config.ClientIdentifier = "mac";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
testScript = ''
|
||||||
|
start_all()
|
||||||
|
|
||||||
|
with subtest("check router network configuration"):
|
||||||
|
router.wait_for_unit("systemd-networkd-wait-online.service")
|
||||||
|
eth1_status = router.succeed("networkctl status eth1")
|
||||||
|
assert "Network File: /etc/systemd/network/01-eth1.network" in eth1_status, \
|
||||||
|
"The router interface eth1 is not using the expected network file"
|
||||||
|
assert "10.0.0.1" in eth1_status, "Did not find expected router IPv4"
|
||||||
|
|
||||||
|
with subtest("check client network configuration"):
|
||||||
|
client.wait_for_unit("systemd-networkd-wait-online.service")
|
||||||
|
eth1_status = client.succeed("networkctl status eth1")
|
||||||
|
assert "Network File: /etc/systemd/network/40-eth1.network" in eth1_status, \
|
||||||
|
"The client interface eth1 is not using the expected network file"
|
||||||
|
assert "10.0.0.10" in eth1_status, "Did not find expected client IPv4"
|
||||||
|
|
||||||
|
with subtest("router and client can reach each other"):
|
||||||
|
client.wait_until_succeeds("ping -c 5 10.0.0.1")
|
||||||
|
router.wait_until_succeeds("ping -c 5 10.0.0.10")
|
||||||
|
'';
|
||||||
|
})
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "bitwig-studio";
|
pname = "bitwig-studio";
|
||||||
version = "4.1";
|
version = "4.1.1";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://downloads.bitwig.com/stable/${version}/${pname}-${version}.deb";
|
url = "https://downloads.bitwig.com/stable/${version}/${pname}-${version}.deb";
|
||||||
sha256 = "sha256-h6TNlfKgN7CPhtY8DxESrydtEsdVPT+Uf+VKcqKVuXw=";
|
sha256 = "sha256-bhd3Ij4y1r5pHrpQkbHuMTNl8Z3w0HsbCkr1C0CVFvQ=";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ dpkg makeWrapper wrapGAppsHook ];
|
nativeBuildInputs = [ dpkg makeWrapper wrapGAppsHook ];
|
||||||
|
|
|
@ -21,20 +21,20 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "gnome-podcasts";
|
pname = "gnome-podcasts";
|
||||||
version = "0.4.9";
|
version = "0.5.0";
|
||||||
|
|
||||||
src = fetchFromGitLab {
|
src = fetchFromGitLab {
|
||||||
domain = "gitlab.gnome.org";
|
domain = "gitlab.gnome.org";
|
||||||
owner = "World";
|
owner = "World";
|
||||||
repo = "podcasts";
|
repo = "podcasts";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "1ah59ac3xm3sqai8zhil8ar30pviw83cm8in1n4id77rv24xkvgm";
|
hash = "sha256-Jk++/QrQt/fjOz2OaEIr1Imq2DmqTjcormCebjO4/Kk=";
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoDeps = rustPlatform.fetchCargoTarball {
|
cargoDeps = rustPlatform.fetchCargoTarball {
|
||||||
inherit src;
|
inherit src;
|
||||||
name = "${pname}-${version}";
|
name = "${pname}-${version}";
|
||||||
sha256 = "1iihpfvkli09ysn46cnif53xizkwzk0m91bljmlzsygp3ip5i5yw";
|
hash = "sha256-jlXpeVabc1h2GU1j9Ff6GZJec+JgFyOdJzsOtdkrEWI=";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "helio-workstation";
|
pname = "helio-workstation";
|
||||||
version = "3.6";
|
version = "3.8";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "helio-fm";
|
owner = "helio-fm";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = version;
|
rev = version;
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
sha256 = "sha256-qW39g6rQ5VPQ3Hx9NmwLbpZiITnzFZDZlcLkE+pJKPc=";
|
sha256 = "sha256-uwRSOJ5WvDH4mfL9pCTCGzuSRT8SIBrI+Wsbumzejv0=";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
|
@ -30,13 +30,13 @@ stdenv.mkDerivation rec {
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
install -Dm755 build/Helio $out/bin
|
install -Dm755 build/helio $out/bin
|
||||||
wrapProgram $out/bin/Helio --prefix PATH ":" ${gnome.zenity}/bin
|
wrapProgram $out/bin/helio --prefix PATH ":" ${gnome.zenity}/bin
|
||||||
|
|
||||||
mkdir -p $out/share
|
mkdir -p $out/share
|
||||||
cp -r ../Deployment/Linux/Debian/x64/usr/share/* $out/share
|
cp -r ../Deployment/Linux/Debian/x64/usr/share/* $out/share
|
||||||
substituteInPlace $out/share/applications/Helio.desktop \
|
substituteInPlace $out/share/applications/Helio.desktop \
|
||||||
--replace "/usr/bin/helio" "$out/bin/Helio"
|
--replace "/usr/bin/helio" "$out/bin/helio"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
mkDerivation rec {
|
mkDerivation rec {
|
||||||
pname = "jamulus";
|
pname = "jamulus";
|
||||||
version = "3.8.0";
|
version = "3.8.1";
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "jamulussoftware";
|
owner = "jamulussoftware";
|
||||||
repo = "jamulus";
|
repo = "jamulus";
|
||||||
rev = "r${lib.replaceStrings [ "." ] [ "_" ] version}";
|
rev = "r${lib.replaceStrings [ "." ] [ "_" ] version}";
|
||||||
sha256 = "sha256-Ni6N7XW34OFNuEkqBEgMcYGmIqb+UZ0uhLt/shRkWRs=";
|
sha256 = "sha256-QtlvcKVqKgRAO/leHy4CgvjNW49HAyZLI2JtKERP7HQ=";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ pkg-config qmake ];
|
nativeBuildInputs = [ pkg-config qmake ];
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "JMusicBot";
|
pname = "JMusicBot";
|
||||||
version = "0.3.4";
|
version = "0.3.6";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/jagrosh/MusicBot/releases/download/${version}/JMusicBot-${version}.jar";
|
url = "https://github.com/jagrosh/MusicBot/releases/download/${version}/JMusicBot-${version}.jar";
|
||||||
sha256 = "sha256-++/ot9k74pkN9Wl7IEjiMIv/q5zklIEdU6uFjam0tmU=";
|
sha256 = "sha256-Hc3dsOADC+jVZScY19OYDkHimntMjdw/BoB3EUS/d0k=";
|
||||||
};
|
};
|
||||||
|
|
||||||
dontUnpack = true;
|
dontUnpack = true;
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
{ lib, stdenv, fetchurl, makeWrapper, pkg-config, MMA, libjack2, libsmf, python2Packages }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (python2Packages) pyGtkGlade pygtksourceview python;
|
|
||||||
in stdenv.mkDerivation rec {
|
|
||||||
version = "12.02.1";
|
|
||||||
pname = "linuxband";
|
|
||||||
|
|
||||||
src = fetchurl {
|
|
||||||
url = "https://linuxband.org/assets/sources/${pname}-${version}.tar.gz";
|
|
||||||
sha256 = "1r71h4yg775m4gax4irrvygmrsclgn503ykmc2qwjsxa42ri4n2n";
|
|
||||||
};
|
|
||||||
|
|
||||||
nativeBuildInputs = [ pkg-config makeWrapper ];
|
|
||||||
buildInputs = [ MMA libjack2 libsmf python pyGtkGlade pygtksourceview ];
|
|
||||||
|
|
||||||
patchPhase = ''
|
|
||||||
sed -i 's@/usr/@${MMA}/@g' src/main/config/linuxband.rc.in
|
|
||||||
cat src/main/config/linuxband.rc.in
|
|
||||||
'';
|
|
||||||
|
|
||||||
postFixup = ''
|
|
||||||
PYTHONPATH=$pyGtkGlade/share/:pygtksourceview/share/:$PYTHONPATH
|
|
||||||
for f in $out/bin/*; do
|
|
||||||
wrapProgram $f \
|
|
||||||
--prefix PYTHONPATH : $PYTHONPATH
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
description = "A GUI front-end for MMA: Type in the chords, choose the groove and it will play an accompaniment";
|
|
||||||
homepage = "https://linuxband.org/";
|
|
||||||
license = lib.licenses.gpl2;
|
|
||||||
maintainers = [ lib.maintainers.magnetophon ];
|
|
||||||
platforms = lib.platforms.linux;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,18 +1,19 @@
|
||||||
{ lib, stdenv, fetchFromGitHub, lv2 }:
|
{ lib, stdenv, fetchFromGitHub, lv2, cairo, pkg-config }:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
|
|
||||||
pname = "molot-lite";
|
pname = "molot-lite";
|
||||||
version = "1.0.0";
|
version = "1.1.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "magnetophon";
|
owner = "magnetophon";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "0xbvicfk1rgp01nlg6hlym9bnygry0nrbv88mv7w6hnacvl63ba4";
|
sha256 = "sha256-0tmobsdCNon6udbkbQw7+EYQKBg2oaXlHIgNEf9U3XE=";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ lv2 ];
|
nativeBuildInputs = [ pkg-config ];
|
||||||
|
buildInputs = [ lv2 cairo ];
|
||||||
|
|
||||||
makeFlags = [ "INSTALL_DIR=$out/lib/lv2" ];
|
makeFlags = [ "INSTALL_DIR=$out/lib/lv2" ];
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "mpc";
|
pname = "mpc";
|
||||||
version = "0.33";
|
version = "0.34";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "MusicPlayerDaemon";
|
owner = "MusicPlayerDaemon";
|
||||||
repo = "mpc";
|
repo = "mpc";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "1qbi0i9cq54rj8z2kapk8x8g1jkw2jz781niwb9i7kw4xfhvy5zx";
|
sha256 = "sha256-2FjYBfak0IjibuU+CNQ0y9Ei8hTZhynS/BK2DNerhVw=";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ libmpdclient ] ++ lib.optionals stdenv.isDarwin [ libiconv ];
|
buildInputs = [ libmpdclient ] ++ lib.optionals stdenv.isDarwin [ libiconv ];
|
||||||
|
|
|
@ -18,13 +18,13 @@ assert pcreSupport -> pcre != null;
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "ncmpc";
|
pname = "ncmpc";
|
||||||
version = "0.45";
|
version = "0.46";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "MusicPlayerDaemon";
|
owner = "MusicPlayerDaemon";
|
||||||
repo = "ncmpc";
|
repo = "ncmpc";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "sha256-KDSHbEZ2PJLEIlXqPvBQ2ZPWno+IoajTjkl9faAXIko=";
|
sha256 = "sha256-FyuN0jkHaJLXqcVbW+OggHkNBjmqH7bS7W/QXUoDjJk=";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ glib ncurses libmpdclient boost ]
|
buildInputs = [ glib ncurses libmpdclient boost ]
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
mkDerivation rec {
|
mkDerivation rec {
|
||||||
pname = "padthv1";
|
pname = "padthv1";
|
||||||
version = "0.9.18";
|
version = "0.9.23";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "mirror://sourceforge/padthv1/${pname}-${version}.tar.gz";
|
url = "mirror://sourceforge/padthv1/${pname}-${version}.tar.gz";
|
||||||
sha256 = "1karrprb3ijrbiwpr43rl3nxnzc33lnmwrd1832psgr3flnr9fp5";
|
sha256 = "sha256-9yFfvlskOYnGraou2S3Qffl8RoYJqE0wnDlOP8mxQgg=";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ libjack2 alsa-lib libsndfile liblo lv2 qt5.qtbase qt5.qttools fftwFloat ];
|
buildInputs = [ libjack2 alsa-lib libsndfile liblo lv2 qt5.qtbase qt5.qttools fftwFloat ];
|
||||||
|
|
|
@ -7,13 +7,13 @@ let
|
||||||
|
|
||||||
in stdenv.mkDerivation rec {
|
in stdenv.mkDerivation rec {
|
||||||
name = "${pname}-${version}";
|
name = "${pname}-${version}";
|
||||||
version = "1.69";
|
version = "1.70";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "graysky2";
|
owner = "graysky2";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "sha256-5WRhVIQlSwWuyvkzrnNW0rdVet9ZzM47gISJpznM8mU=";
|
sha256 = "sha256-ZB1jrr31PF7+vNB+Xo5CATJmYbuDAPwewpDxCVnAowY=";
|
||||||
};
|
};
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
|
|
|
@ -21,14 +21,14 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "deja-dup";
|
pname = "deja-dup";
|
||||||
version = "42.7";
|
version = "42.8";
|
||||||
|
|
||||||
src = fetchFromGitLab {
|
src = fetchFromGitLab {
|
||||||
domain = "gitlab.gnome.org";
|
domain = "gitlab.gnome.org";
|
||||||
owner = "World";
|
owner = "World";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "1q66wccnph78cp1r5mln2iq4bcqdrrchxq3c1pjrzkmzwc6l93gz";
|
sha256 = "sha256-DkRqZAj47wzt4lDvhAbO0PYcRA7oHEo2k69IMLOD3Ps=";
|
||||||
};
|
};
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
|
|
|
@ -24,11 +24,11 @@
|
||||||
with lib;
|
with lib;
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = if withGui then "elements" else "elementsd";
|
pname = if withGui then "elements" else "elementsd";
|
||||||
version = "0.21.0";
|
version = "0.21.0.1";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/ElementsProject/elements/archive/elements-${version}.tar.gz";
|
url = "https://github.com/ElementsProject/elements/archive/elements-${version}.tar.gz";
|
||||||
sha256 = "0d9mcb0nw9qqhv0jhpddi9i4iry3w7b5jifsl5kpcw82qrkvgfgj";
|
sha256 = "00a2lrn77mfmr5dvrqwplk20gaxxq4cd9gcx667hgmfmmz1v6r6b";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs =
|
nativeBuildInputs =
|
||||||
|
|
|
@ -9,17 +9,17 @@ let
|
||||||
|
|
||||||
in buildGoModule rec {
|
in buildGoModule rec {
|
||||||
pname = "go-ethereum";
|
pname = "go-ethereum";
|
||||||
version = "1.10.8";
|
version = "1.10.11";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "ethereum";
|
owner = "ethereum";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "sha256-r4ifLa4CMZvp0MaCkxWo5rWLEnFdX//mYlC08hndXhQ=";
|
sha256 = "sha256-8kPaa2wRKUQBn4LFDnc7tEbLR62f99NS1HIVDeHHzto=";
|
||||||
};
|
};
|
||||||
|
|
||||||
runVend = true;
|
runVend = true;
|
||||||
vendorSha256 = "sha256-e8aKQMVEEf0BzpdljkOBxznj5P1Go/6EbY9mdhDLyrw=";
|
vendorSha256 = "sha256-i2FOAN1ng3WNOWaFowiSSuYR4LA1Bo3tjkvgcClBXSU=";
|
||||||
|
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "monero-cli";
|
pname = "monero-cli";
|
||||||
version = "0.17.2.3";
|
version = "0.17.3.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "monero-project";
|
owner = "monero-project";
|
||||||
repo = "monero";
|
repo = "monero";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0nax991fshfh51grhh2ryfrwwws35k16gzl1l3niva28zff2xmq6";
|
sha256 = "1spsf7m3x4psp9s7mivr6x4886jnbq4i8ll2dl8bv5bsdhcd3pjm";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
|
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
|
||||||
index a8916a7d0..39ec7747b 100644
|
index 5b7f69a56..5536debe8 100644
|
||||||
--- a/external/CMakeLists.txt
|
--- a/external/CMakeLists.txt
|
||||||
+++ b/external/CMakeLists.txt
|
+++ b/external/CMakeLists.txt
|
||||||
@@ -37,34 +37,16 @@
|
@@ -36,22 +36,9 @@
|
||||||
|
# others.
|
||||||
|
|
||||||
find_package(Miniupnpc REQUIRED)
|
find_package(Miniupnpc REQUIRED)
|
||||||
|
-
|
||||||
-message(STATUS "Using in-tree miniupnpc")
|
-message(STATUS "Using in-tree miniupnpc")
|
||||||
|
-set(UPNPC_NO_INSTALL TRUE CACHE BOOL "Disable miniupnp installation" FORCE)
|
||||||
-add_subdirectory(miniupnp/miniupnpc)
|
-add_subdirectory(miniupnp/miniupnpc)
|
||||||
-set_property(TARGET libminiupnpc-static PROPERTY FOLDER "external")
|
-set_property(TARGET libminiupnpc-static PROPERTY FOLDER "external")
|
||||||
|
-set_property(TARGET libminiupnpc-static PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
-if(MSVC)
|
-if(MSVC)
|
||||||
- set_property(TARGET libminiupnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267")
|
- set_property(TARGET libminiupnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267")
|
||||||
-elseif(NOT MSVC)
|
-elseif(NOT MSVC)
|
||||||
|
@ -25,36 +28,16 @@ index a8916a7d0..39ec7747b 100644
|
||||||
|
|
||||||
find_package(Unbound)
|
find_package(Unbound)
|
||||||
|
|
||||||
if(NOT UNBOUND_INCLUDE_DIR OR STATIC)
|
@@ -69,4 +56,3 @@ endif()
|
||||||
- # NOTE: If STATIC is true, CMAKE_FIND_LIBRARY_SUFFIXES has been reordered.
|
|
||||||
- # unbound has config tests which used OpenSSL libraries, so -ldl may need to
|
|
||||||
- # be set in this case.
|
|
||||||
- # The unbound CMakeLists.txt can set it, since it's also needed for the
|
|
||||||
- # static OpenSSL libraries set up there after with target_link_libraries.
|
|
||||||
- add_subdirectory(unbound)
|
|
||||||
-
|
|
||||||
- set(UNBOUND_STATIC true PARENT_SCOPE)
|
|
||||||
- set(UNBOUND_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/unbound/libunbound" PARENT_SCOPE)
|
|
||||||
- set(UNBOUND_LIBRARY "unbound" PARENT_SCOPE)
|
|
||||||
- set(UNBOUND_LIBRARY_DIRS "${LIBEVENT2_LIBDIR}" PARENT_SCOPE)
|
|
||||||
+ set(UNBOUND_STATIC false PARENT_SCOPE)
|
|
||||||
+ set(UPNP_INCLUDE ${MINIUPNP_INCLUDE_DIR} PARENT_SCOPE)
|
|
||||||
+ set(UPNP_LIBRARIES ${MINIUPNP_LIBRARY} PARENT_SCOPE)
|
|
||||||
else()
|
|
||||||
message(STATUS "Found libunbound include (unbound.h) in ${UNBOUND_INCLUDE_DIR}")
|
|
||||||
if(UNBOUND_LIBRARIES)
|
|
||||||
@@ -81,4 +63,5 @@ endif()
|
|
||||||
add_subdirectory(db_drivers)
|
add_subdirectory(db_drivers)
|
||||||
add_subdirectory(easylogging++)
|
add_subdirectory(easylogging++)
|
||||||
add_subdirectory(qrcodegen)
|
add_subdirectory(qrcodegen)
|
||||||
-add_subdirectory(randomx EXCLUDE_FROM_ALL)
|
-add_subdirectory(randomx EXCLUDE_FROM_ALL)
|
||||||
+
|
|
||||||
+find_library(RANDOMX_LIBRARIES NAMES RandomX)
|
|
||||||
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
|
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
|
||||||
index 175741146..088b582f7 100644
|
index d4b39869c..13071d898 100644
|
||||||
--- a/src/p2p/net_node.inl
|
--- a/src/p2p/net_node.inl
|
||||||
+++ b/src/p2p/net_node.inl
|
+++ b/src/p2p/net_node.inl
|
||||||
@@ -60,9 +60,9 @@
|
@@ -61,9 +61,9 @@
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
#include "net/parse.h"
|
#include "net/parse.h"
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "monero-gui";
|
pname = "monero-gui";
|
||||||
version = "0.17.2.3";
|
version = "0.17.3.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "monero-project";
|
owner = "monero-project";
|
||||||
repo = "monero-gui";
|
repo = "monero-gui";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "1d8y5yqyw0db2jdv9mwkczwm2qcwhzyslvq994yq5rvs4vkd8xjg";
|
sha256 = "0rc1p0k16icgfhc7yvkvb8p6570zz0cvigs648l05fcm3mf787rp";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
pname = "trezor-suite";
|
pname = "trezor-suite";
|
||||||
version = "21.11.2";
|
version = "21.12.2";
|
||||||
name = "${pname}-${version}";
|
name = "${pname}-${version}";
|
||||||
|
|
||||||
suffix = {
|
suffix = {
|
||||||
|
@ -19,8 +19,8 @@ let
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/trezor/${pname}/releases/download/v${version}/Trezor-Suite-${version}-${suffix}.AppImage";
|
url = "https://github.com/trezor/${pname}/releases/download/v${version}/Trezor-Suite-${version}-${suffix}.AppImage";
|
||||||
sha512 = { # curl -Lfs https://github.com/trezor/trezor-suite/releases/latest/download/latest-linux{-arm64,}.yml | grep ^sha512 | sed 's/: /-/'
|
sha512 = { # curl -Lfs https://github.com/trezor/trezor-suite/releases/latest/download/latest-linux{-arm64,}.yml | grep ^sha512 | sed 's/: /-/'
|
||||||
aarch64-linux = "sha512-QX5Ak2F1aD846BuGNcP1K/2c77Ut3LK3UiXsUPqiSBGZ9YRgdzROqdGjCVnTBBhxeCfGYQDhWmpuOpNbLr4eYg==";
|
aarch64-linux = "sha512-LzcTFSNN/loYaTDt+QpW8QpSgOTw2097IYdc7mC57Mn4NR/X2hycYZ9ZfZjBh9QFfVu/4R3UN2sA177v6Inomg==";
|
||||||
x86_64-linux = "sha512-ckMlZoLEq3aLzyhoWf2rRE3XxNQhqo6rUHF2NKoV08sXz+Zth2Lk+P3te1vwFQl+Efryl84RTwVGWKmloZ8k9A==";
|
x86_64-linux = "sha512-W/voBZrXaJVDN4eSUDD6lyBR9BqboD2k2/azI1pWm1NFUmDZFM+OGzyiPB3n+6SziAhca32Ot5Wy27sfmIjh3g==";
|
||||||
}.${stdenv.hostPlatform.system} or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
|
}.${stdenv.hostPlatform.system} or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
40
pkgs/applications/editors/cpeditor/default.nix
Normal file
40
pkgs/applications/editors/cpeditor/default.nix
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, fetchFromGitHub
|
||||||
|
, pkg-config
|
||||||
|
, qtbase
|
||||||
|
, qttools
|
||||||
|
, wrapQtAppsHook
|
||||||
|
, cmake
|
||||||
|
, ninja
|
||||||
|
, python3
|
||||||
|
, runtimeShell
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "cpeditor";
|
||||||
|
version = "6.10.1";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "cpeditor";
|
||||||
|
repo = "cpeditor";
|
||||||
|
rev = version;
|
||||||
|
sha256 = "sha256-SIREoOapaZTLtqi0Z07lKmNqF9a9qIpgGxuhqaY3yfU=";
|
||||||
|
fetchSubmodules = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [ cmake ninja pkg-config wrapQtAppsHook python3 ];
|
||||||
|
buildInputs = [ qtbase qttools ];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace src/Core/Runner.cpp --replace "/bin/bash" "${runtimeShell}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "An IDE specially designed for competitive programming";
|
||||||
|
homepage = "https://cpeditor.org";
|
||||||
|
license = licenses.gpl3Plus;
|
||||||
|
platforms = platforms.linux;
|
||||||
|
maintainers = with maintainers; [ rewine ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ stdenv.mkDerivation rec {
|
||||||
version = "27.2";
|
version = "27.2";
|
||||||
|
|
||||||
emacsName = "emacs-${version}";
|
emacsName = "emacs-${version}";
|
||||||
macportVersion = "8.2";
|
macportVersion = "8.3";
|
||||||
name = "emacs-mac-${version}-${macportVersion}";
|
name = "emacs-mac-${version}-${macportVersion}";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
|
@ -18,7 +18,8 @@ stdenv.mkDerivation rec {
|
||||||
|
|
||||||
macportSrc = fetchurl {
|
macportSrc = fetchurl {
|
||||||
url = "ftp://ftp.math.s.chiba-u.ac.jp/emacs/${emacsName}-mac-${macportVersion}.tar.gz";
|
url = "ftp://ftp.math.s.chiba-u.ac.jp/emacs/${emacsName}-mac-${macportVersion}.tar.gz";
|
||||||
sha256 = "1bgm2g3ky7rkj1l27wnmyzqsqxzjng7y9bf72ym37wiyhyi2a9za";
|
sha256 = "0q4lbk3nb8rz1ibmf23plgsh8sx2wvhry5bf5mivgz4m4b6s2yij";
|
||||||
|
name = "${emacsName}-mac-${macportVersion}.tar.xz"; # It's actually compressed with xz, not gz
|
||||||
};
|
};
|
||||||
|
|
||||||
hiresSrc = fetchurl {
|
hiresSrc = fetchurl {
|
||||||
|
@ -37,11 +38,11 @@ stdenv.mkDerivation rec {
|
||||||
|
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
mv $sourceRoot $name
|
mv $sourceRoot $name
|
||||||
tar xzf $macportSrc -C $name --strip-components=1
|
tar xf $macportSrc -C $name --strip-components=1
|
||||||
mv $name $sourceRoot
|
mv $name $sourceRoot
|
||||||
|
|
||||||
# extract retina image resources
|
# extract retina image resources
|
||||||
tar xzfv $hiresSrc --strip 1 -C $sourceRoot
|
tar xfv $hiresSrc --strip 1 -C $sourceRoot
|
||||||
'';
|
'';
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
{ pkgs, fetchurl, python2Packages }:
|
{ pkgs, fetchFromGitHub, python3Packages }:
|
||||||
|
|
||||||
let
|
let
|
||||||
pythonPackages = python2Packages;
|
pythonPackages = python3Packages;
|
||||||
in pythonPackages.buildPythonApplication rec {
|
in pythonPackages.buildPythonApplication rec {
|
||||||
version = "0.9.7";
|
version = "2.1.0";
|
||||||
pname = "nvpy";
|
pname = "nvpy";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchFromGitHub {
|
||||||
url = "https://github.com/cpbotha/nvpy/archive/v${version}.tar.gz";
|
owner = "cpbotha";
|
||||||
sha256 = "1rd3vlaqkg16iz6qcw6rkbq0jmyvc0843wa3brnvn1nz0kla243f";
|
repo = pname;
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "02njvybd8yaqdnc5ghwrm8225z57gg4w7rhmx3w5jqzh16ld4mhh";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
propagatedBuildInputs = with pythonPackages; [
|
propagatedBuildInputs = with pythonPackages; [
|
||||||
markdown
|
markdown
|
||||||
tkinter
|
|
||||||
docutils
|
docutils
|
||||||
|
simplenote
|
||||||
|
tkinter
|
||||||
];
|
];
|
||||||
|
|
||||||
# No tests
|
# No tests
|
||||||
|
|
|
@ -118,7 +118,7 @@ let
|
||||||
packed="resources/app/node_modules.asar"
|
packed="resources/app/node_modules.asar"
|
||||||
unpacked="resources/app/node_modules"
|
unpacked="resources/app/node_modules"
|
||||||
${nodePackages.asar}/bin/asar extract "$packed" "$unpacked"
|
${nodePackages.asar}/bin/asar extract "$packed" "$unpacked"
|
||||||
substituteInPlace $unpacked/sudo-prompt/index.js \
|
substituteInPlace $unpacked/@vscode/sudo-prompt/index.js \
|
||||||
--replace "/usr/bin/pkexec" "/run/wrappers/bin/pkexec" \
|
--replace "/usr/bin/pkexec" "/run/wrappers/bin/pkexec" \
|
||||||
--replace "/bin/bash" "${bash}/bin/bash"
|
--replace "/bin/bash" "${bash}/bin/bash"
|
||||||
rm -rf "$packed"
|
rm -rf "$packed"
|
||||||
|
|
|
@ -14,17 +14,17 @@ let
|
||||||
archive_fmt = if stdenv.isDarwin then "zip" else "tar.gz";
|
archive_fmt = if stdenv.isDarwin then "zip" else "tar.gz";
|
||||||
|
|
||||||
sha256 = {
|
sha256 = {
|
||||||
x86_64-linux = "0wf8bmzag49n81kjb46kj2nkksimm8f7cf4ihpqcw8k5iwasn3j9";
|
x86_64-linux = "1w28rmb9fi45s85rrlzzh6r826dnyisd6lh3j8ir4hx6d34cawsf";
|
||||||
x86_64-darwin = "1s7i5087bvckg66mcb32krv12vxhaw7ii9vm3i6p72wr0sv7dddh";
|
x86_64-darwin = "1fyg3ygqk0z3jcj5bskgprlq8k9j134y75xq06z4xbv1dhgwhswj";
|
||||||
aarch64-linux = "0yzh5javinvas3zz0lliyc77vbcs1jrmxbkr7nic4snscg6wjhcd";
|
aarch64-linux = "0hha9ksbj51zmq0p3d1fwni4jd0yp0wab0w19carmbhnydhrgh22";
|
||||||
aarch64-darwin = "13l6ymz7v18s7ikxbwvkwb0f5ff2j82j5pfj04yy75kq9b5gh0vx";
|
aarch64-darwin = "1cmrh621z7ddl4qh95hm0nwzazshl71a43c6113jf4w6b1kvy5m5";
|
||||||
armv7l-linux = "129wffj9cidk9ysjpq3p0ddn6liwkmrkxhxgz7bqzj8sdhwyq8pz";
|
armv7l-linux = "1kipvqc5hrpgsfw7x2ab5jydf7zksdd3q8qr2mg20kjsdi4skwy4";
|
||||||
}.${system};
|
}.${system};
|
||||||
in
|
in
|
||||||
callPackage ./generic.nix rec {
|
callPackage ./generic.nix rec {
|
||||||
# Please backport all compatible updates to the stable release.
|
# Please backport all compatible updates to the stable release.
|
||||||
# This is important for the extension ecosystem.
|
# This is important for the extension ecosystem.
|
||||||
version = "1.62.3";
|
version = "1.63.0";
|
||||||
pname = "vscode";
|
pname = "vscode";
|
||||||
|
|
||||||
executableName = "code" + lib.optionalString isInsiders "-insiders";
|
executableName = "code" + lib.optionalString isInsiders "-insiders";
|
||||||
|
|
|
@ -13,10 +13,10 @@ let
|
||||||
archive_fmt = if system == "x86_64-darwin" then "zip" else "tar.gz";
|
archive_fmt = if system == "x86_64-darwin" then "zip" else "tar.gz";
|
||||||
|
|
||||||
sha256 = {
|
sha256 = {
|
||||||
x86_64-linux = "0g1c88i0nkg4hys00vhqp0i2n3kjl395fd2rimi2p49y042b5c9g";
|
x86_64-linux = "17kck7pkklhifm6hpsd93wmnyk06vi9sa55gp62m3diymp1b129z";
|
||||||
x86_64-darwin = "1521aqrv9zx2r5cy8h2011iz3v5lvayizlgv8j7j8qi272mmvx5k";
|
x86_64-darwin = "1japc6yyvw07rll53pf2jfg89m2g9jqj5daghg10v1gqk98j7r3x";
|
||||||
aarch64-linux = "1kk0jrhqx6q325zmfg553pqmk6v9cx3a99bsh9rzvdlca94nmpj0";
|
aarch64-linux = "0zg05q0hyldnw5g8b9zdf0ls4s07fixib7v830wa5dyi2sjcv149";
|
||||||
armv7l-linux = "08hy61a9pp18b1x7lnsc7b9y3bvnjmavazz7qkhp5qxl2gs802wm";
|
armv7l-linux = "0mky66cyxhx3cfm35sa4vlwh8m1878rc80jml9mqxdhlrpnxgdiy";
|
||||||
}.${system};
|
}.${system};
|
||||||
|
|
||||||
sourceRoot = {
|
sourceRoot = {
|
||||||
|
@ -31,7 +31,7 @@ in
|
||||||
|
|
||||||
# Please backport all compatible updates to the stable release.
|
# Please backport all compatible updates to the stable release.
|
||||||
# This is important for the extension ecosystem.
|
# This is important for the extension ecosystem.
|
||||||
version = "1.62.3";
|
version = "1.63.0";
|
||||||
pname = "vscodium";
|
pname = "vscodium";
|
||||||
|
|
||||||
executableName = "codium";
|
executableName = "codium";
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "your-editor";
|
pname = "your-editor";
|
||||||
version = "1206";
|
version = "1303";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "kammerdienerb";
|
owner = "your-editor";
|
||||||
repo = "yed";
|
repo = "yed";
|
||||||
rev = "6cdd99fe1359899b26d8967bd376fd5caa5451eb";
|
rev = version;
|
||||||
sha256 = "0XECSolW/xPXd1v3sv9HbJMWuHGnwCOwmHoPNCUsE+w=";
|
sha256 = "BWy/icQs8hVtNeM/mCi6LOah1UG0elU/DgCmfaIPD64=";
|
||||||
};
|
};
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
|
@ -21,8 +21,9 @@ stdenv.mkDerivation rec {
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
description = "Your-editor (yed) is a small and simple terminal editor core that is meant to be extended through a powerful plugin architecture";
|
description = "Your-editor (yed) is a small and simple terminal editor core that is meant to be extended through a powerful plugin architecture";
|
||||||
homepage = "https://your-editor.org/";
|
homepage = "https://your-editor.org/";
|
||||||
|
changelog = "https://github.com/your-editor/yed/blob/${version}/CHANGELOG.md";
|
||||||
license = with licenses; [ mit ];
|
license = with licenses; [ mit ];
|
||||||
platforms = platforms.linux;
|
platforms = platforms.unix;
|
||||||
maintainers = with maintainers; [ uniquepointer ];
|
maintainers = with maintainers; [ uniquepointer ];
|
||||||
mainProgram = "yed";
|
mainProgram = "yed";
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "dcw-gmt";
|
pname = "dcw-gmt";
|
||||||
version = "1.1.4";
|
version = "2.0.1";
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "ftp://ftp.soest.hawaii.edu/gmt/dcw-gmt-${version}.tar.gz";
|
url = "ftp://ftp.soest.hawaii.edu/gmt/dcw-gmt-${version}.tar.gz";
|
||||||
sha256 = "8d47402abcd7f54a0f711365cd022e4eaea7da324edac83611ca035ea443aad3";
|
sha256 = "sha256-XJCylo9Alc9epEo1TcnY+d0bj+VRTgM4/4W0jgNUeiU=";
|
||||||
};
|
};
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{ lib, stdenv, mkDerivation, fetchFromGitLab, qmake, qtbase, qttools, qtserialport, libGLU }:
|
{ lib, stdenv, mkDerivation, fetchFromGitLab, qmake, qtbase, qttools, qtserialport, libGLU }:
|
||||||
mkDerivation rec {
|
mkDerivation rec {
|
||||||
pname = "OSCAR";
|
pname = "OSCAR";
|
||||||
version = "1.2.0";
|
version = "1.3.0";
|
||||||
|
|
||||||
src = fetchFromGitLab {
|
src = fetchFromGitLab {
|
||||||
owner = "pholy";
|
owner = "pholy";
|
||||||
repo = "OSCAR-code";
|
repo = "OSCAR-code";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "10r37d8c2avr167n2s9lhld1c9hmckm444fq163z1jsy9jpid6mg";
|
sha256 = "sha256-oKKwX5HiT8RACiqzZegOxH6IHQn/u0N4ih/ubH6YYjg=";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ qtbase qttools qtserialport libGLU ];
|
buildInputs = [ qtbase qttools qtserialport libGLU ];
|
||||||
|
|
|
@ -27,14 +27,14 @@
|
||||||
|
|
||||||
mkDerivation rec {
|
mkDerivation rec {
|
||||||
pname = "calibre";
|
pname = "calibre";
|
||||||
version = "5.31.1";
|
version = "5.33.2";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://download.calibre-ebook.com/${version}/${pname}-${version}.tar.xz";
|
url = "https://download.calibre-ebook.com/${version}/${pname}-${version}.tar.xz";
|
||||||
sha256 = "sha256-3LGEWuHms54ji9GWSyLl8cFWIRBqHY1Jf/CNPJOywrU=";
|
sha256 = "sha256-wtt3ucCaFq9wLk79CeCz20tMM6AbLtZ4Ln6TxOx0dvI=";
|
||||||
};
|
};
|
||||||
|
|
||||||
# https://sources.debian.org/patches/calibre/5.31.1+dfsg-1
|
# https://sources.debian.org/patches/calibre/5.33.2+dfsg-1
|
||||||
patches = [
|
patches = [
|
||||||
# allow for plugin update check, but no calibre version check
|
# allow for plugin update check, but no calibre version check
|
||||||
(fetchpatch {
|
(fetchpatch {
|
||||||
|
|
|
@ -34,8 +34,8 @@ let
|
||||||
qonlinetranslator = fetchFromGitHub {
|
qonlinetranslator = fetchFromGitHub {
|
||||||
owner = "crow-translate";
|
owner = "crow-translate";
|
||||||
repo = "QOnlineTranslator";
|
repo = "QOnlineTranslator";
|
||||||
rev = "df89083d2f680a8f856b1df00b8846f995cf1fae";
|
rev = "1.5.2";
|
||||||
sha256 = "sha256-I64KGInnYd/QdI5kANJERsF95wMvRlr8kgQhUqXXN/0=";
|
sha256 = "sha256-iGi25aKwff2hNNx6o4kHZV8gVbEQcMgpTTvop3CoLjM=";
|
||||||
};
|
};
|
||||||
circleflags = fetchFromGitHub {
|
circleflags = fetchFromGitHub {
|
||||||
owner = "HatScripts";
|
owner = "HatScripts";
|
||||||
|
@ -52,13 +52,13 @@ let
|
||||||
in
|
in
|
||||||
mkDerivation rec {
|
mkDerivation rec {
|
||||||
pname = "crow-translate";
|
pname = "crow-translate";
|
||||||
version = "2.8.7";
|
version = "2.9.1";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "crow-translate";
|
owner = "crow-translate";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "sha256-0bq9itbFyzdOhdNuUtdCYLTCIhc91MM+YRhJgXC5PPw=";
|
sha256 = "sha256-7Zb6PZO8eLeGPEZD37ja+LZydIQdsgy5gMAMtlS4k5Y=";
|
||||||
};
|
};
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user