Compare commits

..

6 Commits

Author SHA1 Message Date
regnat
a06cd93324 Split installTests
That way the CI will run the different ones on different runners
2022-02-25 08:33:44 +01:00
regnat
38edf8a0b4 Split the CI in several steps 2022-02-24 20:49:09 +01:00
regnat
55b46a5060 testS: poll more eagerly for the daemon start/stop
Polling every 1 second means that even the simplest test takes at least
2 seconds. We can reasonably poll 1/10 of that to make things much
  quicker (esp. given that most of the time 0.1s is enough for the
  daemon to be started or stopped)
2022-02-24 15:30:05 +01:00
regnat
8442d587ce Allow tracking the start and end time of tests 2022-02-24 15:30:05 +01:00
regnat
1e622145b2 Sort the tests by wall time
The tests are scheduled in the order they appear, so running the long
ones first slightly improves the scheduling.

On my machine, this decreases the time of `make install` from 40s to 36s
2022-02-24 15:30:05 +01:00
regnat
76c36742ee Show the elapsed time for each test
To have an idea of what’s taking time
2022-02-24 15:30:05 +01:00
209 changed files with 1837 additions and 3123 deletions

View File

@@ -6,13 +6,15 @@ on:
jobs:
tests:
build:
needs: [check_cachix]
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 60
outputs:
flake-outputs-json: ${{ steps.list-outputs.outputs.json }}
steps:
- uses: actions/checkout@v2.4.0
with:
@@ -25,7 +27,32 @@ jobs:
name: '${{ env.CACHIX_NAME }}'
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix --experimental-features 'nix-command flakes' flake check -L
- run: nix --experimental-features 'nix-command flakes' build -L
- name: List all the tests to run
id: list-outputs
run: scripts/list-tests-flake-outptus-for-gha
test:
needs: [build, check_cachix]
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
outputName: ${{ fromJson(needs.build.outputs.flake-outputs-json) }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2.4.0
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v16
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v10
if: needs.check_cachix.outputs.secret == 'true'
with:
name: '${{ env.CACHIX_NAME }}'
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix --experimental-features 'nix-command flakes' build .#checks.$(nix eval --raw --impure --expr builtins.currentSystem).${{ matrix.outputName }} -L
check_cachix:
name: Cachix secret present for installer tests
@@ -40,7 +67,7 @@ jobs:
run: echo "::set-output name=secret::${{ env._CACHIX_SECRETS != '' }}"
installer:
needs: [tests, check_cachix]
needs: [test, check_cachix]
if: github.event_name == 'push' && needs.check_cachix.outputs.secret == 'true'
runs-on: ubuntu-latest
outputs:
@@ -76,7 +103,7 @@ jobs:
- run: nix-instantiate -E 'builtins.currentTime' --eval
docker_push_image:
needs: [check_cachix, tests]
needs: [check_cachix, build]
if: >-
github.event_name == 'push' &&
github.ref_name == 'master' &&

View File

@@ -2,7 +2,6 @@ makefiles = \
mk/precompiled-headers.mk \
local.mk \
src/libutil/local.mk \
src/nix-find-roots/local.mk \
src/libutil/tests/local.mk \
src/libstore/local.mk \
src/libstore/tests/local.mk \

View File

@@ -282,6 +282,15 @@ AC_CHECK_FUNCS([setresuid setreuid lchown])
AC_CHECK_FUNCS([strsignal posix_fallocate sysconf])
# This is needed if bzip2 is a static library, and the Nix libraries
# are dynamic.
case "${host_os}" in
darwin*)
LDFLAGS="-all_load $LDFLAGS"
;;
esac
AC_ARG_WITH(sandbox-shell, AS_HELP_STRING([--with-sandbox-shell=PATH],[path of a statically-linked shell to use as /bin/sh in sandboxes]),
sandbox_shell=$withval)
AC_SUBST(sandbox_shell)

View File

@@ -6,9 +6,9 @@ builtins:
concatStrings (map
(name:
let builtin = builtins.${name}; in
"<dt id=\"builtins-${name}\"><a href=\"#builtins-${name}\"><code>${name} "
"<dt><code>${name} "
+ concatStringsSep " " (map (s: "<var>${s}</var>") builtin.args)
+ "</code></a></dt>"
+ "</code></dt>"
+ "<dd>\n\n"
+ builtin.doc
+ "\n\n</dd>"

View File

@@ -72,7 +72,6 @@ $(d)/builtins.json: $(bindir)/nix
@mv $@.tmp $@
# Generate the HTML manual.
html: $(docdir)/manual/index.html
install: $(docdir)/manual/index.html
# Generate 'nix' manpages.

View File

@@ -71,7 +71,7 @@
- [Hacking](contributing/hacking.md)
- [CLI guideline](contributing/cli-guideline.md)
- [Release Notes](release-notes/release-notes.md)
- [Release 2.7 (2022-03-07)](release-notes/rl-2.7.md)
- [Release X.Y (202?-??-??)](release-notes/rl-next.md)
- [Release 2.6 (2022-01-24)](release-notes/rl-2.6.md)
- [Release 2.5 (2021-12-13)](release-notes/rl-2.5.md)
- [Release 2.4 (2021-11-01)](release-notes/rl-2.4.md)

View File

@@ -1,33 +0,0 @@
# Release 2.7 (2022-03-07)
* Nix will now make some helpful suggestions when you mistype
something on the command line. For instance, if you type `nix build
nixpkgs#thunderbrd`, it will suggest `thunderbird`.
* A number of "default" flake output attributes have been
renamed. These are:
* `defaultPackage.<system>``packages.<system>.default`
* `defaultApps.<system>``apps.<system>.default`
* `defaultTemplate``templates.default`
* `defaultBundler.<system>``bundlers.<system>.default`
* `overlay``overlays.default`
* `devShell.<system>``devShells.<system>.default`
The old flake output attributes still work, but `nix flake check`
will warn about them.
* Breaking API change: `nix bundle` now supports bundlers of the form
`bundler.<system>.<name>= derivation: another-derivation;`. This
supports additional functionality to inspect evaluation information
during bundling. A new
[repository](https://github.com/NixOS/bundlers) has various bundlers
implemented.
* `nix store ping` now reports the version of the remote Nix daemon.
* `nix flake {init,new}` now display information about which files have been
created.
* Templates can now define a `welcomeText` attribute, which is printed out by
`nix flake {init,new} --template <template>`.

View File

@@ -1 +1,15 @@
# Release X.Y (202?-??-??)
* `nix bundle` breaking API change now supports bundlers of the form
`bundler.<system>.<name>= derivation: another-derivation;`. This supports
additional functionality to inspect evaluation information during bundling. A
new [repository](https://github.com/NixOS/bundlers) has various bundlers
implemented.
* `nix store ping` now reports the version of the remote Nix daemon.
* `nix flake {init,new}` now display information about which files have been
created.
* Templates can now define a `welcomeText` attribute, which is printed out by
`nix flake {init,new} --template <template>`.

8
flake.lock generated
View File

@@ -18,16 +18,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1656604668,
"narHash": "sha256-5g8ll8kgstMtdAhKdAfkv5YuhmxVE+77IuFBubK3i3k=",
"lastModified": 1632864508,
"narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e1029c6170ccec08a5fc0123a4cca1779a0cd43d",
"rev": "82891b5e2c2359d7e58d08849e4c89511ab94234",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.05-small",
"ref": "nixos-21.05-small",
"type": "indirect"
}
},

View File

@@ -1,7 +1,7 @@
{
description = "The purely functional package manager";
inputs.nixpkgs.url = "nixpkgs/nixos-22.05-small";
inputs.nixpkgs.url = "nixpkgs/nixos-21.05-small";
inputs.nixpkgs-regression.url = "nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
inputs.lowdown-src = { url = "github:kristapsdz/lowdown"; flake = false; };
@@ -15,7 +15,7 @@
then ""
else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}";
officialRelease = true;
officialRelease = false;
linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ];
linuxSystems = linux64BitSystems ++ [ "i686-linux" ];
@@ -403,23 +403,6 @@
BINDIR=${placeholder "bin"}/bin
'';
};
nix-find-roots = prev.stdenv.mkDerivation {
name = "nix-find-roots-${version}";
inherit version;
src = "${self}/src/nix-find-roots";
CXXFLAGS = prev.lib.optionalString prev.stdenv.hostPlatform.isStatic "-static";
buildPhase = ''
$CXX $CXXFLAGS -std=c++17 *.cc **/*.cc -I lib -o nix-find-roots
'';
installPhase = ''
mkdir -p $out/bin
cp nix-find-roots $out/bin/
'';
};
};
in {
@@ -550,26 +533,28 @@
nixpkgs = nixpkgs-regression;
};
installTests = forAllSystems (system:
installTestsAgainstSelf = forAllSystems (system:
let pkgs = nixpkgsFor.${system}; in
pkgs.runCommand "install-tests" {
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
againstCurrentUnstable =
# FIXME: temporarily disable this on macOS because of #3605.
if system == "x86_64-linux"
then testNixVersions pkgs pkgs.nix pkgs.nixUnstable
else null;
# Disabled because the latest stable version doesn't handle
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
} "touch $out");
testNixVersions pkgs pkgs.nix pkgs.pkgs.nix
);
installTestsAgainstCurrentUnstable = forAllSystems (system:
let pkgs = nixpkgsFor.${system}; in
# FIXME: temporarily disable this on macOS because of #3605.
if system == "x86_64-linux"
then testNixVersions pkgs pkgs.nix pkgs.nixUnstable
else pkgs.writeText "dummy" "dummy"
);
# Disabled because the latest stable version doesn't handle
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
};
checks = forAllSystems (system: {
binaryTarball = self.hydraJobs.binaryTarball.${system};
perlBindings = self.hydraJobs.perlBindings.${system};
installTests = self.hydraJobs.installTests.${system};
installTestsAgainstCurrentUnstable = self.hydraJobs.installTestsAgainstCurrentUnstable.${system};
installTestsAgainstSelf = self.hydraJobs.installTestsAgainstSelf.${system};
} // (nixpkgs.lib.optionalAttrs (builtins.elem system linux64BitSystems)) {
dockerImage = self.hydraJobs.dockerImage.${system};
});
@@ -577,7 +562,6 @@
packages = forAllSystems (system: {
inherit (nixpkgsFor.${system}) nix;
} // (nixpkgs.lib.optionalAttrs (builtins.elem system linux64BitSystems) {
inherit (nixpkgsFor.${system}.pkgsStatic) nix-find-roots;
nix-static = let
nixpkgs = nixpkgsFor.${system}.pkgsStatic;
in with commonDeps nixpkgs; nixpkgs.stdenv.mkDerivation {

View File

@@ -7,6 +7,8 @@ green=""
yellow=""
normal=""
TESTS_TIMER_LOG=${TESTS_TIMER_LOG:-/dev/null}
post_run_msg="ran test $1..."
if [ -t 1 ]; then
red=""
@@ -14,33 +16,22 @@ if [ -t 1 ]; then
yellow=""
normal=""
fi
(cd tests && env ${TESTS_ENVIRONMENT} init.sh 2>/dev/null > /dev/null)
run_test () {
(cd tests && env ${TESTS_ENVIRONMENT} init.sh 2>/dev/null > /dev/null)
log="$(cd $(dirname $1) && env ${TESTS_ENVIRONMENT} $(basename $1) 2>&1)"
status=$?
}
run_test "$1"
# Hack: Retry the test if it fails with “unexpected EOF reading a line” as these
# appear randomly without anyone knowing why.
# See https://github.com/NixOS/nix/issues/3605 for more info
if [[ $status -ne 0 && $status -ne 99 && \
"$(uname)" == "Darwin" && \
"$log" =~ "unexpected EOF reading a line" \
]]; then
echo "$post_run_msg [${yellow}FAIL$normal] (possibly flaky, so will be retried)"
echo "$log" | sed 's/^/ /'
run_test "$1"
fi
start_time=$(date -u +%s)
echo "$(date -u +%s) $1 start" >> "$TESTS_TIMER_LOG"
log="$(cd $(dirname $1) && env ${TESTS_ENVIRONMENT} $(basename $1) 2>&1)"
status=$?
echo "$(date -u +%s) $1 stop" >> "$TESTS_TIMER_LOG"
stop_time=$(date -u +%s)
elapsed_time=$(($stop_time-$start_time))
if [ $status -eq 0 ]; then
echo "$post_run_msg [${green}PASS$normal]"
echo "$post_run_msg [${green}PASS$normal] in ${elapsed_time}s"
elif [ $status -eq 99 ]; then
echo "$post_run_msg [${yellow}SKIP$normal]"
echo "$post_run_msg [${yellow}SKIP$normal] after ${elapsed_time}s"
else
echo "$post_run_msg [${red}FAIL$normal]"
echo "$post_run_msg [${red}FAIL$normal] in ${elapsed_time}s"
echo "$log" | sed 's/^/ /'
exit "$status"
fi

View File

@@ -240,7 +240,7 @@ SV * convertHash(char * algo, char * s, int toBase32)
PPCODE:
try {
auto h = Hash::parseAny(s, parseHashType(algo));
auto s = h.to_string(toBase32 ? Base32 : Base16, false);
string s = h.to_string(toBase32 ? Base32 : Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());

View File

@@ -246,8 +246,7 @@ get_volume_pass() {
verify_volume_pass() {
local volume_special="$1" # (i.e., disk1s7)
local volume_uuid="$2"
_sudo "to confirm the password actually unlocks the volume" \
/usr/sbin/diskutil apfs unlockVolume "$volume_special" -verify -stdinpassphrase -user "$volume_uuid"
/usr/sbin/diskutil apfs unlockVolume "$volume_special" -verify -stdinpassphrase -user "$volume_uuid"
}
volume_pass_works() {
@@ -686,27 +685,22 @@ encrypt_volume() {
local volume_uuid="$1"
local volume_label="$2"
local password
task "Encrypt the Nix volume" >&2
# Note: mount/unmount are late additions to support the right order
# of operations for creating the volume and then baking its uuid into
# other artifacts; not as well-trod wrt to potential errors, race
# conditions, etc.
_sudo "to mount your Nix volume for encrypting" \
/usr/sbin/diskutil mount "$volume_label"
/usr/sbin/diskutil mount "$volume_label"
password="$(/usr/bin/xxd -l 32 -p -c 256 /dev/random)"
_sudo "to add your Nix volume's password to Keychain" \
/usr/bin/security -i <<EOF
add-generic-password -a "$volume_label" -s "$volume_uuid" -l "$volume_label encryption password" -D "Encrypted volume password" -j "Added automatically by the Nix installer for use by $NIX_VOLUME_MOUNTD_DEST" -w "$password" -T /System/Library/CoreServices/APFSUserAgent -T /System/Library/CoreServices/CSUserAgent -T /usr/bin/security "/Library/Keychains/System.keychain"
EOF
builtin printf "%s" "$password" | _sudo "to actually encrypt your Nix volume" \
builtin printf "%s" "$password" | _sudo "to encrypt your Nix volume" \
/usr/sbin/diskutil apfs encryptVolume "$volume_label" -user disk -stdinpassphrase
_sudo "to unmount the encrypted volume" \
/usr/sbin/diskutil unmount force "$volume_label"
/usr/sbin/diskutil unmount force "$volume_label"
}
create_volume() {

View File

@@ -23,10 +23,10 @@ readonly RED='\033[31m'
# installer allows overriding build user count to speed up installation
# as creating each user takes non-trivial amount of time on macos
readonly NIX_USER_COUNT=${NIX_USER_COUNT:-32}
readonly NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-30000}"
readonly NIX_BUILD_GROUP_ID="30000"
readonly NIX_BUILD_GROUP_NAME="nixbld"
# darwin installer needs to override these
NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-30001}"
NIX_FIRST_BUILD_UID="30001"
NIX_BUILD_USER_NAME_TEMPLATE="nixbld%d"
# Please don't change this. We don't support it, because the
# default shell profile that comes with Nix doesn't support it.

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
set -x
nix build --inputs-from . nixpkgs#jq -o jq
TEST_NAMES=$(nix flake show . --json | ./jq-bin/bin/jq -c ".checks[\"$(nix eval --raw --impure --expr builtins.currentSystem)\"] | keys")
echo "::set-output name=json::$TEST_NAMES"

View File

@@ -14,7 +14,6 @@
#include "pathlocks.hh"
#include "globals.hh"
#include "serialise.hh"
#include "build-result.hh"
#include "store-api.hh"
#include "derivations.hh"
#include "local-store.hh"
@@ -33,7 +32,7 @@ std::string escapeUri(std::string uri)
return uri;
}
static std::string currentLoad;
static string currentLoad;
static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot)
{
@@ -98,7 +97,7 @@ static int main_build_remote(int argc, char * * argv)
}
std::optional<StorePath> drvPath;
std::string storeUri;
string storeUri;
while (true) {
@@ -184,7 +183,7 @@ static int main_build_remote(int argc, char * * argv)
else
{
// build the hint template.
std::string errorText =
string errorText =
"Failed to find a machine for remote build!\n"
"derivation: %s\nrequired (system, features): (%s, %s)";
errorText += "\n%s available machines:";
@@ -194,7 +193,7 @@ static int main_build_remote(int argc, char * * argv)
errorText += "\n(%s, %s, %s, %s)";
// add the template values.
std::string drvstr;
string drvstr;
if (drvPath.has_value())
drvstr = drvPath->to_string();
else
@@ -209,7 +208,7 @@ static int main_build_remote(int argc, char * * argv)
for (auto & m : machines)
error
% concatStringsSep<std::vector<std::string>>(", ", m.systemTypes)
% concatStringsSep<std::vector<string>>(", ", m.systemTypes)
% m.maxJobs
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);

View File

@@ -153,7 +153,7 @@ void BuiltPathsCommand::run(ref<Store> store)
for (auto & p : store->queryAllValidPaths())
paths.push_back(BuiltPath::Opaque{p});
} else {
paths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
paths = toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
if (recursive) {
// XXX: This only computes the store path closure, ignoring
// intermediate realisations

View File

@@ -5,6 +5,7 @@
#include "common-eval-args.hh"
#include "path.hh"
#include "flake/lockfile.hh"
#include "store-api.hh"
#include <optional>
@@ -81,6 +82,14 @@ struct MixFlakeOptions : virtual Args, EvalCommand
{ return {}; }
};
/* How to handle derivations in commands that operate on store paths. */
enum class OperateOn {
/* Operate on the output path. */
Output,
/* Operate on the .drv path. */
Derivation
};
struct SourceExprCommand : virtual Args, MixFlakeOptions
{
std::optional<Path> file;
@@ -104,6 +113,19 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
void completeInstallable(std::string_view prefix);
};
enum class Realise {
/* Build the derivation. Postcondition: the
derivation outputs exist. */
Outputs,
/* Don't build the derivation. Postcondition: the store derivation
exists. */
Derivation,
/* Evaluate in dry-run mode. Postcondition: nothing. */
// FIXME: currently unused, but could be revived if we can
// evaluate derivations in-memory.
Nothing
};
/* A command that operates on a list of "installables", which can be
store paths, attribute paths, Nix expressions, etc. */
struct InstallablesCommand : virtual Args, SourceExprCommand
@@ -216,6 +238,38 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
}
BuiltPaths build(
ref<Store> evalStore,
ref<Store> store, Realise mode,
const std::vector<std::shared_ptr<Installable>> & installables,
BuildMode bMode = bmNormal);
std::set<StorePath> toStorePaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
const std::vector<std::shared_ptr<Installable>> & installables);
StorePath toStorePath(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
std::shared_ptr<Installable> installable);
std::set<StorePath> toDerivations(
ref<Store> store,
const std::vector<std::shared_ptr<Installable>> & installables,
bool useDeriver = false);
BuiltPaths toBuiltPaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
const std::vector<std::shared_ptr<Installable>> & installables);
/* Helper function to generate args that invoke $EDITOR on
filename:lineno. */
Strings editorFor(const Pos & pos);

View File

