Merge remote-tracking branch 'upstream/master' into indexed-store-path-outputs

This commit is contained in:
John Ericson 2022-04-07 19:20:27 +00:00
commit 5c1f2e0fb1
23 changed files with 110 additions and 40 deletions

View file

@ -6,7 +6,8 @@ options:
concatStrings (map concatStrings (map
(name: (name:
let option = options.${name}; in let option = options.${name}; in
" - `${name}` \n\n" " - [`${name}`](#conf-${name})"
+ "<p id=\"conf-${name}\"></p>\n\n"
+ concatStrings (map (s: " ${s}\n") (splitLines option.description)) + "\n\n" + concatStrings (map (s: " ${s}\n") (splitLines option.description)) + "\n\n"
+ (if option.documentDefault + (if option.documentDefault
then " **Default:** " + ( then " **Default:** " + (

View file

@ -1,4 +1,4 @@
# Release X.Y (2022-03-07) # Release 2.7 (2022-03-07)
* Nix will now make some helpful suggestions when you mistype * Nix will now make some helpful suggestions when you mistype
something on the command line. For instance, if you type `nix build something on the command line. For instance, if you type `nix build

View file

@ -32,3 +32,11 @@
paths. Like fixed-output derivations, impure derivations have access paths. Like fixed-output derivations, impure derivations have access
to the network. Only fixed-output derivations and impure derivations to the network. Only fixed-output derivations and impure derivations
can depend on an impure derivation. can depend on an impure derivation.
* The `nixosModule` flake output attribute has been renamed consistent
with the `.default` renames in nix 2.7.
* `nixosModule``nixosModules.default`
As before, the old output will continue to work, but `nix flake check` will
issue a warning about it.

View file

@ -18,11 +18,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1632864508, "lastModified": 1645296114,
"narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -14,7 +14,7 @@ curl -sS -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master
someBuildFailed=0 someBuildFailed=0
for buildId in $BUILDS_FOR_LATEST_EVAL; do for buildId in $BUILDS_FOR_LATEST_EVAL; do
buildInfo=$(curl -sS -H 'Accept: application/json' "https://hydra.nixos.org/build/$buildId") buildInfo=$(curl --fail -sS -H 'Accept: application/json' "https://hydra.nixos.org/build/$buildId")
finished=$(echo "$buildInfo" | jq -r '.finished') finished=$(echo "$buildInfo" | jq -r '.finished')

View file

@ -90,7 +90,7 @@ poly_configure_nix_daemon_service() {
ln -sfn /nix/var/nix/profiles/default/$TMPFILES_SRC $TMPFILES_DEST ln -sfn /nix/var/nix/profiles/default/$TMPFILES_SRC $TMPFILES_DEST
_sudo "to run systemd-tmpfiles once to pick that path up" \ _sudo "to run systemd-tmpfiles once to pick that path up" \
systemd-tmpfiles create --prefix=/nix/var/nix systemd-tmpfiles --create --prefix=/nix/var/nix
_sudo "to set up the nix-daemon service" \ _sudo "to set up the nix-daemon service" \
systemctl link "/nix/var/nix/profiles/default$SERVICE_SRC" systemctl link "/nix/var/nix/profiles/default$SERVICE_SRC"

View file

@ -82,7 +82,7 @@ if [ "$(uname -s)" != "Darwin" ]; then
fi fi
if command -v curl > /dev/null 2>&1; then if command -v curl > /dev/null 2>&1; then
fetch() { curl -L "$1" -o "$2"; } fetch() { curl --fail -L "$1" -o "$2"; }
elif command -v wget > /dev/null 2>&1; then elif command -v wget > /dev/null 2>&1; then
fetch() { wget "$1" -O "$2"; } fetch() { wget "$1" -O "$2"; }
else else

View file

@ -991,7 +991,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
bool contentAddressed = false; bool contentAddressed = false;
bool isImpure = false; bool isImpure = false;
std::optional<std::string> outputHash; std::optional<std::string> outputHash;
std::optional<std::string> outputHashAlgo; std::string outputHashAlgo;
std::optional<FileIngestionMethod> ingestionMethod; std::optional<FileIngestionMethod> ingestionMethod;
StringSet outputs; StringSet outputs;
@ -1190,8 +1190,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
.errPos = posDrvName .errPos = posDrvName
}); });
std::optional<HashType> ht = parseHashTypeOpt(outputHashAlgo.value_or("sha256")); auto h = newHashAllowEmpty(*outputHash, parseHashTypeOpt(outputHashAlgo));
Hash h = newHashAllowEmpty(*outputHash, ht);
auto method = ingestionMethod.value_or(FileIngestionMethod::Flat); auto method = ingestionMethod.value_or(FileIngestionMethod::Flat);
auto outPath = state.store->makeFixedOutputPath(method, h, drvName); auto outPath = state.store->makeFixedOutputPath(method, h, drvName);
@ -1212,7 +1211,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
.errPos = posDrvName .errPos = posDrvName
}); });
auto ht = parseHashType(outputHashAlgo.value_or("sha256")); auto ht = parseHashTypeOpt(outputHashAlgo).value_or(htSHA256);
auto method = ingestionMethod.value_or(FileIngestionMethod::Recursive); auto method = ingestionMethod.value_or(FileIngestionMethod::Recursive);
for (auto & i : outputs) { for (auto & i : outputs) {

View file

@ -61,6 +61,12 @@ static void prim_fetchClosure(EvalState & state, const Pos & pos, Value * * args
.errPos = pos .errPos = pos
}); });
if (!parsedURL.query.empty())
throw Error({
.msg = hintfmt("'fetchClosure' does not support URL query parameters (in '%s')", *fromStoreUrl),
.errPos = pos
});
auto fromStore = openStore(parsedURL.to_string()); auto fromStore = openStore(parsedURL.to_string());
if (toCA) { if (toCA) {
@ -87,6 +93,7 @@ static void prim_fetchClosure(EvalState & state, const Pos & pos, Value * * args
}); });
} }
} else { } else {
if (!state.store->isValidPath(*fromPath))
copyClosure(*fromStore, *state.store, RealisedPath::Set { *fromPath }); copyClosure(*fromStore, *state.store, RealisedPath::Set { *fromPath });
toPath = fromPath; toPath = fromPath;
} }

