forked from lix-project/lix
Merge remote-tracking branch 'origin/master' into markdown
This commit is contained in:
commit
7cdc739ece
1236
doc/manual/command-ref/conf-file.xml
Normal file
1236
doc/manual/command-ref/conf-file.xml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -206,6 +206,26 @@ The following settings are currently available:
|
|||
robustness in case of system crashes, but reduces performance. The
|
||||
default is `true`.
|
||||
|
||||
- `hashed-mirrors`
|
||||
A list of web servers used by `builtins.fetchurl` to obtain files by
|
||||
hash. The default is `http://tarballs.nixos.org/`. Given a hash type
|
||||
*ht* and a base-16 hash *h*, Nix will try to download the file from
|
||||
*hashed-mirror*/*ht*/*h*. This allows files to be downloaded even if
|
||||
they have disappeared from their original URI. For example, given
|
||||
the default mirror `http://tarballs.nixos.org/`, when building the
|
||||
derivation
|
||||
|
||||
```nix
|
||||
builtins.fetchurl {
|
||||
url = "https://example.org/foo-1.2.3.tar.xz";
|
||||
sha256 = "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae";
|
||||
}
|
||||
```
|
||||
|
||||
Nix will attempt to download this file from
|
||||
`http://tarballs.nixos.org/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae`
|
||||
first. If it is not available there, if will try the original URI.
|
||||
|
||||
- `http-connections`
|
||||
The maximum number of parallel TCP connections used to fetch files
|
||||
from binary caches and by other downloads. It defaults to 25. 0
|
||||
|
|
|
@ -80,7 +80,7 @@ SV * queryReferences(char * path)
|
|||
SV * queryPathHash(char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash->to_string(Base32, true);
|
||||
auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base32, true);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
|
@ -106,7 +106,7 @@ SV * queryPathInfo(char * path, int base32)
|
|||
XPUSHs(&PL_sv_undef);
|
||||
else
|
||||
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
|
||||
auto s = info->narHash->to_string(base32 ? Base32 : Base16, true);
|
||||
auto s = info->narHash.to_string(base32 ? Base32 : Base16, true);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
mXPUSHi(info->registrationTime);
|
||||
mXPUSHi(info->narSize);
|
||||
|
@ -224,7 +224,7 @@ SV * hashString(char * algo, int base32, char * s)
|
|||
SV * convertHash(char * algo, char * s, int toBase32)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h(s, parseHashType(algo));
|
||||
auto h = Hash::parseAny(s, parseHashType(algo));
|
||||
string s = h.to_string(toBase32 ? Base32 : Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
|
@ -285,7 +285,7 @@ SV * addToStore(char * srcPath, int recursive, char * algo)
|
|||
SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h(hash, parseHashType(algo));
|
||||
auto h = Hash::parseAny(hash, parseHashType(algo));
|
||||
auto method = recursive ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;
|
||||
auto path = store()->makeFixedOutputPath(method, h, name);
|
||||
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(path).c_str(), 0)));
|
||||
|
@ -303,10 +303,10 @@ SV * derivationFromPath(char * drvPath)
|
|||
hash = newHV();
|
||||
|
||||
HV * outputs = newHV();
|
||||
for (auto & i : drv.outputs)
|
||||
for (auto & i : drv.outputsAndPaths(*store()))
|
||||
hv_store(
|
||||
outputs, i.first.c_str(), i.first.size(),
|
||||
newSVpv(store()->printStorePath(i.second.path(*store(), drv.name)).c_str(), 0),
|
||||
newSVpv(store()->printStorePath(i.second.second).c_str(), 0),
|
||||
0);
|
||||
hv_stores(hash, "outputs", newRV((SV *) outputs));
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@ readonly PROFILE_NIX_FILE="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-
|
|||
|
||||
readonly NIX_INSTALLED_NIX="@nix@"
|
||||
readonly NIX_INSTALLED_CACERT="@cacert@"
|
||||
#readonly NIX_INSTALLED_NIX="/nix/store/j8dbv5w6jl34caywh2ygdy88knx1mdf7-nix-2.3.6"
|
||||
#readonly NIX_INSTALLED_CACERT="/nix/store/7dxhzymvy330i28ii676fl1pqwcahv2f-nss-cacert-3.49.2"
|
||||
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
|
||||
|
||||
readonly ROOT_HOME=$(echo ~root)
|
||||
|
@ -69,9 +71,11 @@ uninstall_directions() {
|
|||
subheader "Uninstalling nix:"
|
||||
local step=0
|
||||
|
||||
if poly_service_installed_check; then
|
||||
if [ -e /run/systemd/system ] && poly_service_installed_check; then
|
||||
step=$((step + 1))
|
||||
poly_service_uninstall_directions "$step"
|
||||
else
|
||||
step=$((step + 1))
|
||||
fi
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
|
@ -250,7 +254,9 @@ function finish_success {
|
|||
echo "But fetching the nixpkgs channel failed. (Are you offline?)"
|
||||
echo "To try again later, run \"sudo -i nix-channel --update nixpkgs\"."
|
||||
fi
|
||||
cat <<EOF
|
||||
|
||||
if [ -e /run/systemd/system ]; then
|
||||
cat <<EOF
|
||||
|
||||
Before Nix will work in your existing shells, you'll need to close
|
||||
them and open them again. Other than that, you should be ready to go.
|
||||
|
@ -264,6 +270,26 @@ hesitate:
|
|||
|
||||
$(contactme)
|
||||
EOF
|
||||
else
|
||||
cat <<EOF
|
||||
|
||||
Before Nix will work in your existing shells, you'll need to close
|
||||
them and open them again. Other than that, you should be ready to go.
|
||||
|
||||
Try it! Open a new terminal, and type:
|
||||
|
||||
$ sudo nix-daemon
|
||||
$ nix-shell -p nix-info --run "nix-info -m"
|
||||
|
||||
Additionally, you may want to add nix-daemon to your init-system.
|
||||
|
||||
Thank you for using this installer. If you have any feedback, don't
|
||||
hesitate:
|
||||
|
||||
$(contactme)
|
||||
EOF
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -664,12 +690,8 @@ main() {
|
|||
# shellcheck source=./install-darwin-multi-user.sh
|
||||
. "$EXTRACTED_NIX_PATH/install-darwin-multi-user.sh"
|
||||
elif [ "$(uname -s)" = "Linux" ]; then
|
||||
if [ -e /run/systemd/system ]; then
|
||||
# shellcheck source=./install-systemd-multi-user.sh
|
||||
. "$EXTRACTED_NIX_PATH/install-systemd-multi-user.sh"
|
||||
else
|
||||
failure "Sorry, the multi-user installation requires systemd on Linux (detected using /run/systemd/system)"
|
||||
fi
|
||||
# shellcheck source=./install-systemd-multi-user.sh
|
||||
. "$EXTRACTED_NIX_PATH/install-systemd-multi-user.sh" # most of this works on non-systemd distros also
|
||||
else
|
||||
failure "Sorry, I don't know what to do on $(uname)"
|
||||
fi
|
||||
|
@ -702,7 +724,10 @@ main() {
|
|||
|
||||
setup_default_profile
|
||||
place_nix_configuration
|
||||
poly_configure_nix_daemon_service
|
||||
|
||||
if [ -e /run/systemd/system ]; then
|
||||
poly_configure_nix_daemon_service
|
||||
fi
|
||||
|
||||
trap finish_success EXIT
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ fi
|
|||
# Determine if we could use the multi-user installer or not
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
|
||||
elif [ "$(uname -s)" = "Linux" ] && [ -e /run/systemd/system ]; then
|
||||
elif [ "$(uname -s)" = "Linux" ]; then
|
||||
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
|
||||
fi
|
||||
|
||||
|
@ -122,7 +122,7 @@ if [ "$(uname -s)" = "Darwin" ]; then
|
|||
fi
|
||||
|
||||
if [ "$INSTALL_MODE" = "daemon" ]; then
|
||||
printf '\e[1;31mSwitching to the Daemon-based Installer\e[0m\n'
|
||||
printf '\e[1;31mSwitching to the Multi-user Installer\e[0m\n'
|
||||
exec "$self/install-multi-user"
|
||||
exit 0
|
||||
fi
|
||||
|
|
|
@ -38,9 +38,9 @@ static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot)
|
|||
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri), slot), true);
|
||||
}
|
||||
|
||||
static bool allSupportedLocally(const std::set<std::string>& requiredFeatures) {
|
||||
static bool allSupportedLocally(Store & store, const std::set<std::string>& requiredFeatures) {
|
||||
for (auto & feature : requiredFeatures)
|
||||
if (!settings.systemFeatures.get().count(feature)) return false;
|
||||
if (!store.systemFeatures.get().count(feature)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -103,10 +103,10 @@ static int _main(int argc, char * * argv)
|
|||
drvPath = store->parseStorePath(readString(source));
|
||||
auto requiredFeatures = readStrings<std::set<std::string>>(source);
|
||||
|
||||
auto canBuildLocally = amWilling
|
||||
auto canBuildLocally = amWilling
|
||||
&& ( neededSystem == settings.thisSystem
|
||||
|| settings.extraPlatforms.get().count(neededSystem) > 0)
|
||||
&& allSupportedLocally(requiredFeatures);
|
||||
&& allSupportedLocally(*store, requiredFeatures);
|
||||
|
||||
/* Error ignored here, will be caught later */
|
||||
mkdir(currentLoad.c_str(), 0777);
|
||||
|
@ -170,7 +170,45 @@ static int _main(int argc, char * * argv)
|
|||
if (rightType && !canBuildLocally)
|
||||
std::cerr << "# postpone\n";
|
||||
else
|
||||
{
|
||||
// build the hint template.
|
||||
string hintstring = "derivation: %s\nrequired (system, features): (%s, %s)";
|
||||
hintstring += "\n%s available machines:";
|
||||
hintstring += "\n(systems, maxjobs, supportedFeatures, mandatoryFeatures)";
|
||||
|
||||
for (unsigned int i = 0; i < machines.size(); ++i) {
|
||||
hintstring += "\n(%s, %s, %s, %s)";
|
||||
}
|
||||
|
||||
// add the template values.
|
||||
string drvstr;
|
||||
if (drvPath.has_value())
|
||||
drvstr = drvPath->to_string();
|
||||
else
|
||||
drvstr = "<unknown>";
|
||||
|
||||
auto hint = hintformat(hintstring);
|
||||
hint
|
||||
% drvstr
|
||||
% neededSystem
|
||||
% concatStringsSep<StringSet>(", ", requiredFeatures)
|
||||
% machines.size();
|
||||
|
||||
for (auto & m : machines) {
|
||||
hint % concatStringsSep<vector<string>>(", ", m.systemTypes)
|
||||
% m.maxJobs
|
||||
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
|
||||
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
|
||||
}
|
||||
|
||||
logErrorInfo(lvlInfo, {
|
||||
.name = "Remote build",
|
||||
.description = "Failed to find a machine for remote build!",
|
||||
.hint = hint
|
||||
});
|
||||
|
||||
std::cerr << "# decline\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -186,15 +224,7 @@ static int _main(int argc, char * * argv)
|
|||
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("connecting to '%s'", bestMachine->storeUri));
|
||||
|
||||
Store::Params storeParams;
|
||||
if (hasPrefix(bestMachine->storeUri, "ssh://")) {
|
||||
storeParams["max-connections"] = "1";
|
||||
storeParams["log-fd"] = "4";
|
||||
if (bestMachine->sshKey != "")
|
||||
storeParams["ssh-key"] = bestMachine->sshKey;
|
||||
}
|
||||
|
||||
sshStore = openStore(bestMachine->storeUri, storeParams);
|
||||
sshStore = bestMachine->openStore();
|
||||
sshStore->connect();
|
||||
storeUri = bestMachine->storeUri;
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@ Value & AttrCursor::forceValue()
|
|||
return v;
|
||||
}
|
||||
|
||||
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
|
||||
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErrors)
|
||||
{
|
||||
if (root->db) {
|
||||
if (!cachedValue)
|
||||
|
@ -422,9 +422,12 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
|
|||
if (attr) {
|
||||
if (std::get_if<missing_t>(&attr->second))
|
||||
return nullptr;
|
||||
else if (std::get_if<failed_t>(&attr->second))
|
||||
throw EvalError("cached failure of attribute '%s'", getAttrPathStr(name));
|
||||
else
|
||||
else if (std::get_if<failed_t>(&attr->second)) {
|
||||
if (forceErrors)
|
||||
debug("reevaluating failed cached attribute '%s'");
|
||||
else
|
||||
throw CachedEvalError("cached failure of attribute '%s'", getAttrPathStr(name));
|
||||
} else
|
||||
return std::make_shared<AttrCursor>(root,
|
||||
std::make_pair(shared_from_this(), name), nullptr, std::move(attr));
|
||||
}
|
||||
|
@ -469,9 +472,9 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
|
|||
return maybeGetAttr(root->state.symbols.create(name));
|
||||
}
|
||||
|
||||
std::shared_ptr<AttrCursor> AttrCursor::getAttr(Symbol name)
|
||||
std::shared_ptr<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
|
||||
{
|
||||
auto p = maybeGetAttr(name);
|
||||
auto p = maybeGetAttr(name, forceErrors);
|
||||
if (!p)
|
||||
throw Error("attribute '%s' does not exist", getAttrPathStr(name));
|
||||
return p;
|
||||
|
@ -600,7 +603,7 @@ bool AttrCursor::isDerivation()
|
|||
|
||||
StorePath AttrCursor::forceDerivation()
|
||||
{
|
||||
auto aDrvPath = getAttr(root->state.sDrvPath);
|
||||
auto aDrvPath = getAttr(root->state.sDrvPath, true);
|
||||
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
|
||||
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
|
||||
/* The eval cache contains 'drvPath', but the actual path has
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
namespace nix::eval_cache {
|
||||
|
||||
MakeError(CachedEvalError, EvalError);
|
||||
|
||||
class AttrDb;
|
||||
class AttrCursor;
|
||||
|
||||
|
@ -92,11 +94,11 @@ public:
|
|||
|
||||
std::string getAttrPathStr(Symbol name) const;
|
||||
|
||||
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name);
|
||||
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false);
|
||||
|
||||
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
|
||||
|
||||
std::shared_ptr<AttrCursor> getAttr(Symbol name);
|
||||
std::shared_ptr<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
|
||||
|
||||
std::shared_ptr<AttrCursor> getAttr(std::string_view name);
|
||||
|
||||
|
|
|
@ -345,6 +345,7 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
|
|||
, sStructuredAttrs(symbols.create("__structuredAttrs"))
|
||||
, sBuilder(symbols.create("builder"))
|
||||
, sArgs(symbols.create("args"))
|
||||
, sContentAddressed(symbols.create("__contentAddressed"))
|
||||
, sOutputHash(symbols.create("outputHash"))
|
||||
, sOutputHashAlgo(symbols.create("outputHashAlgo"))
|
||||
, sOutputHashMode(symbols.create("outputHashMode"))
|
||||
|
@ -1256,10 +1257,10 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
|||
try {
|
||||
lambda.body->eval(*this, env2, v);
|
||||
} catch (Error & e) {
|
||||
addErrorTrace(e, lambda.pos, "while evaluating %s",
|
||||
(lambda.name.set()
|
||||
? "'" + (string) lambda.name + "'"
|
||||
: "anonymous lambdaction"));
|
||||
addErrorTrace(e, lambda.pos, "while evaluating %s",
|
||||
(lambda.name.set()
|
||||
? "'" + (string) lambda.name + "'"
|
||||
: "anonymous lambda"));
|
||||
addErrorTrace(e, pos, "from call site%s", "");
|
||||
throw;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
|
||||
sFile, sLine, sColumn, sFunctor, sToString,
|
||||
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
|
||||
sContentAddressed,
|
||||
sOutputHash, sOutputHashAlgo, sOutputHashMode,
|
||||
sRecurseForDerivations,
|
||||
sDescription, sSelf, sEpsilon;
|
||||
|
@ -374,6 +375,9 @@ struct EvalSettings : Config
|
|||
|
||||
Setting<bool> traceFunctionCalls{this, false, "trace-function-calls",
|
||||
"Emit log messages for each function entry and exit at the 'vomit' log level (-vvvv)."};
|
||||
|
||||
Setting<bool> useEvalCache{this, true, "eval-cache",
|
||||
"Whether to use the flake evaluation cache."};
|
||||
};
|
||||
|
||||
extern EvalSettings evalSettings;
|
||||
|
|
|
@ -113,9 +113,9 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
|
|||
state.mkList(*outputsVal, drv.outputs.size());
|
||||
unsigned int outputs_index = 0;
|
||||
|
||||
for (const auto & o : drv.outputs) {
|
||||
for (const auto & o : drv.outputsAndPaths(*state.store)) {
|
||||
v2 = state.allocAttr(w, state.symbols.create(o.first));
|
||||
mkString(*v2, state.store->printStorePath(o.second.path(*state.store, drv.name)), {"!" + o.first + "!" + path});
|
||||
mkString(*v2, state.store->printStorePath(o.second.second), {"!" + o.first + "!" + path});
|
||||
outputsVal->listElems()[outputs_index] = state.allocValue();
|
||||
mkString(*(outputsVal->listElems()[outputs_index++]), o.first);
|
||||
}
|
||||
|
@ -583,6 +583,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
|
||||
PathSet context;
|
||||
|
||||
bool contentAddressed = false;
|
||||
std::optional<std::string> outputHash;
|
||||
std::string outputHashAlgo;
|
||||
auto ingestionMethod = FileIngestionMethod::Flat;
|
||||
|
@ -639,9 +640,14 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
if (i->value->type == tNull) continue;
|
||||
}
|
||||
|
||||
if (i->name == state.sContentAddressed) {
|
||||
settings.requireExperimentalFeature("ca-derivations");
|
||||
contentAddressed = state.forceBool(*i->value, pos);
|
||||
}
|
||||
|
||||
/* The `args' attribute is special: it supplies the
|
||||
command-line arguments to the builder. */
|
||||
if (i->name == state.sArgs) {
|
||||
else if (i->name == state.sArgs) {
|
||||
state.forceList(*i->value, pos);
|
||||
for (unsigned int n = 0; n < i->value->listSize(); ++n) {
|
||||
string s = state.coerceToString(posDrvName, *i->value->listElems()[n], context, true);
|
||||
|
@ -694,7 +700,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
}
|
||||
|
||||
} catch (Error & e) {
|
||||
e.addTrace(posDrvName,
|
||||
e.addTrace(posDrvName,
|
||||
"while evaluating the attribute '%1%' of the derivation '%2%'",
|
||||
key, drvName);
|
||||
throw;
|
||||
|
@ -761,7 +767,10 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
});
|
||||
|
||||
if (outputHash) {
|
||||
/* Handle fixed-output derivations. */
|
||||
/* Handle fixed-output derivations.
|
||||
|
||||
Ignore `__contentAddressed` because fixed output derivations are
|
||||
already content addressed. */
|
||||
if (outputs.size() != 1 || *(outputs.begin()) != "out")
|
||||
throw Error({
|
||||
.hint = hintfmt("multiple outputs are not supported in fixed-output derivations"),
|
||||
|
@ -774,7 +783,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
auto outPath = state.store->makeFixedOutputPath(ingestionMethod, h, drvName);
|
||||
if (!jsonObject) drv.env["out"] = state.store->printStorePath(outPath);
|
||||
drv.outputs.insert_or_assign("out", DerivationOutput {
|
||||
.output = DerivationOutputFixed {
|
||||
.output = DerivationOutputCAFixed {
|
||||
.hash = FixedOutputHash {
|
||||
.method = ingestionMethod,
|
||||
.hash = std::move(h),
|
||||
|
@ -783,6 +792,19 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
});
|
||||
}
|
||||
|
||||
else if (contentAddressed) {
|
||||
HashType ht = parseHashType(outputHashAlgo);
|
||||
for (auto & i : outputs) {
|
||||
if (!jsonObject) drv.env[i] = hashPlaceholder(i);
|
||||
drv.outputs.insert_or_assign(i, DerivationOutput {
|
||||
.output = DerivationOutputCAFloating {
|
||||
.method = ingestionMethod,
|
||||
.hashType = std::move(ht),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* Compute a hash over the "masked" store derivation, which is
|
||||
the final one except that in the list of outputs, the
|
||||
|
@ -800,7 +822,9 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
});
|
||||
}
|
||||
|
||||
Hash h = hashDerivationModulo(*state.store, Derivation(drv), true);
|
||||
// Regular, non-CA derivation should always return a single hash and not
|
||||
// hash per output.
|
||||
Hash h = std::get<0>(hashDerivationModulo(*state.store, Derivation(drv), true));
|
||||
|
||||
for (auto & i : outputs) {
|
||||
auto outPath = state.store->makeOutputPath(i, h, drvName);
|
||||
|
@ -815,7 +839,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
}
|
||||
|
||||
/* Write the resulting term into the Nix store directory. */
|
||||
auto drvPath = writeDerivation(state.store, drv, drvName, state.repair);
|
||||
auto drvPath = writeDerivation(state.store, drv, state.repair);
|
||||
auto drvPathS = state.store->printStorePath(drvPath);
|
||||
|
||||
printMsg(lvlChatty, "instantiated '%1%' -> '%2%'", drvName, drvPathS);
|
||||
|
@ -828,9 +852,9 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
|
||||
state.mkAttrs(v, 1 + drv.outputs.size());
|
||||
mkString(*state.allocAttr(v, state.sDrvPath), drvPathS, {"=" + drvPathS});
|
||||
for (auto & i : drv.outputs) {
|
||||
for (auto & i : drv.outputsAndPaths(*state.store)) {
|
||||
mkString(*state.allocAttr(v, state.symbols.create(i.first)),
|
||||
state.store->printStorePath(i.second.path(*state.store, drv.name)), {"!" + i.first + "!" + drvPathS});
|
||||
state.store->printStorePath(i.second.second), {"!" + i.first + "!" + drvPathS});
|
||||
}
|
||||
v.attrs->sort();
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
|
|||
// be both a revision or a branch/tag name.
|
||||
auto value = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||
if (std::regex_match(value, revRegex))
|
||||
rev = Hash(value, htSHA1);
|
||||
rev = Hash::parseAny(value, htSHA1);
|
||||
else
|
||||
ref = value;
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
|||
: hashFile(htSHA256, path);
|
||||
if (hash != *expectedHash)
|
||||
throw Error((unsigned int) 102, "hash mismatch in file downloaded from '%s':\n wanted: %s\n got: %s",
|
||||
*url, expectedHash->to_string(Base32, true), hash->to_string(Base32, true));
|
||||
*url, expectedHash->to_string(Base32, true), hash.to_string(Base32, true));
|
||||
}
|
||||
|
||||
if (state.allowedPaths)
|
||||
|
|
|
@ -130,12 +130,12 @@ std::pair<Tree, Input> Input::fetch(ref<Store> store) const
|
|||
tree.actualPath = store->toRealPath(tree.storePath);
|
||||
|
||||
auto narHash = store->queryPathInfo(tree.storePath)->narHash;
|
||||
input.attrs.insert_or_assign("narHash", narHash->to_string(SRI, true));
|
||||
input.attrs.insert_or_assign("narHash", narHash.to_string(SRI, true));
|
||||
|
||||
if (auto prevNarHash = getNarHash()) {
|
||||
if (narHash != *prevNarHash)
|
||||
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'",
|
||||
to_string(), tree.actualPath, prevNarHash->to_string(SRI, true), narHash->to_string(SRI, true));
|
||||
to_string(), tree.actualPath, prevNarHash->to_string(SRI, true), narHash.to_string(SRI, true));
|
||||
}
|
||||
|
||||
if (auto prevLastModified = getLastModified()) {
|
||||
|
@ -200,9 +200,12 @@ std::string Input::getType() const
|
|||
|
||||
std::optional<Hash> Input::getNarHash() const
|
||||
{
|
||||
if (auto s = maybeGetStrAttr(attrs, "narHash"))
|
||||
// FIXME: require SRI hash.
|
||||
return newHashAllowEmpty(*s, htSHA256);
|
||||
if (auto s = maybeGetStrAttr(attrs, "narHash")) {
|
||||
auto hash = s->empty() ? Hash(htSHA256) : Hash::parseSRI(*s);
|
||||
if (hash.type != htSHA256)
|
||||
throw UsageError("narHash must use SHA-256");
|
||||
return hash;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -216,7 +219,7 @@ std::optional<std::string> Input::getRef() const
|
|||
std::optional<Hash> Input::getRev() const
|
||||
{
|
||||
if (auto s = maybeGetStrAttr(attrs, "rev"))
|
||||
return Hash(*s, htSHA1);
|
||||
return Hash::parseAny(*s, htSHA1);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ struct GitInputScheme : InputScheme
|
|||
args.push_back(*ref);
|
||||
}
|
||||
|
||||
if (input.getRev()) throw Error("cloning a specific revision is not implemented");
|
||||
if (input.getRev()) throw UnimplementedError("cloning a specific revision is not implemented");
|
||||
|
||||
args.push_back(destDir);
|
||||
|
||||
|
@ -269,7 +269,7 @@ struct GitInputScheme : InputScheme
|
|||
// modified dirty file?
|
||||
input.attrs.insert_or_assign(
|
||||
"lastModified",
|
||||
haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "log", "-1", "--format=%ct", "HEAD" })) : 0);
|
||||
haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
|
||||
|
||||
return {
|
||||
Tree(store->printStorePath(storePath), std::move(storePath)),
|
||||
|
@ -293,14 +293,14 @@ struct GitInputScheme : InputScheme
|
|||
|
||||
if (!input.getRev())
|
||||
input.attrs.insert_or_assign("rev",
|
||||
Hash(chomp(runProgram("git", true, { "-C", actualUrl, "rev-parse", *input.getRef() })), htSHA1).gitRev());
|
||||
Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "rev-parse", *input.getRef() })), htSHA1).gitRev());
|
||||
|
||||
repoDir = actualUrl;
|
||||
|
||||
} else {
|
||||
|
||||
if (auto res = getCache()->lookup(store, mutableAttrs)) {
|
||||
auto rev2 = Hash(getStrAttr(res->first, "rev"), htSHA1);
|
||||
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1);
|
||||
if (!input.getRev() || input.getRev() == rev2) {
|
||||
input.attrs.insert_or_assign("rev", rev2.gitRev());
|
||||
return makeResult(res->first, std::move(res->second));
|
||||
|
@ -370,7 +370,7 @@ struct GitInputScheme : InputScheme
|
|||
}
|
||||
|
||||
if (!input.getRev())
|
||||
input.attrs.insert_or_assign("rev", Hash(chomp(readFile(localRefFile)), htSHA1).gitRev());
|
||||
input.attrs.insert_or_assign("rev", Hash::parseAny(chomp(readFile(localRefFile)), htSHA1).gitRev());
|
||||
}
|
||||
|
||||
bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "rev-parse", "--is-shallow-repository" })) == "true";
|
||||
|
@ -421,7 +421,7 @@ struct GitInputScheme : InputScheme
|
|||
|
||||
auto storePath = store->addToStore(name, tmpDir, FileIngestionMethod::Recursive, htSHA256, filter);
|
||||
|
||||
auto lastModified = std::stoull(runProgram("git", true, { "-C", repoDir, "log", "-1", "--format=%ct", input.getRev()->gitRev() }));
|
||||
auto lastModified = std::stoull(runProgram("git", true, { "-C", repoDir, "log", "-1", "--format=%ct", "--no-show-signature", input.getRev()->gitRev() }));
|
||||
|
||||
Attrs infoAttrs({
|
||||
{"rev", input.getRev()->gitRev()},
|
||||
|
|
|
@ -29,7 +29,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
if (path.size() == 2) {
|
||||
} else if (path.size() == 3) {
|
||||
if (std::regex_match(path[2], revRegex))
|
||||
rev = Hash(path[2], htSHA1);
|
||||
rev = Hash::parseAny(path[2], htSHA1);
|
||||
else if (std::regex_match(path[2], refRegex))
|
||||
ref = path[2];
|
||||
else
|
||||
|
@ -41,7 +41,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
if (name == "rev") {
|
||||
if (rev)
|
||||
throw BadURL("URL '%s' contains multiple commit hashes", url.url);
|
||||
rev = Hash(value, htSHA1);
|
||||
rev = Hash::parseAny(value, htSHA1);
|
||||
}
|
||||
else if (name == "ref") {
|
||||
if (!std::regex_match(value, refRegex))
|
||||
|
@ -191,7 +191,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
|||
readFile(
|
||||
store->toRealPath(
|
||||
downloadFile(store, url, "source", false).storePath)));
|
||||
auto rev = Hash(std::string { json["sha"] }, htSHA1);
|
||||
auto rev = Hash::parseAny(std::string { json["sha"] }, htSHA1);
|
||||
debug("HEAD revision for '%s' is %s", url, rev.gitRev());
|
||||
return rev;
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
|||
readFile(
|
||||
store->toRealPath(
|
||||
downloadFile(store, url, "source", false).storePath)));
|
||||
auto rev = Hash(std::string(json[0]["id"]), htSHA1);
|
||||
auto rev = Hash::parseAny(std::string(json[0]["id"]), htSHA1);
|
||||
debug("HEAD revision for '%s' is %s", url, rev.gitRev());
|
||||
return rev;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ struct IndirectInputScheme : InputScheme
|
|||
if (path.size() == 1) {
|
||||
} else if (path.size() == 2) {
|
||||
if (std::regex_match(path[1], revRegex))
|
||||
rev = Hash(path[1], htSHA1);
|
||||
rev = Hash::parseAny(path[1], htSHA1);
|
||||
else if (std::regex_match(path[1], refRegex))
|
||||
ref = path[1];
|
||||
else
|
||||
|
@ -29,7 +29,7 @@ struct IndirectInputScheme : InputScheme
|
|||
ref = path[1];
|
||||
if (!std::regex_match(path[2], revRegex))
|
||||
throw BadURL("in flake URL '%s', '%s' is not a commit hash", url.url, path[2]);
|
||||
rev = Hash(path[2], htSHA1);
|
||||
rev = Hash::parseAny(path[2], htSHA1);
|
||||
} else
|
||||
throw BadURL("GitHub URL '%s' is invalid", url.url);
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ struct MercurialInputScheme : InputScheme
|
|||
});
|
||||
|
||||
if (auto res = getCache()->lookup(store, mutableAttrs)) {
|
||||
auto rev2 = Hash(getStrAttr(res->first, "rev"), htSHA1);
|
||||
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1);
|
||||
if (!input.getRev() || input.getRev() == rev2) {
|
||||
input.attrs.insert_or_assign("rev", rev2.gitRev());
|
||||
return makeResult(res->first, std::move(res->second));
|
||||
|
@ -252,7 +252,7 @@ struct MercurialInputScheme : InputScheme
|
|||
runProgram("hg", true, { "log", "-R", cacheDir, "-r", revOrRef, "--template", "{node} {rev} {branch}" }));
|
||||
assert(tokens.size() == 3);
|
||||
|
||||
input.attrs.insert_or_assign("rev", Hash(tokens[0], htSHA1).gitRev());
|
||||
input.attrs.insert_or_assign("rev", Hash::parseAny(tokens[0], htSHA1).gitRev());
|
||||
auto revCount = std::stoull(tokens[1]);
|
||||
input.attrs.insert_or_assign("ref", tokens[2]);
|
||||
|
||||
|
|
|
@ -67,8 +67,10 @@ DownloadFileResult downloadFile(
|
|||
StringSink sink;
|
||||
dumpString(*res.data, sink);
|
||||
auto hash = hashString(htSHA256, *res.data);
|
||||
ValidPathInfo info(store->makeFixedOutputPath(FileIngestionMethod::Flat, hash, name));
|
||||
info.narHash = hashString(htSHA256, *sink.s);
|
||||
ValidPathInfo info {
|
||||
store->makeFixedOutputPath(FileIngestionMethod::Flat, hash, name),
|
||||
hashString(htSHA256, *sink.s),
|
||||
};
|
||||
info.narSize = sink.s->size();
|
||||
info.ca = FixedOutputHash {
|
||||
.method = FileIngestionMethod::Flat,
|
||||
|
|
|
@ -362,7 +362,7 @@ public:
|
|||
auto width = getWindowSize().second;
|
||||
if (width <= 0) width = std::numeric_limits<decltype(width)>::max();
|
||||
|
||||
writeToStderr("\r" + filterANSIEscapes(line, false, width) + "\e[K");
|
||||
writeToStderr("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K");
|
||||
}
|
||||
|
||||
std::string getStatus(State & state)
|
||||
|
|
|
@ -143,7 +143,7 @@ struct FileSource : FdSource
|
|||
void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource,
|
||||
RepairFlag repair, CheckSigsFlag checkSigs)
|
||||
{
|
||||
assert(info.narHash && info.narSize);
|
||||
assert(info.narSize);
|
||||
|
||||
if (!repair && isValidPath(info.path)) {
|
||||
// FIXME: copyNAR -> null sink
|
||||
|
@ -153,6 +153,8 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource
|
|||
|
||||
auto [fdTemp, fnTemp] = createTempFile();
|
||||
|
||||
AutoDelete autoDelete(fnTemp);
|
||||
|
||||
auto now1 = std::chrono::steady_clock::now();
|
||||
|
||||
/* Read the NAR simultaneously into a CompressionSink+FileSink (to
|
||||
|
@ -167,6 +169,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource
|
|||
TeeSource teeSource(narSource, *compressionSink);
|
||||
narAccessor = makeNarAccessor(teeSource);
|
||||
compressionSink->finish();
|
||||
fileSink.flush();
|
||||
}
|
||||
|
||||
auto now2 = std::chrono::steady_clock::now();
|
||||
|
@ -216,7 +219,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource
|
|||
}
|
||||
}
|
||||
|
||||
upsertFile(std::string(info.path.to_string()) + ".ls", jsonOut.str(), "application/json");
|
||||
upsertFile(std::string(info.path.hashPart()) + ".ls", jsonOut.str(), "application/json");
|
||||
}
|
||||
|
||||
/* Optionally maintain an index of DWARF debug info files
|
||||
|
@ -280,7 +283,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource
|
|||
if (repair || !fileExists(narInfo->url)) {
|
||||
stats.narWrite++;
|
||||
upsertFile(narInfo->url,
|
||||
std::make_shared<std::fstream>(fnTemp, std::ios_base::in),
|
||||
std::make_shared<std::fstream>(fnTemp, std::ios_base::in | std::ios_base::binary),
|
||||
"application/x-nix-nar");
|
||||
} else
|
||||
stats.narWriteAverted++;
|
||||
|
@ -309,14 +312,10 @@ void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink)
|
|||
{
|
||||
auto info = queryPathInfo(storePath).cast<const NarInfo>();
|
||||
|
||||
uint64_t narSize = 0;
|
||||
LengthSink narSize;
|
||||
TeeSink tee { sink, narSize };
|
||||
|
||||
LambdaSink wrapperSink([&](const unsigned char * data, size_t len) {
|
||||
sink(data, len);
|
||||
narSize += len;
|
||||
});
|
||||
|
||||
auto decompressor = makeDecompressionSink(info->compression, wrapperSink);
|
||||
auto decompressor = makeDecompressionSink(info->compression, tee);
|
||||
|
||||
try {
|
||||
getFile(info->url, *decompressor);
|
||||
|
@ -328,7 +327,7 @@ void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink)
|
|||
|
||||
stats.narRead++;
|
||||
//stats.narReadCompressedBytes += nar->size(); // FIXME
|
||||
stats.narReadBytes += narSize;
|
||||
stats.narReadBytes += narSize.length;
|
||||
}
|
||||
|
||||
void BinaryCacheStore::queryPathInfoUncached(const StorePath & storePath,
|
||||
|
@ -382,7 +381,10 @@ StorePath BinaryCacheStore::addToStore(const string & name, const Path & srcPath
|
|||
h = hashString(hashAlgo, s);
|
||||
}
|
||||
|
||||
ValidPathInfo info(makeFixedOutputPath(method, *h, name));
|
||||
ValidPathInfo info {
|
||||
makeFixedOutputPath(method, *h, name),
|
||||
Hash::dummy, // Will be fixed in addToStore, which recomputes nar hash
|
||||
};
|
||||
|
||||
auto source = StringSource { *sink.s };
|
||||
addToStore(info, source, repair, CheckSigs);
|
||||
|
@ -393,7 +395,10 @@ StorePath BinaryCacheStore::addToStore(const string & name, const Path & srcPath
|
|||
StorePath BinaryCacheStore::addTextToStore(const string & name, const string & s,
|
||||
const StorePathSet & references, RepairFlag repair)
|
||||
{
|
||||
ValidPathInfo info(computeStorePathForText(name, s, references));
|
||||
ValidPathInfo info {
|
||||
computeStorePathForText(name, s, references),
|
||||
Hash::dummy, // Will be fixed in addToStore, which recomputes nar hash
|
||||
};
|
||||
info.references = references;
|
||||
|
||||
if (repair || !isValidPath(info.path)) {
|
||||
|
|
|
@ -806,8 +806,8 @@ private:
|
|||
/* RAII object to delete the chroot directory. */
|
||||
std::shared_ptr<AutoDelete> autoDelChroot;
|
||||
|
||||
/* Whether this is a fixed-output derivation. */
|
||||
bool fixedOutput;
|
||||
/* The sort of derivation we are building. */
|
||||
DerivationType derivationType;
|
||||
|
||||
/* Whether to run the build in a private network namespace. */
|
||||
bool privateNetwork = false;
|
||||
|
@ -1181,8 +1181,8 @@ void DerivationGoal::haveDerivation()
|
|||
|
||||
retrySubstitution = false;
|
||||
|
||||
for (auto & i : drv->outputs)
|
||||
worker.store.addTempRoot(i.second.path(worker.store, drv->name));
|
||||
for (auto & i : drv->outputsAndPaths(worker.store))
|
||||
worker.store.addTempRoot(i.second.second);
|
||||
|
||||
/* Check what outputs paths are not already valid. */
|
||||
auto invalidOutputs = checkPathValidity(false, buildMode == bmRepair);
|
||||
|
@ -1195,9 +1195,9 @@ void DerivationGoal::haveDerivation()
|
|||
|
||||
parsedDrv = std::make_unique<ParsedDerivation>(drvPath, *drv);
|
||||
|
||||
if (parsedDrv->contentAddressed()) {
|
||||
if (drv->type() == DerivationType::CAFloating) {
|
||||
settings.requireExperimentalFeature("ca-derivations");
|
||||
throw Error("ca-derivations isn't implemented yet");
|
||||
throw UnimplementedError("ca-derivations isn't implemented yet");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1288,14 +1288,14 @@ void DerivationGoal::repairClosure()
|
|||
|
||||
/* Get the output closure. */
|
||||
StorePathSet outputClosure;
|
||||
for (auto & i : drv->outputs) {
|
||||
for (auto & i : drv->outputsAndPaths(worker.store)) {
|
||||
if (!wantOutput(i.first, wantedOutputs)) continue;
|
||||
worker.store.computeFSClosure(i.second.path(worker.store, drv->name), outputClosure);
|
||||
worker.store.computeFSClosure(i.second.second, outputClosure);
|
||||
}
|
||||
|
||||
/* Filter out our own outputs (which we have already checked). */
|
||||
for (auto & i : drv->outputs)
|
||||
outputClosure.erase(i.second.path(worker.store, drv->name));
|
||||
for (auto & i : drv->outputsAndPaths(worker.store))
|
||||
outputClosure.erase(i.second.second);
|
||||
|
||||
/* Get all dependencies of this derivation so that we know which
|
||||
derivation is responsible for which path in the output
|
||||
|
@ -1306,8 +1306,8 @@ void DerivationGoal::repairClosure()
|
|||
for (auto & i : inputClosure)
|
||||
if (i.isDerivation()) {
|
||||
Derivation drv = worker.store.derivationFromPath(i);
|
||||
for (auto & j : drv.outputs)
|
||||
outputsToDrv.insert_or_assign(j.second.path(worker.store, drv.name), i);
|
||||
for (auto & j : drv.outputsAndPaths(worker.store))
|
||||
outputsToDrv.insert_or_assign(j.second.second, i);
|
||||
}
|
||||
|
||||
/* Check each path (slow!). */
|
||||
|
@ -1392,12 +1392,12 @@ void DerivationGoal::inputsRealised()
|
|||
|
||||
debug("added input paths %s", worker.store.showPaths(inputPaths));
|
||||
|
||||
/* Is this a fixed-output derivation? */
|
||||
fixedOutput = drv->isFixedOutput();
|
||||
/* What type of derivation are we building? */
|
||||
derivationType = drv->type();
|
||||
|
||||
/* Don't repeat fixed-output derivations since they're already
|
||||
verified by their output hash.*/
|
||||
nrRounds = fixedOutput ? 1 : settings.buildRepeat + 1;
|
||||
nrRounds = derivationIsFixed(derivationType) ? 1 : settings.buildRepeat + 1;
|
||||
|
||||
/* Okay, try to build. Note that here we don't wait for a build
|
||||
slot to become available, since we don't need one if there is a
|
||||
|
@ -1466,16 +1466,16 @@ void DerivationGoal::tryToBuild()
|
|||
|
||||
/* If any of the outputs already exist but are not valid, delete
|
||||
them. */
|
||||
for (auto & i : drv->outputs) {
|
||||
if (worker.store.isValidPath(i.second.path(worker.store, drv->name))) continue;
|
||||
debug("removing invalid path '%s'", worker.store.printStorePath(i.second.path(worker.store, drv->name)));
|
||||
deletePath(worker.store.Store::toRealPath(i.second.path(worker.store, drv->name)));
|
||||
for (auto & i : drv->outputsAndPaths(worker.store)) {
|
||||
if (worker.store.isValidPath(i.second.second)) continue;
|
||||
debug("removing invalid path '%s'", worker.store.printStorePath(i.second.second));
|
||||
deletePath(worker.store.Store::toRealPath(i.second.second));
|
||||
}
|
||||
|
||||
/* Don't do a remote build if the derivation has the attribute
|
||||
`preferLocalBuild' set. Also, check and repair modes are only
|
||||
supported for local builds. */
|
||||
bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally();
|
||||
bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally(worker.store);
|
||||
|
||||
/* Is the build hook willing to accept this job? */
|
||||
if (!buildLocally) {
|
||||
|
@ -1783,7 +1783,7 @@ void DerivationGoal::buildDone()
|
|||
st =
|
||||
dynamic_cast<NotDeterministic*>(&e) ? BuildResult::NotDeterministic :
|
||||
statusOk(status) ? BuildResult::OutputRejected :
|
||||
fixedOutput || diskFull ? BuildResult::TransientFailure :
|
||||
derivationIsImpure(derivationType) || diskFull ? BuildResult::TransientFailure :
|
||||
BuildResult::PermanentFailure;
|
||||
}
|
||||
|
||||
|
@ -1919,8 +1919,8 @@ StorePathSet DerivationGoal::exportReferences(const StorePathSet & storePaths)
|
|||
for (auto & j : paths2) {
|
||||
if (j.isDerivation()) {
|
||||
Derivation drv = worker.store.derivationFromPath(j);
|
||||
for (auto & k : drv.outputs)
|
||||
worker.store.computeFSClosure(k.second.path(worker.store, drv.name), paths);
|
||||
for (auto & k : drv.outputsAndPaths(worker.store))
|
||||
worker.store.computeFSClosure(k.second.second, paths);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1964,13 +1964,13 @@ void linkOrCopy(const Path & from, const Path & to)
|
|||
void DerivationGoal::startBuilder()
|
||||
{
|
||||
/* Right platform? */
|
||||
if (!parsedDrv->canBuildLocally())
|
||||
if (!parsedDrv->canBuildLocally(worker.store))
|
||||
throw Error("a '%s' with features {%s} is required to build '%s', but I am a '%s' with features {%s}",
|
||||
drv->platform,
|
||||
concatStringsSep(", ", parsedDrv->getRequiredSystemFeatures()),
|
||||
worker.store.printStorePath(drvPath),
|
||||
settings.thisSystem,
|
||||
concatStringsSep<StringSet>(", ", settings.systemFeatures));
|
||||
concatStringsSep<StringSet>(", ", worker.store.systemFeatures));
|
||||
|
||||
if (drv->isBuiltin())
|
||||
preloadNSS();
|
||||
|
@ -1996,7 +1996,7 @@ void DerivationGoal::startBuilder()
|
|||
else if (settings.sandboxMode == smDisabled)
|
||||
useChroot = false;
|
||||
else if (settings.sandboxMode == smRelaxed)
|
||||
useChroot = !fixedOutput && !noChroot;
|
||||
useChroot = !(derivationIsImpure(derivationType)) && !noChroot;
|
||||
}
|
||||
|
||||
if (worker.store.storeDir != worker.store.realStoreDir) {
|
||||
|
@ -2014,8 +2014,8 @@ void DerivationGoal::startBuilder()
|
|||
chownToBuilder(tmpDir);
|
||||
|
||||
/* Substitute output placeholders with the actual output paths. */
|
||||
for (auto & output : drv->outputs)
|
||||
inputRewrites[hashPlaceholder(output.first)] = worker.store.printStorePath(output.second.path(worker.store, drv->name));
|
||||
for (auto & output : drv->outputsAndPaths(worker.store))
|
||||
inputRewrites[hashPlaceholder(output.first)] = worker.store.printStorePath(output.second.second);
|
||||
|
||||
/* Construct the environment passed to the builder. */
|
||||
initEnv();
|
||||
|
@ -2165,7 +2165,7 @@ void DerivationGoal::startBuilder()
|
|||
"nogroup:x:65534:\n") % sandboxGid).str());
|
||||
|
||||
/* Create /etc/hosts with localhost entry. */
|
||||
if (!fixedOutput)
|
||||
if (!(derivationIsImpure(derivationType)))
|
||||
writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n::1 localhost\n");
|
||||
|
||||
/* Make the closure of the inputs available in the chroot,
|
||||
|
@ -2199,8 +2199,8 @@ void DerivationGoal::startBuilder()
|
|||
rebuilding a path that is in settings.dirsInChroot
|
||||
(typically the dependencies of /bin/sh). Throw them
|
||||
out. */
|
||||
for (auto & i : drv->outputs)
|
||||
dirsInChroot.erase(worker.store.printStorePath(i.second.path(worker.store, drv->name)));
|
||||
for (auto & i : drv->outputsAndPaths(worker.store))
|
||||
dirsInChroot.erase(worker.store.printStorePath(i.second.second));
|
||||
|
||||
#elif __APPLE__
|
||||
/* We don't really have any parent prep work to do (yet?)
|
||||
|
@ -2373,7 +2373,7 @@ void DerivationGoal::startBuilder()
|
|||
us.
|
||||
*/
|
||||
|
||||
if (!fixedOutput)
|
||||
if (!(derivationIsImpure(derivationType)))
|
||||
privateNetwork = true;
|
||||
|
||||
userNamespaceSync.create();
|
||||
|
@ -2574,7 +2574,7 @@ void DerivationGoal::initEnv()
|
|||
derivation, tell the builder, so that for instance `fetchurl'
|
||||
can skip checking the output. On older Nixes, this environment
|
||||
variable won't be set, so `fetchurl' will do the check. */
|
||||
if (fixedOutput) env["NIX_OUTPUT_CHECKED"] = "1";
|
||||
if (derivationIsFixed(derivationType)) env["NIX_OUTPUT_CHECKED"] = "1";
|
||||
|
||||
/* *Only* if this is a fixed-output derivation, propagate the
|
||||
values of the environment variables specified in the
|
||||
|
@ -2585,7 +2585,7 @@ void DerivationGoal::initEnv()
|
|||
to the builder is generally impure, but the output of
|
||||
fixed-output derivations is by definition pure (since we
|
||||
already know the cryptographic hash of the output). */
|
||||
if (fixedOutput) {
|
||||
if (derivationIsImpure(derivationType)) {
|
||||
for (auto & i : parsedDrv->getStringsAttr("impureEnvVars").value_or(Strings()))
|
||||
env[i] = getEnv(i).value_or("");
|
||||
}
|
||||
|
@ -2612,8 +2612,8 @@ void DerivationGoal::writeStructuredAttrs()
|
|||
|
||||
/* Add an "outputs" object containing the output paths. */
|
||||
nlohmann::json outputs;
|
||||
for (auto & i : drv->outputs)
|
||||
outputs[i.first] = rewriteStrings(worker.store.printStorePath(i.second.path(worker.store, drv->name)), inputRewrites);
|
||||
for (auto & i : drv->outputsAndPaths(worker.store))
|
||||
outputs[i.first] = rewriteStrings(worker.store.printStorePath(i.second.second), inputRewrites);
|
||||
json["outputs"] = outputs;
|
||||
|
||||
/* Handle exportReferencesGraph. */
|
||||
|
@ -2815,9 +2815,9 @@ struct RestrictedStore : public LocalFSStore
|
|||
if (!goal.isAllowed(path.path))
|
||||