Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
600aff6dec | ||
|
|
de67cf2666 | ||
|
|
013df0ae74 | ||
|
|
875bf80541 | ||
|
|
3401d234f8 | ||
|
|
a53f28aa80 | ||
|
|
f58b74cb5b | ||
|
|
3ba1c8dab8 | ||
|
|
395661e833 | ||
|
|
b92ac2da34 | ||
|
|
255704a98c | ||
|
|
a6dcd6bae0 |
@@ -16,8 +16,6 @@ Checks:
|
|||||||
- -bugprone-unchecked-optional-access
|
- -bugprone-unchecked-optional-access
|
||||||
# many warnings, seems like a questionable lint
|
# many warnings, seems like a questionable lint
|
||||||
- -bugprone-branch-clone
|
- -bugprone-branch-clone
|
||||||
# extremely noisy before clang 19: https://github.com/llvm/llvm-project/issues/93959
|
|
||||||
- -bugprone-multi-level-implicit-pointer-conversion
|
|
||||||
# all thrown exceptions must derive from std::exception
|
# all thrown exceptions must derive from std::exception
|
||||||
- hicpp-exception-baseclass
|
- hicpp-exception-baseclass
|
||||||
# capturing async lambdas are dangerous
|
# capturing async lambdas are dangerous
|
||||||
@@ -35,4 +33,3 @@ Checks:
|
|||||||
|
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
bugprone-reserved-identifier.AllowedIdentifiers: '__asan_default_options'
|
bugprone-reserved-identifier.AllowedIdentifiers: '__asan_default_options'
|
||||||
bugprone-unused-return-value.AllowCastToVoid: true
|
|
||||||
|
|||||||
@@ -1,59 +1,4 @@
|
|||||||
# Lix 2.91 "Dragon's Breath" (2024-08-12)
|
# Lix 2.91 "Dragon's Breath" (2024-08-12)
|
||||||
# Lix 2.91.3 (2025-06-30)
|
|
||||||
|
|
||||||
## Fixes
|
|
||||||
- Revert CVE-2025-52992 failed mitigation [fj#883](https://git.lix.systems/lix-project/lix/issues/883) [fj#887](https://git.lix.systems/lix-project/lix/issues/887) [cl/3420](https://gerrit.lix.systems/c/lix/+/3420) [cl/3524](https://gerrit.lix.systems/c/lix/+/3524) [cl/3523](https://gerrit.lix.systems/c/lix/+/3523) [cl/3522](https://gerrit.lix.systems/c/lix/+/3522)
|
|
||||||
|
|
||||||
Following the initial mitigation of **CVE-2025-52992** in `cl/3420`, we
|
|
||||||
received reports of **unexpected deletion of in-use store paths**.
|
|
||||||
|
|
||||||
Upon investigation, we found that the patch did **not correctly cancel all
|
|
||||||
automatic deleters**, resulting in potentially critical path loss during normal
|
|
||||||
operation.
|
|
||||||
|
|
||||||
Given the severity and time-sensitive nature of the situation ([see incident
|
|
||||||
report](https://lix.systems/blog/2025-06-27-lix-critical-bug/)), we evaluated
|
|
||||||
possible options to repair the behavior safely. However, we concluded that a
|
|
||||||
rushed fix would either:
|
|
||||||
|
|
||||||
* **Overdelete**, i.e. breaking running systems, or,
|
|
||||||
* **Underdelete**, effectively **reopening CVE-2025-52992** while leaving
|
|
||||||
orphaned paths behind.
|
|
||||||
|
|
||||||
As **CVE-2025-52992 has no known exploit vector**, and correctness is critical
|
|
||||||
in the Lix project, we have **fully reverted the previous mitigations**.
|
|
||||||
|
|
||||||
Moving forward, the Lix team will rework this code path in a **long-term,
|
|
||||||
correctness-first fix** on the main branch. We will explore backporting it to
|
|
||||||
stable channels once its safety is assured.
|
|
||||||
|
|
||||||
We are deeply sorry for the stability incident and the Lix team remain
|
|
||||||
available for assisting you in recovering your systems.
|
|
||||||
|
|
||||||
Many thanks to [Raito Bezarius](https://git.lix.systems/raito) and [eldritch horrors](https://git.lix.systems/pennae) for this.
|
|
||||||
- Fallback to safe temp dir when build-dir is unwritable [fj#876](https://git.lix.systems/lix-project/lix/issues/876) [cl/3502](https://gerrit.lix.systems/c/lix/+/3502)
|
|
||||||
|
|
||||||
Non-daemon builds started failing with a permission error after introducing the `build-dir` option:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ nix build --store ~/scratch nixpkgs#hello --rebuild
|
|
||||||
error: creating directory '/nix/var/nix/builds/nix-build-hello-2.12.2.drv-0': Permission denied
|
|
||||||
```
|
|
||||||
|
|
||||||
This happens because:
|
|
||||||
|
|
||||||
1. These builds are not run via the daemon, which owns `/nix/var/nix/builds`.
|
|
||||||
2. The user lacks permissions for that path.
|
|
||||||
|
|
||||||
We considered making `build-dir` a store-level option and defaulting it to `<chroot-root>/nix/var/nix/builds` for chroot stores, but opted instead for a fallback: if the default fails, Nix now creates a safe build directory under `/tmp`.
|
|
||||||
|
|
||||||
To avoid CVE-2025-52991, the fallback uses an extra path component between `/tmp` and the build dir.
|
|
||||||
|
|
||||||
**Note**: this fallback clutters `/tmp` with build directories that are not cleaned up. To prevent this, explicitly set `build-dir` to a path managed by Lix, even for local workloads.
|
|
||||||
|
|
||||||
Many thanks to [Raito Bezarius](https://git.lix.systems/raito) and [eldritch horrors](https://git.lix.systems/pennae) for this.
|
|
||||||
|
|
||||||
|
|
||||||
# Lix 2.91.2 (2025-06-23)
|
# Lix 2.91.2 (2025-06-23)
|
||||||
|
|
||||||
## Breaking Changes
|
## Breaking Changes
|
||||||
|
|||||||
+39
-38
@@ -62,37 +62,38 @@ let
|
|||||||
++ autoLayered
|
++ autoLayered
|
||||||
++ extraPkgs;
|
++ extraPkgs;
|
||||||
|
|
||||||
users = {
|
users =
|
||||||
|
{
|
||||||
|
|
||||||
root = {
|
root = {
|
||||||
uid = 0;
|
uid = 0;
|
||||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||||
home = "/root";
|
home = "/root";
|
||||||
gid = 0;
|
gid = 0;
|
||||||
groups = [ "root" ];
|
groups = [ "root" ];
|
||||||
description = "System administrator";
|
description = "System administrator";
|
||||||
};
|
|
||||||
|
|
||||||
nobody = {
|
|
||||||
uid = 65534;
|
|
||||||
shell = "${pkgs.shadow}/bin/nologin";
|
|
||||||
home = "/var/empty";
|
|
||||||
gid = 65534;
|
|
||||||
groups = [ "nobody" ];
|
|
||||||
description = "Unprivileged account (don't use!)";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// lib.listToAttrs (
|
|
||||||
map (n: {
|
|
||||||
name = "nixbld${toString n}";
|
|
||||||
value = {
|
|
||||||
uid = 30000 + n;
|
|
||||||
gid = 30000;
|
|
||||||
groups = [ "nixbld" ];
|
|
||||||
description = "Nix build user ${toString n}";
|
|
||||||
};
|
};
|
||||||
}) (lib.lists.range 1 32)
|
|
||||||
);
|
nobody = {
|
||||||
|
uid = 65534;
|
||||||
|
shell = "${pkgs.shadow}/bin/nologin";
|
||||||
|
home = "/var/empty";
|
||||||
|
gid = 65534;
|
||||||
|
groups = [ "nobody" ];
|
||||||
|
description = "Unprivileged account (don't use!)";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// lib.listToAttrs (
|
||||||
|
map (n: {
|
||||||
|
name = "nixbld${toString n}";
|
||||||
|
value = {
|
||||||
|
uid = 30000 + n;
|
||||||
|
gid = 30000;
|
||||||
|
groups = [ "nixbld" ];
|
||||||
|
description = "Nix build user ${toString n}";
|
||||||
|
};
|
||||||
|
}) (lib.lists.range 1 32)
|
||||||
|
);
|
||||||
|
|
||||||
groups = {
|
groups = {
|
||||||
root.gid = 0;
|
root.gid = 0;
|
||||||
@@ -192,11 +193,13 @@ let
|
|||||||
in
|
in
|
||||||
''
|
''
|
||||||
{
|
{
|
||||||
${lib.concatStringsSep "\n" (
|
${
|
||||||
builtins.map (output: ''
|
lib.concatStringsSep "\n" (
|
||||||
${output} = { outPath = "${lib.getOutput output drv}"; };
|
builtins.map (output: ''
|
||||||
'') outputs
|
${output} = { outPath = "${lib.getOutput output drv}"; };
|
||||||
)}
|
'') outputs
|
||||||
|
)
|
||||||
|
}
|
||||||
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
|
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
|
||||||
name = "${drv.name}";
|
name = "${drv.name}";
|
||||||
outPath = "${drv}";
|
outPath = "${drv}";
|
||||||
@@ -358,10 +361,8 @@ let
|
|||||||
"org.opencontainers.image.source" = "https://git.lix.systems/lix-project/lix";
|
"org.opencontainers.image.source" = "https://git.lix.systems/lix-project/lix";
|
||||||
"org.opencontainers.image.vendor" = "Lix project";
|
"org.opencontainers.image.vendor" = "Lix project";
|
||||||
"org.opencontainers.image.version" = pkgs.nix.version;
|
"org.opencontainers.image.version" = pkgs.nix.version;
|
||||||
"org.opencontainers.image.description" =
|
"org.opencontainers.image.description" = "Minimal Lix container image, with some batteries included.";
|
||||||
"Minimal Lix container image, with some batteries included.";
|
} // lib.optionalAttrs (lixRevision != null) { "org.opencontainers.image.revision" = lixRevision; };
|
||||||
}
|
|
||||||
// lib.optionalAttrs (lixRevision != null) { "org.opencontainers.image.revision" = lixRevision; };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
|
|||||||
Generated
+8
-67
@@ -16,22 +16,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lowdown-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1633514407,
|
|
||||||
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
|
|
||||||
"owner": "kristapsdz",
|
|
||||||
"repo": "lowdown",
|
|
||||||
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "kristapsdz",
|
|
||||||
"repo": "lowdown",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix2container": {
|
"nix2container": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@@ -48,44 +32,18 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nix_2_18": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [
|
|
||||||
"flake-compat"
|
|
||||||
],
|
|
||||||
"lowdown-src": "lowdown-src",
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"nixpkgs-regression": [
|
|
||||||
"nixpkgs-regression"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1730375271,
|
|
||||||
"narHash": "sha256-RrOFlDGmRXcVRV2p2HqHGqvzGNyWoD0Dado/BNlJ1SI=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nix",
|
|
||||||
"rev": "0f665ff6779454f2117dcc32e44380cda7f45523",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "2.18.9",
|
|
||||||
"repo": "nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1705033721,
|
"lastModified": 1735651292,
|
||||||
"narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=",
|
"narHash": "sha256-YLbzcBtYo1/FEzFsB3AnM16qFc6fWPMIoOuSoDwvg9g=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea",
|
"rev": "0da3c44a9460a26d2025ec3ed2ec60a895eb1114",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-23.05-small",
|
"ref": "nixos-24.05-small",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -106,30 +64,14 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1757198069,
|
|
||||||
"narHash": "sha256-m3VUcOD4rTs8J7S+3dOjWMrAjw6RcITC3XYQ98zhEFs=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "0747026fc57ecb9c28901c7f7a2b5dc40e8af43c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-25.05-small",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pre-commit-hooks": {
|
"pre-commit-hooks": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1733318908,
|
"lastModified": 1721042469,
|
||||||
"narHash": "sha256-SVQVsbafSM1dJ4fpgyBqLZ+Lft+jcQuMtEL3lQWx2Sk=",
|
"narHash": "sha256-6FPUl7HVtvRHCCBQne7Ylp4p+dpP3P/OYuzjztZ4s70=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "git-hooks.nix",
|
"repo": "git-hooks.nix",
|
||||||
"rev": "6f4e2a2112050951a314d2733a994fbab94864c6",
|
"rev": "f451c19376071a90d8c58ab1a953c6e9840527fd",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -142,8 +84,7 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
"nix2container": "nix2container",
|
"nix2container": "nix2container",
|
||||||
"nix_2_18": "nix_2_18",
|
"nixpkgs": "nixpkgs",
|
||||||
"nixpkgs": "nixpkgs_2",
|
|
||||||
"nixpkgs-regression": "nixpkgs-regression",
|
"nixpkgs-regression": "nixpkgs-regression",
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
"pre-commit-hooks": "pre-commit-hooks"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,8 @@
|
|||||||
description = "Lix: A modern, delicious implementation of the Nix package manager";
|
description = "Lix: A modern, delicious implementation of the Nix package manager";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05-small";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05-small";
|
||||||
nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
||||||
|
|
||||||
# Required because Nix 2.18 is not in Nixpkgs ≥ 25.05 anymore.
|
|
||||||
nix_2_18 = {
|
|
||||||
url = "github:NixOS/nix/2.18.9";
|
|
||||||
# NOTE(Raito): this is not possible because patches on libseccomp does not apply anymore on this Nix.
|
|
||||||
# Let's keep the latest known nixpkgs useable with Nix 2.18 for our tests.
|
|
||||||
# inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.nixpkgs-regression.follows = "nixpkgs-regression";
|
|
||||||
inputs.flake-compat.follows = "flake-compat";
|
|
||||||
};
|
|
||||||
|
|
||||||
pre-commit-hooks = {
|
pre-commit-hooks = {
|
||||||
url = "github:cachix/git-hooks.nix";
|
url = "github:cachix/git-hooks.nix";
|
||||||
flake = false;
|
flake = false;
|
||||||
@@ -36,7 +25,6 @@
|
|||||||
nixpkgs-regression,
|
nixpkgs-regression,
|
||||||
pre-commit-hooks,
|
pre-commit-hooks,
|
||||||
nix2container,
|
nix2container,
|
||||||
nix_2_18,
|
|
||||||
flake-compat,
|
flake-compat,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
@@ -173,16 +161,6 @@
|
|||||||
{
|
{
|
||||||
nixStable = prev.nix;
|
nixStable = prev.nix;
|
||||||
|
|
||||||
nixVersions = prev.nixVersions // {
|
|
||||||
nix_2_3 = prev.nixVersions.nix_2_3.overrideAttrs (old: {
|
|
||||||
meta = old.meta // {
|
|
||||||
knownVulnerabilities = [ ];
|
|
||||||
};
|
|
||||||
});
|
|
||||||
# Nix 2.18 has been removed from Nixpkgs ≥ 25.05, so we need to reintroduce it ourselves for our tests.
|
|
||||||
nix_2_18 = nix_2_18.outputs.packages.${currentStdenv.hostPlatform.system}.default;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Forward from the previous stage as we don’t want it to pick the lowdown override
|
# Forward from the previous stage as we don’t want it to pick the lowdown override
|
||||||
nixUnstable = prev.nixUnstable;
|
nixUnstable = prev.nixUnstable;
|
||||||
|
|
||||||
@@ -368,16 +346,13 @@
|
|||||||
in
|
in
|
||||||
pkgs.symlinkJoin {
|
pkgs.symlinkJoin {
|
||||||
name = "nixpkgs-lib-tests";
|
name = "nixpkgs-lib-tests";
|
||||||
paths = [
|
paths =
|
||||||
testWithNix
|
[ testWithNix ]
|
||||||
]
|
# FIXME: This is disabled on darwin due to a nixpkgs bug https://github.com/NixOS/nixpkgs/issues/319147
|
||||||
# NOTE: nixpkgs 25.05 is being ... *creative*, and requires this dance to override
|
# After that is fixed, it should be restored to use lib/tests/release.nix as before, rather than this reimplementation.
|
||||||
# the evaluator used for the test. it will break again in the future, don't worry.
|
++ lib.optionals pkgs.stdenv.isLinux [
|
||||||
++ lib.optionals pkgs.stdenv.isLinux [
|
(import (nixpkgs + "/pkgs/test/release") { inherit pkgs lib nix; })
|
||||||
((pkgs.callPackage "${nixpkgs}/ci/eval" { inherit nix; }).attrpathsSuperset {
|
];
|
||||||
evalSystem = system;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -301,11 +301,6 @@ editline = dependency('libeditline', 'editline', version : '>=1.14', required :
|
|||||||
|
|
||||||
lowdown = dependency('lowdown', version : '>=0.9.0', required : true, include_type : 'system')
|
lowdown = dependency('lowdown', version : '>=0.9.0', required : true, include_type : 'system')
|
||||||
|
|
||||||
# TODO(sterni): drop the corresponding #ifdef after NixOS 25.05 is EOL which still distributes lowdown < 1.4.0
|
|
||||||
if lowdown.version().version_compare('>= 1.4.0')
|
|
||||||
add_project_arguments('-DLOWDOWN_SEPARATE_TERM_OPTS', language: 'cpp')
|
|
||||||
endif
|
|
||||||
|
|
||||||
# HACK(Qyriad): rapidcheck's pkg-config doesn't include the libs lol
|
# HACK(Qyriad): rapidcheck's pkg-config doesn't include the libs lol
|
||||||
# Note: technically we 'check' for rapidcheck twice, for the internal-api-docs handling above,
|
# Note: technically we 'check' for rapidcheck twice, for the internal-api-docs handling above,
|
||||||
# but Meson will cache the result of the first one, and the required : arguments are different.
|
# but Meson will cache the result of the first one, and the required : arguments are different.
|
||||||
@@ -480,7 +475,6 @@ add_project_arguments(
|
|||||||
# It would be nice for our headers to be idempotent instead.
|
# It would be nice for our headers to be idempotent instead.
|
||||||
'-include', 'config.h',
|
'-include', 'config.h',
|
||||||
'-Wno-deprecated-declarations',
|
'-Wno-deprecated-declarations',
|
||||||
'-Wno-missing-field-initializers',
|
|
||||||
'-Wimplicit-fallthrough',
|
'-Wimplicit-fallthrough',
|
||||||
'-Werror=switch',
|
'-Werror=switch',
|
||||||
'-Werror=switch-enum',
|
'-Werror=switch-enum',
|
||||||
|
|||||||
+67
-65
@@ -179,13 +179,12 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
|
|
||||||
VERSION_SUFFIX = versionSuffix;
|
VERSION_SUFFIX = versionSuffix;
|
||||||
|
|
||||||
outputs = [
|
outputs =
|
||||||
"out"
|
[ "out" ]
|
||||||
]
|
++ lib.optionals (!finalAttrs.dontBuild) [
|
||||||
++ lib.optionals (!finalAttrs.dontBuild) [
|
"dev"
|
||||||
"dev"
|
"doc"
|
||||||
"doc"
|
];
|
||||||
];
|
|
||||||
|
|
||||||
dontBuild = lintInsteadOfBuild;
|
dontBuild = lintInsteadOfBuild;
|
||||||
|
|
||||||
@@ -221,65 +220,67 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
# We only include CMake so that Meson can locate toml11, which only ships CMake dependency metadata.
|
# We only include CMake so that Meson can locate toml11, which only ships CMake dependency metadata.
|
||||||
dontUseCmakeConfigure = true;
|
dontUseCmakeConfigure = true;
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs =
|
||||||
python3
|
[
|
||||||
meson
|
python3
|
||||||
ninja
|
meson
|
||||||
cmake
|
ninja
|
||||||
]
|
cmake
|
||||||
++ [
|
]
|
||||||
(lib.getBin lowdown-unsandboxed)
|
++ [
|
||||||
mdbook
|
(lib.getBin lowdown-unsandboxed)
|
||||||
mdbook-linkcheck
|
mdbook
|
||||||
]
|
mdbook-linkcheck
|
||||||
++ [
|
]
|
||||||
pkg-config
|
++ [
|
||||||
|
pkg-config
|
||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
git
|
git
|
||||||
mercurial
|
mercurial
|
||||||
jq
|
jq
|
||||||
lsof
|
lsof
|
||||||
]
|
]
|
||||||
++ lib.optional hostPlatform.isLinux util-linuxMinimal
|
++ lib.optional hostPlatform.isLinux util-linuxMinimal
|
||||||
++ lib.optional (!officialRelease && buildUnreleasedNotes) build-release-notes
|
++ lib.optional (!officialRelease && buildUnreleasedNotes) build-release-notes
|
||||||
++ lib.optional internalApiDocs doxygen
|
++ lib.optional internalApiDocs doxygen
|
||||||
++ lib.optionals lintInsteadOfBuild [
|
++ lib.optionals lintInsteadOfBuild [
|
||||||
# required for a wrapped clang-tidy
|
# required for a wrapped clang-tidy
|
||||||
llvmPackages.clang-tools
|
llvmPackages.clang-tools
|
||||||
# required for run-clang-tidy
|
# required for run-clang-tidy
|
||||||
llvmPackages.clang-unwrapped
|
llvmPackages.clang-unwrapped
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs =
|
||||||
curl
|
[
|
||||||
bzip2
|
curl
|
||||||
xz
|
bzip2
|
||||||
brotli
|
xz
|
||||||
editline-lix
|
brotli
|
||||||
openssl
|
editline-lix
|
||||||
sqlite
|
openssl
|
||||||
libarchive
|
sqlite
|
||||||
boost
|
libarchive
|
||||||
lowdown
|
boost
|
||||||
libsodium
|
lowdown
|
||||||
toml11
|
libsodium
|
||||||
lix-doc
|
toml11
|
||||||
pegtl
|
lix-doc
|
||||||
]
|
pegtl
|
||||||
++ lib.optionals hostPlatform.isLinux [
|
]
|
||||||
libseccomp
|
++ lib.optionals hostPlatform.isLinux [
|
||||||
busybox-sandbox-shell
|
libseccomp
|
||||||
passt-lix
|
busybox-sandbox-shell
|
||||||
]
|
passt-lix
|
||||||
++ lib.optional internalApiDocs rapidcheck
|
]
|
||||||
++ lib.optional hostPlatform.isx86_64 libcpuid
|
++ lib.optional internalApiDocs rapidcheck
|
||||||
# There have been issues building these dependencies
|
++ lib.optional hostPlatform.isx86_64 libcpuid
|
||||||
++ lib.optional (hostPlatform.canExecute buildPlatform) aws-sdk-cpp-nix
|
# There have been issues building these dependencies
|
||||||
++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs
|
++ lib.optional (hostPlatform.canExecute buildPlatform) aws-sdk-cpp-nix
|
||||||
# I am so sorry. This is because checkInputs are required to pass
|
++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs
|
||||||
# configure, but we don't actually want to *run* the checks here.
|
# I am so sorry. This is because checkInputs are required to pass
|
||||||
++ lib.optionals lintInsteadOfBuild finalAttrs.checkInputs;
|
# configure, but we don't actually want to *run* the checks here.
|
||||||
|
++ lib.optionals lintInsteadOfBuild finalAttrs.checkInputs;
|
||||||
|
|
||||||
checkInputs = [
|
checkInputs = [
|
||||||
gtest
|
gtest
|
||||||
@@ -426,6 +427,7 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
just,
|
just,
|
||||||
nixfmt-rfc-style,
|
nixfmt-rfc-style,
|
||||||
skopeo,
|
skopeo,
|
||||||
|
xonsh,
|
||||||
|
|
||||||
# Lix specific packages
|
# Lix specific packages
|
||||||
pre-commit-checks,
|
pre-commit-checks,
|
||||||
@@ -445,7 +447,7 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
p.requests
|
p.requests
|
||||||
p.xdg-base-dirs
|
p.xdg-base-dirs
|
||||||
p.packaging
|
p.packaging
|
||||||
p.xonsh
|
(p.toPythonModule xonsh.passthru.unwrapped)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
pythonEnv = python3.withPackages pythonPackages;
|
pythonEnv = python3.withPackages pythonPackages;
|
||||||
|
|||||||
+13
-12
@@ -35,18 +35,19 @@ perl.pkgs.toPerlModule (
|
|||||||
ninja
|
ninja
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs =
|
||||||
nix
|
[
|
||||||
curl
|
nix
|
||||||
bzip2
|
curl
|
||||||
xz
|
bzip2
|
||||||
perl
|
xz
|
||||||
boost
|
perl
|
||||||
perlPackages.DBI
|
boost
|
||||||
perlPackages.DBDSQLite
|
perlPackages.DBI
|
||||||
]
|
perlPackages.DBDSQLite
|
||||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
]
|
||||||
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||||
|
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
||||||
|
|
||||||
# Nixpkgs' Meson hook likes to set this to "plain".
|
# Nixpkgs' Meson hook likes to set this to "plain".
|
||||||
mesonBuildType = "debugoptimized";
|
mesonBuildType = "debugoptimized";
|
||||||
|
|||||||
+4
-1
@@ -19,7 +19,10 @@ endif
|
|||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
perl = find_program('perl')
|
# Really version 5.8.0, but Perl's version string is of the form
|
||||||
|
# "This is perl 5, version 38, subversion 2", for 5.38.2, so as far
|
||||||
|
# as Meson is concerned, the version of Perl we need is 8 or greater.
|
||||||
|
perl = find_program('perl', version : '>=8')
|
||||||
|
|
||||||
# "compiler to convert Perl XS code into C code"
|
# "compiler to convert Perl XS code into C code"
|
||||||
xsubpp = find_program('xsubpp')
|
xsubpp = find_program('xsubpp')
|
||||||
|
|||||||
+2
-17
@@ -11,28 +11,13 @@ namespace nix {
|
|||||||
std::string renderMarkdownToTerminal(std::string_view markdown)
|
std::string renderMarkdownToTerminal(std::string_view markdown)
|
||||||
{
|
{
|
||||||
int windowWidth = getWindowSize().second;
|
int windowWidth = getWindowSize().second;
|
||||||
size_t lowdown_cols = std::max(windowWidth - 5, 60);
|
|
||||||
|
|
||||||
struct lowdown_opts opts{
|
struct lowdown_opts opts {
|
||||||
.type = LOWDOWN_TERM,
|
.type = LOWDOWN_TERM,
|
||||||
#ifdef LOWDOWN_SEPARATE_TERM_OPTS
|
|
||||||
.term =
|
|
||||||
{
|
|
||||||
.cols = lowdown_cols,
|
|
||||||
.width = 0,
|
|
||||||
.hmargin = 0,
|
|
||||||
.hpadding = 4,
|
|
||||||
.vmargin = 0,
|
|
||||||
.centre = 0,
|
|
||||||
},
|
|
||||||
// maxdepth needs to be part of the ifdefs to match declaration order
|
|
||||||
.maxdepth = 20,
|
.maxdepth = 20,
|
||||||
#else
|
.cols = (size_t) std::max(windowWidth - 5, 60),
|
||||||
.maxdepth = 20,
|
|
||||||
.cols = lowdown_cols,
|
|
||||||
.hmargin = 0,
|
.hmargin = 0,
|
||||||
.vmargin = 0,
|
.vmargin = 0,
|
||||||
#endif /* LOWDOWN_SEPARATE_TERM_OPTS */
|
|
||||||
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
||||||
.oflags = LOWDOWN_TERM_NOLINK,
|
.oflags = LOWDOWN_TERM_NOLINK,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
|
|||||||
try {
|
try {
|
||||||
auto colon = fn.rfind(':');
|
auto colon = fn.rfind(':');
|
||||||
if (colon == std::string::npos) fail();
|
if (colon == std::string::npos) fail();
|
||||||
|
std::string filename(fn, 0, colon);
|
||||||
auto lineno = std::stoi(std::string(fn, colon + 1, std::string::npos));
|
auto lineno = std::stoi(std::string(fn, colon + 1, std::string::npos));
|
||||||
return {CanonPath(fn.substr(0, colon)), lineno};
|
return {CanonPath(fn.substr(0, colon)), lineno};
|
||||||
} catch (std::invalid_argument & e) {
|
} catch (std::invalid_argument & e) {
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ struct ExprAttrs : Expr
|
|||||||
AttrDef() { };
|
AttrDef() { };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T chooseByKind(const T & plain, const T & inherited, const T & inheritedFrom) const
|
const T & chooseByKind(const T & plain, const T & inherited, const T & inheritedFrom) const
|
||||||
{
|
{
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Kind::Plain:
|
case Kind::Plain:
|
||||||
|
|||||||
@@ -624,13 +624,10 @@ struct nothing : p::nothing<Rule> {
|
|||||||
static_assert(!std::is_base_of_v<semantic, Rule>);
|
static_assert(!std::is_base_of_v<semantic, Rule>);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Self, typename OpCtx, typename AttrPathT, typename ExprT>
|
template<typename Self, typename OpCtx, typename AttrPathT, typename ExprT>
|
||||||
struct operator_semantics
|
struct operator_semantics {
|
||||||
{
|
|
||||||
private:
|
|
||||||
operator_semantics() = default;
|
|
||||||
friend Self;
|
|
||||||
public:
|
|
||||||
struct has_attr : grammar::op::has_attr {
|
struct has_attr : grammar::op::has_attr {
|
||||||
AttrPathT path;
|
AttrPathT path;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -250,7 +250,9 @@ std::optional<Hash> Input::getNarHash() const
|
|||||||
|
|
||||||
std::optional<std::string> Input::getRef() const
|
std::optional<std::string> Input::getRef() const
|
||||||
{
|
{
|
||||||
return maybeGetStrAttr(attrs, "ref");
|
if (auto s = maybeGetStrAttr(attrs, "ref"))
|
||||||
|
return *s;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Hash> Input::getRev() const
|
std::optional<Hash> Input::getRev() const
|
||||||
@@ -271,12 +273,16 @@ std::optional<Hash> Input::getRev() const
|
|||||||
|
|
||||||
std::optional<uint64_t> Input::getRevCount() const
|
std::optional<uint64_t> Input::getRevCount() const
|
||||||
{
|
{
|
||||||
return maybeGetIntAttr(attrs, "revCount");
|
if (auto n = maybeGetIntAttr(attrs, "revCount"))
|
||||||
|
return *n;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<time_t> Input::getLastModified() const
|
std::optional<time_t> Input::getLastModified() const
|
||||||
{
|
{
|
||||||
return maybeGetIntAttr(attrs, "lastModified");
|
if (auto n = maybeGetIntAttr(attrs, "lastModified"))
|
||||||
|
return *n;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsedURL InputScheme::toURL(const Input & input) const
|
ParsedURL InputScheme::toURL(const Input & input) const
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ std::optional<std::string> readHeadCached(const std::string & actualUrl)
|
|||||||
// This function must behave the same way, so we return the expired
|
// This function must behave the same way, so we return the expired
|
||||||
// cached ref here.
|
// cached ref here.
|
||||||
warn("could not get HEAD ref for repository '%s'; using expired cached ref '%s'", actualUrl, *cachedRef);
|
warn("could not get HEAD ref for repository '%s'; using expired cached ref '%s'", actualUrl, *cachedRef);
|
||||||
return cachedRef;
|
return *cachedRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|||||||
@@ -1212,7 +1212,7 @@ HookReply DerivationGoal::tryBuildHook()
|
|||||||
hook->toHook.writeSide.reset();
|
hook->toHook.writeSide.reset();
|
||||||
|
|
||||||
/* Create the log file and pipe. */
|
/* Create the log file and pipe. */
|
||||||
openLogFile();
|
Path logFile = openLogFile();
|
||||||
|
|
||||||
std::set<int> fds;
|
std::set<int> fds;
|
||||||
fds.insert(hook->fromHook.readSide.get());
|
fds.insert(hook->fromHook.readSide.get());
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ bool LocalDerivationGoal::cleanupDecideWhetherDiskFull()
|
|||||||
if (statvfs(localStore.realStoreDir.get().c_str(), &st) == 0 &&
|
if (statvfs(localStore.realStoreDir.get().c_str(), &st) == 0 &&
|
||||||
(uint64_t) st.f_bavail * st.f_bsize < required)
|
(uint64_t) st.f_bavail * st.f_bsize < required)
|
||||||
diskFull = true;
|
diskFull = true;
|
||||||
if (statvfs(tmpDirRoot.c_str(), &st) == 0 &&
|
if (statvfs(tmpDir.c_str(), &st) == 0 &&
|
||||||
(uint64_t) st.f_bavail * st.f_bsize < required)
|
(uint64_t) st.f_bavail * st.f_bsize < required)
|
||||||
diskFull = true;
|
diskFull = true;
|
||||||
}
|
}
|
||||||
@@ -363,9 +363,13 @@ void LocalDerivationGoal::cleanupPostOutputsRegisteredModeCheck()
|
|||||||
|
|
||||||
void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
|
void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
|
||||||
{
|
{
|
||||||
/* Delete unused redirected outputs (when doing hash rewriting). */
|
/* In the past, redirected outputs were manually tracked for deletion.
|
||||||
for (auto & i : redirectedOutputs)
|
* Now that we have the scratch outputs cleaner which are a superset of
|
||||||
deletePath(worker.store.Store::toRealPath(i.second));
|
* redirected outputs, we just fire all uncancelled automatic deleters now.
|
||||||
|
*
|
||||||
|
* This should clean up any paths that IS NOT registered in the database.
|
||||||
|
*/
|
||||||
|
scratchOutputsCleaner.clear();
|
||||||
|
|
||||||
/* Delete the chroot (if we were using one). */
|
/* Delete the chroot (if we were using one). */
|
||||||
autoDelChroot.reset(); /* this runs the destructor */
|
autoDelChroot.reset(); /* this runs the destructor */
|
||||||
@@ -475,88 +479,25 @@ void LocalDerivationGoal::startBuilder()
|
|||||||
settings.thisSystem,
|
settings.thisSystem,
|
||||||
concatStringsSep<StringSet>(", ", worker.store.systemFeatures));
|
concatStringsSep<StringSet>(", ", worker.store.systemFeatures));
|
||||||
|
|
||||||
try {
|
createDirs(settings.buildDir.get());
|
||||||
auto buildDir = worker.buildDirOverride.value_or(settings.buildDir.get());
|
|
||||||
|
|
||||||
createDirs(buildDir);
|
/* Create a temporary directory where the build will take
|
||||||
|
place. */
|
||||||
/* Create a temporary directory where the build will take
|
tmpDir = createTempDir(
|
||||||
place. */
|
settings.buildDir.get(),
|
||||||
tmpDirRoot =
|
"nix-build-" + std::string(drvPath.name()),
|
||||||
createTempDir(buildDir, "nix-build-" + std::string(drvPath.name()), false, false, 0700);
|
false,
|
||||||
} catch (SysError & e) {
|
false,
|
||||||
/*
|
0700
|
||||||
* Fallback to the global tmpdir and create a safe space there
|
);
|
||||||
* only if it's a permission error.
|
|
||||||
*/
|
|
||||||
if (e.errNo != EACCES) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto globalTmp = defaultTempDir();
|
|
||||||
createDirs(globalTmp);
|
|
||||||
#if __APPLE__
|
|
||||||
/* macOS filesystem namespacing does not exist, to avoid breaking builds, we need to weaken
|
|
||||||
* the mode bits on the top-level directory. This avoids issues like
|
|
||||||
* https://github.com/NixOS/nix/pull/11031. */
|
|
||||||
constexpr int toplevelDirMode = 0755;
|
|
||||||
#else
|
|
||||||
constexpr int toplevelDirMode = 0700;
|
|
||||||
#endif
|
|
||||||
auto nixBuildsTmp =
|
|
||||||
createTempDir(globalTmp, fmt("nix-builds-%s", geteuid()), false, false, toplevelDirMode);
|
|
||||||
warn(
|
|
||||||
"Failed to use the system-wide build directory '%s', falling back to a temporary "
|
|
||||||
"directory inside '%s'",
|
|
||||||
settings.buildDir.get(),
|
|
||||||
nixBuildsTmp
|
|
||||||
);
|
|
||||||
worker.buildDirOverride = nixBuildsTmp;
|
|
||||||
tmpDirRoot = createTempDir(
|
|
||||||
nixBuildsTmp, "nix-build-" + std::string(drvPath.name()), false, false, 0700
|
|
||||||
);
|
|
||||||
}
|
|
||||||
/* The TOCTOU between the previous mkdir call and this open call is unavoidable due to
|
/* The TOCTOU between the previous mkdir call and this open call is unavoidable due to
|
||||||
* POSIX semantics.*/
|
* POSIX semantics.*/
|
||||||
tmpDirRootFd = AutoCloseFD{open(tmpDirRoot.c_str(), O_RDONLY | O_NOFOLLOW | O_DIRECTORY)};
|
tmpDirFd = AutoCloseFD{open(tmpDir.c_str(), O_RDONLY | O_NOFOLLOW | O_DIRECTORY)};
|
||||||
if (!tmpDirRootFd)
|
|
||||||
throw SysError("failed to open the build temporary directory descriptor '%1%'", tmpDirRoot);
|
|
||||||
|
|
||||||
// place the actual build directory in a subdirectory of tmpDirRoot. if
|
|
||||||
// we do not do this a build can `chown 777` its build directory and so
|
|
||||||
// make it accessible to everyone in the system, breaking isolation. we
|
|
||||||
// also need the intermediate level to be inaccessible to others. build
|
|
||||||
// processes must be able to at least traverse to the directory though,
|
|
||||||
// without being able to chmod. this means either mode 0750 or 0710. we
|
|
||||||
// cannot use 0710 because the libarchive we link with is compiled with
|
|
||||||
// an old apple sdk that does not have O_SEARCH, which makes libarchive
|
|
||||||
// try to open tmpDirRoot for *read* and fail because g+r is not set. a
|
|
||||||
// future update to nixpkgs may fix this. until then we do not lose any
|
|
||||||
// security by setting mode 0750 because we use only a single subdir in
|
|
||||||
// tmpDirRoot, so being able to list its parent doesn't break anything.
|
|
||||||
//
|
|
||||||
// use a short name to not increase the path length too much on darwin.
|
|
||||||
// darwin has a severe sockaddr_un path length limitation, so this does
|
|
||||||
// make a difference over more evocative names. we use `b` for `build`.
|
|
||||||
tmpDir = tmpDirRoot + "/b";
|
|
||||||
if (mkdirat(tmpDirRootFd.get(), "b", 0700)) {
|
|
||||||
throw SysError("failed to create the build temporary directory '%1%'", tmpDir);
|
|
||||||
}
|
|
||||||
tmpDirFd = AutoCloseFD{openat(tmpDirRootFd.get(), "b", O_RDONLY | O_NOFOLLOW | O_DIRECTORY)};
|
|
||||||
if (!tmpDirFd)
|
if (!tmpDirFd)
|
||||||
throw SysError("failed to open the build temporary directory descriptor '%1%'", tmpDir);
|
throw SysError("failed to open the build temporary directory descriptor '%1%'", tmpDir);
|
||||||
|
|
||||||
chownToBuilder(tmpDirFd);
|
chownToBuilder(tmpDirFd);
|
||||||
|
|
||||||
if (buildUser) {
|
|
||||||
if (fchown(tmpDirRootFd.get(), -1, buildUser->getGID()) == -1) {
|
|
||||||
throw SysError("cannot change ownership of '%1%'", tmpDirRoot);
|
|
||||||
}
|
|
||||||
if (fchmod(tmpDirRootFd.get(), 0750) == -1) {
|
|
||||||
throw SysError("cannot change mode of '%1%'", tmpDirRoot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto & [outputName, status] : initialOutputs) {
|
for (auto & [outputName, status] : initialOutputs) {
|
||||||
/* Set scratch path we'll actually use during the build.
|
/* Set scratch path we'll actually use during the build.
|
||||||
|
|
||||||
@@ -586,6 +527,10 @@ void LocalDerivationGoal::startBuilder()
|
|||||||
to use a temporary path */
|
to use a temporary path */
|
||||||
makeFallbackPath(status.known->path);
|
makeFallbackPath(status.known->path);
|
||||||
scratchOutputs.insert_or_assign(outputName, scratchPath);
|
scratchOutputs.insert_or_assign(outputName, scratchPath);
|
||||||
|
/* Schedule this scratch output path for automatic deletion
|
||||||
|
* if we do not cancel it, e.g. when registering the outputs.
|
||||||
|
*/
|
||||||
|
scratchOutputsCleaner.insert_or_assign(outputName, worker.store.printStorePath(scratchPath));
|
||||||
|
|
||||||
/* Substitute output placeholders with the scratch output paths.
|
/* Substitute output placeholders with the scratch output paths.
|
||||||
We'll use during the build. */
|
We'll use during the build. */
|
||||||
@@ -608,8 +553,6 @@ void LocalDerivationGoal::startBuilder()
|
|||||||
std::string h2 { scratchPath.hashPart() };
|
std::string h2 { scratchPath.hashPart() };
|
||||||
inputRewrites[h1] = h2;
|
inputRewrites[h1] = h2;
|
||||||
}
|
}
|
||||||
|
|
||||||
redirectedOutputs.insert_or_assign(std::move(fixedFinalPath), std::move(scratchPath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct the environment passed to the builder. */
|
/* Construct the environment passed to the builder. */
|
||||||
@@ -778,7 +721,7 @@ void LocalDerivationGoal::startBuilder()
|
|||||||
printMsg(lvlVomit, "setting builder env variable '%1%'='%2%'", i.first, i.second);
|
printMsg(lvlVomit, "setting builder env variable '%1%'='%2%'", i.first, i.second);
|
||||||
|
|
||||||
/* Create the log file. */
|
/* Create the log file. */
|
||||||
openLogFile();
|
Path logFile = openLogFile();
|
||||||
|
|
||||||
/* Create a pseudoterminal to get the output of the builder. */
|
/* Create a pseudoterminal to get the output of the builder. */
|
||||||
builderOut = AutoCloseFD{posix_openpt(O_RDWR | O_NOCTTY)};
|
builderOut = AutoCloseFD{posix_openpt(O_RDWR | O_NOCTTY)};
|
||||||
@@ -1903,8 +1846,6 @@ void LocalDerivationGoal::runChild()
|
|||||||
|
|
||||||
if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") {
|
if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") {
|
||||||
Strings sandboxArgs;
|
Strings sandboxArgs;
|
||||||
sandboxArgs.push_back("_NIX_BUILD_TOP");
|
|
||||||
sandboxArgs.push_back(tmpDir);
|
|
||||||
sandboxArgs.push_back("_GLOBAL_TMP_DIR");
|
sandboxArgs.push_back("_GLOBAL_TMP_DIR");
|
||||||
sandboxArgs.push_back(globalTmpDir);
|
sandboxArgs.push_back(globalTmpDir);
|
||||||
if (allowLocalNetworking) {
|
if (allowLocalNetworking) {
|
||||||
@@ -2441,6 +2382,10 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
|
|||||||
localStore.registerValidPaths({{oldInfo.path, oldInfo}});
|
localStore.registerValidPaths({{oldInfo.path, oldInfo}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't register anything, since we already have the
|
||||||
|
previous versions which we're comparing.
|
||||||
|
NOTE: this means that the `.check` path will be automatically deleted.
|
||||||
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2464,8 +2409,13 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
|
|||||||
/* If it's a CA path, register it right away. This is necessary if it
|
/* If it's a CA path, register it right away. This is necessary if it
|
||||||
isn't statically known so that we can safely unlock the path before
|
isn't statically known so that we can safely unlock the path before
|
||||||
the next iteration */
|
the next iteration */
|
||||||
if (newInfo.ca)
|
if (newInfo.ca) {
|
||||||
localStore.registerValidPaths({{newInfo.path, newInfo}});
|
localStore.registerValidPaths({{newInfo.path, newInfo}});
|
||||||
|
/* Cancel automatic deletion of that output if it was a scratch output. */
|
||||||
|
if (auto cleaner = scratchOutputsCleaner.extract(outputName)) {
|
||||||
|
cleaner.mapped().cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
infos.emplace(outputName, std::move(newInfo));
|
infos.emplace(outputName, std::move(newInfo));
|
||||||
}
|
}
|
||||||
@@ -2493,6 +2443,13 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
|
|||||||
infos2.insert_or_assign(newInfo.path, newInfo);
|
infos2.insert_or_assign(newInfo.path, newInfo);
|
||||||
}
|
}
|
||||||
localStore.registerValidPaths(infos2);
|
localStore.registerValidPaths(infos2);
|
||||||
|
|
||||||
|
/* Cancel automatic deletion of that output if it was a scratch output that we just registered. */
|
||||||
|
for (auto & [outputName, _ ] : infos) {
|
||||||
|
if (auto cleaner = scratchOutputsCleaner.extract(outputName)) {
|
||||||
|
cleaner.mapped().cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In case of a fixed-output derivation hash mismatch, throw an
|
/* In case of a fixed-output derivation hash mismatch, throw an
|
||||||
@@ -2526,6 +2483,13 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
|
|||||||
builtOutputs.emplace(outputName, thisRealisation);
|
builtOutputs.emplace(outputName, thisRealisation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NOTE: At this point, all outputs MAY NOT have been registered.
|
||||||
|
* Therefore, there may remains auto-deleters pending in the cleaner list (`scratchOutputsCleaner`).
|
||||||
|
*
|
||||||
|
* They will be finally deleted but we have no way to assert they all have been, e.g.
|
||||||
|
* `assert(scratchOutputsCleaner.size() == 0)` cannot be written.
|
||||||
|
*/
|
||||||
|
|
||||||
return builtOutputs;
|
return builtOutputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2715,16 +2679,16 @@ void LocalDerivationGoal::checkOutputs(const std::map<std::string, ValidPathInfo
|
|||||||
|
|
||||||
void LocalDerivationGoal::deleteTmpDir(bool force)
|
void LocalDerivationGoal::deleteTmpDir(bool force)
|
||||||
{
|
{
|
||||||
if (tmpDirRoot != "") {
|
if (tmpDir != "") {
|
||||||
/* Don't keep temporary directories for builtins because they
|
/* Don't keep temporary directories for builtins because they
|
||||||
might have privileged stuff (like a copy of netrc). */
|
might have privileged stuff (like a copy of netrc). */
|
||||||
if (settings.keepFailed && !force && !drv->isBuiltin()) {
|
if (settings.keepFailed && !force && !drv->isBuiltin()) {
|
||||||
printError("note: keeping build directory '%s'", tmpDirRoot);
|
printError("note: keeping build directory '%s'", tmpDir);
|
||||||
chmod(tmpDirRoot.c_str(), 0755);
|
chmod(tmpDir.c_str(), 0755);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
deletePath(tmpDirRoot);
|
deletePath(tmpDir);
|
||||||
tmpDirRoot = "";
|
tmpDir = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ struct LocalDerivationGoal : public DerivationGoal
|
|||||||
/**
|
/**
|
||||||
* The temporary directory.
|
* The temporary directory.
|
||||||
*/
|
*/
|
||||||
Path tmpDirRoot, tmpDir;
|
Path tmpDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The temporary directory file descriptor
|
* The temporary directory file descriptor
|
||||||
*/
|
*/
|
||||||
AutoCloseFD tmpDirRootFd, tmpDirFd;
|
AutoCloseFD tmpDirFd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path of the temporary directory in the sandbox.
|
* The path of the temporary directory in the sandbox.
|
||||||
@@ -107,8 +107,6 @@ struct LocalDerivationGoal : public DerivationGoal
|
|||||||
* Hash rewriting.
|
* Hash rewriting.
|
||||||
*/
|
*/
|
||||||
StringMap inputRewrites, outputRewrites;
|
StringMap inputRewrites, outputRewrites;
|
||||||
typedef map<StorePath, StorePath> RedirectedOutputs;
|
|
||||||
RedirectedOutputs redirectedOutputs;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The outputs paths used during the build.
|
* The outputs paths used during the build.
|
||||||
@@ -125,6 +123,19 @@ struct LocalDerivationGoal : public DerivationGoal
|
|||||||
* self-references.
|
* self-references.
|
||||||
*/
|
*/
|
||||||
OutputPathMap scratchOutputs;
|
OutputPathMap scratchOutputs;
|
||||||
|
/**
|
||||||
|
* Output paths used during the build are scheduled for
|
||||||
|
* automatic cleanup unless they have been successfully built.
|
||||||
|
*
|
||||||
|
* `registerOutputs` take care of cancelling the cleanups
|
||||||
|
* and clearing this vector.
|
||||||
|
*
|
||||||
|
* `startBuilder` take care of filling this vector
|
||||||
|
* as `scratchOutputs` gets filled.
|
||||||
|
*
|
||||||
|
* This is a map from output names to automatic delete handles.
|
||||||
|
*/
|
||||||
|
std::map<std::string, AutoDelete> scratchOutputsCleaner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path registration info from the previous round, if we're
|
* Path registration info from the previous round, if we're
|
||||||
|
|||||||
@@ -26,14 +26,12 @@ R""(
|
|||||||
; Allow getpwuid.
|
; Allow getpwuid.
|
||||||
(allow mach-lookup (global-name "com.apple.system.opendirectoryd.libinfo"))
|
(allow mach-lookup (global-name "com.apple.system.opendirectoryd.libinfo"))
|
||||||
|
|
||||||
; Access to /tmp and the build directory.
|
; Access to /tmp.
|
||||||
; The network-outbound/network-inbound ones are for unix domain sockets, which
|
; The network-outbound/network-inbound ones are for unix domain sockets, which
|
||||||
; we allow access to in TMPDIR (but if we allow them more broadly, you could in
|
; we allow access to in TMPDIR (but if we allow them more broadly, you could in
|
||||||
; theory escape the sandbox)
|
; theory escape the sandbox)
|
||||||
(allow file* process-exec network-outbound network-inbound
|
(allow file* process-exec network-outbound network-inbound
|
||||||
(literal "/tmp")
|
(literal "/tmp") (subpath TMPDIR))
|
||||||
(subpath TMPDIR)
|
|
||||||
(subpath (param "_NIX_BUILD_TOP")))
|
|
||||||
|
|
||||||
; Some packages like to read the system version.
|
; Some packages like to read the system version.
|
||||||
(allow file-read*
|
(allow file-read*
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ public:
|
|||||||
|
|
||||||
Store & store;
|
Store & store;
|
||||||
Store & evalStore;
|
Store & evalStore;
|
||||||
std::optional<Path> buildDirOverride;
|
|
||||||
|
|
||||||
struct HookState {
|
struct HookState {
|
||||||
std::unique_ptr<HookInstance> instance;
|
std::unique_ptr<HookInstance> instance;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ WireFormatGenerator CommonProto::Serialise<std::optional<ContentAddress>>::write
|
|||||||
{
|
{
|
||||||
return [](std::string s) -> WireFormatGenerator {
|
return [](std::string s) -> WireFormatGenerator {
|
||||||
co_yield s;
|
co_yield s;
|
||||||
}(caOpt ? renderContentAddress(caOpt) : "");
|
}(caOpt ? renderContentAddress(*caOpt) : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,15 +45,8 @@ std::string SecretKey::signDetached(std::string_view data) const
|
|||||||
{
|
{
|
||||||
unsigned char sig[crypto_sign_BYTES];
|
unsigned char sig[crypto_sign_BYTES];
|
||||||
unsigned long long sigLen;
|
unsigned long long sigLen;
|
||||||
crypto_sign_detached(
|
crypto_sign_detached(sig, &sigLen, charptr_cast<const unsigned char *>(data.data()), data.size(),
|
||||||
sig,
|
charptr_cast<const unsigned char *>(key.data()));
|
||||||
&sigLen,
|
|
||||||
// the following is not a string function so no null termination issues are possible here.
|
|
||||||
// NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
|
|
||||||
charptr_cast<const unsigned char *>(data.data()),
|
|
||||||
data.size(),
|
|
||||||
charptr_cast<const unsigned char *>(key.data())
|
|
||||||
);
|
|
||||||
return name + ":" + base64Encode(std::string(reinterpret_cast<char *>(sig), sigLen));
|
return name + ":" + base64Encode(std::string(reinterpret_cast<char *>(sig), sigLen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,14 @@ void Store::exportPaths(const StorePathSet & paths, Sink & sink)
|
|||||||
auto sorted = topoSortPaths(paths);
|
auto sorted = topoSortPaths(paths);
|
||||||
std::reverse(sorted.begin(), sorted.end());
|
std::reverse(sorted.begin(), sorted.end());
|
||||||
|
|
||||||
|
std::string doneLabel("paths exported");
|
||||||
|
//logger->incExpected(doneLabel, sorted.size());
|
||||||
|
|
||||||
for (auto & path : sorted) {
|
for (auto & path : sorted) {
|
||||||
|
//Activity act(*logger, lvlInfo, "exporting path '%s'", path);
|
||||||
sink << 1;
|
sink << 1;
|
||||||
exportPath(path, sink);
|
exportPath(path, sink);
|
||||||
|
//logger->incProgress(doneLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
sink << 0;
|
sink << 0;
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ struct NarAccessor : public FSAccessor
|
|||||||
|
|
||||||
NarMember * find(const Path & path)
|
NarMember * find(const Path & path)
|
||||||
{
|
{
|
||||||
|
Path canon = path == "" ? "" : canonPath(path);
|
||||||
NarMember * current = &root;
|
NarMember * current = &root;
|
||||||
auto end = path.end();
|
auto end = path.end();
|
||||||
for (auto it = path.begin(); it != end; ) {
|
for (auto it = path.begin(); it != end; ) {
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ std::string NarInfo::to_string(const Store & store) const
|
|||||||
res += "Sig: " + sig + "\n";
|
res += "Sig: " + sig + "\n";
|
||||||
|
|
||||||
if (ca)
|
if (ca)
|
||||||
res += "CA: " + renderContentAddress(ca) + "\n";
|
res += "CA: " + renderContentAddress(*ca) + "\n";
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ SQLiteStmt::Use::~Use()
|
|||||||
SQLiteStmt::Use & SQLiteStmt::Use::operator () (std::string_view value, bool notNull)
|
SQLiteStmt::Use & SQLiteStmt::Use::operator () (std::string_view value, bool notNull)
|
||||||
{
|
{
|
||||||
if (notNull) {
|
if (notNull) {
|
||||||
if (sqlite3_bind_text(stmt, curArg++, value.data(), value.length(), SQLITE_TRANSIENT) != SQLITE_OK)
|
if (sqlite3_bind_text(stmt, curArg++, value.data(), -1, SQLITE_TRANSIENT) != SQLITE_OK)
|
||||||
SQLiteError::throw_(stmt.db, "binding argument");
|
SQLiteError::throw_(stmt.db, "binding argument");
|
||||||
} else
|
} else
|
||||||
bind();
|
bind();
|
||||||
|
|||||||
@@ -1322,7 +1322,8 @@ std::optional<StorePath> Store::getBuildDerivationPath(const StorePath & path)
|
|||||||
if (!path.isDerivation()) {
|
if (!path.isDerivation()) {
|
||||||
try {
|
try {
|
||||||
auto info = queryPathInfo(path);
|
auto info = queryPathInfo(path);
|
||||||
return info->deriver;
|
if (!info->deriver) return std::nullopt;
|
||||||
|
return *info->deriver;
|
||||||
} catch (InvalidPath &) {
|
} catch (InvalidPath &) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,7 +239,6 @@ struct BrotliCompressionSink : ChunkedCompressionSink
|
|||||||
|
|
||||||
void writeInternal(std::string_view data) override
|
void writeInternal(std::string_view data) override
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
|
|
||||||
auto next_in = charptr_cast<const uint8_t *>(data.data());
|
auto next_in = charptr_cast<const uint8_t *>(data.data());
|
||||||
size_t avail_in = data.size();
|
size_t avail_in = data.size();
|
||||||
uint8_t * next_out = outbuf;
|
uint8_t * next_out = outbuf;
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ static void _deletePath(const Path & path, uint64_t & bytesFreed)
|
|||||||
throw SysError("opening directory '%1%'", path);
|
throw SysError("opening directory '%1%'", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
_deletePath(dirfd.get(), std::string(baseNameOf(path)), bytesFreed);
|
_deletePath(dirfd.get(), baseNameOf(path).data(), bytesFreed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ std::string hiliteMatches(
|
|||||||
out.append(s.substr(last_end, m.position() - last_end));
|
out.append(s.substr(last_end, m.position() - last_end));
|
||||||
// Merge continous matches
|
// Merge continous matches
|
||||||
ssize_t end = start + m.length();
|
ssize_t end = start + m.length();
|
||||||
for (++it; it != matches.end() && (*it).position() <= end; ++it) {
|
while (++it != matches.end() && (*it).position() <= end) {
|
||||||
auto n = *it;
|
auto n = *it;
|
||||||
ssize_t nend = start + (n.position() - start + n.length());
|
ssize_t nend = start + (n.position() - start + n.length());
|
||||||
if (nend > end)
|
if (nend > end)
|
||||||
|
|||||||
@@ -38,6 +38,6 @@ const nlohmann::json & ensureType(
|
|||||||
nlohmann::json(expectedType).type_name(),
|
nlohmann::json(expectedType).type_name(),
|
||||||
value.type_name());
|
value.type_name());
|
||||||
|
|
||||||
return value; // NOLINT(bugprone-return-const-ref-from-parameter)
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,12 +258,12 @@ extern Verbosity verbosity;
|
|||||||
* level. Note that this has to be implemented as a macro to ensure that the
|
* level. Note that this has to be implemented as a macro to ensure that the
|
||||||
* arguments are evaluated lazily.
|
* arguments are evaluated lazily.
|
||||||
*/
|
*/
|
||||||
#define printMsgUsing(loggerParam, level, args...) \
|
#define printMsgUsing(loggerParam, level, args...) \
|
||||||
do { \
|
do { \
|
||||||
auto _lix_logger_print_lvl = level; \
|
auto __lvl = level; \
|
||||||
if (_lix_logger_print_lvl <= nix::verbosity) { \
|
if (__lvl <= nix::verbosity) { \
|
||||||
loggerParam->log(_lix_logger_print_lvl, fmt(args)); \
|
loggerParam->log(__lvl, fmt(args)); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define printMsg(level, args...) printMsgUsing(logger, level, args)
|
#define printMsg(level, args...) printMsgUsing(logger, level, args)
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ void RefScanSink::operator () (std::string_view data)
|
|||||||
previous fragment and the start of the current fragment. */
|
previous fragment and the start of the current fragment. */
|
||||||
auto s = tail;
|
auto s = tail;
|
||||||
auto tailLen = std::min(data.size(), refLength);
|
auto tailLen = std::min(data.size(), refLength);
|
||||||
s.append(data.data(), tailLen); // NOLINT(bugprone-suspicious-stringview-data-usage)
|
s.append(data.data(), tailLen);
|
||||||
search(s, hashes, seen);
|
search(s, hashes, seen);
|
||||||
|
|
||||||
search(data, hashes, seen);
|
search(data, hashes, seen);
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ void Source::operator () (char * data, size_t len)
|
|||||||
|
|
||||||
void Source::drainInto(Sink & sink)
|
void Source::drainInto(Sink & sink)
|
||||||
{
|
{
|
||||||
|
std::string s;
|
||||||
std::array<char, 8192> buf;
|
std::array<char, 8192> buf;
|
||||||
while (true) {
|
while (true) {
|
||||||
size_t n;
|
size_t n;
|
||||||
@@ -250,7 +251,7 @@ Error readError(Source & source)
|
|||||||
auto type = readString(source);
|
auto type = readString(source);
|
||||||
assert(type == "Error");
|
assert(type == "Error");
|
||||||
auto level = (Verbosity) readInt(source);
|
auto level = (Verbosity) readInt(source);
|
||||||
readString(source); // removed (name)
|
auto name = readString(source); // removed
|
||||||
auto msg = readString(source);
|
auto msg = readString(source);
|
||||||
ErrorInfo info {
|
ErrorInfo info {
|
||||||
.level = level,
|
.level = level,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ bool shouldANSI(StandardOutputStream fileno)
|
|||||||
// FIXME(jade): replace with TerminalCodeEater. wowie this is evil code.
|
// FIXME(jade): replace with TerminalCodeEater. wowie this is evil code.
|
||||||
std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int width, bool eatTabs)
|
std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int width, bool eatTabs)
|
||||||
{
|
{
|
||||||
std::string t;
|
std::string t, e;
|
||||||
size_t w = 0;
|
size_t w = 0;
|
||||||
auto i = s.begin();
|
auto i = s.begin();
|
||||||
|
|
||||||
|
|||||||
@@ -80,18 +80,12 @@ typename T::mapped_type * get(T & map, const typename T::key_type & key)
|
|||||||
* Get a value for the specified key from an associate container, or a default value if the key isn't present.
|
* Get a value for the specified key from an associate container, or a default value if the key isn't present.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
const typename T::mapped_type & getOr(
|
const typename T::mapped_type & getOr(T & map,
|
||||||
T & map [[clang::lifetimebound]],
|
|
||||||
const typename T::key_type & key,
|
const typename T::key_type & key,
|
||||||
const typename T::mapped_type & defaultValue [[clang::lifetimebound]]
|
const typename T::mapped_type & defaultValue)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
auto i = map.find(key);
|
auto i = map.find(key);
|
||||||
if (i == map.end()) {
|
if (i == map.end()) return defaultValue;
|
||||||
/* FIXME(Raito): `[[clang::lifetimebound]]` has no effect on `defaultValue` warning. */
|
|
||||||
// NOLINTNEXTLINE(bugprone-return-const-ref-from-parameter)
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
return i->second;
|
return i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1313,7 +1313,7 @@ static void opSwitchGeneration(Globals & globals, Strings opFlags, Strings opArg
|
|||||||
throw UsageError("exactly one argument expected");
|
throw UsageError("exactly one argument expected");
|
||||||
|
|
||||||
if (auto dstGen = string2Int<GenerationNumber>(opArgs.front()))
|
if (auto dstGen = string2Int<GenerationNumber>(opArgs.front()))
|
||||||
switchGeneration(globals.profile, dstGen, globals.dryRun);
|
switchGeneration(globals.profile, *dstGen, globals.dryRun);
|
||||||
else
|
else
|
||||||
throw UsageError("expected a generation number");
|
throw UsageError("expected a generation number");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,8 @@ struct CmdBundle : InstallableCommand
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto outPathS = store->printStorePath(outPath);
|
||||||
|
|
||||||
if (!outLink) {
|
if (!outLink) {
|
||||||
auto * attr = vRes->attrs->get(evalState->sName);
|
auto * attr = vRes->attrs->get(evalState->sName);
|
||||||
if (!attr)
|
if (!attr)
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
|
|||||||
std::cout << '\t';
|
std::cout << '\t';
|
||||||
Strings ss;
|
Strings ss;
|
||||||
if (info->ultimate) ss.push_back("ultimate");
|
if (info->ultimate) ss.push_back("ultimate");
|
||||||
if (info->ca) ss.push_back("ca:" + renderContentAddress(info->ca));
|
if (info->ca) ss.push_back("ca:" + renderContentAddress(*info->ca));
|
||||||
for (auto & sig : info->sigs) ss.push_back(sig);
|
for (auto & sig : info->sigs) ss.push_back(sig);
|
||||||
std::cout << concatStringsSep(" ", ss);
|
std::cout << concatStringsSep(" ", ss);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ struct CmdSearch : InstallableCommand, MixJSON
|
|||||||
{"description", description},
|
{"description", description},
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
auto name2 = hiliteMatches(name.name, nameMatches, ANSI_GREEN, "\e[0;2m");
|
||||||
if (results > 1) logger->cout("");
|
if (results > 1) logger->cout("");
|
||||||
logger->cout(
|
logger->cout(
|
||||||
"* %s%s",
|
"* %s%s",
|
||||||
|
|||||||
@@ -40,9 +40,13 @@ struct CmdCopySigs : StorePathsCommand
|
|||||||
|
|
||||||
ThreadPool pool;
|
ThreadPool pool;
|
||||||
|
|
||||||
|
std::string doneLabel = "done";
|
||||||
std::atomic<size_t> added{0};
|
std::atomic<size_t> added{0};
|
||||||
|
|
||||||
|
//logger->setExpected(doneLabel, storePaths.size());
|
||||||
|
|
||||||
auto doPath = [&](const Path & storePathS) {
|
auto doPath = [&](const Path & storePathS) {
|
||||||
|
//Activity act(*logger, lvlInfo, "getting signatures for '%s'", storePath);
|
||||||
|
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
||||||
@@ -74,6 +78,8 @@ struct CmdCopySigs : StorePathsCommand
|
|||||||
store->addSignatures(storePath, newSigs);
|
store->addSignatures(storePath, newSigs);
|
||||||
added += newSigs.size();
|
added += newSigs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//logger->incProgress(doneLabel);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto & storePath : storePaths)
|
for (auto & storePath : storePaths)
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ private:
|
|||||||
OptionalFileEntryRef File,
|
OptionalFileEntryRef File,
|
||||||
StringRef SearchPath, StringRef RelativePath,
|
StringRef SearchPath, StringRef RelativePath,
|
||||||
const Module *Imported,
|
const Module *Imported,
|
||||||
bool ModuleImported,
|
|
||||||
SrcMgr::CharacteristicKind FileType) override;
|
SrcMgr::CharacteristicKind FileType) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ void FixIncludesCallbacks::LexedFileChanged(FileID, LexedFileChangeReason,
|
|||||||
void FixIncludesCallbacks::InclusionDirective(
|
void FixIncludesCallbacks::InclusionDirective(
|
||||||
SourceLocation, const Token &, StringRef FileName, bool IsAngled,
|
SourceLocation, const Token &, StringRef FileName, bool IsAngled,
|
||||||
CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef,
|
CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef,
|
||||||
StringRef, const Module *, bool, SrcMgr::CharacteristicKind) {
|
StringRef, const Module *, SrcMgr::CharacteristicKind) {
|
||||||
if (Ignore)
|
if (Ignore)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -80,4 +80,4 @@ out="$(nix-build 2>&1 failing.nix \
|
|||||||
[[ "$out" =~ .*"note: keeping build directory".* ]]
|
[[ "$out" =~ .*"note: keeping build directory".* ]]
|
||||||
|
|
||||||
build_dir="$(grep "note: keeping build" <<< "$out" | sed -E "s/^(.*)note: keeping build directory '(.*)'(.*)$/\2/")"
|
build_dir="$(grep "note: keeping build" <<< "$out" | sed -E "s/^(.*)note: keeping build directory '(.*)'(.*)$/\2/")"
|
||||||
[[ "foo" = $(<"$build_dir"/b/bar) ]]
|
[[ "foo" = $(<"$build_dir"/bar) ]]
|
||||||
|
|||||||
@@ -170,28 +170,3 @@ test "$(<<<"$out" grep -E '^error:' | wc -l)" = 3
|
|||||||
<<<"$out" grepQuiet -E "error: 2 dependencies of derivation '.*-x4\\.drv' failed to build"
|
<<<"$out" grepQuiet -E "error: 2 dependencies of derivation '.*-x4\\.drv' failed to build"
|
||||||
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
|
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
|
||||||
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
|
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
|
||||||
|
|
||||||
# Ensure when if the system build dir is inaccessible, we can still build things
|
|
||||||
BUILD_DIR=$(mktemp -d)
|
|
||||||
chmod 0000 "$BUILD_DIR"
|
|
||||||
nix --build-dir "$BUILD_DIR" build -E 'with import ./config.nix; mkDerivation { name = "test"; buildCommand = "echo rawr > $out"; }' --impure --no-link
|
|
||||||
|
|
||||||
# ensure that the build directory parent is not world-accessible
|
|
||||||
chmod 0755 "$BUILD_DIR"
|
|
||||||
FIFO="$BUILD_DIR/fifo"
|
|
||||||
mkfifo "$FIFO"
|
|
||||||
(
|
|
||||||
echo > "$FIFO"
|
|
||||||
trap 'echo > "$FIFO"' EXIT
|
|
||||||
mode=$(stat -c %a $BUILD_DIR/b/*)
|
|
||||||
[ "$mode" = "700" -o "$mode" = "710" ]
|
|
||||||
) &
|
|
||||||
nix build --build-dir "$BUILD_DIR/b" -E '
|
|
||||||
with import ./config.nix; mkDerivation {
|
|
||||||
name = "test";
|
|
||||||
buildCommand = "cat '"$FIFO"'; cat '"$FIFO"' > $out";
|
|
||||||
}' \
|
|
||||||
--extra-sandbox-paths "$FIFO" \
|
|
||||||
--impure \
|
|
||||||
--no-link
|
|
||||||
wait
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ test_custom_build_dir() {
|
|||||||
[ "$status" = "100" ]
|
[ "$status" = "100" ]
|
||||||
[[ 1 == "$(count "$customBuildDir/nix-build-"*)" ]]
|
[[ 1 == "$(count "$customBuildDir/nix-build-"*)" ]]
|
||||||
local buildDir="$customBuildDir/nix-build-"*
|
local buildDir="$customBuildDir/nix-build-"*
|
||||||
grep $checkBuildId $buildDir/b/checkBuildId
|
grep $checkBuildId $buildDir/checkBuildId
|
||||||
}
|
}
|
||||||
test_custom_build_dir
|
test_custom_build_dir
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
nix-repl> 1 + 1
|
nix-repl> 1 + 1
|
||||||
2
|
2
|
||||||
|
|
||||||
nix-repl> :doc builtins.add
|
nix-repl> :doc builtins.head
|
||||||
Synopsis: builtins.add e1 e2
|
Synopsis: builtins.head list
|
||||||
|
|
||||||
Return the sum of the numbers e1 and e2.
|
|
||||||
|
|
||||||
|
Return the first element of a list; abort evaluation if
|
||||||
|
the argument isn’t a list or is an empty list. You can
|
||||||
|
test whether a list is empty by comparing it with [].
|
||||||
|
|
||||||
nix-repl> f = a: "" + a
|
nix-repl> f = a: "" + a
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ let
|
|||||||
defaults = {
|
defaults = {
|
||||||
nixpkgs.pkgs = nixpkgsFor.${system}.native;
|
nixpkgs.pkgs = nixpkgsFor.${system}.native;
|
||||||
nix.checkAllErrors = false;
|
nix.checkAllErrors = false;
|
||||||
# nixos-option fails to build with lix and no tests use any of the tools
|
|
||||||
system.disableInstallerTools = true;
|
|
||||||
};
|
};
|
||||||
_module.args.nixpkgs = nixpkgs;
|
_module.args.nixpkgs = nixpkgs;
|
||||||
_module.args.system = system;
|
_module.args.system = system;
|
||||||
@@ -148,6 +146,9 @@ in
|
|||||||
|
|
||||||
symlinkResolvconf = runNixOSTestFor "x86_64-linux" ./symlink-resolvconf.nix;
|
symlinkResolvconf = runNixOSTestFor "x86_64-linux" ./symlink-resolvconf.nix;
|
||||||
|
|
||||||
|
# Use this test to test things that cannot easily be tested under chroot Nix stores in functional test suite.
|
||||||
|
non-chroot-misc = runNixOSTestFor "x86_64-linux" ./non-chroot-misc;
|
||||||
|
|
||||||
noNewPrivilegesInSandbox = runNixOSTestFor "x86_64-linux" ./no-new-privileges/sandbox.nix;
|
noNewPrivilegesInSandbox = runNixOSTestFor "x86_64-linux" ./no-new-privileges/sandbox.nix;
|
||||||
|
|
||||||
noNewPrivilegesOutsideSandbox = runNixOSTestFor "x86_64-linux" ./no-new-privileges/no-sandbox.nix;
|
noNewPrivilegesOutsideSandbox = runNixOSTestFor "x86_64-linux" ./no-new-privileges/no-sandbox.nix;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ in
|
|||||||
# Fetching from a server with an untrusted cert should fail.
|
# Fetching from a server with an untrusted cert should fail.
|
||||||
err = machine.fail("nix build --no-substitute --expr 'import <nix/fetchurl.nix> { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }' 2>&1")
|
err = machine.fail("nix build --no-substitute --expr 'import <nix/fetchurl.nix> { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }' 2>&1")
|
||||||
print(err)
|
print(err)
|
||||||
assert "SSL peer certificate or SSH remote key was not OK" in err
|
assert "SSL certificate problem: self-signed certificate" in err or "SSL peer certificate or SSH remote key was not OK" in err
|
||||||
|
|
||||||
# Fetching from a server with a trusted cert should work via environment variable override.
|
# Fetching from a server with a trusted cert should work via environment variable override.
|
||||||
machine.succeed("NIX_SSL_CERT_FILE=/tmp/cafile.pem nix build --no-substitute --expr 'import <nix/fetchurl.nix> { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }'")
|
machine.succeed("NIX_SSL_CERT_FILE=/tmp/cafile.pem nix build --no-substitute --expr 'import <nix/fetchurl.nix> { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }'")
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ in {
|
|||||||
server.wait_for_unit("network-online.target")
|
server.wait_for_unit("network-online.target")
|
||||||
client.wait_for_unit("network-online.target")
|
client.wait_for_unit("network-online.target")
|
||||||
|
|
||||||
client.succeed("mkdir -m 700 /root/.ssh || [[ -d /root/.ssh ]]")
|
client.succeed("mkdir -m 700 /root/.ssh")
|
||||||
client.copy_from_host("key", "/root/.ssh/id_ed25519")
|
client.copy_from_host("key", "/root/.ssh/id_ed25519")
|
||||||
client.succeed("chmod 600 /root/.ssh/id_ed25519")
|
client.succeed("chmod 600 /root/.ssh/id_ed25519")
|
||||||
|
|
||||||
# Install the SSH key on the server.
|
# Install the SSH key on the server.
|
||||||
server.succeed("mkdir -m 700 /root/.ssh || [[ -d /root/.ssh ]]")
|
server.succeed("mkdir -m 700 /root/.ssh")
|
||||||
server.copy_from_host("key.pub", "/root/.ssh/authorized_keys")
|
server.copy_from_host("key.pub", "/root/.ssh/authorized_keys")
|
||||||
server.wait_for_unit("sshd.service")
|
server.wait_for_unit("sshd.service")
|
||||||
client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world' >&2")
|
client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world' >&2")
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{ ... }:
|
||||||
|
# Misc things we want to test inside of a non redirected, non chroot Nix store.
|
||||||
|
let
|
||||||
|
nonAutoCleaningFailingDerivationCode = ''
|
||||||
|
derivation {
|
||||||
|
name = "scratch-failing";
|
||||||
|
system = builtins.currentSystem;
|
||||||
|
builder = "/bin/sh";
|
||||||
|
args = [ (builtins.toFile "builder.sh" "echo bonjour > $out; echo out: $out; false") ];
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "non-chroot-sandbox-misc";
|
||||||
|
|
||||||
|
nodes.machine = {
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = { nodes }: ''
|
||||||
|
import re
|
||||||
|
start_all()
|
||||||
|
|
||||||
|
# You might ask yourself why write such a convoluted thing?
|
||||||
|
# The condition for fooling Nix into NOT cleaning up the output path are non trivial and unclear.
|
||||||
|
# This is one of those: create a derivation, mkdir or touch the $out path, communicate it back.
|
||||||
|
# Even with a sandboxed Lix, you will observe leftovers before 2.93.0. After this version, this test passes.
|
||||||
|
result = machine.fail("""nix-build --substituters "" -E '${nonAutoCleaningFailingDerivationCode}' 2>&1""")
|
||||||
|
match = re.search(r'out: (\S+)', result)
|
||||||
|
assert match is not None, "Did not find Nix store path in the result of the failing build"
|
||||||
|
outpath = match.group(1).strip()
|
||||||
|
print(f"Found Nix store path: {outpath}")
|
||||||
|
machine.fail(f'stat {outpath}')
|
||||||
|
'';
|
||||||
|
}
|
||||||
@@ -48,7 +48,6 @@ in
|
|||||||
imports = [ test.config.builders.config ];
|
imports = [ test.config.builders.config ];
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
virtualisation.writableStore = true;
|
virtualisation.writableStore = true;
|
||||||
virtualisation.additionalPaths = [ config.system.build.extraUtils ];
|
|
||||||
nix.settings.sandbox = true;
|
nix.settings.sandbox = true;
|
||||||
nix.settings.substituters = lib.mkForce [ ];
|
nix.settings.substituters = lib.mkForce [ ];
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "2.91.3",
|
"version": "2.91.2",
|
||||||
"official_release": false,
|
"official_release": true,
|
||||||
"release_name": "Dragon's Breath"
|
"release_name": "Dragon's Breath"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user