View file

@ -285,9 +285,11 @@ struct GitInputScheme : InputScheme
auto files = tokenizeString<std::set<std::string>>( auto files = tokenizeString<std::set<std::string>>(
runProgram("git", true, gitOpts), "\0"s); runProgram("git", true, gitOpts), "\0"s);
Path actualPath(absPath(actualUrl));
PathFilter filter = [&](const Path & p) -> bool { PathFilter filter = [&](const Path & p) -> bool {
assert(hasPrefix(p, actualUrl)); assert(hasPrefix(p, actualPath));
std::string file(p, actualUrl.size() + 1); std::string file(p, actualPath.size() + 1);
auto st = lstat(p); auto st = lstat(p);
@ -300,13 +302,13 @@ struct GitInputScheme : InputScheme
return files.count(file); return files.count(file);
}; };
auto storePath = store->addToStore(input.getName(), actualUrl, FileIngestionMethod::Recursive, htSHA256, filter); auto storePath = store->addToStore(input.getName(), actualPath, FileIngestionMethod::Recursive, htSHA256, filter);
// FIXME: maybe we should use the timestamp of the last // FIXME: maybe we should use the timestamp of the last
// modified dirty file? // modified dirty file?
input.attrs.insert_or_assign( input.attrs.insert_or_assign(
"lastModified", "lastModified",
hasHead ? std::stoull(runProgram("git", true, { "-C", actualUrl, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0); hasHead ? std::stoull(runProgram("git", true, { "-C", actualPath, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
return {std::move(storePath), input}; return {std::move(storePath), input};
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "realisation.hh" #include "realisation.hh"
#include "derived-path.hh"
#include <string> #include <string>
#include <chrono> #include <chrono>

View file

@ -41,7 +41,7 @@ void DrvOutputSubstitutionGoal::tryNext()
if (subs.size() == 0) { if (subs.size() == 0) {
/* None left. Terminate this goal and let someone else deal /* None left. Terminate this goal and let someone else deal
with it. */ with it. */
debug("drv output '%s' is required, but there is no substituter that can provide it", id.to_string()); debug("derivation output '%s' is required, but there is no substituter that can provide it", id.to_string());
/* Hack: don't indicate failure if there were no substituters. /* Hack: don't indicate failure if there were no substituters.
In that case the calling derivation should just do a In that case the calling derivation should just do a

View file

@ -24,9 +24,16 @@ PathSubstitutionGoal::~PathSubstitutionGoal()
} }
void PathSubstitutionGoal::done(ExitCode result, BuildResult::Status status) void PathSubstitutionGoal::done(
ExitCode result,
BuildResult::Status status,
std::optional<std::string> errorMsg)
{ {
buildResult.status = status; buildResult.status = status;
if (errorMsg) {
debug(*errorMsg);
buildResult.errorMsg = *errorMsg;
}
amDone(result); amDone(result);
} }
@ -67,12 +74,14 @@ void PathSubstitutionGoal::tryNext()
if (subs.size() == 0) { if (subs.size() == 0) {
/* None left. Terminate this goal and let someone else deal /* None left. Terminate this goal and let someone else deal
with it. */ with it. */
debug("path '%s' is required, but there is no substituter that can build it", worker.store.printStorePath(storePath));
/* Hack: don't indicate failure if there were no substituters. /* Hack: don't indicate failure if there were no substituters.
In that case the calling derivation should just do a In that case the calling derivation should just do a
build. */ build. */
done(substituterFailed ? ecFailed : ecNoSubstituters, BuildResult::NoSubstituters); done(
substituterFailed ? ecFailed : ecNoSubstituters,
BuildResult::NoSubstituters,
fmt("path '%s' is required, but there is no substituter that can build it", worker.store.printStorePath(storePath)));
if (substituterFailed) { if (substituterFailed) {
worker.failedSubstitutions++; worker.failedSubstitutions++;
@ -169,10 +178,10 @@ void PathSubstitutionGoal::referencesValid()
trace("all references realised"); trace("all references realised");
if (nrFailed > 0) { if (nrFailed > 0) {
debug("some references of path '%s' could not be realised", worker.store.printStorePath(storePath));
done( done(
nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed, nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed,
BuildResult::DependencyFailed); BuildResult::DependencyFailed,
fmt("some references of path '%s' could not be realised", worker.store.printStorePath(storePath)));
return; return;
} }

View file

@ -53,7 +53,10 @@ struct PathSubstitutionGoal : public Goal
/* Content address for recomputing store path */ /* Content address for recomputing store path */
std::optional<ContentAddress> ca; std::optional<ContentAddress> ca;
void done(ExitCode result, BuildResult::Status status); void done(
ExitCode result,
BuildResult::Status status,
std::optional<std::string> errorMsg = {});
public: public:
PathSubstitutionGoal(const StorePath & storePath, Worker & worker, RepairFlag repair = NoRepair, std::optional<ContentAddress> ca = std::nullopt); PathSubstitutionGoal(const StorePath & storePath, Worker & worker, RepairFlag repair = NoRepair, std::optional<ContentAddress> ca = std::nullopt);

View file

@ -1259,9 +1259,9 @@ template<class C> C tokenizeString(std::string_view s, std::string_view separato
{ {
C result; C result;
auto pos = s.find_first_not_of(separators, 0); auto pos = s.find_first_not_of(separators, 0);
while (pos != std::string::npos) { while (pos != std::string_view::npos) {
auto end = s.find_first_of(separators, pos + 1); auto end = s.find_first_of(separators, pos + 1);
if (end == std::string::npos) end = s.size(); if (end == std::string_view::npos) end = s.size();
result.insert(result.end(), std::string(s, pos, end - pos)); result.insert(result.end(), std::string(s, pos, end - pos));
pos = s.find_first_not_of(separators, end); pos = s.find_first_not_of(separators, end);
} }
@ -1471,6 +1471,7 @@ constexpr char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
std::string base64Encode(std::string_view s) std::string base64Encode(std::string_view s)
{ {
std::string res; std::string res;
res.reserve((s.size() + 2) / 3 * 4);
int data = 0, nbits = 0; int data = 0, nbits = 0;
for (char c : s) { for (char c : s) {
@ -1502,6 +1503,9 @@ std::string base64Decode(std::string_view s)
}(); }();
std::string res; std::string res;
// Some sequences are missing the padding consisting of up to two '='.
// vvv
res.reserve((s.size() + 2) / 4 * 3);
unsigned int d = 0, bits = 0; unsigned int d = 0, bits = 0;
for (char c : s) { for (char c : s) {
@ -1688,7 +1692,9 @@ void setStackSize(size_t stackSize)
#endif #endif
} }
#if __linux__
static AutoCloseFD fdSavedMountNamespace; static AutoCloseFD fdSavedMountNamespace;
#endif
void saveMountNamespace() void saveMountNamespace()
{ {
@ -1707,8 +1713,13 @@ void restoreMountNamespace()
{ {
#if __linux__ #if __linux__
try { try {
auto savedCwd = absPath(".");
if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1) if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1)
throw SysError("restoring parent mount namespace"); throw SysError("restoring parent mount namespace");
if (chdir(savedCwd.c_str()) == -1) {
throw SysError("restoring cwd");
}
} catch (Error & e) { } catch (Error & e) {
debug(e.msg()); debug(e.msg());
} }

View file

@ -24,12 +24,12 @@ std::string formatProtocol(unsigned int proto)
} }
bool checkPass(const std::string & msg) { bool checkPass(const std::string & msg) {
logger->log(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg); notice(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg);
return true; return true;
} }
bool checkFail(const std::string & msg) { bool checkFail(const std::string & msg) {
logger->log(ANSI_RED "[FAIL] " ANSI_NORMAL + msg); notice(ANSI_RED "[FAIL] " ANSI_NORMAL + msg);
return false; return false;
} }

View file

@ -463,7 +463,7 @@ struct CmdFlakeCheck : FlakeCommand
for (auto & attr : *v.attrs) { for (auto & attr : *v.attrs) {
std::string name(attr.name); std::string name(attr.name);
if (name != "path" && name != "description") if (name != "path" && name != "description" && name != "welcomeText")
throw Error("template '%s' has unsupported attribute '%s'", attrPath, name); throw Error("template '%s' has unsupported attribute '%s'", attrPath, name);
} }
} catch (Error & e) { } catch (Error & e) {
@ -508,6 +508,7 @@ struct CmdFlakeCheck : FlakeCommand
name == "defaultBundler" ? "bundlers.<system>.default" : name == "defaultBundler" ? "bundlers.<system>.default" :
name == "overlay" ? "overlays.default" : name == "overlay" ? "overlays.default" :
name == "devShell" ? "devShells.<system>.default" : name == "devShell" ? "devShells.<system>.default" :
name == "nixosModule" ? "nixosModules.default" :
""; "";
if (replacement != "") if (replacement != "")
warn("flake output attribute '%s' is deprecated; use '%s' instead", name, replacement); warn("flake output attribute '%s' is deprecated; use '%s' instead", name, replacement);

View file

@ -97,19 +97,30 @@ struct ProfileManifest
auto json = nlohmann::json::parse(readFile(manifestPath)); auto json = nlohmann::json::parse(readFile(manifestPath));
auto version = json.value("version", 0); auto version = json.value("version", 0);
if (version != 1) std::string sUrl;
std::string sOriginalUrl;
switch(version){
case 1:
sUrl = "uri";
sOriginalUrl = "originalUri";
break;
case 2:
sUrl = "url";
sOriginalUrl = "originalUrl";
break;
default:
throw Error("profile manifest '%s' has unsupported version %d", manifestPath, version); throw Error("profile manifest '%s' has unsupported version %d", manifestPath, version);
}
for (auto & e : json["elements"]) { for (auto & e : json["elements"]) {
ProfileElement element; ProfileElement element;
for (auto & p : e["storePaths"]) for (auto & p : e["storePaths"])
element.storePaths.insert(state.store->parseStorePath((std::string) p)); element.storePaths.insert(state.store->parseStorePath((std::string) p));
element.active = e["active"]; element.active = e["active"];
if (e.value("uri", "") != "") { if (e.value(sUrl,"") != "") {
auto originalUrl = e.value("originalUrl", e["originalUri"]);
element.source = ProfileElementSource{ element.source = ProfileElementSource{
parseFlakeRef(originalUrl), parseFlakeRef(e[sOriginalUrl]),
parseFlakeRef(e["uri"]), parseFlakeRef(e[sUrl]),
e["attrPath"] e["attrPath"]
}; };
} }
@ -144,13 +155,13 @@ struct ProfileManifest
obj["active"] = element.active; obj["active"] = element.active;
if (element.source) { if (element.source) {
obj["originalUrl"] = element.source->originalRef.to_string(); obj["originalUrl"] = element.source->originalRef.to_string();
obj["uri"] = element.source->resolvedRef.to_string(); obj["url"] = element.source->resolvedRef.to_string();
obj["attrPath"] = element.source->attrPath; obj["attrPath"] = element.source->attrPath;
} }
array.push_back(obj); array.push_back(obj);
} }
nlohmann::json json; nlohmann::json json;
json["version"] = 1; json["version"] = 2;
json["elements"] = array; json["elements"] = array;
return json.dump(); return json.dump();
} }

View file

@ -182,6 +182,7 @@ struct CmdRun : InstallableCommand
{ {
auto state = getEvalState(); auto state = getEvalState();
lockFlags.applyNixConfig = true;
auto app = installable->toApp(*state).resolve(getEvalStore(), store); auto app = installable->toApp(*state).resolve(getEvalStore(), store);
Strings allArgs{app.program}; Strings allArgs{app.program};

View file

@ -64,8 +64,7 @@ rec {
dependentFixedOutput = mkDerivation { dependentFixedOutput = mkDerivation {
name = "dependent-fixed-output"; name = "dependent-fixed-output";
outputHashMode = "recursive"; outputHashMode = "recursive";
outputHashAlgo = "sha256"; outputHash = "sha512-7aJcmSuEuYP5tGKcmGY8bRr/lrCjJlOxP2mIUjO/vMQeg6gx/65IbzRWES8EKiPDOs9z+wF30lEfcwxM/cT4pw==";
outputHash = "sha256-QvtAMbUl/uvi+LCObmqOhvNOapHdA2raiI4xG5zI5pA=";
buildCommand = '' buildCommand = ''
cat ${dependentCA}/dep cat ${dependentCA}/dep
echo foo > $out echo foo > $out

View file

@ -56,3 +56,15 @@ nix copy --to file://$cacheDir $caPath
fromPath = $caPath; fromPath = $caPath;
} }
") = $caPath ]] ") = $caPath ]]
# Check that URL query parameters aren't allowed.
clearStore
narCache=$TEST_ROOT/nar-cache
rm -rf $narCache
(! nix eval -v --raw --expr "
builtins.fetchClosure {
fromStore = \"file://$cacheDir?local-nar-cache=$narCache\";
fromPath = $caPath;
}
")
(! [ -e $narCache ])

View file

@ -7,7 +7,9 @@ fi
clearStore clearStore
repo=$TEST_ROOT/git # Intentionally not in a canonical form
# See https://github.com/NixOS/nix/issues/6195
repo=$TEST_ROOT/./git
export _NIX_FORCE_HTTP=1 export _NIX_FORCE_HTTP=1

View file

@ -376,6 +376,9 @@ cat > $templatesDir/flake.nix <<EOF
trivial = { trivial = {
path = ./trivial; path = ./trivial;
description = "A trivial flake"; description = "A trivial flake";
welcomeText = ''
Welcome to my trivial flake
'';
}; };
default = trivial; default = trivial;
}; };