@@ -158,10 +158,7 @@ SourceExprCommand::SourceExprCommand()
Strings SourceExprCommand::getDefaultFlakeAttrPaths()
{
return {
"packages." + settings.thisSystem.get() + ".default",
"defaultPackage." + settings.thisSystem.get()
};
return {"defaultPackage." + settings.thisSystem.get()};
}
Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
@@ -272,9 +269,9 @@ void completeFlakeRefWithFragment(
auto attr = root->findAlongAttrPath(attrPath);
if (!attr) continue;
for (auto & attr2 : (*attr)->getAttrs()) {
for (auto & attr2 : attr->getAttrs()) {
if (hasPrefix(attr2, lastAttr)) {
auto attrPath2 = (*attr)->getAttrPath(attr2);
auto attrPath2 = attr->getAttrPath(attr2);
/* Strip the attrpath prefix. */
attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size());
completions->add(flakeRefS + "#" + concatStringsSep(".", attrPath2));
@@ -468,10 +465,11 @@ std::vector<InstallableValue::DerivationInfo> InstallableAttrPath::toDerivations
std::vector<DerivationInfo> res;
for (auto & drvInfo : drvInfos) {
auto drvPath = drvInfo.queryDrvPath();
if (!drvPath)
throw Error("'%s' is not a derivation", what());
res.push_back({ *drvPath, drvInfo.queryOutputName() });
res.push_back({
state->store->parseStorePath(drvInfo.queryDrvPath()),
state->store->maybeParseStorePath(drvInfo.queryOutPath()),
drvInfo.queryOutputName()
});
}
return res;
@@ -568,37 +566,31 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
auto cache = openEvalCache(*state, lockedFlake);
auto root = cache->getRoot();
Suggestions suggestions;
for (auto & attrPath : getActualAttrPaths()) {
debug("trying flake output attribute '%s'", attrPath);
auto attrOrSuggestions = root->findAlongAttrPath(
auto attr = root->findAlongAttrPath(
parseAttrPath(*state, attrPath),
true
);
if (!attrOrSuggestions) {
suggestions += attrOrSuggestions.getSuggestions();
continue;
}
auto attr = *attrOrSuggestions;
if (!attr) continue;
if (!attr->isDerivation())
throw Error("flake output attribute '%s' is not a derivation", attrPath);
auto drvPath = attr->forceDerivation();
auto drvInfo = DerivationInfo {
auto drvInfo = DerivationInfo{
std::move(drvPath),
state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()),
attr->getAttr(state->sOutputName)->getString()
};
return {attrPath, lockedFlake->flake.lockedRef, std::move(drvInfo)};
}
throw Error(suggestions, "flake '%s' does not provide attribute %s",
throw Error("flake '%s' does not provide attribute %s",
flakeRef, showAttrPaths(getActualAttrPaths()));
}
@@ -617,24 +609,17 @@ std::pair<Value *, Pos> InstallableFlake::toValue(EvalState & state)
auto emptyArgs = state.allocBindings(0);
Suggestions suggestions;
for (auto & attrPath : getActualAttrPaths()) {
try {
auto [v, pos] = findAlongAttrPath(state, attrPath, *emptyArgs, *vOutputs);
state.forceValue(*v, pos);
return {v, pos};
} catch (AttrPathNotFound & e) {
suggestions += e.info().suggestions;
}
}
throw Error(
suggestions,
"flake '%s' does not provide attribute %s",
flakeRef,
showAttrPaths(getActualAttrPaths())
);
throw Error("flake '%s' does not provide attribute %s",
flakeRef, showAttrPaths(getActualAttrPaths()));
}
std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
@@ -649,7 +634,7 @@ InstallableFlake::getCursors(EvalState & state)
for (auto & attrPath : getActualAttrPaths()) {
auto attr = root->findAlongAttrPath(parseAttrPath(state, attrPath));
if (attr) res.push_back({*attr, attrPath});
if (attr) res.push_back({attr, attrPath});
}
return res;
@@ -799,7 +784,7 @@ BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPa
return res;
}
BuiltPaths Installable::build(
BuiltPaths build(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
@@ -824,7 +809,7 @@ BuiltPaths Installable::build(
return getBuiltPaths(evalStore, store, pathsToBuild);
}
BuiltPaths Installable::toBuiltPaths(
BuiltPaths toBuiltPaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
@@ -832,19 +817,19 @@ BuiltPaths Installable::toBuiltPaths(
const std::vector<std::shared_ptr<Installable>> & installables)
{
if (operateOn == OperateOn::Output)
return Installable::build(evalStore, store, mode, installables);
return build(evalStore, store, mode, installables);
else {
if (mode == Realise::Nothing)
settings.readOnlyMode = true;
BuiltPaths res;
for (auto & drvPath : Installable::toDerivations(store, installables, true))
for (auto & drvPath : toDerivations(store, installables, true))
res.push_back(BuiltPath::Opaque{drvPath});
return res;
}
}
StorePathSet Installable::toStorePaths(
StorePathSet toStorePaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn,
@@ -858,7 +843,7 @@ StorePathSet Installable::toStorePaths(
return outPaths;
}
StorePath Installable::toStorePath(
StorePath toStorePath(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn,
@@ -872,7 +857,7 @@ StorePath Installable::toStorePath(
return *paths.begin();
}
StorePathSet Installable::toDerivations(
StorePathSet toDerivations(
ref<Store> store,
const std::vector<std::shared_ptr<Installable>> & installables,
bool useDeriver)

View File

@@ -5,7 +5,6 @@
#include "path-with-outputs.hh"
#include "derived-path.hh"
#include "eval.hh"
#include "store-api.hh"
#include "flake/flake.hh"
#include <optional>
@@ -30,27 +29,6 @@ struct UnresolvedApp
App resolve(ref<Store> evalStore, ref<Store> store);
};
enum class Realise {
/* Build the derivation. Postcondition: the
derivation outputs exist. */
Outputs,
/* Don't build the derivation. Postcondition: the store derivation
exists. */
Derivation,
/* Evaluate in dry-run mode. Postcondition: nothing. */
// FIXME: currently unused, but could be revived if we can
// evaluate derivations in-memory.
Nothing
};
/* How to handle derivations in commands that operate on store paths. */
enum class OperateOn {
/* Operate on the output path. */
Output,
/* Operate on the .drv path. */
Derivation
};
struct Installable
{
virtual ~Installable() { }
@@ -90,39 +68,6 @@ struct Installable
{
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
}
static BuiltPaths build(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
const std::vector<std::shared_ptr<Installable>> & installables,
BuildMode bMode = bmNormal);
static std::set<StorePath> toStorePaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
const std::vector<std::shared_ptr<Installable>> & installables);
static StorePath toStorePath(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
std::shared_ptr<Installable> installable);
static std::set<StorePath> toDerivations(
ref<Store> store,
const std::vector<std::shared_ptr<Installable>> & installables,
bool useDeriver = false);
static BuiltPaths toBuiltPaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
const std::vector<std::shared_ptr<Installable>> & installables);
};
struct InstallableValue : Installable
@@ -134,6 +79,7 @@ struct InstallableValue : Installable
struct DerivationInfo
{
StorePath drvPath;
std::optional<StorePath> outPath;
std::string outputName;
};
@@ -185,9 +131,4 @@ ref<eval_cache::EvalCache> openEvalCache(
EvalState & state,
std::shared_ptr<flake::LockedFlake> lockedFlake);
BuiltPaths getBuiltPaths(
ref<Store> evalStore,
ref<Store> store,
const DerivedPaths & hopefullyBuiltPaths);
}

View File

@@ -9,7 +9,7 @@ namespace nix {
static Strings parseAttrPath(std::string_view s)
{
Strings res;
std::string cur;
string cur;
auto i = s.begin();
while (i != s.end()) {
if (*i == '.') {
@@ -41,7 +41,7 @@ std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s)
}
std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const std::string & attrPath,
std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn)
{
Strings tokens = parseAttrPath(attrPath);
@@ -74,14 +74,8 @@ std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const std::string &
throw Error("empty attribute name in selection path '%1%'", attrPath);
Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
if (a == v->attrs->end()) {
std::set<std::string> attrNames;
for (auto & attr : *v->attrs)
attrNames.insert(attr.name);
auto suggestions = Suggestions::bestMatches(attrNames, attr);
throw AttrPathNotFound(suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath);
}
if (a == v->attrs->end())
throw AttrPathNotFound("attribute '%1%' in selection path '%2%' not found", attr, attrPath);
v = &*a->value;
pos = *a->pos;
}
@@ -127,7 +121,7 @@ Pos findPackageFilename(EvalState & state, Value & v, std::string what)
std::string filename(pos, 0, colon);
unsigned int lineno;
try {
lineno = std::stoi(std::string(pos, colon + 1, std::string::npos));
lineno = std::stoi(std::string(pos, colon + 1, string::npos));
} catch (std::invalid_argument & e) {
throw ParseError("cannot parse line number '%s'", pos);
}

View File

@@ -10,11 +10,8 @@ namespace nix {
MakeError(AttrPathNotFound, Error);
MakeError(NoPositionInfo, Error);
std::pair<Value *, Pos> findAlongAttrPath(
EvalState & state,
const std::string & attrPath,
Bindings & autoArgs,
Value & vIn);
std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn);
/* Heuristic to find the filename and lineno or a nix value. */
Pos findPackageFilename(EvalState & state, Value & v, std::string what);

View File

@@ -105,7 +105,7 @@ public:
for (size_t n = 0; n < size_; n++)
res.emplace_back(&attrs[n]);
std::sort(res.begin(), res.end(), [](const Attr * a, const Attr * b) {
return (const std::string &) a->name < (const std::string &) b->name;
return (const string &) a->name < (const string &) b->name;
});
return res;
}

View File

@@ -77,7 +77,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
for (auto & i : autoArgs) {
auto v = state.allocValue();
if (i.second[0] == 'E')
state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), absPath(".")));
state.mkThunk_(*v, state.parseExprFromString(string(i.second, 1), absPath(".")));
else
v->mkString(((std::string_view) i.second).substr(1));
res.insert(state.symbols.create(i.first), v);
@@ -85,17 +85,17 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
return res.finish();
}
Path lookupFileArg(EvalState & state, std::string_view s)
Path lookupFileArg(EvalState & state, string s)
{
if (isUri(s)) {
return state.store->toRealPath(
fetchers::downloadTarball(
state.store, resolveUri(s), "source", false).first.storePath);
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p(s.substr(1, s.size() - 2));
Path p = s.substr(1, s.size() - 2);
return state.findFile(p);
} else
return absPath(std::string(s));
return absPath(s);
}
}

View File

@@ -22,6 +22,6 @@ private:
std::map<std::string, std::string> autoArgs;
};
Path lookupFileArg(EvalState & state, std::string_view s);
Path lookupFileArg(EvalState & state, string s);
}

View File

@@ -406,16 +406,6 @@ Value & AttrCursor::forceValue()
return v;
}
Suggestions AttrCursor::getSuggestionsForAttr(Symbol name)
{
auto attrNames = getAttrs();
std::set<std::string> strAttrNames;
for (auto & name : attrNames)
strAttrNames.insert(std::string(name));
return Suggestions::bestMatches(strAttrNames, name);
}
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErrors)
{
if (root->db) {
@@ -456,11 +446,6 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
return nullptr;
//throw TypeError("'%s' is not an attribute set", getAttrPathStr());
for (auto & attr : *v.attrs) {
if (root->db)
root->db->setPlaceholder({cachedValue->first, attr.name});
}
auto attr = v.attrs->get(name);
if (!attr) {
@@ -479,7 +464,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
cachedValue2 = {root->db->setPlaceholder({cachedValue->first, name}), placeholder_t()};
}
return make_ref<AttrCursor>(
return std::make_shared<AttrCursor>(
root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2));
}
@@ -488,31 +473,27 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
return maybeGetAttr(root->state.symbols.create(name));
}
ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
std::shared_ptr<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
{
auto p = maybeGetAttr(name, forceErrors);
if (!p)
throw Error("attribute '%s' does not exist", getAttrPathStr(name));
return ref(p);
return p;
}
ref<AttrCursor> AttrCursor::getAttr(std::string_view name)
std::shared_ptr<AttrCursor> AttrCursor::getAttr(std::string_view name)
{
return getAttr(root->state.symbols.create(name));
}
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
std::shared_ptr<AttrCursor> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
{
auto res = shared_from_this();
for (auto & attr : attrPath) {
auto child = res->maybeGetAttr(attr, force);
if (!child) {
auto suggestions = res->getSuggestionsForAttr(attr);
return OrSuggestions<ref<AttrCursor>>::failed(suggestions);
}
res = child;
res = res->maybeGetAttr(attr, force);
if (!res) return {};
}
return ref(res);
return res;
}
std::string AttrCursor::getString()
@@ -615,7 +596,7 @@ std::vector<Symbol> AttrCursor::getAttrs()
for (auto & attr : *getValue().attrs)
attrs.push_back(attr.name);
std::sort(attrs.begin(), attrs.end(), [](const Symbol & a, const Symbol & b) {
return (const std::string &) a < (const std::string &) b;
return (const string &) a < (const string &) b;
});
if (root->db)

View File

@@ -94,17 +94,15 @@ public:
std::string getAttrPathStr(Symbol name) const;
Suggestions getSuggestionsForAttr(Symbol name);
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false);
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
ref<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
std::shared_ptr<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
ref<AttrCursor> getAttr(std::string_view name);
std::shared_ptr<AttrCursor> getAttr(std::string_view name);
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false);
std::shared_ptr<AttrCursor> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false);
std::string getString();

View File

@@ -63,15 +63,9 @@ static char * dupString(const char * s)
}
// When there's no need to write to the string, we can optimize away empty
// string allocations.
// This function handles makeImmutableStringWithLen(null, 0) by returning the
// empty string.
static const char * makeImmutableStringWithLen(const char * s, size_t size)
static char * dupStringWithLen(const char * s, size_t size)
{
char * t;
if (size == 0)
return "";
#if HAVE_BOEHMGC
t = GC_STRNDUP(s, size);
#else
@@ -81,10 +75,6 @@ static const char * makeImmutableStringWithLen(const char * s, size_t size)
return t;
}
static inline const char * makeImmutableString(std::string_view s) {
return makeImmutableStringWithLen(s.data(), s.size());
}
RootValue allocRootValue(Value * v)
{
@@ -96,20 +86,25 @@ RootValue allocRootValue(Value * v)
}
void Value::print(std::ostream & str, std::set<const void *> * seen) const
void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v)
{
checkInterrupt();
switch (internalType) {
if (!active.insert(&v).second) {
str << "<CYCLE>";
return;
}
switch (v.internalType) {
case tInt:
str << integer;
str << v.integer;
break;
case tBool:
str << (boolean ? "true" : "false");
str << (v.boolean ? "true" : "false");
break;
case tString:
str << "\"";
for (const char * i = string.s; *i; i++)
for (const char * i = v.string.s; *i; i++)
if (*i == '\"' || *i == '\\') str << "\\" << *i;
else if (*i == '\n') str << "\\n";
else if (*i == '\r') str << "\\r";
@@ -119,38 +114,30 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
str << "\"";
break;
case tPath:
str << path; // !!! escaping?
str << v.path; // !!! escaping?
break;
case tNull:
str << "null";
break;
case tAttrs: {
if (seen && !attrs->empty() && !seen->insert(attrs).second)
str << "«repeated»";
else {
str << "{ ";
for (auto & i : attrs->lexicographicOrder()) {
str << i->name << " = ";
i->value->print(str, seen);
str << "; ";
}
str << "}";
str << "{ ";
for (auto & i : v.attrs->lexicographicOrder()) {
str << i->name << " = ";
printValue(str, active, *i->value);
str << "; ";
}
str << "}";
break;
}
case tList1:
case tList2:
case tListN:
if (seen && listSize() && !seen->insert(listElems()).second)
str << "«repeated»";
else {
str << "[ ";
for (auto v2 : listItems()) {
v2->print(str, seen);
str << " ";
}
str << "]";
str << "[ ";
for (auto v2 : v.listItems()) {
printValue(str, active, *v2);
str << " ";
}
str << "]";
break;
case tThunk:
case tApp:
@@ -166,32 +153,28 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
str << "<PRIMOP-APP>";
break;
case tExternal:
str << *external;
str << *v.external;
break;
case tFloat:
str << fpoint;
str << v.fpoint;
break;
default:
abort();
}
}
void Value::print(std::ostream & str, bool showRepeated) const
{
std::set<const void *> seen;
print(str, showRepeated ? nullptr : &seen);
active.erase(&v);
}
std::ostream & operator << (std::ostream & str, const Value & v)
{
v.print(str, false);
std::set<const Value *> active;
printValue(str, active, v);
return str;
}
const Value * getPrimOp(const Value &v) {
const Value *getPrimOp(const Value &v) {
const Value * primOp = &v;
while (primOp->isPrimOpApp()) {
primOp = primOp->primOpApp.left;
@@ -200,7 +183,7 @@ const Value * getPrimOp(const Value &v) {
return primOp;
}
std::string_view showType(ValueType type)
string showType(ValueType type)
{
switch (type) {
case nInt: return "an integer";
@@ -219,20 +202,20 @@ std::string_view showType(ValueType type)
}
std::string showType(const Value & v)
string showType(const Value & v)
{
switch (v.internalType) {
case tString: return v.string.context ? "a string with context" : "a string";
case tPrimOp:
return fmt("the built-in function '%s'", std::string(v.primOp->name));
return fmt("the built-in function '%s'", string(v.primOp->name));
case tPrimOpApp:
return fmt("the partially applied built-in function '%s'", std::string(getPrimOp(v)->primOp->name));
return fmt("the partially applied built-in function '%s'", string(getPrimOp(v)->primOp->name));
case tExternal: return v.external->showType();
case tThunk: return "a thunk";
case tApp: return "a function application";
case tBlackhole: return "a black hole";
default:
return std::string(showType(v.type()));
return showType(v.type());
}
}
@@ -373,7 +356,7 @@ void initGC()
/* Very hacky way to parse $NIX_PATH, which is colon-separated, but
can contain URLs (e.g. "nixpkgs=https://bla...:foo=https://"). */
static Strings parseNixPath(const std::string & s)
static Strings parseNixPath(const string & s)
{
Strings res;
@@ -534,14 +517,6 @@ void EvalState::allowPath(const StorePath & storePath)
allowedPaths->insert(store->toRealPath(storePath));
}
void EvalState::allowAndSetStorePathString(const StorePath &storePath, Value & v)
{
allowPath(storePath);
auto path = store->printStorePath(storePath);
v.mkString(path, PathSet({path}));
}
Path EvalState::checkSourcePath(const Path & path_)
{
if (!allowedPaths) return path_;
@@ -631,7 +606,7 @@ Path EvalState::toRealPath(const Path & path, const PathSet & context)
}
Value * EvalState::addConstant(const std::string & name, Value & v)
Value * EvalState::addConstant(const string & name, Value & v)
{
Value * v2 = allocValue();
*v2 = v;
@@ -640,19 +615,19 @@ Value * EvalState::addConstant(const std::string & name, Value & v)
}
void EvalState::addConstant(const std::string & name, Value * v)
void EvalState::addConstant(const string & name, Value * v)
{
staticBaseEnv.vars.emplace_back(symbols.create(name), baseEnvDispl);
baseEnv.values[baseEnvDispl++] = v;
auto name2 = name.substr(0, 2) == "__" ? name.substr(2) : name;
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v));
}
Value * EvalState::addPrimOp(const std::string & name,
Value * EvalState::addPrimOp(const string & name,
size_t arity, PrimOpFun primOp)
{
auto name2 = name.substr(0, 2) == "__" ? name.substr(2) : name;
auto name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
Symbol sym = symbols.create(name2);
/* Hack to make constants lazy: turn them into a application of
@@ -700,7 +675,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
}
Value & EvalState::getBuiltin(const std::string & name)
Value & EvalState::getBuiltin(const string & name)
{
return *baseEnv.values[0]->attrs->find(symbols.create(name))->value;
}
@@ -728,12 +703,12 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
evaluator. So here are some helper functions for throwing
exceptions. */
LocalNoInlineNoReturn(void throwEvalError(const char * s, const std::string & s2))
LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2))
{
throw EvalError(s, s2);
}
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const std::string & s2))
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2))
{
throw EvalError({
.msg = hintfmt(s, s2),
@@ -741,12 +716,12 @@ LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const
});
}
LocalNoInlineNoReturn(void throwEvalError(const char * s, const std::string & s2, const std::string & s3))
LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, const string & s3))
{
throw EvalError(s, s2, s3);
}
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const std::string & s2, const std::string & s3))
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2, const string & s3))
{
throw EvalError({
.msg = hintfmt(s, s2, s3),
@@ -784,7 +759,7 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
throw TypeError(s, showType(v));
}
LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s, const std::string & s1))
LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s, const string & s1))
{
throw AssertionError({
.msg = hintfmt(s, s1),
@@ -792,7 +767,7 @@ LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s,
});
}
LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char * s, const std::string & s1))
LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char * s, const string & s1))
{
throw UndefinedVarError({
.msg = hintfmt(s, s1),
@@ -800,7 +775,7 @@ LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char *
});
}
LocalNoInlineNoReturn(void throwMissingArgumentError(const Pos & pos, const char * s, const std::string & s1))
LocalNoInlineNoReturn(void throwMissingArgumentError(const Pos & pos, const char * s, const string & s1))
{
throw MissingArgumentError({
.msg = hintfmt(s, s1),
@@ -808,12 +783,12 @@ LocalNoInlineNoReturn(void throwMissingArgumentError(const Pos & pos, const char
});
}
LocalNoInline(void addErrorTrace(Error & e, const char * s, const std::string & s2))
LocalNoInline(void addErrorTrace(Error & e, const char * s, const string & s2))
{
e.addTrace(std::nullopt, s, s2);
}
LocalNoInline(void addErrorTrace(Error & e, const Pos & pos, const char * s, const std::string & s2))
LocalNoInline(void addErrorTrace(Error & e, const Pos & pos, const char * s, const string & s2))
{
e.addTrace(pos, s, s2);
}
@@ -821,7 +796,7 @@ LocalNoInline(void addErrorTrace(Error & e, const Pos & pos, const char * s, con
void Value::mkString(std::string_view s)
{
mkString(makeImmutableString(s));
mkString(dupStringWithLen(s.data(), s.size()));
}
@@ -852,7 +827,7 @@ void Value::mkStringMove(const char * s, const PathSet & context)
void Value::mkPath(std::string_view s)
{
mkPath(makeImmutableString(s));
mkPath(dupStringWithLen(s.data(), s.size()));
}
@@ -1246,7 +1221,7 @@ void ExprVar::eval(EvalState & state, Env & env, Value & v)
}
static std::string showAttrPath(EvalState & state, Env & env, const AttrPath & attrPath)
static string showAttrPath(EvalState & state, Env & env, const AttrPath & attrPath)
{
std::ostringstream out;
bool first = true;
@@ -1420,7 +1395,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
if (loggerSettings.showTrace.get()) {
addErrorTrace(e, lambda.pos, "while evaluating %s",
(lambda.name.set()
? "'" + (const std::string &) lambda.name + "'"
? "'" + (string) lambda.name + "'"
: "anonymous lambda"));
addErrorTrace(e, pos, "from call site%s", "");
}
@@ -1908,7 +1883,7 @@ std::string_view EvalState::forceString(Value & v, const Pos & pos)
/* Decode a context string !<name>!<path> into a pair <path,
name>. */
std::pair<std::string, std::string> decodeContext(std::string_view s)
std::pair<string, string> decodeContext(std::string_view s)
{
if (s.at(0) == '!') {
size_t index = s.find("!", 1);
@@ -1971,7 +1946,7 @@ bool EvalState::isDerivation(Value & v)
}
std::optional<std::string> EvalState::tryAttrsToString(const Pos & pos, Value & v,
std::optional<string> EvalState::tryAttrsToString(const Pos & pos, Value & v,
PathSet & context, bool coerceMore, bool copyToStore)
{
auto i = v.attrs->find(sToString);
@@ -2026,7 +2001,7 @@ BackedStringView EvalState::coerceToString(const Pos & pos, Value & v, PathSet &
if (v.type() == nNull) return "";
if (v.isList()) {
std::string result;
string result;
for (auto [n, v2] : enumerate(v.listItems())) {
result += *coerceToString(pos, *v2, context, coerceMore, copyToStore);
if (n < v.listSize() - 1
@@ -2042,7 +2017,7 @@ BackedStringView EvalState::coerceToString(const Pos & pos, Value & v, PathSet &
}
std::string EvalState::copyPathToStore(PathSet & context, const Path & path)
string EvalState::copyPathToStore(PathSet & context, const Path & path)
{
if (nix::isDerivation(path))
throwEvalError("file names are not allowed to end in '%1%'", drvExtension);
@@ -2068,25 +2043,13 @@ std::string EvalState::copyPathToStore(PathSet & context, const Path & path)
Path EvalState::coerceToPath(const Pos & pos, Value & v, PathSet & context)
{
auto path = coerceToString(pos, v, context, false, false).toOwned();
string path = coerceToString(pos, v, context, false, false).toOwned();
if (path == "" || path[0] != '/')
throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path);
return path;
}
StorePath EvalState::coerceToStorePath(const Pos & pos, Value & v, PathSet & context)
{
auto path = coerceToString(pos, v, context, false, false).toOwned();
if (auto storePath = store->maybeParseStorePath(path))
return *storePath;
throw EvalError({
.msg = hintfmt("path '%1%' is not in the Nix store", path),
.errPos = pos
});
}
bool EvalState::eqValues(Value & v1, Value & v2)
{
forceValue(v1, noPos);
@@ -2250,11 +2213,11 @@ void EvalState::printStats()
for (auto & i : functionCalls) {
auto obj = list.object();
if (i.first->name.set())
obj.attr("name", (const std::string &) i.first->name);
obj.attr("name", (const string &) i.first->name);
else
obj.attr("name", nullptr);
if (i.first->pos) {
obj.attr("file", (const std::string &) i.first->pos.file);
obj.attr("file", (const string &) i.first->pos.file);
obj.attr("line", i.first->pos.line);
obj.attr("column", i.first->pos.column);
}
@@ -2266,7 +2229,7 @@ void EvalState::printStats()
for (auto & i : attrSelects) {
auto obj = list.object();
if (i.first) {
obj.attr("file", (const std::string &) i.first.file);
obj.attr("file", (const string &) i.first.file);
obj.attr("line", i.first.line);
obj.attr("column", i.first.column);
}
@@ -2283,7 +2246,7 @@ void EvalState::printStats()
}
std::string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const
string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const
{
throw TypeError({
.msg = hintfmt("cannot coerce %1% to a string", showType()),

View File

@@ -150,7 +150,7 @@ public:
const Pos & pos
);
void addToSearchPath(const std::string & s);
void addToSearchPath(const string & s);
SearchPath getSearchPath() { return searchPath; }
@@ -161,9 +161,6 @@ public:
the real store path if `store` is a chroot store. */
void allowPath(const StorePath & storePath);
/* Allow access to a store path and return it as a string. */
void allowAndSetStorePathString(const StorePath & storePath, Value & v);
/* Check whether access to a path is allowed and throw an error if
not. Otherwise return the canonicalised path. */
Path checkSourcePath(const Path & path);
@@ -254,7 +251,7 @@ public:
set with attribute `type = "derivation"'). */
bool isDerivation(Value & v);
std::optional<std::string> tryAttrsToString(const Pos & pos, Value & v,
std::optional<string> tryAttrsToString(const Pos & pos, Value & v,
PathSet & context, bool coerceMore = false, bool copyToStore = true);
/* String coercion. Converts strings, paths and derivations to a
@@ -265,16 +262,13 @@ public:
bool coerceMore = false, bool copyToStore = true,
bool canonicalizePath = true);
std::string copyPathToStore(PathSet & context, const Path & path);
string copyPathToStore(PathSet & context, const Path & path);
/* Path coercion. Converts strings, paths and derivations to a
path. The result is guaranteed to be a canonicalised, absolute
path. Nothing is copied to the store. */
Path coerceToPath(const Pos & pos, Value & v, PathSet & context);
/* Like coerceToPath, but the result must be a store path. */
StorePath coerceToStorePath(const Pos & pos, Value & v, PathSet & context);
public:
/* The base environment, containing the builtin functions and
@@ -290,18 +284,18 @@ private:
void createBaseEnv();
Value * addConstant(const std::string & name, Value & v);
Value * addConstant(const string & name, Value & v);
void addConstant(const std::string & name, Value * v);
void addConstant(const string & name, Value * v);
Value * addPrimOp(const std::string & name,
Value * addPrimOp(const string & name,
size_t arity, PrimOpFun primOp);
Value * addPrimOp(PrimOp && primOp);
public:
Value & getBuiltin(const std::string & name);
Value & getBuiltin(const string & name);
struct Doc
{
@@ -420,12 +414,12 @@ private:
/* Return a string representing the type of the value `v'. */
std::string_view showType(ValueType type);
std::string showType(const Value & v);
string showType(ValueType type);
string showType(const Value & v);
/* Decode a context string !<name>!<path> into a pair <path,
name>. */
std::pair<std::string, std::string> decodeContext(std::string_view s);
std::pair<string, string> decodeContext(std::string_view s);
/* If `path' refers to a directory, then append "/default.nix". */
Path resolveExprPath(Path path);

View File

@@ -1,6 +1,5 @@
#include "flake.hh"
#include "globals.hh"
#include "fetch-settings.hh"
#include <nlohmann/json.hpp>
@@ -54,7 +53,7 @@ void ConfigFile::apply()
auto trustedList = readTrustedList();
bool trusted = false;
if (nix::fetchSettings.acceptFlakeConfig){
if (nix::settings.acceptFlakeConfig){
trusted = true;
} else if (auto saved = get(get(trustedList, name).value_or(std::map<std::string, bool>()), valueS)) {
trusted = *saved;

View File

@@ -6,7 +6,6 @@
#include "store-api.hh"
#include "fetchers.hh"
#include "finally.hh"
#include "fetch-settings.hh"
namespace nix {
@@ -255,7 +254,7 @@ static Flake getFlake(
for (auto & setting : *nixConfig->value->attrs) {
forceTrivialValue(state, *setting.value, *setting.pos);
if (setting.value->type() == nString)
flake.config.settings.insert({setting.name, std::string(state.forceStringNoCtx(*setting.value, *setting.pos))});
flake.config.settings.insert({setting.name, string(state.forceStringNoCtx(*setting.value, *setting.pos))});
else if (setting.value->type() == nPath) {
PathSet emptyContext = {};
flake.config.settings.emplace(
@@ -316,7 +315,7 @@ LockedFlake lockFlake(
FlakeCache flakeCache;
auto useRegistries = lockFlags.useRegistries.value_or(fetchSettings.useRegistries);
auto useRegistries = lockFlags.useRegistries.value_or(settings.useRegistries);
auto flake = getFlake(state, topRef, useRegistries, flakeCache);
@@ -502,7 +501,7 @@ LockedFlake lockFlake(
this input. */
debug("creating new input '%s'", inputPathS);
if (!lockFlags.allowMutable && !input.ref->input.isLocked())
if (!lockFlags.allowMutable && !input.ref->input.isImmutable())
throw Error("cannot update flake input '%s' in pure mode", inputPathS);
if (input.isFlake) {
@@ -592,7 +591,7 @@ LockedFlake lockFlake(
if (lockFlags.writeLockFile) {
if (auto sourcePath = topRef.input.getSourcePath()) {
if (!newLockFile.isImmutable()) {
if (fetchSettings.warnDirty)
if (settings.warnDirty)
warn("will not write lock file of flake '%s' because it has a mutable input", topRef);
} else {
if (!lockFlags.updateLockFile)
@@ -619,7 +618,7 @@ LockedFlake lockFlake(
if (lockFlags.commitLockFile) {
std::string cm;
cm = fetchSettings.commitLockFileSummary.get();
cm = settings.commitLockFileSummary.get();
if (cm == "") {
cm = fmt("%s: %s", relPath, lockFileExists ? "Update" : "Add");
@@ -651,7 +650,7 @@ LockedFlake lockFlake(
now. Corner case: we could have reverted from a
dirty to a clean tree! */
if (flake.lockedRef.input == prevLockedRef.input
&& !flake.lockedRef.input.isLocked())
&& !flake.lockedRef.input.isImmutable())
throw Error("'%s' did not change after I updated its 'flake.lock' file; is 'flake.lock' under version control?", flake.originalRef);
}
} else
@@ -708,16 +707,16 @@ static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Va
{
state.requireExperimentalFeatureOnEvaluation(Xp::Flakes, "builtins.getFlake", pos);
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos));
string flakeRefS(state.forceStringNoCtx(*args[0], pos));
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
if (evalSettings.pureEval && !flakeRef.input.isLocked())
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, pos);
if (evalSettings.pureEval && !flakeRef.input.isImmutable())
throw Error("cannot call 'getFlake' on mutable flake reference '%s', at %s (use --impure to override)", flakeRefS, pos);
callFlake(state,
lockFlake(state, flakeRef,
LockFlags {
.updateLockFile = false,
.useRegistries = !evalSettings.pureEval && fetchSettings.useRegistries,
.useRegistries = !evalSettings.pureEval && settings.useRegistries,
.allowMutable = !evalSettings.pureEval,
}),
v);

View File

@@ -98,7 +98,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
if (std::regex_match(url, match, flakeRegex)) {
auto parsedURL = ParsedURL{
.url = url,
.base = "flake:" + match.str(1),
.base = "flake:" + std::string(match[1]),
.scheme = "flake",
.authority = "",
.path = match[1],
@@ -106,12 +106,12 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
return std::make_pair(
FlakeRef(Input::fromURL(parsedURL), ""),
percentDecode(match.str(6)));
percentDecode(std::string(match[6])));
}
else if (std::regex_match(url, match, pathUrlRegex)) {
std::string path = match[1];
std::string fragment = percentDecode(match.str(3));
std::string fragment = percentDecode(std::string(match[3]));
if (baseDir) {
/* Check if 'url' is a path (either absolute or relative

View File

@@ -35,7 +35,7 @@ LockedNode::LockedNode(const nlohmann::json & json)
, originalRef(getFlakeRef(json, "original", nullptr))
, isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true)
{
if (!lockedRef.input.isLocked())
if (!lockedRef.input.isImmutable())
throw Error("lockfile contains mutable lock '%s'",
fetchers::attrsToJSON(lockedRef.input.toAttrs()));
}
@@ -220,7 +220,7 @@ bool LockFile::isImmutable() const
for (auto & i : nodes) {
if (i == root) continue;
auto lockedNode = std::dynamic_pointer_cast<const LockedNode>(i);
if (lockedNode && !lockedNode->lockedRef.input.isLocked()) return false;
if (lockedNode && !lockedNode->lockedRef.input.isImmutable()) return false;
}
return true;

View File

@@ -11,8 +11,8 @@
namespace nix {
DrvInfo::DrvInfo(EvalState & state, std::string attrPath, Bindings * attrs)
: state(&state), attrs(attrs), attrPath(std::move(attrPath))
DrvInfo::DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs)
: state(&state), attrs(attrs), attrPath(attrPath)
{
}
@@ -22,7 +22,7 @@ DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPat
{
auto [drvPath, selectedOutputs] = parsePathWithOutputs(*store, drvPathWithOutputs);
this->drvPath = drvPath;
this->drvPath = store->printStorePath(drvPath);
auto drv = store->derivationFromPath(drvPath);
@@ -41,11 +41,13 @@ DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPat
throw Error("derivation '%s' does not have output '%s'", store->printStorePath(drvPath), outputName);
auto & [outputName, output] = *i;
outPath = {output.path(*store, drv.name, outputName)};
auto optStorePath = output.path(*store, drv.name, outputName);
if (optStorePath)
outPath = store->printStorePath(*optStorePath);
}
std::string DrvInfo::queryName() const
string DrvInfo::queryName() const
{
if (name == "" && attrs) {
auto i = attrs->find(state->sName);
@@ -56,7 +58,7 @@ std::string DrvInfo::queryName() const
}
std::string DrvInfo::querySystem() const
string DrvInfo::querySystem() const
{
if (system == "" && attrs) {
auto i = attrs->find(state->sSystem);
@@ -66,35 +68,24 @@ std::string DrvInfo::querySystem() const
}
std::optional<StorePath> DrvInfo::queryDrvPath() const
string DrvInfo::queryDrvPath() const
{
if (!drvPath && attrs) {
if (drvPath == "" && attrs) {
Bindings::iterator i = attrs->find(state->sDrvPath);
PathSet context;
if (i == attrs->end())
drvPath = {std::nullopt};
else
drvPath = {state->coerceToStorePath(*i->pos, *i->value, context)};
drvPath = i != attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "";
}
return drvPath.value_or(std::nullopt);
return drvPath;
}
StorePath DrvInfo::requireDrvPath() const
{
if (auto drvPath = queryDrvPath())
return *drvPath;
throw Error("derivation does not contain a 'drvPath' attribute");
}
StorePath DrvInfo::queryOutPath() const
string DrvInfo::queryOutPath() const
{
if (!outPath && attrs) {
Bindings::iterator i = attrs->find(state->sOutPath);
PathSet context;
if (i != attrs->end())
outPath = state->coerceToStorePath(*i->pos, *i->value, context);
outPath = state->coerceToPath(*i->pos, *i->value, context);
}
if (!outPath)
throw UnimplementedError("CA derivations are not yet supported");
@@ -113,7 +104,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
/* For each output... */
for (auto elem : i->value->listItems()) {
/* Evaluate the corresponding set. */
std::string name(state->forceStringNoCtx(*elem, *i->pos));
string name(state->forceStringNoCtx(*elem, *i->pos));
Bindings::iterator out = attrs->find(state->symbols.create(name));
if (out == attrs->end()) continue; // FIXME: throw error?
state->forceAttrs(*out->value, *i->pos);
@@ -122,10 +113,10 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
Bindings::iterator outPath = out->value->attrs->find(state->sOutPath);
if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
PathSet context;
outputs.emplace(name, state->coerceToStorePath(*outPath->pos, *outPath->value, context));
outputs[name] = state->coerceToPath(*outPath->pos, *outPath->value, context);
}
} else
outputs.emplace("out", queryOutPath());
outputs["out"] = queryOutPath();
}
if (!onlyOutputsToInstall || !attrs)
return outputs;
@@ -147,7 +138,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
}
std::string DrvInfo::queryOutputName() const
string DrvInfo::queryOutputName() const
{
if (outputName == "" && attrs) {
Bindings::iterator i = attrs->find(state->sOutputName);
@@ -199,7 +190,7 @@ bool DrvInfo::checkMeta(Value & v)
}
Value * DrvInfo::queryMeta(const std::string & name)
Value * DrvInfo::queryMeta(const string & name)
{
if (!getMeta()) return 0;
Bindings::iterator a = meta->find(state->symbols.create(name));
@@ -208,7 +199,7 @@ Value * DrvInfo::queryMeta(const std::string & name)
}
std::string DrvInfo::queryMetaString(const std::string & name)
string DrvInfo::queryMetaString(const string & name)
{
Value * v = queryMeta(name);
if (!v || v->type() != nString) return "";
@@ -216,7 +207,7 @@ std::string DrvInfo::queryMetaString(const std::string & name)
}
NixInt DrvInfo::queryMetaInt(const std::string & name, NixInt def)
NixInt DrvInfo::queryMetaInt(const string & name, NixInt def)
{
Value * v = queryMeta(name);
if (!v) return def;
@@ -230,7 +221,7 @@ NixInt DrvInfo::queryMetaInt(const std::string & name, NixInt def)
return def;
}
NixFloat DrvInfo::queryMetaFloat(const std::string & name, NixFloat def)
NixFloat DrvInfo::queryMetaFloat(const string & name, NixFloat def)
{
Value * v = queryMeta(name);
if (!v) return def;
@@ -245,7 +236,7 @@ NixFloat DrvInfo::queryMetaFloat(const std::string & name, NixFloat def)
}
bool DrvInfo::queryMetaBool(const std::string & name, bool def)
bool DrvInfo::queryMetaBool(const string & name, bool def)
{
Value * v = queryMeta(name);
if (!v) return def;
@@ -260,7 +251,7 @@ bool DrvInfo::queryMetaBool(const std::string & name, bool def)
}
void DrvInfo::setMeta(const std::string & name, Value * v)
void DrvInfo::setMeta(const string & name, Value * v)
{
getMeta();
auto attrs = state->buildBindings(1 + (meta ? meta->size() : 0));
@@ -283,7 +274,7 @@ typedef std::set<Bindings *> Done;
The result boolean indicates whether it makes sense
for the caller to recursively search for derivations in `v'. */
static bool getDerivation(EvalState & state, Value & v,
const std::string & attrPath, DrvInfos & drvs, Done & done,
const string & attrPath, DrvInfos & drvs, Done & done,
bool ignoreAssertionFailures)
{
try {
@@ -320,7 +311,7 @@ std::optional<DrvInfo> getDerivation(EvalState & state, Value & v,
}
static std::string addToPath(const std::string & s1, const std::string & s2)
static string addToPath(const string & s1, const string & s2)
{
return s1.empty() ? s2 : s1 + "." + s2;
}
@@ -330,7 +321,7 @@ static std::regex attrRegex("[A-Za-z_][A-Za-z0-9-_+]*");
static void getDerivations(EvalState & state, Value & vIn,
const std::string & pathPrefix, Bindings & autoArgs,
const string & pathPrefix, Bindings & autoArgs,
DrvInfos & drvs, Done & done,
bool ignoreAssertionFailures)
{
@@ -355,7 +346,7 @@ static void getDerivations(EvalState & state, Value & vIn,
debug("evaluating attribute '%1%'", i->name);
if (!std::regex_match(std::string(i->name), attrRegex))
continue;
std::string pathPrefix2 = addToPath(pathPrefix, i->name);
string pathPrefix2 = addToPath(pathPrefix, i->name);
if (combineChannels)
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
@@ -373,7 +364,7 @@ static void getDerivations(EvalState & state, Value & vIn,
else if (v.type() == nList) {
for (auto [n, elem] : enumerate(v.listItems())) {
std::string pathPrefix2 = addToPath(pathPrefix, fmt("%d", n));
string pathPrefix2 = addToPath(pathPrefix, fmt("%d", n));
if (getDerivation(state, *elem, pathPrefix2, drvs, done, ignoreAssertionFailures))
getDerivations(state, *elem, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
}
@@ -383,7 +374,7 @@ static void getDerivations(EvalState & state, Value & vIn,
}
void getDerivations(EvalState & state, Value & v, const std::string & pathPrefix,
void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
Bindings & autoArgs, DrvInfos & drvs, bool ignoreAssertionFailures)
{
Done done;

View File

@@ -1,7 +1,6 @@
#pragma once
#include "eval.hh"
#include "path.hh"
#include <string>
#include <map>
@@ -13,16 +12,16 @@ namespace nix {
struct DrvInfo
{
public:
typedef std::map<std::string, StorePath> Outputs;
typedef std::map<string, Path> Outputs;
private:
EvalState * state;
mutable std::string name;
mutable std::string system;
mutable std::optional<std::optional<StorePath>> drvPath;
mutable std::optional<StorePath> outPath;
mutable std::string outputName;
mutable string name;
mutable string system;
mutable string drvPath;
mutable std::optional<string> outPath;
mutable string outputName;
Outputs outputs;
bool failed = false; // set if we get an AssertionError
@@ -34,37 +33,36 @@ private:
bool checkMeta(Value & v);
public:
std::string attrPath; /* path towards the derivation */
string attrPath; /* path towards the derivation */
DrvInfo(EvalState & state) : state(&state) { };
DrvInfo(EvalState & state, std::string attrPath, Bindings * attrs);
DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs);
DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs);
std::string queryName() const;
std::string querySystem() const;
std::optional<StorePath> queryDrvPath() const;
StorePath requireDrvPath() const;
StorePath queryOutPath() const;
std::string queryOutputName() const;
string queryName() const;
string querySystem() const;
string queryDrvPath() const;
string queryOutPath() const;
string queryOutputName() const;
/** Return the list of outputs. The "outputs to install" are determined by `meta.outputsToInstall`. */
Outputs queryOutputs(bool onlyOutputsToInstall = false);
StringSet queryMetaNames();
Value * queryMeta(const std::string & name);
std::string queryMetaString(const std::string & name);
NixInt queryMetaInt(const std::string & name, NixInt def);
NixFloat queryMetaFloat(const std::string & name, NixFloat def);
bool queryMetaBool(const std::string & name, bool def);
void setMeta(const std::string & name, Value * v);
Value * queryMeta(const string & name);
string queryMetaString(const string & name);
NixInt queryMetaInt(const string & name, NixInt def);
NixFloat queryMetaFloat(const string & name, NixFloat def);
bool queryMetaBool(const string & name, bool def);
void setMeta(const string & name, Value * v);
/*
MetaInfo queryMetaInfo(EvalState & state) const;
MetaValue queryMetaInfo(EvalState & state, const string & name) const;
*/
void setName(const std::string & s) { name = s; }
void setDrvPath(StorePath path) { drvPath = {{std::move(path)}}; }
void setOutPath(StorePath path) { outPath = {{std::move(path)}}; }
void setName(const string & s) { name = s; }
void setDrvPath(const string & s) { drvPath = s; }
void setOutPath(const string & s) { outPath = s; }
void setFailed() { failed = true; };
bool hasFailed() { return failed; };
@@ -83,7 +81,7 @@ typedef std::list<DrvInfo> DrvInfos;
std::optional<DrvInfo> getDerivation(EvalState & state,
Value & v, bool ignoreAssertionFailures);
void getDerivations(EvalState & state, Value & v, const std::string & pathPrefix,
void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
Bindings & autoArgs, DrvInfos & drvs,
bool ignoreAssertionFailures);

View File

@@ -16,10 +16,10 @@ std::ostream & operator << (std::ostream & str, const Expr & e)
return str;
}
static void showString(std::ostream & str, std::string_view s)
static void showString(std::ostream & str, const string & s)
{
str << '"';
for (auto c : s)
for (auto c : (string) s)
if (c == '"' || c == '\\' || c == '$') str << "\\" << c;
else if (c == '\n') str << "\\n";
else if (c == '\r') str << "\\r";
@@ -28,7 +28,7 @@ static void showString(std::ostream & str, std::string_view s)
str << '"';
}
static void showId(std::ostream & str, std::string_view s)
static void showId(std::ostream & str, const string & s)
{
if (s.empty())
str << "\"\"";
@@ -103,18 +103,11 @@ void ExprAttrs::show(std::ostream & str) const
{
if (recursive) str << "rec ";
str << "{ ";
typedef const decltype(attrs)::value_type * Attr;
std::vector<Attr> sorted;
for (auto & i : attrs) sorted.push_back(&i);
std::sort(sorted.begin(), sorted.end(), [](Attr a, Attr b) {
return (const std::string &) a->first < (const std::string &) b->first;
});
for (auto & i : sorted) {
if (i->second.inherited)
str << "inherit " << i->first << " " << "; ";
for (auto & i : attrs)
if (i.second.inherited)
str << "inherit " << i.first << " " << "; ";
else
str << i->first << " = " << *i->second.e << "; ";
}
str << i.first << " = " << *i.second.e << "; ";
for (auto & i : dynamicAttrs)
str << "\"${" << *i.nameExpr << "}\" = " << *i.valueExpr << "; ";
str << "}";
@@ -218,7 +211,7 @@ std::ostream & operator << (std::ostream & str, const Pos & pos)
auto f = format(ANSI_BOLD "%1%" ANSI_NORMAL ":%2%:%3%");
switch (pos.origin) {
case foFile:
f % (const std::string &) pos.file;
f % (string) pos.file;
break;
case foStdin:
case foString:
@@ -234,7 +227,7 @@ std::ostream & operator << (std::ostream & str, const Pos & pos)
}
std::string showAttrPath(const AttrPath & attrPath)
string showAttrPath(const AttrPath & attrPath)
{
std::ostringstream out;
bool first = true;
@@ -468,9 +461,9 @@ void ExprLambda::setName(Symbol & name)
}
std::string ExprLambda::showNamePos() const
string ExprLambda::showNamePos() const
{
return fmt("%1% at %2%", name.set() ? "'" + (std::string) name + "'" : "anonymous function", pos);
return (format("%1% at %2%") % (name.set() ? "'" + (string) name + "'" : "anonymous function") % pos).str();
}

View File

@@ -26,21 +26,18 @@ struct Pos
FileOrigin origin;
Symbol file;
unsigned int line, column;
Pos() : origin(foString), line(0), column(0) { }
Pos() : origin(foString), line(0), column(0) { };
Pos(FileOrigin origin, const Symbol & file, unsigned int line, unsigned int column)
: origin(origin), file(file), line(line), column(column) { }
: origin(origin), file(file), line(line), column(column) { };
operator bool() const
{
return line != 0;
}
bool operator < (const Pos & p2) const
{
if (!line) return p2.line;
if (!p2.line) return false;
int d = ((const std::string &) file).compare((const std::string &) p2.file);
int d = ((string) file).compare((string) p2.file);
if (d < 0) return true;
if (d > 0) return false;
if (line < p2.line) return true;
@@ -71,7 +68,7 @@ struct AttrName
typedef std::vector<AttrName> AttrPath;
std::string showAttrPath(const AttrPath & attrPath);
string showAttrPath(const AttrPath & attrPath);
/* Abstract syntax of Nix expressions. */
@@ -113,7 +110,7 @@ struct ExprFloat : Expr
struct ExprString : Expr
{
std::string s;
string s;
Value v;
ExprString(std::string s) : s(std::move(s)) { v.mkString(this->s.data()); };
COMMON_METHODS
@@ -122,9 +119,9 @@ struct ExprString : Expr
struct ExprPath : Expr
{
std::string s;
string s;
Value v;
ExprPath(std::string s) : s(std::move(s)) { v.mkPath(this->s.c_str()); };
ExprPath(const string & s) : s(s) { v.mkPath(this->s.c_str()); };
COMMON_METHODS
Value * maybeThunk(EvalState & state, Env & env);
};
@@ -252,7 +249,7 @@ struct ExprLambda : Expr
{
};
void setName(Symbol & name);
std::string showNamePos() const;
string showNamePos() const;
inline bool hasFormals() const { return formals != nullptr; }
COMMON_METHODS
};

View File

@@ -244,7 +244,7 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols,
es2->emplace_back(i->first, e);
};
const auto trimString = [&] (const StringToken & t) {
std::string s2;
string s2;
for (size_t j = 0; j < t.l; ++j) {
if (atStartOfLine) {
if (t.p[j] == ' ') {
@@ -268,9 +268,9 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols,
/* Remove the last line if it is empty and consists only of
spaces. */
if (n == 1) {
std::string::size_type p = s2.find_last_of('\n');
if (p != std::string::npos && s2.find_first_not_of(' ', p + 1) == std::string::npos)
s2 = std::string(s2, 0, p + 1);
string::size_type p = s2.find_last_of('\n');
if (p != string::npos && s2.find_first_not_of(' ', p + 1) == string::npos)
s2 = string(s2, 0, p + 1);
}
es2->emplace_back(i->first, new ExprString(s2));
@@ -466,7 +466,7 @@ expr_simple
$$ = new ExprConcatStrings(CUR_POS, false, $2);
}
| SPATH {
std::string path($1.p + 1, $1.l - 2);
string path($1.p + 1, $1.l - 2);
$$ = new ExprCall(CUR_POS,
new ExprVar(data->symbols.create("__findFile")),
{new ExprVar(data->symbols.create("__nixPath")),
@@ -479,7 +479,7 @@ expr_simple
.msg = hintfmt("URL literals are disabled"),
.errPos = CUR_POS
});
$$ = new ExprString(std::string($1));
$$ = new ExprString(string($1));
}
| '(' expr ')' { $$ = $2; }
/* Let expressions `let {..., body = ...}' are just desugared
@@ -494,19 +494,19 @@ expr_simple
;
string_parts
: STR { $$ = new ExprString(std::string($1)); }
: STR { $$ = new ExprString(string($1)); }
| string_parts_interpolated { $$ = new ExprConcatStrings(CUR_POS, true, $1); }
| { $$ = new ExprString(""); }
;
string_parts_interpolated
: string_parts_interpolated STR
{ $$ = $1; $1->emplace_back(makeCurPos(@2, data), new ExprString(std::string($2))); }
{ $$ = $1; $1->emplace_back(makeCurPos(@2, data), new ExprString(string($2))); }
| string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->emplace_back(makeCurPos(@2, data), $3); }
| DOLLAR_CURLY expr '}' { $$ = new std::vector<std::pair<Pos, Expr *> >; $$->emplace_back(makeCurPos(@1, data), $2); }
| STR DOLLAR_CURLY expr '}' {
$$ = new std::vector<std::pair<Pos, Expr *> >;
$$->emplace_back(makeCurPos(@1, data), new ExprString(std::string($1)));
$$->emplace_back(makeCurPos(@1, data), new ExprString(string($1)));
$$->emplace_back(makeCurPos(@2, data), $3);
}
;
@@ -520,7 +520,7 @@ path_start
$$ = new ExprPath(path);
}
| HPATH {
Path path(getHome() + std::string($1.p + 1, $1.l - 1));
Path path(getHome() + string($1.p + 1, $1.l - 1));
$$ = new ExprPath(path);
}
;
@@ -738,16 +738,16 @@ Expr * EvalState::parseStdin()
}
void EvalState::addToSearchPath(const std::string & s)
void EvalState::addToSearchPath(const string & s)
{
size_t pos = s.find('=');
std::string prefix;
string prefix;
Path path;
if (pos == std::string::npos) {
if (pos == string::npos) {
path = s;
} else {
prefix = std::string(s, 0, pos);
path = std::string(s, pos + 1);
prefix = string(s, 0, pos);
path = string(s, pos + 1);
}
searchPath.emplace_back(prefix, path);

View File

@@ -141,7 +141,7 @@ static void mkOutputString(
BindingsBuilder & attrs,
const StorePath & drvPath,
const BasicDerivation & drv,
const std::pair<std::string, DerivationOutput> & o)
const std::pair<string, DerivationOutput> & o)
{
auto optOutputPath = o.second.path(*state.store, drv.name, o.first);
attrs.alloc(o.first).mkString(
@@ -314,7 +314,7 @@ void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value
{
auto path = realisePath(state, pos, *args[0]);
std::string sym(state.forceStringNoCtx(*args[1], pos));
string sym(state.forceStringNoCtx(*args[1], pos));
void *handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (!handle)
@@ -386,7 +386,7 @@ void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v)
static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0], pos);
std::string t;
string t;
switch (args[0]->type()) {
case nInt: t = "int"; break;
case nBool: t = "bool"; break;
@@ -707,7 +707,7 @@ static RegisterPrimOp primop_abort({
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
auto s = state.coerceToString(pos, *args[0], context).toOwned();
string s = state.coerceToString(pos, *args[0], context).toOwned();
throw Abort("evaluation aborted with the following error message: '%1%'", s);
}
});
@@ -725,7 +725,7 @@ static RegisterPrimOp primop_throw({
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
auto s = state.coerceToString(pos, *args[0], context).toOwned();
string s = state.coerceToString(pos, *args[0], context).toOwned();
throw ThrownError(s);
}
});
@@ -826,7 +826,7 @@ static RegisterPrimOp primop_tryEval({
/* Return an environment variable. Use with care. */
static void prim_getEnv(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
std::string name(state.forceStringNoCtx(*args[0], pos));
string name(state.forceStringNoCtx(*args[0], pos));
v.mkString(evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or(""));
}
@@ -935,7 +935,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
pos
);
std::string drvName;
string drvName;
Pos & posDrvName(*attr->pos);
try {
drvName = state.forceStringNoCtx(*attr->value, pos);
@@ -973,7 +973,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
for (auto & i : args[0]->attrs->lexicographicOrder()) {
if (i->name == state.sIgnoreNulls) continue;
const std::string & key = i->name;
const string & key = i->name;
vomit("processing attribute '%1%'", key);
auto handleHashMode = [&](const std::string_view s) {
@@ -1031,7 +1031,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
else if (i->name == state.sArgs) {
state.forceList(*i->value, pos);
for (auto elem : i->value->listItems()) {
auto s = state.coerceToString(posDrvName, *elem, context, true).toOwned();
string s = state.coerceToString(posDrvName, *elem, context, true).toOwned();
drv.args.push_back(s);
}
}
@@ -1118,7 +1118,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
/* Handle derivation outputs of the form !<name>!<path>. */
else if (path.at(0) == '!') {
auto ctx = decodeContext(path);
std::pair<string, string> ctx = decodeContext(path);
drv.inputDrvs[state.store->parseStorePath(ctx.first)].insert(ctx.second);
}
@@ -1440,8 +1440,8 @@ static RegisterPrimOp primop_dirOf({
static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
auto path = realisePath(state, pos, *args[0]);
auto s = readFile(path);
if (s.find((char) 0) != std::string::npos)
string s = readFile(path);
if (s.find((char) 0) != string::npos)
throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path);
StorePathSet refs;
if (state.store->isInStore(path)) {
@@ -1474,7 +1474,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
for (auto v2 : args[0]->listItems()) {
state.forceAttrs(*v2, pos);
std::string prefix;
string prefix;
Bindings::iterator i = v2->attrs->find(state.sPrefix);
if (i != v2->attrs->end())
prefix = state.forceStringNoCtx(*i->value, pos);
@@ -1488,7 +1488,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
);
PathSet context;
auto path = state.coerceToString(pos, *i->value, context, false, false).toOwned();
string path = state.coerceToString(pos, *i->value, context, false, false).toOwned();
try {
auto rewrites = state.realiseContext(context);
@@ -1754,8 +1754,8 @@ static RegisterPrimOp primop_fromJSON({
static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
std::string name(state.forceStringNoCtx(*args[0], pos));
std::string contents(state.forceString(*args[1], context, pos));
string name(state.forceStringNoCtx(*args[0], pos));
string contents(state.forceString(*args[1], context, pos));
StorePathSet refs;
@@ -1863,7 +1863,7 @@ static RegisterPrimOp primop_toFile({
static void addPath(
EvalState & state,
const Pos & pos,
const std::string & name,
const string & name,
Path path,
Value * filterFun,
FileIngestionMethod method,
@@ -1919,15 +1919,20 @@ static void addPath(
if (expectedHash)
expectedStorePath = state.store->makeFixedOutputPath(method, *expectedHash, name);
Path dstPath;
if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) {
StorePath dstPath = settings.readOnlyMode
dstPath = state.store->printStorePath(settings.readOnlyMode
? state.store->computeStorePathForPath(name, path, method, htSHA256, filter).first
: state.store->addToStore(name, path, method, htSHA256, filter, state.repair, refs);
if (expectedHash && expectedStorePath != dstPath)
: state.store->addToStore(name, path, method, htSHA256, filter, state.repair, refs));
if (expectedHash && expectedStorePath != state.store->parseStorePath(dstPath))
throw Error("store path mismatch in (possibly filtered) path added from '%s'", path);
state.allowAndSetStorePathString(dstPath, v);
} else
state.allowAndSetStorePathString(*expectedStorePath, v);
dstPath = state.store->printStorePath(*expectedStorePath);
v.mkString(dstPath, {dstPath});
state.allowPath(dstPath);
} catch (Error & e) {
e.addTrace(pos, "while adding path '%s'", path);
throw;
@@ -2011,14 +2016,14 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value
{
state.forceAttrs(*args[0], pos);
Path path;
std::string name;
string name;
Value * filterFun = nullptr;
auto method = FileIngestionMethod::Recursive;
std::optional<Hash> expectedHash;
PathSet context;
for (auto & attr : *args[0]->attrs) {
auto & n(attr.name);
const string & n(attr.name);
if (n == "path")
path = state.coerceToPath(*attr.pos, *attr.value, context);
else if (attr.name == state.sName)
@@ -3611,7 +3616,7 @@ static void prim_concatStringsSep(EvalState & state, const Pos & pos, Value * *
auto sep = state.forceString(*args[0], context, pos);
state.forceList(*args[1], pos);
std::string res;
string res;
res.reserve((args[1]->listSize() + 32) * sep.size());
bool first = true;
@@ -3644,12 +3649,12 @@ static void prim_replaceStrings(EvalState & state, const Pos & pos, Value * * ar
.errPos = pos
});
std::vector<std::string> from;
std::vector<string> from;
from.reserve(args[0]->listSize());
for (auto elem : args[0]->listItems())
from.emplace_back(state.forceString(*elem, pos));
std::vector<std::pair<std::string, PathSet>> to;
std::vector<std::pair<string, PathSet>> to;
to.reserve(args[1]->listSize());
for (auto elem : args[1]->listItems()) {
PathSet ctx;
@@ -3660,7 +3665,7 @@ static void prim_replaceStrings(EvalState & state, const Pos & pos, Value * * ar
PathSet context;
auto s = state.forceString(*args[2], context, pos);
std::string res;
string res;
// Loops one past last character to handle the case where 'from' contains an empty string.
for (size_t p = 0; p <= s.size(); ) {
bool found = false;

View File

@@ -37,7 +37,7 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & po
PathSet context2;
for (auto & p : context)
context2.insert(p.at(0) == '=' ? std::string(p, 1) : p);
context2.insert(p.at(0) == '=' ? string(p, 1) : p);
v.mkString(*s, context2);
}
@@ -76,13 +76,13 @@ static void prim_getContext(EvalState & state, const Pos & pos, Value * * args,
auto contextInfos = std::map<Path, ContextInfo>();
for (const auto & p : context) {
Path drv;
std::string output;
string output;
const Path * path = &p;
if (p.at(0) == '=') {
drv = std::string(p, 1);
drv = string(p, 1);
path = &drv;
} else if (p.at(0) == '!') {
std::pair<std::string, std::string> ctx = decodeContext(p);
std::pair<string, string> ctx = decodeContext(p);
drv = ctx.first;
output = ctx.second;
path = &drv;
@@ -166,7 +166,7 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
.errPos = *i.pos
});
}
context.insert("=" + std::string(i.name));
context.insert("=" + string(i.name));
}
}

View File

@@ -62,7 +62,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
fetchers::Attrs attrs;
attrs.insert_or_assign("type", "hg");
attrs.insert_or_assign("url", url.find("://") != std::string::npos ? url : "file://" + url);
attrs.insert_or_assign("name", std::string(name));
attrs.insert_or_assign("name", string(name));
if (ref) attrs.insert_or_assign("ref", *ref);
if (rev) attrs.insert_or_assign("rev", rev->gitRev());
auto input = fetchers::Input::fromAttrs(std::move(attrs));

View File

@@ -19,7 +19,7 @@ void emitTreeAttrs(
bool emptyRevFallback,
bool forceDirty)
{
assert(input.isLocked());
assert(input.isImmutable());
auto attrs = state.buildBindings(8);
@@ -166,8 +166,8 @@ static void fetchTree(
if (!evalSettings.pureEval && !input.isDirect())
input = lookupInRegistries(state.store, input).first;
if (evalSettings.pureEval && !input.isLocked())
throw Error("in pure evaluation mode, 'fetchTree' requires a locked input, at %s", pos);
if (evalSettings.pureEval && !input.isImmutable())
throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input, at %s", pos);
auto [tree, input2] = input.fetch(state.store);
@@ -186,7 +186,7 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V
static RegisterPrimOp primop_fetchTree("fetchTree", 1, prim_fetchTree);
static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
const std::string & who, bool unpack, std::string name)
const string & who, bool unpack, std::string name)
{
std::optional<std::string> url;
std::optional<Hash> expectedHash;
@@ -198,7 +198,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
state.forceAttrs(*args[0], pos);
for (auto & attr : *args[0]->attrs) {
std::string n(attr.name);
string n(attr.name);
if (n == "url")
url = state.forceStringNoCtx(*attr.value, *attr.pos);
else if (n == "sha256")
@@ -230,21 +230,6 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
if (evalSettings.pureEval && !expectedHash)
throw Error("in pure evaluation mode, '%s' requires a 'sha256' argument", who);
// early exit if pinned and already in the store
if (expectedHash && expectedHash->type == htSHA256) {
auto expectedPath =
unpack
? state.store->makeFixedOutputPath(FileIngestionMethod::Recursive, *expectedHash, name, {})
: state.store->makeFixedOutputPath(FileIngestionMethod::Flat, *expectedHash, name, {});
if (state.store->isValidPath(expectedPath)) {
state.allowAndSetStorePathString(expectedPath, v);
return;
}
}
// TODO: fetching may fail, yet the path may be substitutable.
// https://github.com/NixOS/nix/issues/4313
auto storePath =
unpack
? fetchers::downloadTarball(state.store, *url, name, (bool) expectedHash).first.storePath
@@ -259,7 +244,10 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
*url, expectedHash->to_string(Base32, true), hash.to_string(Base32, true));
}
state.allowAndSetStorePathString(storePath, v);
state.allowPath(storePath);
auto path = state.store->printStorePath(storePath);
v.mkString(path, PathSet({path}));
}
static void prim_fetchurl(EvalState & state, const Pos & pos, Value * * args, Value & v)

View File

@@ -9,7 +9,7 @@ static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Va
{
auto toml = state.forceStringNoCtx(*args[0], pos);
std::istringstream tomlStream(std::string{toml});
std::istringstream tomlStream(string{toml});
std::function<void(Value &, toml::value)> visit;

View File

@@ -9,7 +9,7 @@
namespace nix {
static XMLAttrs singletonAttrs(const std::string & name, const std::string & value)
static XMLAttrs singletonAttrs(const string & name, const string & value)
{
XMLAttrs attrs;
attrs[name] = value;

View File

@@ -114,14 +114,11 @@ struct Value
private:
InternalType internalType;
friend std::string showType(const Value & v);
void print(std::ostream & str, std::set<const void *> * seen) const;
friend std::string showType(const Value & v);
friend void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v);
public:
void print(std::ostream & str, bool showRepeated = false) const;
// Functions needed to distinguish the type
// These should be removed eventually, by putting the functionality that's
// needed by callers into methods of this type

View File

@@ -52,13 +52,13 @@ struct CacheImpl : Cache
const Attrs & inAttrs,
const Attrs & infoAttrs,
const StorePath & storePath,
bool locked) override
bool immutable) override
{
_state.lock()->add.use()
(attrsToJSON(inAttrs).dump())
(attrsToJSON(infoAttrs).dump())
(store->printStorePath(storePath))
(locked)
(immutable)
(time(0)).exec();
}
@@ -91,7 +91,7 @@ struct CacheImpl : Cache
auto infoJSON = stmt.getStr(0);
auto storePath = store->parseStorePath(stmt.getStr(1));
auto locked = stmt.getInt(2) != 0;
auto immutable = stmt.getInt(2) != 0;
auto timestamp = stmt.getInt(3);
store->addTempRoot(storePath);
@@ -105,7 +105,7 @@ struct CacheImpl : Cache
inAttrsJSON, infoJSON, store->printStorePath(storePath));
return Result {
.expired = !locked && (settings.tarballTtl.get() == 0 || timestamp + settings.tarballTtl < time(0)),
.expired = !immutable && (settings.tarballTtl.get() == 0 || timestamp + settings.tarballTtl < time(0)),
.infoAttrs = jsonToAttrs(nlohmann::json::parse(infoJSON)),
.storePath = std::move(storePath)
};

View File

@@ -13,7 +13,7 @@ struct Cache
const Attrs & inAttrs,
const Attrs & infoAttrs,
const StorePath & storePath,
bool locked) = 0;
bool immutable) = 0;
virtual std::optional<std::pair<Attrs, StorePath>> lookup(
ref<Store> store,

View File

@@ -1,13 +0,0 @@
#include "fetch-settings.hh"
namespace nix {
FetchSettings::FetchSettings()
{
}
FetchSettings fetchSettings;
static GlobalConfig::Register rFetchSettings(&fetchSettings);
}

View File

@@ -1,93 +0,0 @@
#pragma once
#include "types.hh"
#include "config.hh"
#include "util.hh"
#include <map>
#include <limits>
#include <sys/types.h>
namespace nix {
struct FetchSettings : public Config
{
FetchSettings();
Setting<StringMap> accessTokens{this, {}, "access-tokens",
R"(
Access tokens used to access protected GitHub, GitLab, or
other locations requiring token-based authentication.
Access tokens are specified as a string made up of
space-separated `host=token` values. The specific token
used is selected by matching the `host` portion against the
"host" specification of the input. The actual use of the
`token` value is determined by the type of resource being
accessed:
* Github: the token value is the OAUTH-TOKEN string obtained
as the Personal Access Token from the Github server (see
https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps).
* Gitlab: the token value is either the OAuth2 token or the
Personal Access Token (these are different types tokens
for gitlab, see
https://docs.gitlab.com/12.10/ee/api/README.html#authentication).
The `token` value should be `type:tokenstring` where
`type` is either `OAuth2` or `PAT` to indicate which type
of token is being specified.
Example `~/.config/nix/nix.conf`:
```
access-tokens = github.com=23ac...b289 gitlab.mycompany.com=PAT:A123Bp_Cd..EfG gitlab.com=OAuth2:1jklw3jk
```
Example `~/code/flake.nix`:
```nix
input.foo = {
type = "gitlab";
host = "gitlab.mycompany.com";
owner = "mycompany";
repo = "pro";
};
```
This example specifies three tokens, one each for accessing
github.com, gitlab.mycompany.com, and sourceforge.net.
The `input.foo` uses the "gitlab" fetcher, which might
requires specifying the token type along with the token
value.
)"};
Setting<bool> allowDirty{this, true, "allow-dirty",
"Whether to allow dirty Git/Mercurial trees."};
Setting<bool> warnDirty{this, true, "warn-dirty",
"Whether to warn about dirty Git/Mercurial trees."};
Setting<std::string> flakeRegistry{this, "https://github.com/NixOS/flake-registry/raw/master/flake-registry.json", "flake-registry",
"Path or URI of the global flake registry."};
Setting<bool> useRegistries{this, true, "use-registries",
"Whether to use flake registries to resolve flake references."};
Setting<bool> acceptFlakeConfig{this, false, "accept-flake-config",
"Whether to accept nix configuration from a flake without prompting."};
Setting<std::string> commitLockFileSummary{
this, "", "commit-lockfile-summary",
R"(
The commit summary to use when committing changed flake lock files. If
empty, the summary is generated based on the action performed.
)"};
};
// FIXME: don't use a global variable.
extern FetchSettings fetchSettings;
}

View File

@@ -24,11 +24,11 @@ static void fixupInput(Input & input)
input.getType();
input.getRef();
if (input.getRev())
input.locked = true;
input.immutable = true;
input.getRevCount();
input.getLastModified();
if (input.getNarHash())
input.locked = true;
input.immutable = true;
}
Input Input::fromURL(const ParsedURL & url)
@@ -165,7 +165,7 @@ std::pair<Tree, Input> Input::fetch(ref<Store> store) const
input.to_string(), *prevRevCount);
}
input.locked = true;
input.immutable = true;
assert(input.hasAllInfo());
@@ -209,7 +209,7 @@ StorePath Input::computeStorePath(Store & store) const
{
auto narHash = getNarHash();
if (!narHash)
throw Error("cannot compute store path for unlocked input '%s'", to_string());
throw Error("cannot compute store path for mutable input '%s'", to_string());
return store.makeFixedOutputPath(FileIngestionMethod::Recursive, *narHash, getName());
}

View File

@@ -34,7 +34,7 @@ struct Input
std::shared_ptr<InputScheme> scheme; // note: can be null
Attrs attrs;
bool locked = false;
bool immutable = false;
bool direct = true;
/* path of the parent of this input, used for relative path resolution */
@@ -59,9 +59,9 @@ public:
one that goes through a registry. */
bool isDirect() const { return direct; }
/* Check whether this is a "locked" input, that is,
/* Check whether this is an "immutable" input, that is,
one that contains a commit hash or content hash. */
bool isLocked() const { return locked; }
bool isImmutable() const { return immutable; }
bool hasAllInfo() const;
@@ -69,8 +69,6 @@ public:
bool contains(const Input & other) const;
/* Fetch the input into the Nix store, returning the location in
the Nix store and the locked input. */
std::pair<Tree, Input> fetch(ref<Store> store) const;
Input applyOverrides(
@@ -148,14 +146,14 @@ DownloadFileResult downloadFile(
ref<Store> store,
const std::string & url,
const std::string & name,
bool locked,
bool immutable,
const Headers & headers = {});
std::pair<Tree, time_t> downloadTarball(
ref<Store> store,
const std::string & url,
const std::string & name,
bool locked,
bool immutable,
const Headers & headers = {});
}

View File

@@ -6,8 +6,6 @@
#include "url-parts.hh"
#include "pathlocks.hh"
#include "fetch-settings.hh"
#include <sys/time.h>
#include <sys/wait.h>
@@ -189,7 +187,7 @@ struct GitInputScheme : InputScheme
if (submodules) cacheType += "-submodules";
if (allRefs) cacheType += "-all-refs";
auto getLockedAttrs = [&]()
auto getImmutableAttrs = [&]()
{
return Attrs({
{"type", cacheType},
@@ -210,7 +208,7 @@ struct GitInputScheme : InputScheme
};
if (input.getRev()) {
if (auto res = getCache()->lookup(store, getLockedAttrs()))
if (auto res = getCache()->lookup(store, getImmutableAttrs()))
return makeResult(res->first, std::move(res->second));
}
@@ -248,10 +246,10 @@ struct GitInputScheme : InputScheme
/* This is an unclean working tree. So copy all tracked files. */
if (!fetchSettings.allowDirty)
if (!settings.allowDirty)
throw Error("Git tree '%s' is dirty", actualUrl);
if (fetchSettings.warnDirty)
if (settings.warnDirty)
warn("Git tree '%s' is dirty", actualUrl);
auto gitOpts = Strings({ "-C", actualUrl, "ls-files", "-z" });
@@ -290,7 +288,7 @@ struct GitInputScheme : InputScheme
if (!input.getRef()) input.attrs.insert_or_assign("ref", isLocal ? readHead(actualUrl) : "master");
Attrs unlockedAttrs({
Attrs mutableAttrs({
{"type", cacheType},
{"name", name},
{"url", actualUrl},
@@ -309,7 +307,7 @@ struct GitInputScheme : InputScheme
} else {
if (auto res = getCache()->lookup(store, unlockedAttrs)) {
if (auto res = getCache()->lookup(store, mutableAttrs)) {
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1);
if (!input.getRev() || input.getRev() == rev2) {
input.attrs.insert_or_assign("rev", rev2.gitRev());
@@ -406,7 +404,7 @@ struct GitInputScheme : InputScheme
/* Now that we know the ref, check again whether we have it in
the store. */
if (auto res = getCache()->lookup(store, getLockedAttrs()))
if (auto res = getCache()->lookup(store, getImmutableAttrs()))
return makeResult(res->first, std::move(res->second));
Path tmpDir = createTempDir();
@@ -478,14 +476,14 @@ struct GitInputScheme : InputScheme
if (!_input.getRev())
getCache()->add(
store,
unlockedAttrs,
mutableAttrs,
infoAttrs,
storePath,
false);
getCache()->add(
store,
getLockedAttrs(),
getImmutableAttrs(),
infoAttrs,
storePath,
true);

View File

@@ -1,13 +1,11 @@
#include "filetransfer.hh"
#include "cache.hh"
#include "fetchers.hh"
#include "globals.hh"
#include "store-api.hh"
#include "types.hh"
#include "url-parts.hh"
#include "fetchers.hh"
#include "fetch-settings.hh"
#include <optional>
#include <nlohmann/json.hpp>
#include <fstream>
@@ -159,7 +157,7 @@ struct GitArchiveInputScheme : InputScheme
std::optional<std::string> getAccessToken(const std::string & host) const
{
auto tokens = fetchSettings.accessTokens.get();
auto tokens = settings.accessTokens.get();
if (auto token = get(tokens, host))
return *token;
return {};
@@ -195,12 +193,12 @@ struct GitArchiveInputScheme : InputScheme
input.attrs.erase("ref");
input.attrs.insert_or_assign("rev", rev->gitRev());
Attrs lockedAttrs({
Attrs immutableAttrs({
{"type", "git-tarball"},
{"rev", rev->gitRev()},
});
if (auto res = getCache()->lookup(store, lockedAttrs)) {
if (auto res = getCache()->lookup(store, immutableAttrs)) {
input.attrs.insert_or_assign("lastModified", getIntAttr(res->first, "lastModified"));
return {std::move(res->second), input};
}
@@ -213,7 +211,7 @@ struct GitArchiveInputScheme : InputScheme
getCache()->add(
store,
lockedAttrs,
immutableAttrs,
{
{"rev", rev->gitRev()},
{"lastModified", uint64_t(lastModified)}

View File

@@ -5,8 +5,6 @@
#include "store-api.hh"
#include "url-parts.hh"
#include "fetch-settings.hh"
#include <sys/time.h>
using namespace std::string_literals;
@@ -28,7 +26,7 @@ static RunOptions hgOptions(const Strings & args)
}
// runProgram wrapper that uses hgOptions instead of stock RunOptions.
static std::string runHg(const Strings & args, const std::optional<std::string> & input = {})
static string runHg(const Strings & args, const std::optional<std::string> & input = {})
{
RunOptions opts = hgOptions(args);
opts.input = input;
@@ -167,10 +165,10 @@ struct MercurialInputScheme : InputScheme
/* This is an unclean working tree. So copy all tracked
files. */
if (!fetchSettings.allowDirty)
if (!settings.allowDirty)
throw Error("Mercurial tree '%s' is unclean", actualUrl);
if (fetchSettings.warnDirty)
if (settings.warnDirty)
warn("Mercurial tree '%s' is unclean", actualUrl);
input.attrs.insert_or_assign("ref", chomp(runHg({ "branch", "-R", actualUrl })));
@@ -201,7 +199,7 @@ struct MercurialInputScheme : InputScheme
if (!input.getRef()) input.attrs.insert_or_assign("ref", "default");
auto getLockedAttrs = [&]()
auto getImmutableAttrs = [&]()
{
return Attrs({
{"type", "hg"},
@@ -220,20 +218,20 @@ struct MercurialInputScheme : InputScheme
};
if (input.getRev()) {
if (auto res = getCache()->lookup(store, getLockedAttrs()))
if (auto res = getCache()->lookup(store, getImmutableAttrs()))
return makeResult(res->first, std::move(res->second));
}
auto revOrRef = input.getRev() ? input.getRev()->gitRev() : *input.getRef();
Attrs unlockedAttrs({
Attrs mutableAttrs({
{"type", "hg"},
{"name", name},
{"url", actualUrl},
{"ref", *input.getRef()},
});
if (auto res = getCache()->lookup(store, unlockedAttrs)) {
if (auto res = getCache()->lookup(store, mutableAttrs)) {
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1);
if (!input.getRev() || input.getRev() == rev2) {
input.attrs.insert_or_assign("rev", rev2.gitRev());
@@ -256,7 +254,7 @@ struct MercurialInputScheme : InputScheme
runHg({ "pull", "-R", cacheDir, "--", actualUrl });
}
catch (ExecError & e) {
auto transJournal = cacheDir + "/.hg/store/journal";
string transJournal = cacheDir + "/.hg/store/journal";
/* hg throws "abandoned transaction" error only if this file exists */
if (pathExists(transJournal)) {
runHg({ "recover", "-R", cacheDir });
@@ -279,7 +277,7 @@ struct MercurialInputScheme : InputScheme
auto revCount = std::stoull(tokens[1]);
input.attrs.insert_or_assign("ref", tokens[2]);
if (auto res = getCache()->lookup(store, getLockedAttrs()))
if (auto res = getCache()->lookup(store, getImmutableAttrs()))
return makeResult(res->first, std::move(res->second));
Path tmpDir = createTempDir();
@@ -299,14 +297,14 @@ struct MercurialInputScheme : InputScheme
if (!_input.getRev())
getCache()->add(
store,
unlockedAttrs,
mutableAttrs,
infoAttrs,
storePath,
false);
getCache()->add(
store,
getLockedAttrs(),
getImmutableAttrs(),
infoAttrs,
storePath,
true);

View File

@@ -5,8 +5,6 @@
#include "store-api.hh"
#include "local-fs-store.hh"
#include "fetch-settings.hh"
#include <nlohmann/json.hpp>
namespace nix::fetchers {
@@ -152,7 +150,7 @@ void overrideRegistry(
static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
{
static auto reg = [&]() {
auto path = fetchSettings.flakeRegistry.get();
auto path = settings.flakeRegistry.get();
if (!hasPrefix(path, "/")) {
auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath;

View File

@@ -13,7 +13,7 @@ DownloadFileResult downloadFile(
ref<Store> store,
const std::string & url,
const std::string & name,
bool locked,
bool immutable,
const Headers & headers)
{
// FIXME: check store
@@ -88,7 +88,7 @@ DownloadFileResult downloadFile(
inAttrs,
infoAttrs,
*storePath,
locked);
immutable);
if (url != res.effectiveUri)
getCache()->add(
@@ -100,7 +100,7 @@ DownloadFileResult downloadFile(
},
infoAttrs,
*storePath,
locked);
immutable);
return {
.storePath = std::move(*storePath),
@@ -113,7 +113,7 @@ std::pair<Tree, time_t> downloadTarball(
ref<Store> store,
const std::string & url,
const std::string & name,
bool locked,
bool immutable,
const Headers & headers)
{
Attrs inAttrs({
@@ -130,7 +130,7 @@ std::pair<Tree, time_t> downloadTarball(
getIntAttr(cached->infoAttrs, "lastModified")
};
auto res = downloadFile(store, url, name, locked, headers);
auto res = downloadFile(store, url, name, immutable, headers);
std::optional<StorePath> unpackedStorePath;
time_t lastModified;
@@ -160,7 +160,7 @@ std::pair<Tree, time_t> downloadTarball(
inAttrs,
infoAttrs,
*unpackedStorePath,
locked);
immutable);
return {
Tree { .actualPath = store->toRealPath(*unpackedStorePath), .storePath = std::move(*unpackedStorePath) },
@@ -202,7 +202,7 @@ struct TarballInputScheme : InputScheme
Input input;
input.attrs = attrs;
//input.locked = (bool) maybeGetStrAttr(input.attrs, "hash");
//input.immutable = (bool) maybeGetStrAttr(input.attrs, "hash");
return input;
}

View File

@@ -4,7 +4,7 @@
namespace nix {
MixCommonArgs::MixCommonArgs(const std::string & programName)
MixCommonArgs::MixCommonArgs(const string & programName)
: programName(programName)
{
addFlag({

View File

@@ -11,8 +11,8 @@ class MixCommonArgs : public virtual Args
{
void initialFlagsProcessed() override;
public:
std::string programName;
MixCommonArgs(const std::string & programName);
string programName;
MixCommonArgs(const string & programName);
protected:
virtual void pluginsInited() {}
};

View File

@@ -1,7 +1,6 @@
#include "globals.hh"
#include "shared.hh"
#include "store-api.hh"
#include "gc-store.hh"
#include "util.hh"
#include "loggers.hh"
@@ -95,7 +94,7 @@ void printMissing(ref<Store> store, const StorePathSet & willBuild,
}
std::string getArg(const std::string & opt,
string getArg(const string & opt,
Strings::iterator & i, const Strings::iterator & end)
{
++i;
@@ -323,14 +322,14 @@ void parseCmdLine(int argc, char * * argv,
}
void parseCmdLine(const std::string & programName, const Strings & args,
void parseCmdLine(const string & programName, const Strings & args,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg)
{
LegacyArgs(programName, parseArg).parseCmdline(args);
}
void printVersion(const std::string & programName)
void printVersion(const string & programName)
{
std::cout << format("%1% (Nix) %2%") % programName % nixVersion << std::endl;
if (verbosity > lvlInfo) {
@@ -353,7 +352,7 @@ void printVersion(const std::string & programName)
}
void showManPage(const std::string & name)
void showManPage(const string & name)
{
restoreProcessContext();
setenv("MANPATH", settings.nixManDir.c_str(), 1);
@@ -362,13 +361,13 @@ void showManPage(const std::string & name)
}
int handleExceptions(const std::string & programName, std::function<void()> fun)
int handleExceptions(const string & programName, std::function<void()> fun)
{
ReceiveInterrupts receiveInterrupts; // FIXME: need better place for this
ErrorInfo::programName = baseNameOf(programName);
std::string error = ANSI_RED "error:" ANSI_NORMAL " ";
string error = ANSI_RED "error:" ANSI_NORMAL " ";
try {
try {
fun();
@@ -408,7 +407,7 @@ RunPager::RunPager()
if (!isatty(STDOUT_FILENO)) return;
char * pager = getenv("NIX_PAGER");
if (!pager) pager = getenv("PAGER");
if (pager && ((std::string) pager == "" || (std::string) pager == "cat")) return;
if (pager && ((string) pager == "" || (string) pager == "cat")) return;
Pipe toPager;
toPager.create();

View File

@@ -22,7 +22,7 @@ public:
virtual ~Exit();
};
int handleExceptions(const std::string & programName, std::function<void()> fun);
int handleExceptions(const string & programName, std::function<void()> fun);
/* Don't forget to call initPlugins() after settings are initialized! */
void initNix();
@@ -30,10 +30,10 @@ void initNix();
void parseCmdLine(int argc, char * * argv,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg);
void parseCmdLine(const std::string & programName, const Strings & args,
void parseCmdLine(const string & programName, const Strings & args,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg);
void printVersion(const std::string & programName);
void printVersion(const string & programName);
/* Ugh. No better place to put this. */
void printGCWarning();
@@ -50,10 +50,10 @@ void printMissing(ref<Store> store, const StorePathSet & willBuild,
const StorePathSet & willSubstitute, const StorePathSet & unknown,
uint64_t downloadSize, uint64_t narSize, Verbosity lvl = lvlInfo);
std::string getArg(const std::string & opt,
string getArg(const string & opt,
Strings::iterator & i, const Strings::iterator & end);
template<class N> N getIntArg(const std::string & opt,
template<class N> N getIntArg(const string & opt,
Strings::iterator & i, const Strings::iterator & end, bool allowUnit)
{
++i;
@@ -76,7 +76,7 @@ struct LegacyArgs : public MixCommonArgs
/* Show the manual page for the specified program. */
void showManPage(const std::string & name);
void showManPage(const string & name);
/* The constructor of this class starts a pager if stdout is a
terminal and $PAGER is set. Stdout is redirected to the pager. */
@@ -96,7 +96,7 @@ extern volatile ::sig_atomic_t blockInt;
/* GC helpers. */
std::string showBytes(uint64_t bytes);
string showBytes(uint64_t bytes);
struct GCResults;

View File

@@ -385,14 +385,8 @@ void BinaryCacheStore::queryPathInfoUncached(const StorePath & storePath,
}});
}
StorePath BinaryCacheStore::addToStore(
std::string_view name,
const Path & srcPath,
FileIngestionMethod method,
HashType hashAlgo,
PathFilter & filter,
RepairFlag repair,
const StorePathSet & references)
StorePath BinaryCacheStore::addToStore(const string & name, const Path & srcPath,
FileIngestionMethod method, HashType hashAlgo, PathFilter & filter, RepairFlag repair, const StorePathSet & references)
{
/* FIXME: Make BinaryCacheStore::addToStoreCommon support
non-recursive+sha256 so we can just use the default
@@ -424,11 +418,8 @@ StorePath BinaryCacheStore::addToStore(
})->path;
}
StorePath BinaryCacheStore::addTextToStore(
std::string_view name,
std::string_view s,
const StorePathSet & references,
RepairFlag repair)
StorePath BinaryCacheStore::addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair)
{
auto textHash = hashString(htSHA256, s);
auto path = makeTextPath(name, textHash, references);

View File

@@ -101,20 +101,12 @@ public:
StorePath addToStoreFromDump(Source & dump, std::string_view name,
FileIngestionMethod method, HashType hashAlgo, RepairFlag repair, const StorePathSet & references) override;
StorePath addToStore(
std::string_view name,
const Path & srcPath,
FileIngestionMethod method,
HashType hashAlgo,
PathFilter & filter,
RepairFlag repair,
const StorePathSet & references) override;
StorePath addToStore(const string & name, const Path & srcPath,
FileIngestionMethod method, HashType hashAlgo,
PathFilter & filter, RepairFlag repair, const StorePathSet & references) override;
StorePath addTextToStore(
std::string_view name,
std::string_view s,
const StorePathSet & references,
RepairFlag repair) override;
StorePath addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair) override;
void registerDrvOutput(const Realisation & info) override;

View File

@@ -1,77 +0,0 @@
#pragma once
#include "realisation.hh"
#include <string>
#include <chrono>
namespace nix {
struct BuildResult
{
/* Note: don't remove status codes, and only add new status codes
at the end of the list, to prevent client/server
incompatibilities in the nix-store --serve protocol. */
enum Status {
Built = 0,
Substituted,
AlreadyValid,
PermanentFailure,
InputRejected,
OutputRejected,
TransientFailure, // possibly transient
CachedFailure, // no longer used
TimedOut,
MiscFailure,
DependencyFailed,
LogLimitExceeded,
NotDeterministic,
ResolvesToAlreadyValid,
} status = MiscFailure;
std::string errorMsg;
std::string toString() const {
auto strStatus = [&]() {
switch (status) {
case Built: return "Built";
case Substituted: return "Substituted";
case AlreadyValid: return "AlreadyValid";
case PermanentFailure: return "PermanentFailure";
case InputRejected: return "InputRejected";
case OutputRejected: return "OutputRejected";
case TransientFailure: return "TransientFailure";
case CachedFailure: return "CachedFailure";
case TimedOut: return "TimedOut";
case MiscFailure: return "MiscFailure";
case DependencyFailed: return "DependencyFailed";
case LogLimitExceeded: return "LogLimitExceeded";
case NotDeterministic: return "NotDeterministic";
case ResolvesToAlreadyValid: return "ResolvesToAlreadyValid";
default: return "Unknown";
};
}();
return strStatus + ((errorMsg == "") ? "" : " : " + errorMsg);
}
/* How many times this build was performed. */
unsigned int timesBuilt = 0;
/* If timesBuilt > 1, whether some builds did not produce the same
result. (Note that 'isNonDeterministic = false' does not mean
the build is deterministic, just that we don't have evidence of
non-determinism.) */
bool isNonDeterministic = false;
DrvOutputs builtOutputs;
/* The start/stop times of the build (or one of the rounds, if it
was repeated). */
time_t startTime = 0, stopTime = 0;
bool success() {
return status == Built || status == Substituted || status == AlreadyValid || status == ResolvesToAlreadyValid;
}
};
}

View File

@@ -116,7 +116,7 @@ DerivationGoal::~DerivationGoal()
}
std::string DerivationGoal::key()
string DerivationGoal::key()
{
/* Ensure that derivations get built in order of their name,
i.e. a derivation named "aardvark" always comes before
@@ -1013,7 +1013,7 @@ HookReply DerivationGoal::tryBuildHook()
/* Read the first line of input, which should be a word indicating
whether the hook wishes to perform the build. */
std::string reply;
string reply;
while (true) {
auto s = [&]() {
try {
@@ -1025,8 +1025,8 @@ HookReply DerivationGoal::tryBuildHook()
}();
if (handleJSONLogMessage(s, worker.act, worker.hook->activities, true))
;
else if (s.substr(0, 2) == "# ") {
reply = s.substr(2);
else if (string(s, 0, 2) == "# ") {
reply = string(s, 2);
break;
}
else {
@@ -1140,10 +1140,10 @@ Path DerivationGoal::openLogFile()
logDir = localStore->logDir;
else
logDir = settings.nixLogDir;
Path dir = fmt("%s/%s/%s/", logDir, LocalFSStore::drvsLogDir, baseName.substr(0, 2));
Path dir = fmt("%s/%s/%s/", logDir, LocalFSStore::drvsLogDir, string(baseName, 0, 2));
createDirs(dir);
Path logFileName = fmt("%s/%s%s", dir, baseName.substr(2),
Path logFileName = fmt("%s/%s%s", dir, string(baseName, 2),
settings.compressLog ? ".bz2" : "");
fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
@@ -1175,11 +1175,10 @@ bool DerivationGoal::isReadDesc(int fd)
return fd == hook->builderOut.readSide.get();
}
void DerivationGoal::handleChildOutput(int fd, std::string_view data)
void DerivationGoal::handleChildOutput(int fd, const string & data)
{
// local & `ssh://`-builds are dealt with here.
auto isWrittenToLog = isReadDesc(fd);
if (isWrittenToLog)
if (isReadDesc(fd))
{
logSize += data.size();
if (settings.maxLogSize && logSize > settings.maxLogSize) {
@@ -1208,16 +1207,7 @@ void DerivationGoal::handleChildOutput(int fd, std::string_view data)
if (hook && fd == hook->fromHook.readSide.get()) {
for (auto c : data)
if (c == '\n') {
auto json = parseJSONMessage(currentHookLine);
if (json) {
auto s = handleJSONLogMessage(*json, worker.act, hook->activities, true);
// ensure that logs from a builder using `ssh-ng://` as protocol
// are also available to `nix log`.
if (s && !isWrittenToLog && logSink && (*json)["type"] == resBuildLogLine) {
auto f = (*json)["fields"];
(*logSink)((f.size() > 0 ? f.at(0).get<std::string>() : "") + "\n");
}
}
handleJSONLogMessage(currentHookLine, worker.act, hook->activities, true);
currentHookLine.clear();
} else
currentHookLine += c;

View File

@@ -2,7 +2,6 @@
#include "parsed-derivations.hh"
#include "lock.hh"
#include "build-result.hh"
#include "store-api.hh"
#include "pathlocks.hh"
#include "goal.hh"
@@ -146,7 +145,7 @@ struct DerivationGoal : public Goal
void timedOut(Error && ex) override;
std::string key() override;
string key() override;
void work() override;
@@ -201,7 +200,7 @@ struct DerivationGoal : public Goal
virtual bool isReadDesc(int fd);
/* Callback used by the worker to write to the log. */
void handleChildOutput(int fd, std::string_view data) override;
void handleChildOutput(int fd, const string & data) override;
void handleEOF(int fd) override;
void flushLine();

View File

@@ -137,7 +137,7 @@ void DrvOutputSubstitutionGoal::finished()
amDone(ecSuccess);
}
std::string DrvOutputSubstitutionGoal::key()
string DrvOutputSubstitutionGoal::key()
{
/* "a$" ensures substitution goals happen before derivation
goals. */

View File

@@ -51,7 +51,7 @@ public:
void timedOut(Error && ex) override { abort(); };
std::string key() override;
string key() override;
void work() override;
void handleEOF(int fd) override;

View File

@@ -5,8 +5,8 @@ namespace nix {
bool CompareGoalPtrs::operator() (const GoalPtr & a, const GoalPtr & b) const {
std::string s1 = a->key();
std::string s2 = b->key();
string s1 = a->key();
string s2 = b->key();
return s1 < s2;
}

View File

@@ -50,7 +50,7 @@ struct Goal : public std::enable_shared_from_this<Goal>
unsigned int nrIncompleteClosure;
/* Name of this goal for debugging purposes. */
std::string name;
string name;
/* Whether the goal is finished. */
ExitCode exitCode;
@@ -75,7 +75,7 @@ struct Goal : public std::enable_shared_from_this<Goal>
virtual void waiteeDone(GoalPtr waitee, ExitCode result);
virtual void handleChildOutput(int fd, std::string_view data)
virtual void handleChildOutput(int fd, const string & data)
{
abort();
}
@@ -87,7 +87,7 @@ struct Goal : public std::enable_shared_from_this<Goal>
void trace(const FormatOrString & fs);
std::string getName()
string getName()
{
return name;
}
@@ -97,7 +97,7 @@ struct Goal : public std::enable_shared_from_this<Goal>
by the worker (important!), etc. */
virtual void timedOut(Error && ex) = 0;
virtual std::string key() = 0;
virtual string key() = 0;
void amDone(ExitCode result, std::optional<Error> ex = {});

View File

@@ -1,5 +1,4 @@
#include "local-derivation-goal.hh"
#include "gc-store.hh"
#include "hook-instance.hh"
#include "worker.hh"
#include "builtins.hh"
@@ -482,12 +481,12 @@ void LocalDerivationGoal::startBuilder()
temporary build directory. The text files have the format used
by `nix-store --register-validity'. However, the deriver
fields are left empty. */
auto s = get(drv->env, "exportReferencesGraph").value_or("");
string s = get(drv->env, "exportReferencesGraph").value_or("");
Strings ss = tokenizeString<Strings>(s);
if (ss.size() % 2 != 0)
throw BuildError("odd number of tokens in 'exportReferencesGraph': '%1%'", s);
for (Strings::iterator i = ss.begin(); i != ss.end(); ) {
auto fileName = *i++;
string fileName = *i++;
static std::regex regex("[A-Za-z_][A-Za-z0-9_.-]*");
if (!std::regex_match(fileName, regex))
throw Error("invalid file name '%s' in 'exportReferencesGraph'", fileName);
@@ -518,10 +517,10 @@ void LocalDerivationGoal::startBuilder()
i.pop_back();
}
size_t p = i.find('=');
if (p == std::string::npos)
if (p == string::npos)
dirsInChroot[i] = {i, optional};
else
dirsInChroot[i.substr(0, p)] = {i.substr(p + 1), optional};
dirsInChroot[string(i, 0, p)] = {string(i, p + 1), optional};
}
dirsInChroot[tmpDirInSandbox] = tmpDir;
@@ -672,10 +671,9 @@ void LocalDerivationGoal::startBuilder()
auto state = stBegin;
auto lines = runProgram(settings.preBuildHook, false, args);
auto lastPos = std::string::size_type{0};
for (auto nlPos = lines.find('\n'); nlPos != std::string::npos;
nlPos = lines.find('\n', lastPos))
{
auto line = lines.substr(lastPos, nlPos - lastPos);
for (auto nlPos = lines.find('\n'); nlPos != string::npos;
nlPos = lines.find('\n', lastPos)) {
auto line = std::string{lines, lastPos, nlPos - lastPos};
lastPos = nlPos + 1;
if (state == stBegin) {
if (line == "extra-sandbox-paths" || line == "extra-chroot-dirs") {
@@ -688,10 +686,10 @@ void LocalDerivationGoal::startBuilder()
state = stBegin;
} else {
auto p = line.find('=');
if (p == std::string::npos)
if (p == string::npos)
dirsInChroot[line] = line;
else
dirsInChroot[line.substr(0, p)] = line.substr(p + 1);
dirsInChroot[string(line, 0, p)] = string(line, p + 1);
}
}
}
@@ -943,7 +941,7 @@ void LocalDerivationGoal::startBuilder()
/* Check if setting up the build environment failed. */
std::vector<std::string> msgs;
while (true) {
std::string msg = [&]() {
string msg = [&]() {
try {
return readLine(builderOut.readSide.get());
} catch (Error & e) {
@@ -955,8 +953,8 @@ void LocalDerivationGoal::startBuilder()
throw;
}
}();
if (msg.substr(0, 1) == "\2") break;
if (msg.substr(0, 1) == "\1") {
if (string(msg, 0, 1) == "\2") break;
if (string(msg, 0, 1) == "\1") {
FdSource source(builderOut.readSide.get());
auto ex = readError(source);
ex.addTrace({}, "while setting up the build environment");
@@ -992,7 +990,7 @@ void LocalDerivationGoal::initTmpDir() {
env[i.first] = i.second;
} else {
auto hash = hashString(htSHA256, i.first);
std::string fn = ".attr-" + hash.to_string(Base32, false);
string fn = ".attr-" + hash.to_string(Base32, false);
Path p = tmpDir + "/" + fn;
writeFile(p, rewriteStrings(i.second, inputRewrites));
chownToBuilder(p);
@@ -1083,7 +1081,7 @@ void LocalDerivationGoal::writeStructuredAttrs()
for (auto & [i, v] : json["outputs"].get<nlohmann::json::object_t>()) {
/* The placeholder must have a rewrite, so we use it to cover both the
cases where we know or don't know the output path ahead of time. */
rewritten[i] = rewriteStrings((std::string) v, inputRewrites);
rewritten[i] = rewriteStrings(v, inputRewrites);
}
json["outputs"] = rewritten;
@@ -1128,7 +1126,7 @@ struct RestrictedStoreConfig : virtual LocalFSStoreConfig
/* A wrapper around LocalStore that only allows building/querying of
paths that are in the input closures of the build or were added via
recursive Nix calls. */
struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual LocalFSStore, public virtual GcStore
struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual LocalFSStore
{
ref<LocalStore> next;
@@ -1189,14 +1187,10 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override
{ throw Error("queryPathFromHashPart"); }
StorePath addToStore(
std::string_view name,
const Path & srcPath,
FileIngestionMethod method,
HashType hashAlgo,
PathFilter & filter,
RepairFlag repair,
const StorePathSet & references) override
StorePath addToStore(const string & name, const Path & srcPath,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter, RepairFlag repair = NoRepair,
const StorePathSet & references = StorePathSet()) override
{ throw Error("addToStore"); }
void addToStore(const ValidPathInfo & info, Source & narSource,
@@ -1206,24 +1200,17 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
goal.addDependency(info.path);
}
StorePath addTextToStore(
std::string_view name,
std::string_view s,
const StorePathSet & references,
RepairFlag repair = NoRepair) override
StorePath addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair = NoRepair) override
{
auto path = next->addTextToStore(name, s, references, repair);
goal.addDependency(path);
return path;
}
StorePath addToStoreFromDump(
Source & dump,
std::string_view name,
FileIngestionMethod method,
HashType hashAlgo,
RepairFlag repair,
const StorePathSet & references) override
StorePath addToStoreFromDump(Source & dump, std::string_view name,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair,
const StorePathSet & references = StorePathSet()) override
{
auto path = next->addToStoreFromDump(dump, name, method, hashAlgo, repair, references);
goal.addDependency(path);
@@ -1394,7 +1381,7 @@ void LocalDerivationGoal::startDaemon()
try {
daemon::processConnection(store, from, to,
daemon::NotTrusted, daemon::Recursive,
[&](Store & store) {});
[&](Store & store) { store.createUser("nobody", 65535); });
debug("terminated daemon connection");
} catch (SysError &) {
ignoreException();
@@ -1934,7 +1921,7 @@ void LocalDerivationGoal::runChild()
"can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin",
i.first, i.second.source);
std::string path = i.first;
string path = i.first;
struct stat st;
if (lstat(path.c_str(), &st)) {
if (i.second.optional && errno == ENOENT)
@@ -1986,7 +1973,7 @@ void LocalDerivationGoal::runChild()
args.push_back("IMPORT_DIR=" + settings.nixDataDir + "/nix/sandbox/");
if (allowLocalNetworking) {
args.push_back("-D");
args.push_back(std::string("_ALLOW_LOCAL_NETWORKING=1"));
args.push_back(string("_ALLOW_LOCAL_NETWORKING=1"));
}
args.push_back(drv->builder);
} else {
@@ -2005,7 +1992,7 @@ void LocalDerivationGoal::runChild()
args.push_back(rewriteStrings(i, inputRewrites));
/* Indicate that we managed to set up the build environment. */
writeFull(STDERR_FILENO, std::string("\2\n"));
writeFull(STDERR_FILENO, string("\2\n"));
/* Execute the program. This should not return. */
if (drv->isBuiltin()) {
@@ -2023,7 +2010,7 @@ void LocalDerivationGoal::runChild()
else if (drv->builder == "builtin:unpack-channel")
builtinUnpackChannel(drv2);
else
throw Error("unsupported builtin builder '%1%'", drv->builder.substr(8));
throw Error("unsupported builtin builder '%1%'", string(drv->builder, 8));
_exit(0);
} catch (std::exception & e) {
writeFull(STDERR_FILENO, e.what() + std::string("\n"));
@@ -2384,10 +2371,14 @@ void LocalDerivationGoal::registerOutputs()
[&](DerivationOutputCAFloating dof) {
return newInfoFromCA(dof);
},
[&](DerivationOutputDeferred) -> ValidPathInfo {
[&](DerivationOutputDeferred) {
// No derivation should reach that point without having been
// rewritten first
assert(false);
// Ugly, but the compiler insists on having this return a value
// of type `ValidPathInfo` despite the `assert(false)`, so
// let's provide it
return *(ValidPathInfo*)0;
},
}, output.output);
@@ -2703,7 +2694,7 @@ void LocalDerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & out
}
if (!badPaths.empty()) {
std::string badPathsStr;
string badPathsStr;
for (auto & i : badPaths) {
badPathsStr += "\n ";
badPathsStr += worker.store.printStorePath(i);

View File

@@ -58,11 +58,11 @@ struct LocalDerivationGoal : public DerivationGoal
typedef map<Path, ChrootPath> DirsInChroot; // maps target path to source path
DirsInChroot dirsInChroot;
typedef map<std::string, std::string> Environment;
typedef map<string, string> Environment;
Environment env;
#if __APPLE__
typedef std::string SandboxProfile;
typedef string SandboxProfile;
SandboxProfile additionalSandboxProfile;
#endif

View File

@@ -272,7 +272,7 @@ void PathSubstitutionGoal::finished()
}
void PathSubstitutionGoal::handleChildOutput(int fd, std::string_view data)
void PathSubstitutionGoal::handleChildOutput(int fd, const string & data)
{
}

View File

@@ -59,7 +59,7 @@ public:
void timedOut(Error && ex) override { abort(); };
std::string key() override
string key() override
{
/* "a$" ensures substitution goals happen before derivation
goals. */
@@ -77,7 +77,7 @@ public:
void finished();
/* Callback used by the worker to write to the log. */
void handleChildOutput(int fd, std::string_view data) override;
void handleChildOutput(int fd, const string & data) override;
void handleEOF(int fd) override;
void cleanup() override;

View File

@@ -394,7 +394,7 @@ void Worker::waitForInput()
} else {
printMsg(lvlVomit, "%1%: read %2% bytes",
goal->getName(), rd);
std::string data((char *) buffer.data(), rd);
string data((char *) buffer.data(), rd);
j->lastOutput = after;
goal->handleChildOutput(k, data);
}

View File

@@ -123,7 +123,7 @@ void buildProfile(const Path & out, Packages && pkgs)
createLinks(state, pkgDir, out, priority);
try {
for (const auto & p : tokenizeString<std::vector<std::string>>(
for (const auto & p : tokenizeString<std::vector<string>>(
readFile(pkgDir + "/nix-support/propagated-user-env-packages"), " \n"))
if (!done.count(p))
postponed.insert(p);
@@ -161,7 +161,7 @@ void buildProfile(const Path & out, Packages && pkgs)
void builtinBuildenv(const BasicDerivation & drv)
{
auto getAttr = [&](const std::string & name) {
auto getAttr = [&](const string & name) {
auto i = drv.env.find(name);
if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
return i->second;

View File

@@ -16,7 +16,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
writeFile(settings.netrcFile, netrcData, 0600);
}
auto getAttr = [&](const std::string & name) {
auto getAttr = [&](const string & name) {
auto i = drv.env.find(name);
if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
return i->second;

View File

@@ -5,7 +5,7 @@ namespace nix {
void builtinUnpackChannel(const BasicDerivation & drv)
{
auto getAttr = [&](const std::string & name) {
auto getAttr = [&](const string & name) {
auto i = drv.env.find(name);
if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
return i->second;

View File

@@ -1,9 +1,7 @@
#include "daemon.hh"
#include "monitor-fd.hh"
#include "worker-protocol.hh"
#include "build-result.hh"
#include "store-api.hh"
#include "gc-store.hh"
#include "path-with-outputs.hh"
#include "finally.hh"
#include "archive.hh"
@@ -481,8 +479,8 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
}
case wopAddTextToStore: {
std::string suffix = readString(from);
std::string s = readString(from);
string suffix = readString(from);
string s = readString(from);
auto refs = worker_proto::read(*store, from, Phantom<StorePathSet> {});
logger->startWork();
auto path = store->addTextToStore(suffix, s, refs, NoRepair);
@@ -624,12 +622,9 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
case wopAddIndirectRoot: {
Path path = absPath(readString(from));
logger->startWork();
auto & gcStore = requireGcStore(*store);
gcStore.addIndirectRoot(path);
store->addIndirectRoot(path);
logger->stopWork();
to << 1;
break;
}
@@ -644,8 +639,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
case wopFindRoots: {
logger->startWork();
auto & gcStore = requireGcStore(*store);
Roots roots = gcStore.findRoots(!trusted);
Roots roots = store->findRoots(!trusted);
logger->stopWork();
size_t size = 0;
@@ -676,8 +670,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
logger->startWork();
if (options.ignoreLiveness)
throw Error("you are not allowed to ignore liveness");
auto & gcStore = requireGcStore(*store);
gcStore.collectGarbage(options, results);
store->collectGarbage(options, results);
logger->stopWork();
to << results.paths << results.bytesFreed << 0 /* obsolete */;
@@ -705,8 +698,8 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
if (GET_PROTOCOL_MINOR(clientVersion) >= 12) {
unsigned int n = readInt(from);
for (unsigned int i = 0; i < n; i++) {
auto name = readString(from);
auto value = readString(from);
string name = readString(from);
string value = readString(from);
clientSettings.overrides.emplace(name, value);
}
}

View File

@@ -82,7 +82,7 @@ bool derivationIsImpure(DerivationType dt) {
bool BasicDerivation::isBuiltin() const
{
return builder.substr(0, 8) == "builtin:";
return string(builder, 0, 8) == "builtin:";
}
@@ -104,19 +104,19 @@ StorePath writeDerivation(Store & store,
/* Read string `s' from stream `str'. */
static void expect(std::istream & str, std::string_view s)
static void expect(std::istream & str, const string & s)
{
char s2[s.size()];
str.read(s2, s.size());
if (std::string(s2, s.size()) != s)
if (string(s2, s.size()) != s)
throw FormatError("expected string '%1%'", s);
}
/* Read a C-style string from stream `str'. */
static std::string parseString(std::istream & str)
static string parseString(std::istream & str)
{
std::string res;
string res;
expect(str, "\"");
int c;
while ((c = str.get()) != '"')
@@ -172,7 +172,7 @@ static DerivationOutput parseDerivationOutput(const Store & store,
{
if (hashAlgo != "") {
auto method = FileIngestionMethod::Flat;
if (hashAlgo.substr(0, 2) == "r:") {
if (string(hashAlgo, 0, 2) == "r:") {
method = FileIngestionMethod::Recursive;
hashAlgo = hashAlgo.substr(2);
}
@@ -260,8 +260,8 @@ Derivation parseDerivation(const Store & store, std::string && s, std::string_vi
/* Parse the environment variables. */
expect(str, ",[");
while (!endOfList(str)) {
expect(str, "("); auto name = parseString(str);
expect(str, ","); auto value = parseString(str);
expect(str, "("); string name = parseString(str);
expect(str, ","); string value = parseString(str);
expect(str, ")");
drv.env[name] = value;
}
@@ -271,7 +271,7 @@ Derivation parseDerivation(const Store & store, std::string && s, std::string_vi
}
static void printString(std::string & res, std::string_view s)
static void printString(string & res, std::string_view s)
{
boost::container::small_vector<char, 64 * 1024> buffer;
buffer.reserve(s.size() * 2 + 2);
@@ -289,7 +289,7 @@ static void printString(std::string & res, std::string_view s)
}
static void printUnquotedString(std::string & res, std::string_view s)
static void printUnquotedString(string & res, std::string_view s)
{
res += '"';
res.append(s);
@@ -298,7 +298,7 @@ static void printUnquotedString(std::string & res, std::string_view s)
template<class ForwardIterator>
static void printStrings(std::string & res, ForwardIterator i, ForwardIterator j)
static void printStrings(string & res, ForwardIterator i, ForwardIterator j)
{
res += '[';
bool first = true;
@@ -311,7 +311,7 @@ static void printStrings(std::string & res, ForwardIterator i, ForwardIterator j
template<class ForwardIterator>
static void printUnquotedStrings(std::string & res, ForwardIterator i, ForwardIterator j)
static void printUnquotedStrings(string & res, ForwardIterator i, ForwardIterator j)
{
res += '[';
bool first = true;
@@ -323,10 +323,10 @@ static void printUnquotedStrings(std::string & res, ForwardIterator i, ForwardIt
}
std::string Derivation::unparse(const Store & store, bool maskOutputs,
string Derivation::unparse(const Store & store, bool maskOutputs,
std::map<std::string, StringSet> * actualInputs) const
{
std::string s;
string s;
s.reserve(65536);
s += "Derive([";
@@ -401,7 +401,7 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
// FIXME: remove
bool isDerivation(const std::string & fileName)
bool isDerivation(const string & fileName)
{
return hasSuffix(fileName, drvExtension);
}
@@ -593,7 +593,7 @@ std::map<std::string, Hash> staticOutputHashes(Store & store, const Derivation &
}
bool wantOutput(const std::string & output, const std::set<std::string> & wanted)
bool wantOutput(const string & output, const std::set<string> & wanted)
{
return wanted.empty() || wanted.find(output) != wanted.end();
}

View File

@@ -59,19 +59,21 @@ struct DerivationOutput
std::optional<StorePath> path(const Store & store, std::string_view drvName, std::string_view outputName) const;
};
typedef std::map<std::string, DerivationOutput> DerivationOutputs;
typedef std::map<string, DerivationOutput> DerivationOutputs;
/* These are analogues to the previous DerivationOutputs data type, but they
also contains, for each output, the (optional) store path in which it would
be written. To calculate values of these types, see the corresponding
functions in BasicDerivation */
typedef std::map<std::string, std::pair<DerivationOutput, std::optional<StorePath>>>
typedef std::map<string, std::pair<DerivationOutput, std::optional<StorePath>>>
DerivationOutputsAndOptPaths;
/* For inputs that are sub-derivations, we specify exactly which
output IDs we are interested in. */
typedef std::map<StorePath, StringSet> DerivationInputs;
typedef std::map<string, string> StringPairs;
enum struct DerivationType : uint8_t {
InputAddressed,
DeferredInputAddressed,
@@ -101,7 +103,7 @@ struct BasicDerivation
{
DerivationOutputs outputs; /* keyed on symbolic IDs */
StorePathSet inputSrcs; /* inputs that are sources */
std::string platform;
string platform;
Path builder;
Strings args;
StringPairs env;
@@ -162,7 +164,7 @@ StorePath writeDerivation(Store & store,
Derivation parseDerivation(const Store & store, std::string && s, std::string_view name);
// FIXME: remove
bool isDerivation(const std::string & fileName);
bool isDerivation(const string & fileName);
/* Calculate the name that will be used for the store path for this
output.
@@ -220,7 +222,7 @@ typedef std::map<StorePath, DrvHashModulo> DrvHashes;
// FIXME: global, though at least thread-safe.
extern Sync<DrvHashes> drvHashes;
bool wantOutput(const std::string & output, const std::set<std::string> & wanted);
bool wantOutput(const string & output, const std::set<string> & wanted);
struct Source;
struct Sink;

View File

@@ -75,9 +75,9 @@ DerivedPath::Built DerivedPath::Built::parse(const Store & store, std::string_vi
assert(n != s.npos);
auto drvPath = store.parseStorePath(s.substr(0, n));
auto outputsS = s.substr(n + 1);
std::set<std::string> outputs;
std::set<string> outputs;
if (outputsS != "*")
outputs = tokenizeString<std::set<std::string>>(outputsS, ",");
outputs = tokenizeString<std::set<string>>(outputsS, ",");
return {drvPath, outputs};
}

View File

@@ -21,7 +21,7 @@ struct DummyStore : public virtual DummyStoreConfig, public virtual Store
, Store(params)
{ }
std::string getUri() override
string getUri() override
{
return *uriSchemes().begin();
}
@@ -43,11 +43,8 @@ struct DummyStore : public virtual DummyStoreConfig, public virtual Store
RepairFlag repair, CheckSigsFlag checkSigs) override
{ unsupported("addToStore"); }
StorePath addTextToStore(
std::string_view name,
std::string_view s,
const StorePathSet & references,
RepairFlag repair) override
StorePath addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair) override
{ unsupported("addTextToStore"); }
void narFromPath(const StorePath & path, Sink & sink) override

View File

@@ -33,12 +33,12 @@ FileTransferSettings fileTransferSettings;
static GlobalConfig::Register rFileTransferSettings(&fileTransferSettings);
std::string resolveUri(std::string_view uri)
std::string resolveUri(const std::string & uri)
{
if (uri.compare(0, 8, "channel:") == 0)
return "https://nixos.org/channels/" + std::string(uri.substr(8)) + "/nixexprs.tar.xz";
return "https://nixos.org/channels/" + std::string(uri, 8) + "/nixexprs.tar.xz";
else
return std::string(uri);
return uri;
}
struct curlFileTransfer : public FileTransfer
@@ -197,15 +197,15 @@ struct curlFileTransfer : public FileTransfer
result.etag = "";
result.data.clear();
result.bodySize = 0;
statusMsg = trim(match.str(1));
statusMsg = trim(match[1]);
acceptRanges = false;
encoding = "";
} else {
auto i = line.find(':');
if (i != std::string::npos) {
std::string name = toLower(trim(line.substr(0, i)));
if (i != string::npos) {
string name = toLower(trim(string(line, 0, i)));
if (name == "etag") {
result.etag = trim(line.substr(i + 1));
result.etag = trim(string(line, i + 1));
/* Hack to work around a GitHub bug: it sends
ETags, but ignores If-None-Match. So if we get
the expected ETag on a 200 response, then shut
@@ -218,8 +218,8 @@ struct curlFileTransfer : public FileTransfer
return 0;
}
} else if (name == "content-encoding")
encoding = trim(line.substr(i + 1));
else if (name == "accept-ranges" && toLower(trim(line.substr(i + 1))) == "bytes")
encoding = trim(string(line, i + 1));
else if (name == "accept-ranges" && toLower(trim(std::string(line, i + 1))) == "bytes")
acceptRanges = true;
}
}
@@ -866,18 +866,18 @@ FileTransferError::FileTransferError(FileTransfer::Error error, std::optional<st
// FIXME: Due to https://github.com/NixOS/nix/issues/3841 we don't know how
// to print different messages for different verbosity levels. For now
// we add some heuristics for detecting when we want to show the response.
if (response && (response->size() < 1024 || response->find("<html>") != std::string::npos))
if (response && (response->size() < 1024 || response->find("<html>") != string::npos))
err.msg = hintfmt("%1%\n\nresponse body:\n\n%2%", normaltxt(hf.str()), chomp(*response));
else
err.msg = hf;
}
bool isUri(std::string_view s)
bool isUri(const string & s)
{
if (s.compare(0, 8, "channel:") == 0) return true;
size_t pos = s.find("://");
if (pos == std::string::npos) return false;
std::string scheme(s, 0, pos);
if (pos == string::npos) return false;
string scheme(s, 0, pos);
return scheme == "http" || scheme == "https" || scheme == "file" || scheme == "channel" || scheme == "git" || scheme == "s3" || scheme == "ssh";
}

View File

@@ -119,17 +119,17 @@ class FileTransferError : public Error
{
public:
FileTransfer::Error error;
std::optional<std::string> response; // intentionally optional
std::optional<string> response; // intentionally optional
template<typename... Args>
FileTransferError(FileTransfer::Error error, std::optional<std::string> response, const Args & ... args);
FileTransferError(FileTransfer::Error error, std::optional<string> response, const Args & ... args);
virtual const char* sname() const override { return "FileTransferError"; }
};
bool isUri(std::string_view s);
bool isUri(const string & s);
/* Resolve deprecated 'channel:<foo>' URLs. */
std::string resolveUri(std::string_view uri);
std::string resolveUri(const std::string & uri);
}

View File

@@ -1,13 +0,0 @@
#include "gc-store.hh"
namespace nix {
GcStore & requireGcStore(Store & store)
{
auto * gcStore = dynamic_cast<GcStore *>(&store);
if (!gcStore)
throw UsageError("Garbage collection not supported by this store");
return *gcStore;
}
}

View File

@@ -1,84 +0,0 @@
#pragma once
#include "store-api.hh"
namespace nix {
typedef std::unordered_map<StorePath, std::unordered_set<std::string>> Roots;
struct GCOptions
{
/* Garbage collector operation:
- `gcReturnLive': return the set of paths reachable from
(i.e. in the closure of) the roots.
- `gcReturnDead': return the set of paths not reachable from
the roots.
- `gcDeleteDead': actually delete the latter set.
- `gcDeleteSpecific': delete the paths listed in
`pathsToDelete', insofar as they are not reachable.
*/
typedef enum {
gcReturnLive,
gcReturnDead,
gcDeleteDead,
gcDeleteSpecific,
} GCAction;
GCAction action{gcDeleteDead};
/* If `ignoreLiveness' is set, then reachability from the roots is
ignored (dangerous!). However, the paths must still be
unreferenced *within* the store (i.e., there can be no other
store paths that depend on them). */
bool ignoreLiveness{false};
/* For `gcDeleteSpecific', the paths to delete. */
StorePathSet pathsToDelete;
/* Stop after at least `maxFreed' bytes have been freed. */
uint64_t maxFreed{std::numeric_limits<uint64_t>::max()};
};
struct GCResults
{
/* Depending on the action, the GC roots, or the paths that would
be or have been deleted. */
PathSet paths;
/* For `gcReturnDead', `gcDeleteDead' and `gcDeleteSpecific', the
number of bytes that would be or was freed. */
uint64_t bytesFreed = 0;
};
struct GcStore : public virtual Store
{
/* Add an indirect root, which is merely a symlink to `path' from
/nix/var/nix/gcroots/auto/<hash of `path'>. `path' is supposed
to be a symlink to a store path. The garbage collector will
automatically remove the indirect root when it finds that
`path' has disappeared. */
virtual void addIndirectRoot(const Path & path) = 0;
/* Find the roots of the garbage collector. Each root is a pair
(link, storepath) where `link' is the path of the symlink
outside of the Nix store that point to `storePath'. If
'censor' is true, privacy-sensitive information about roots
found in /proc is censored. */
virtual Roots findRoots(bool censor) = 0;
/* Perform a garbage collection. */
virtual void collectGarbage(const GCOptions & options, GCResults & results) = 0;
};
GcStore & requireGcStore(Store & store);
}

View File

@@ -3,7 +3,6 @@
#include "local-store.hh"
#include "local-fs-store.hh"
#include "finally.hh"
#include "find-roots.hh"
#include <functional>
#include <queue>
@@ -26,7 +25,6 @@ namespace nix {
static std::string gcSocketPath = "/gc-socket/socket";
static std::string rootsSocketPath = "/gc-roots-socket/socket";
static std::string gcRootsDir = "gcroots";
@@ -49,8 +47,9 @@ static void makeSymlink(const Path & link, const Path & target)
void LocalStore::addIndirectRoot(const Path & path)
{
std::string hash = hashString(htSHA1, path).to_string(Base32, false);
Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", stateDir, gcRootsDir, hash));
string hash = hashString(htSHA1, path).to_string(Base32, false);
Path realRoot = canonPath((format("%1%/%2%/auto/%3%")
% stateDir % gcRootsDir % hash).str());
makeSymlink(realRoot, path);
}
@@ -124,7 +123,7 @@ void LocalStore::addTempRoot(const StorePath & path)
collector is running. So we have to connect to the garbage
collector and inform it about our root. */
if (!state->fdRootsSocket) {
auto socketPath = stateDir.get() + rootsSocketPath;
auto socketPath = stateDir.get() + gcSocketPath;
debug("connecting to '%s'", socketPath);
state->fdRootsSocket = createUnixDomainSocket();
try {
@@ -163,7 +162,7 @@ void LocalStore::addTempRoot(const StorePath & path)
}
/* Append the store path to the temporary roots file. */
auto s = printStorePath(path) + '\0';
string s = printStorePath(path) + '\0';
writeFull(state->fdTempRoots.get(), s);
}
@@ -204,12 +203,12 @@ void LocalStore::findTempRoots(Roots & tempRoots, bool censor)
}
/* Read the entire file. */
auto contents = readFile(fd.get());
string contents = readFile(fd.get());
/* Extract the roots. */
std::string::size_type pos = 0, end;
string::size_type pos = 0, end;
while ((end = contents.find((char) 0, pos)) != std::string::npos) {
while ((end = contents.find((char) 0, pos)) != string::npos) {
Path root(contents, pos, end - pos);
debug("got temporary root '%s'", root);
tempRoots[parseStorePath(root)].emplace(censor ? censored : fmt("{temp:%d}", pid));
@@ -218,32 +217,79 @@ void LocalStore::findTempRoots(Roots & tempRoots, bool censor)
}
}
void LocalStore::findRootsNoTempNoExternalDaemon(Roots & roots, bool censor)
void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
{
debug("Cant connect to the tracing daemon socket, fallback to the internal trace");
using namespace nix::roots_tracer;
const TracerConfig opts {
.storeDir = fs::path(storeDir),
.stateDir = fs::path(stateDir.get())
auto foundRoot = [&](const Path & path, const Path & target) {
try {
auto storePath = toStorePath(target).first;
if (isValidPath(storePath))
roots[std::move(storePath)].emplace(path);
else
printInfo("skipping invalid root from '%1%' to '%2%'", path, target);
} catch (BadStorePath &) { }
};
const std::set<fs::path> standardRoots = {
opts.stateDir / fs::path(gcRootsDir),
opts.stateDir / fs::path("gcroots"),
};
auto traceResult = traceStaticRoots(opts, standardRoots);
auto runtimeRoots = getRuntimeRoots(opts);
traceResult.storeRoots.insert(runtimeRoots.begin(), runtimeRoots.end());
for (auto & [rawRootInStore, externalRoots] : traceResult.storeRoots) {
if (!isInStore(rawRootInStore)) continue;
auto rootInStore = toStorePath(rawRootInStore).first;
if (!isValidPath(rootInStore)) continue;
std::unordered_set<std::string> primRoots;
for (const auto & externalRoot : externalRoots)
primRoots.insert(externalRoot.string());
roots.emplace(rootInStore, primRoots);
try {
if (type == DT_UNKNOWN)
type = getFileType(path);
if (type == DT_DIR) {
for (auto & i : readDirectory(path))
findRoots(path + "/" + i.name, i.type, roots);
}
else if (type == DT_LNK) {
Path target = readLink(path);
if (isInStore(target))
foundRoot(path, target);
/* Handle indirect roots. */
else {
target = absPath(target, dirOf(path));
if (!pathExists(target)) {
if (isInDir(path, stateDir + "/" + gcRootsDir + "/auto")) {
printInfo(format("removing stale link from '%1%' to '%2%'") % path % target);
unlink(path.c_str());
}
} else {
struct stat st2 = lstat(target);
if (!S_ISLNK(st2.st_mode)) return;
Path target2 = readLink(target);
if (isInStore(target2)) foundRoot(target, target2);
}
}
}
else if (type == DT_REG) {
auto storePath = maybeParseStorePath(storeDir + "/" + std::string(baseNameOf(path)));
if (storePath && isValidPath(*storePath))
roots[std::move(*storePath)].emplace(path);
}
}
catch (SysError & e) {
/* We only ignore permanent failures. */
if (e.errNo == EACCES || e.errNo == ENOENT || e.errNo == ENOTDIR)
printInfo("cannot read potential root '%1%'", path);
else
throw;
}
}
void LocalStore::findRootsNoTemp(Roots & roots, bool censor)
{
/* Process direct roots in {gcroots,profiles}. */
findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
findRoots(stateDir + "/profiles", DT_UNKNOWN, roots);
/* Add additional roots returned by different platforms-specific
heuristics. This is typically used to add running programs to
the set of roots (to prevent them from being garbage collected). */
findRuntimeRoots(roots, censor);
}
@@ -257,53 +303,153 @@ Roots LocalStore::findRoots(bool censor)
return roots;
}
void LocalStore::findRootsNoTemp(Roots & roots, bool censor)
typedef std::unordered_map<Path, std::unordered_set<std::string>> UncheckedRoots;
static void readProcLink(const string & file, UncheckedRoots & roots)
{
auto fd = createUnixDomainSocket();
std::string socketPath = settings.gcSocketPath.get() != "auto"
? settings.gcSocketPath.get()
: stateDir.get() + gcSocketPath;
try {
nix::connect(fd.get(), socketPath);
} catch (SysError & e) {
return findRootsNoTempNoExternalDaemon(roots, censor);
/* 64 is the starting buffer size gnu readlink uses... */
auto bufsiz = ssize_t{64};
try_again:
char buf[bufsiz];
auto res = readlink(file.c_str(), buf, bufsiz);
if (res == -1) {
if (errno == ENOENT || errno == EACCES || errno == ESRCH)
return;
throw SysError("reading symlink");
}
if (res == bufsiz) {
if (SSIZE_MAX / 2 < bufsiz)
throw Error("stupidly long symlink");
bufsiz *= 2;
goto try_again;
}
if (res > 0 && buf[0] == '/')
roots[std::string(static_cast<char *>(buf), res)]
.emplace(file);
}
settings.requireExperimentalFeature(Xp::ExternalGCDaemon);
static string quoteRegexChars(const string & raw)
{
static auto specialRegex = std::regex(R"([.^$\\*+?()\[\]{}|])");
return std::regex_replace(raw, specialRegex, R"(\$&)");
}
#if __linux__
static void readFileRoots(const char * path, UncheckedRoots & roots)
{
try {
StringMap unescapes = {
{ "\\n", "\n"},
{ "\\t", "\t"},
};
while (true) {
auto line = readLine(fd.get());
if (line.empty()) break; // TODO: Handle the broken symlinks
auto parsedLine = tokenizeString<std::vector<std::string>>(line, "\t");
if (parsedLine.size() != 2)
throw Error("Invalid result from the gc helper");
auto rawDestPath = rewriteStrings(parsedLine[0], unescapes);
auto retainer = rewriteStrings(parsedLine[1], unescapes);
if (!isInStore(rawDestPath)) continue;
try {
auto destPath = toStorePath(rawDestPath).first;
if (!isValidPath(destPath)) continue;
roots[destPath].insert(
(!censor || isInDir(retainer, stateDir.get())) ? retainer : censored);
} catch (Error &) {
roots[readFile(path)].emplace(path);
} catch (SysError & e) {
if (e.errNo != ENOENT && e.errNo != EACCES)
throw;
}
}
#endif
void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
{
UncheckedRoots unchecked;
auto procDir = AutoCloseDir{opendir("/proc")};
if (procDir) {
struct dirent * ent;
auto digitsRegex = std::regex(R"(^\d+$)");
auto mapRegex = std::regex(R"(^\s*\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(/\S+)\s*$)");
auto storePathRegex = std::regex(quoteRegexChars(storeDir) + R"(/[0-9a-z]+[0-9a-zA-Z\+\-\._\?=]*)");
while (errno = 0, ent = readdir(procDir.get())) {
checkInterrupt();
if (std::regex_match(ent->d_name, digitsRegex)) {
readProcLink(fmt("/proc/%s/exe" ,ent->d_name), unchecked);
readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked);
auto fdStr = fmt("/proc/%s/fd", ent->d_name);
auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
if (!fdDir) {
if (errno == ENOENT || errno == EACCES)
continue;
throw SysError("opening %1%", fdStr);
}
struct dirent * fd_ent;
while (errno = 0, fd_ent = readdir(fdDir.get())) {
if (fd_ent->d_name[0] != '.')
readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
}
if (errno) {
if (errno == ESRCH)
continue;
throw SysError("iterating /proc/%1%/fd", ent->d_name);
}
fdDir.reset();
try {
auto mapFile = fmt("/proc/%s/maps", ent->d_name);
auto mapLines = tokenizeString<std::vector<string>>(readFile(mapFile), "\n");
for (const auto & line : mapLines) {
auto match = std::smatch{};
if (std::regex_match(line, match, mapRegex))
unchecked[match[1]].emplace(mapFile);
}
auto envFile = fmt("/proc/%s/environ", ent->d_name);
auto envString = readFile(envFile);
auto env_end = std::sregex_iterator{};
for (auto i = std::sregex_iterator{envString.begin(), envString.end(), storePathRegex}; i != env_end; ++i)
unchecked[i->str()].emplace(envFile);
} catch (SysError & e) {
if (errno == ENOENT || errno == EACCES || errno == ESRCH)
continue;
throw;
}
}
}
} catch (EndOfFile &) {
if (errno)
throw SysError("iterating /proc");
}
#if !defined(__linux__)
// lsof is really slow on OS X. This actually causes the gc-concurrent.sh test to fail.
// See: https://github.com/NixOS/nix/issues/3011
// Because of this we disable lsof when running the tests.
if (getEnv("_NIX_TEST_NO_LSOF") != "1") {
try {
std::regex lsofRegex(R"(^n(/.*)$)");
auto lsofLines =
tokenizeString<std::vector<string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n");
for (const auto & line : lsofLines) {
std::smatch match;
if (std::regex_match(line, match, lsofRegex))
unchecked[match[1]].emplace("{lsof}");
}
} catch (ExecError & e) {
/* lsof not installed, lsof failed */
}
}
#endif
#if __linux__
readFileRoots("/proc/sys/kernel/modprobe", unchecked);
readFileRoots("/proc/sys/kernel/fbsplash", unchecked);
readFileRoots("/proc/sys/kernel/poweroff_cmd", unchecked);
#endif
for (auto & [target, links] : unchecked) {
if (!isInStore(target)) continue;
try {
auto path = toStorePath(target).first;
if (!isValidPath(path)) continue;
debug("got additional root '%1%'", printStorePath(path));
if (censor)
roots[path].insert(censored);
else
roots[path].insert(links.begin(), links.end());
} catch (BadStorePath &) { }
}
}
typedef std::unordered_map<Path, std::unordered_set<std::string>> UncheckedRoots;
struct GCLimitReached { };
void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
{
bool shouldDelete = options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific;
@@ -346,7 +492,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
FdLock gcLock(fdGCLock.get(), ltWrite, true, "waiting for the big garbage collector lock...");
/* Start the server for receiving new roots. */
auto socketPath = stateDir.get() + rootsSocketPath;
auto socketPath = stateDir.get() + gcSocketPath;
createDirs(dirOf(socketPath));
auto fdServer = createUnixDomainSocket(socketPath, 0666);
@@ -454,7 +600,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
printInfo("finding garbage collector roots...");
Roots rootMap;
if (!options.ignoreLiveness)
rootMap = findRoots(true);
findRootsNoTemp(rootMap, true);
for (auto & i : rootMap) roots.insert(i.first);
@@ -638,7 +784,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
struct dirent * dirent;
while (errno = 0, dirent = readdir(dir.get())) {
checkInterrupt();
std::string name = dirent->d_name;
string name = dirent->d_name;
if (name == "." || name == ".." || name == linksName) continue;
if (auto storePath = maybeParseStorePath(storeDir + "/" + name))
@@ -679,7 +825,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
struct dirent * dirent;
while (errno = 0, dirent = readdir(dir.get())) {
checkInterrupt();
std::string name = dirent->d_name;
string name = dirent->d_name;
if (name == "." || name == "..") continue;
Path path = linksDir + "/" + name;

View File

@@ -100,7 +100,7 @@ std::vector<Path> getUserConfigFiles()
// Use the paths specified in NIX_USER_CONF_FILES if it has been defined
auto nixConfFiles = getEnv("NIX_USER_CONF_FILES");
if (nixConfFiles.has_value()) {
return tokenizeString<std::vector<std::string>>(nixConfFiles.value(), ":");
return tokenizeString<std::vector<string>>(nixConfFiles.value(), ":");
}
// Use the paths specified by the XDG spec
@@ -181,7 +181,7 @@ bool Settings::isWSL1()
return hasSuffix(utsbuf.release, "-Microsoft");
}
const std::string nixVersion = PACKAGE_VERSION;
const string nixVersion = PACKAGE_VERSION;
NLOHMANN_JSON_SERIALIZE_ENUM(SandboxMode, {
{SandboxMode::smEnabled, true},

View File

@@ -94,13 +94,6 @@ public:
Setting<std::string> storeUri{this, getEnv("NIX_REMOTE").value_or("auto"), "store",
"The default Nix store to use."};
Setting<std::string> gcSocketPath {
this,
"auto",
"gc-socket-path",
"Path to the socket used to communicate with an external GC."
};
Setting<bool> keepFailed{this, false, "keep-failed",
"Whether to keep temporary directories of failed builds."};
@@ -120,7 +113,7 @@ public:
bool verboseBuild = true;
Setting<size_t> logLines{this, 10, "log-lines",
"The number of lines of the tail of "
"If `verbose-build` is false, the number of lines of the tail of "
"the log to show if a build fails."};
MaxBuildJobsSetting maxBuildJobs{
@@ -887,6 +880,55 @@ public:
are loaded as plugins (non-recursively).
)"};
Setting<StringMap> accessTokens{this, {}, "access-tokens",
R"(
Access tokens used to access protected GitHub, GitLab, or
other locations requiring token-based authentication.
Access tokens are specified as a string made up of
space-separated `host=token` values. The specific token
used is selected by matching the `host` portion against the
"host" specification of the input. The actual use of the
`token` value is determined by the type of resource being
accessed:
* Github: the token value is the OAUTH-TOKEN string obtained
as the Personal Access Token from the Github server (see
https://docs.github.com/en/developers/apps/authorizing-oath-apps).
* Gitlab: the token value is either the OAuth2 token or the
Personal Access Token (these are different types tokens
for gitlab, see
https://docs.gitlab.com/12.10/ee/api/README.html#authentication).
The `token` value should be `type:tokenstring` where
`type` is either `OAuth2` or `PAT` to indicate which type
of token is being specified.
Example `~/.config/nix/nix.conf`:
```
access-tokens = github.com=23ac...b289 gitlab.mycompany.com=PAT:A123Bp_Cd..EfG gitlab.com=OAuth2:1jklw3jk
```
Example `~/code/flake.nix`:
```nix
input.foo = {
type = "gitlab";
host = "gitlab.mycompany.com";
owner = "mycompany";
repo = "pro";
};
```
This example specifies three tokens, one each for accessing
github.com, gitlab.mycompany.com, and sourceforge.net.
The `input.foo` uses the "gitlab" fetcher, which might
requires specifying the token type along with the token
value.
)"};
Setting<std::set<ExperimentalFeature>> experimentalFeatures{this, {}, "experimental-features",
"Experimental Nix features to enable."};
@@ -894,9 +936,18 @@ public:
void requireExperimentalFeature(const ExperimentalFeature &);
Setting<bool> allowDirty{this, true, "allow-dirty",
"Whether to allow dirty Git/Mercurial trees."};
Setting<bool> warnDirty{this, true, "warn-dirty",
"Whether to warn about dirty Git/Mercurial trees."};
Setting<size_t> narBufferSize{this, 32 * 1024 * 1024, "nar-buffer-size",
"Maximum size of NARs before spilling them to disk."};
Setting<std::string> flakeRegistry{this, "https://github.com/NixOS/flake-registry/raw/master/flake-registry.json", "flake-registry",
"Path or URI of the global flake registry."};
Setting<bool> allowSymlinkedStore{
this, false, "allow-symlinked-store",
R"(
@@ -909,6 +960,19 @@ public:
resolves to a different location from that of the build machine. You
can enable this setting if you are sure you're not going to do that.
)"};
Setting<bool> useRegistries{this, true, "use-registries",
"Whether to use flake registries to resolve flake references."};
Setting<bool> acceptFlakeConfig{this, false, "accept-flake-config",
"Whether to accept nix configuration from a flake without prompting."};
Setting<std::string> commitLockFileSummary{
this, "", "commit-lockfile-summary",
R"(
The commit summary to use when committing changed flake lock files. If
empty, the summary is generated based on the action performed.
)"};
};
@@ -924,6 +988,6 @@ void loadConfFile();
// Used by the Settings constructor
std::vector<Path> getUserConfigFiles();
extern const std::string nixVersion;
extern const string nixVersion;
}

View File

@@ -2,7 +2,6 @@
#include "pool.hh"
#include "remote-store.hh"
#include "serve-protocol.hh"
#include "build-result.hh"
#include "store-api.hh"
#include "path-with-outputs.hh"
#include "worker-protocol.hh"
@@ -49,7 +48,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
static std::set<std::string> uriSchemes() { return {"ssh"}; }
LegacySSHStore(const std::string & scheme, const std::string & host, const Params & params)
LegacySSHStore(const string & scheme, const string & host, const Params & params)
: StoreConfig(params)
, LegacySSHStoreConfig(params)
, Store(params)
@@ -108,7 +107,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
return conn;
};
std::string getUri() override
string getUri() override
{
return *uriSchemes().begin() + "://" + host;
}
@@ -226,21 +225,13 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override
{ unsupported("queryPathFromHashPart"); }
StorePath addToStore(
std::string_view name,
const Path & srcPath,
FileIngestionMethod method,
HashType hashAlgo,
PathFilter & filter,
RepairFlag repair,
const StorePathSet & references) override
StorePath addToStore(const string & name, const Path & srcPath,
FileIngestionMethod method, HashType hashAlgo,
PathFilter & filter, RepairFlag repair, const StorePathSet & references) override
{ unsupported("addToStore"); }
StorePath addTextToStore(
std::string_view name,
std::string_view s,
const StorePathSet & references,
RepairFlag repair) override
StorePath addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair) override
{ unsupported("addTextToStore"); }
private:

View File

@@ -85,7 +85,7 @@ void LocalFSStore::narFromPath(const StorePath & path, Sink & sink)
dumpPath(getRealStoreDir() + std::string(printStorePath(path), storeDir.size()), sink);
}
const std::string LocalFSStore::drvsLogDir = "drvs";
const string LocalFSStore::drvsLogDir = "drvs";
std::optional<std::string> LocalFSStore::getBuildLog(const StorePath & path_)
{

View File

@@ -1,7 +1,6 @@
#pragma once
#include "store-api.hh"
#include "gc-store.hh"
namespace nix {
@@ -24,11 +23,11 @@ struct LocalFSStoreConfig : virtual StoreConfig
"physical path to the Nix store"};
};
class LocalFSStore : public virtual LocalFSStoreConfig, public virtual Store, virtual GcStore
class LocalFSStore : public virtual LocalFSStoreConfig, public virtual Store
{
public:
const static std::string drvsLogDir;
const static string drvsLogDir;
LocalFSStore(const Params & params);

View File

@@ -70,7 +70,7 @@ int getSchema(Path schemaPath)
{
int curSchema = 0;
if (pathExists(schemaPath)) {
auto s = readFile(schemaPath);
string s = readFile(schemaPath);
auto n = string2Int<int>(s);
if (!n)
throw Error("'%1%' is corrupt", schemaPath);
@@ -185,6 +185,8 @@ LocalStore::LocalStore(const Params & params)
throw SysError("could not set permissions on '%s' to 755", perUserDir);
}
createUser(getUserName(), getuid());
/* Optionally, create directories and set permissions for a
multi-user install. */
if (getuid() == 0 && settings.buildUsersGroup != "") {
@@ -237,7 +239,7 @@ LocalStore::LocalStore(const Params & params)
res = posix_fallocate(fd.get(), 0, settings.reservedSize);
#endif
if (res == -1) {
writeFull(fd.get(), std::string(settings.reservedSize, 'X'));
writeFull(fd.get(), string(settings.reservedSize, 'X'));
[[gnu::unused]] auto res2 = ftruncate(fd.get(), settings.reservedSize);
}
}
@@ -448,7 +450,7 @@ void LocalStore::openDB(State & state, bool create)
throw SysError("Nix database directory '%1%' is not writable", dbDir);
/* Open the Nix database. */
std::string dbPath = dbDir + "/db.sqlite";
string dbPath = dbDir + "/db.sqlite";
auto & db(state.db);
state.db = SQLite(dbPath, create);
@@ -469,19 +471,19 @@ void LocalStore::openDB(State & state, bool create)
should be safe enough. If the user asks for it, don't sync at
all. This can cause database corruption if the system
crashes. */
std::string syncMode = settings.fsyncMetadata ? "normal" : "off";
string syncMode = settings.fsyncMetadata ? "normal" : "off";
db.exec("pragma synchronous = " + syncMode);
/* Set the SQLite journal mode. WAL mode is fastest, so it's the
default. */
std::string mode = settings.useSQLiteWAL ? "wal" : "truncate";
std::string prevMode;
string mode = settings.useSQLiteWAL ? "wal" : "truncate";
string prevMode;
{
SQLiteStmt stmt;
stmt.create(db, "pragma main.journal_mode;");
if (sqlite3_step(stmt) != SQLITE_ROW)
throwSQLiteError(db, "querying journal mode");
prevMode = std::string((const char *) sqlite3_column_text(stmt, 0));
prevMode = string((const char *) sqlite3_column_text(stmt, 0));
}
if (prevMode != mode &&
sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK)
@@ -677,7 +679,7 @@ void LocalStore::checkDerivationOutputs(const StorePath & drvPath, const Derivat
{
assert(drvPath.isDerivation());
std::string drvName(drvPath.name());
drvName = drvName.substr(0, drvName.size() - drvExtension.size());
drvName = string(drvName, 0, drvName.size() - drvExtension.size());
auto envHasRightPath = [&](const StorePath & actual, const std::string & varName)
{
@@ -784,11 +786,7 @@ void LocalStore::registerDrvOutput(const Realisation & info)
});
}
void LocalStore::cacheDrvOutputMapping(
State & state,
const uint64_t deriver,
const std::string & outputName,
const StorePath & output)
void LocalStore::cacheDrvOutputMapping(State & state, const uint64_t deriver, const string & outputName, const StorePath & output)
{
retrySQLite<void>([&]() {
state.stmts->AddDerivationOutput.use()
@@ -797,6 +795,7 @@ void LocalStore::cacheDrvOutputMapping(
(printStorePath(output))
.exec();
});
}
@@ -1437,9 +1436,7 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name
}
StorePath LocalStore::addTextToStore(
std::string_view name,
std::string_view s,
StorePath LocalStore::addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair)
{
auto hash = hashString(htSHA256, s);
@@ -1551,7 +1548,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
for (auto & link : readDirectory(linksDir)) {
printMsg(lvlTalkative, "checking contents of '%s'", link.name);
Path linkPath = linksDir + "/" + link.name;
std::string hash = hashPath(htSHA256, linkPath).first.to_string(Base32, false);
string hash = hashPath(htSHA256, linkPath).first.to_string(Base32, false);
if (hash != link.name) {
printError("link '%s' was modified! expected hash '%s', got '%s'",
linkPath, link.name, hash);
@@ -1784,6 +1781,20 @@ void LocalStore::signPathInfo(ValidPathInfo & info)
}
void LocalStore::createUser(const std::string & userName, uid_t userId)
{
for (auto & dir : {
fmt("%s/profiles/per-user/%s", stateDir, userName),
fmt("%s/gcroots/per-user/%s", stateDir, userName)
}) {
createDirs(dir);
if (chmod(dir.c_str(), 0755) == -1)
throw SysError("changing permissions of directory '%s'", dir);
if (chown(dir.c_str(), userId, getgid()) == -1)
throw SysError("changing owner of directory '%s'", dir);
}
}
std::optional<std::pair<int64_t, Realisation>> LocalStore::queryRealisationCore_(
LocalStore::State & state,
const DrvOutput & id)

View File

@@ -5,7 +5,6 @@
#include "pathlocks.hh"
#include "store-api.hh"
#include "local-fs-store.hh"
#include "gc-store.hh"
#include "sync.hh"
#include "util.hh"
@@ -44,7 +43,7 @@ struct LocalStoreConfig : virtual LocalFSStoreConfig
};
class LocalStore : public virtual LocalStoreConfig, public virtual LocalFSStore, public virtual GcStore
class LocalStore : public virtual LocalStoreConfig, public virtual LocalFSStore
{
private:
@@ -148,11 +147,8 @@ public:
StorePath addToStoreFromDump(Source & dump, std::string_view name,
FileIngestionMethod method, HashType hashAlgo, RepairFlag repair, const StorePathSet & references) override;
StorePath addTextToStore(
std::string_view name,
std::string_view s,
const StorePathSet & references,
RepairFlag repair) override;
StorePath addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair) override;
void addTempRoot(const StorePath & path) override;
@@ -208,11 +204,7 @@ public:
derivation 'deriver'. */
void registerDrvOutput(const Realisation & info) override;
void registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) override;
void cacheDrvOutputMapping(
State & state,
const uint64_t deriver,
const std::string & outputName,
const StorePath & output);
void cacheDrvOutputMapping(State & state, const uint64_t deriver, const string & outputName, const StorePath & output);
std::optional<const Realisation> queryRealisation_(State & state, const DrvOutput & id);
std::optional<std::pair<int64_t, Realisation>> queryRealisationCore_(State & state, const DrvOutput & id);
@@ -254,7 +246,7 @@ private:
void findRootsNoTemp(Roots & roots, bool censor);
void findRootsNoTempNoExternalDaemon(Roots & roots, bool censor);
void findRuntimeRoots(Roots & roots, bool censor);
Path createTempDirInStore();
@@ -275,6 +267,8 @@ private:
void signPathInfo(ValidPathInfo & info);
void signRealisation(Realisation &);
void createUser(const std::string & userName, uid_t userId) override;
// XXX: Make a generic `Store` method
FixedOutputHash hashCAPath(
const FileIngestionMethod & method,

View File

@@ -6,7 +6,7 @@ libstore_DIR := $(d)
libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc $(d)/build/*.cc)
libstore_LIBS = libutil libfindroots
libstore_LIBS = libutil
libstore_LDFLAGS += $(SQLITE3_LIBS) $(LIBCURL_LIBS) $(SODIUM_LIBS) -pthread
ifdef HOST_LINUX
@@ -32,7 +32,7 @@ ifeq ($(HAVE_SECCOMP), 1)
endif
libstore_CXXFLAGS += \
-I src/libutil -I src/libstore -I src/libstore/build -I src/nix-find-roots/lib \
-I src/libutil -I src/libstore -I src/libstore/build \
-DNIX_PREFIX=\"$(prefix)\" \
-DNIX_STORE_DIR=\"$(storedir)\" \
-DNIX_DATA_DIR=\"$(datadir)\" \

View File

@@ -13,7 +13,7 @@ private:
AutoCloseFD fdUserLock;
bool isEnabled = false;
std::string user;
string user;
uid_t uid = 0;
gid_t gid = 0;
std::vector<gid_t> supplementaryGIDs;
@@ -23,7 +23,7 @@ public:
void kill();
std::string getUser() { return user; }
string getUser() { return user; }
uid_t getUID() { assert(uid); return uid; }
uid_t getGID() { assert(gid); return gid; }
std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; }

View File

@@ -39,19 +39,19 @@ Machine::Machine(decltype(storeUri) storeUri,
sshPublicHostKey(sshPublicHostKey)
{}
bool Machine::allSupported(const std::set<std::string> & features) const
bool Machine::allSupported(const std::set<string> & features) const
{
return std::all_of(features.begin(), features.end(),
[&](const std::string & feature) {
[&](const string & feature) {
return supportedFeatures.count(feature) ||
mandatoryFeatures.count(feature);
});
}
bool Machine::mandatoryMet(const std::set<std::string> & features) const
bool Machine::mandatoryMet(const std::set<string> & features) const
{
return std::all_of(mandatoryFeatures.begin(), mandatoryFeatures.end(),
[&](const std::string & feature) {
[&](const string & feature) {
return features.count(feature);
});
}
@@ -89,7 +89,7 @@ ref<Store> Machine::openStore() const
static std::vector<std::string> expandBuilderLines(const std::string & builders)
{
std::vector<std::string> result;
for (auto line : tokenizeString<std::vector<std::string>>(builders, "\n;")) {
for (auto line : tokenizeString<std::vector<string>>(builders, "\n;")) {
trim(line);
line.erase(std::find(line.begin(), line.end(), '#'), line.end());
if (line.empty()) continue;
@@ -117,7 +117,7 @@ static std::vector<std::string> expandBuilderLines(const std::string & builders)
static Machine parseBuilderLine(const std::string & line)
{
const auto tokens = tokenizeString<std::vector<std::string>>(line);
const auto tokens = tokenizeString<std::vector<string>>(line);
auto isSet = [&](size_t fieldIndex) {
return tokens.size() > fieldIndex && tokens[fieldIndex] != "" && tokens[fieldIndex] != "-";
@@ -146,18 +146,17 @@ static Machine parseBuilderLine(const std::string & line)
return {
tokens[0],
isSet(1) ? tokenizeString<std::vector<std::string>>(tokens[1], ",") : std::vector<std::string>{settings.thisSystem},
isSet(1) ? tokenizeString<std::vector<string>>(tokens[1], ",") : std::vector<string>{settings.thisSystem},
isSet(2) ? tokens[2] : "",
isSet(3) ? parseUnsignedIntField(3) : 1U,
isSet(4) ? parseUnsignedIntField(4) : 1U,
isSet(5) ? tokenizeString<std::set<std::string>>(tokens[5], ",") : std::set<std::string>{},
isSet(6) ? tokenizeString<std::set<std::string>>(tokens[6], ",") : std::set<std::string>{},
isSet(5) ? tokenizeString<std::set<string>>(tokens[5], ",") : std::set<string>{},
isSet(6) ? tokenizeString<std::set<string>>(tokens[6], ",") : std::set<string>{},
isSet(7) ? ensureBase64(7) : ""
};
}
static Machines parseBuilderLines(const std::vector<std::string> & builders)
{
static Machines parseBuilderLines(const std::vector<std::string>& builders) {
Machines result;
std::transform(builders.begin(), builders.end(), std::back_inserter(result), parseBuilderLine);
return result;

View File

@@ -90,7 +90,7 @@ struct NarAccessor : public FSAccessor
void receiveContents(std::string_view data) override
{ }
void createSymlink(const Path & path, const std::string & target) override
void createSymlink(const Path & path, const string & target) override
{
createMember(path,
NarMember{FSAccessor::Type::tSymlink, false, 0, 0, target});

View File

@@ -11,7 +11,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
return Error("NAR info file '%1%' is corrupt", whence);
};
auto parseHashField = [&](const std::string & s) {
auto parseHashField = [&](const string & s) {
try {
return Hash::parseAnyPrefixed(s);
} catch (BadHash &) {

View File

@@ -77,7 +77,7 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
continue;
}
std::string name = dirent->d_name;
string name = dirent->d_name;
if (name == "." || name == "..") continue;
names.push_back(name);
}

Some files were not shown because too many files have changed in this diff Show More