mirror of
https://github.com/NixOS/nix.git
synced 2025-11-21 09:49:36 +01:00
Merge remote-tracking branch 'detsys/detsys-main' into lazy-trees-v2
This commit is contained in:
commit
577b331464
52 changed files with 398 additions and 235 deletions
|
|
@ -214,6 +214,8 @@ struct InstallableCommand : virtual Args, SourceExprCommand
|
|||
{
|
||||
InstallableCommand();
|
||||
|
||||
virtual void preRun(ref<Store> store);
|
||||
|
||||
virtual void run(ref<Store> store, ref<Installable> installable) = 0;
|
||||
|
||||
void run(ref<Store> store) override;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ void completeFlakeInputAttrPath(
|
|||
std::string_view prefix)
|
||||
{
|
||||
for (auto & flakeRef : flakeRefs) {
|
||||
auto flake = flake::getFlake(*evalState, flakeRef, true);
|
||||
auto flake = flake::getFlake(*evalState, flakeRef, fetchers::UseRegistries::All);
|
||||
for (auto & input : flake.inputs)
|
||||
if (hasPrefix(input.first, prefix))
|
||||
completions.add(input.first);
|
||||
|
|
@ -903,8 +903,13 @@ InstallableCommand::InstallableCommand()
|
|||
});
|
||||
}
|
||||
|
||||
void InstallableCommand::preRun(ref<Store> store)
|
||||
{
|
||||
}
|
||||
|
||||
void InstallableCommand::run(ref<Store> store)
|
||||
{
|
||||
preRun(store);
|
||||
auto installable = parseInstallable(store, _installable);
|
||||
run(store, std::move(installable));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,9 +84,17 @@ bool EvalSettings::isPseudoUrl(std::string_view s)
|
|||
|
||||
std::string EvalSettings::resolvePseudoUrl(std::string_view url)
|
||||
{
|
||||
if (hasPrefix(url, "channel:"))
|
||||
return "https://nixos.org/channels/" + std::string(url.substr(8)) + "/nixexprs.tar.xz";
|
||||
else
|
||||
if (hasPrefix(url, "channel:")) {
|
||||
auto realUrl = "https://nixos.org/channels/" + std::string(url.substr(8)) + "/nixexprs.tar.xz";
|
||||
static bool haveWarned = false;
|
||||
warnOnce(haveWarned,
|
||||
"Channels are deprecated in favor of flakes in Determinate Nix. "
|
||||
"Instead of '%s', use '%s'. "
|
||||
"See https://zero-to-nix.com for a guide to Nix flakes. "
|
||||
"For details and to offer feedback on the deprecation process, see: https://github.com/DeterminateSystems/nix-src/issues/34.",
|
||||
url, realUrl);
|
||||
return realUrl;
|
||||
} else
|
||||
return std::string(url);
|
||||
}
|
||||
|
||||
|
|
@ -103,4 +111,4 @@ Path getNixDefExpr()
|
|||
: getHome() + "/.nix-defexpr";
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
} // namespace nix
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ static void fetchTree(
|
|||
}
|
||||
|
||||
if (!state.settings.pureEval && !input.isDirect())
|
||||
input = lookupInRegistries(state.store, input).first;
|
||||
input = lookupInRegistries(state.store, input, fetchers::UseRegistries::Limited).first;
|
||||
|
||||
if (state.settings.pureEval && !input.isLocked()) {
|
||||
if (input.getNarHash())
|
||||
|
|
@ -202,7 +202,7 @@ static void fetchTree(
|
|||
throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string());
|
||||
}
|
||||
|
||||
auto cachedInput = state.inputCache->getAccessor(state.store, input, false);
|
||||
auto cachedInput = state.inputCache->getAccessor(state.store, input, fetchers::UseRegistries::No);
|
||||
|
||||
auto storePath = state.mountInput(cachedInput.lockedInput, input, cachedInput.accessor, true);
|
||||
|
||||
|
|
|
|||
|
|
@ -393,10 +393,10 @@ struct GitInputScheme : InputScheme
|
|||
{
|
||||
if (workdirInfo.isDirty) {
|
||||
if (!settings.allowDirty)
|
||||
throw Error("Git tree '%s' is dirty", locationToArg());
|
||||
throw Error("Git tree '%s' has uncommitted changes", locationToArg());
|
||||
|
||||
if (settings.warnDirty)
|
||||
warn("Git tree '%s' is dirty", locationToArg());
|
||||
warn("Git tree '%s' has uncommitted changes", locationToArg());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace nix::fetchers {
|
||||
|
||||
enum class UseRegistries : int;
|
||||
|
||||
struct InputCache
|
||||
{
|
||||
struct CachedResult
|
||||
|
|
@ -11,7 +13,7 @@ struct InputCache
|
|||
Input lockedInput;
|
||||
};
|
||||
|
||||
CachedResult getAccessor(ref<Store> store, const Input & originalInput, bool useRegistries);
|
||||
CachedResult getAccessor(ref<Store> store, const Input & originalInput, UseRegistries useRegistries);
|
||||
|
||||
struct CachedInput
|
||||
{
|
||||
|
|
@ -26,6 +28,8 @@ struct InputCache
|
|||
virtual void clear() = 0;
|
||||
|
||||
static ref<InputCache> create();
|
||||
|
||||
virtual ~InputCache() = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,11 @@ void overrideRegistry(
|
|||
const Input & to,
|
||||
const Attrs & extraAttrs);
|
||||
|
||||
using RegistryFilter = std::function<bool(Registry::RegistryType)>;
|
||||
enum class UseRegistries : int {
|
||||
No,
|
||||
All,
|
||||
Limited, // global and flag registry only
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewrite a flakeref using the registries. If `filter` is set, only
|
||||
|
|
@ -74,6 +78,6 @@ using RegistryFilter = std::function<bool(Registry::RegistryType)>;
|
|||
std::pair<Input, Attrs> lookupInRegistries(
|
||||
ref<Store> store,
|
||||
const Input & input,
|
||||
const RegistryFilter & filter = {});
|
||||
UseRegistries useRegistries);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
namespace nix::fetchers {
|
||||
|
||||
InputCache::CachedResult InputCache::getAccessor(ref<Store> store, const Input & originalInput, bool useRegistries)
|
||||
InputCache::CachedResult
|
||||
InputCache::getAccessor(ref<Store> store, const Input & originalInput, UseRegistries useRegistries)
|
||||
{
|
||||
auto fetched = lookup(originalInput);
|
||||
Input resolvedInput = originalInput;
|
||||
|
|
@ -15,13 +16,8 @@ InputCache::CachedResult InputCache::getAccessor(ref<Store> store, const Input &
|
|||
auto [accessor, lockedInput] = originalInput.getAccessor(store);
|
||||
fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor});
|
||||
} else {
|
||||
if (useRegistries) {
|
||||
auto [res, extraAttrs] =
|
||||
lookupInRegistries(store, originalInput, [](fetchers::Registry::RegistryType type) {
|
||||
/* Only use the global registry and CLI flags
|
||||
to resolve indirect flakerefs. */
|
||||
return type == fetchers::Registry::Flag || type == fetchers::Registry::Global;
|
||||
});
|
||||
if (useRegistries != fetchers::UseRegistries::No) {
|
||||
auto [res, extraAttrs] = lookupInRegistries(store, originalInput, useRegistries);
|
||||
resolvedInput = std::move(res);
|
||||
fetched = lookup(resolvedInput);
|
||||
if (!fetched) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ std::shared_ptr<Registry> Registry::read(
|
|||
const Settings & settings,
|
||||
const Path & path, RegistryType type)
|
||||
{
|
||||
debug("reading registry '%s'", path);
|
||||
|
||||
auto registry = std::make_shared<Registry>(settings, type);
|
||||
|
||||
if (!pathExists(path))
|
||||
|
|
@ -179,29 +181,36 @@ Registries getRegistries(const Settings & settings, ref<Store> store)
|
|||
std::pair<Input, Attrs> lookupInRegistries(
|
||||
ref<Store> store,
|
||||
const Input & _input,
|
||||
const RegistryFilter & filter)
|
||||
UseRegistries useRegistries)
|
||||
{
|
||||
Attrs extraAttrs;
|
||||
int n = 0;
|
||||
Input input(_input);
|
||||
|
||||
if (useRegistries == UseRegistries::No)
|
||||
return {input, extraAttrs};
|
||||
|
||||
restart:
|
||||
|
||||
n++;
|
||||
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());
|
||||
|
||||
for (auto & registry : getRegistries(*input.settings, store)) {
|
||||
if (filter && !filter(registry->type)) continue;
|
||||
if (useRegistries == UseRegistries::Limited
|
||||
&& !(registry->type == fetchers::Registry::Flag || registry->type == fetchers::Registry::Global))
|
||||
continue;
|
||||
// FIXME: O(n)
|
||||
for (auto & entry : registry->entries) {
|
||||
if (entry.exact) {
|
||||
if (entry.from == input) {
|
||||
debug("resolved flakeref '%s' against registry %d exactly", input.to_string(), registry->type);
|
||||
input = entry.to;
|
||||
extraAttrs = entry.extraAttrs;
|
||||
goto restart;
|
||||
}
|
||||
} else {
|
||||
if (entry.from.contains(input)) {
|
||||
debug("resolved flakeref '%s' against registry %d", input.to_string(), registry->type);
|
||||
input = entry.to.applyOverrides(
|
||||
!entry.from.getRef() && input.getRef() ? input.getRef() : std::optional<std::string>(),
|
||||
!entry.from.getRev() && input.getRev() ? input.getRev() : std::optional<Hash>());
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ static FlakeRef applySelfAttrs(
|
|||
static Flake getFlake(
|
||||
EvalState & state,
|
||||
const FlakeRef & originalRef,
|
||||
bool useRegistries,
|
||||
fetchers::UseRegistries useRegistries,
|
||||
const InputAttrPath & lockRootAttrPath,
|
||||
bool requireLockable)
|
||||
{
|
||||
|
|
@ -341,7 +341,7 @@ static Flake getFlake(
|
|||
debug("refetching input '%s' due to self attribute", newLockedRef);
|
||||
// FIXME: need to remove attrs that are invalidated by the changed input attrs, such as 'narHash'.
|
||||
newLockedRef.input.attrs.erase("narHash");
|
||||
auto cachedInput2 = state.inputCache->getAccessor(state.store, newLockedRef.input, useRegistries);
|
||||
auto cachedInput2 = state.inputCache->getAccessor(state.store, newLockedRef.input, fetchers::UseRegistries::No);
|
||||
cachedInput.accessor = cachedInput2.accessor;
|
||||
lockedRef = FlakeRef(std::move(cachedInput2.lockedInput), newLockedRef.subdir);
|
||||
}
|
||||
|
|
@ -353,7 +353,7 @@ static Flake getFlake(
|
|||
lockRootAttrPath);
|
||||
}
|
||||
|
||||
Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistries, bool requireLockable)
|
||||
Flake getFlake(EvalState & state, const FlakeRef & originalRef, fetchers::UseRegistries useRegistries, bool requireLockable)
|
||||
{
|
||||
return getFlake(state, originalRef, useRegistries, {}, requireLockable);
|
||||
}
|
||||
|
|
@ -376,8 +376,15 @@ LockedFlake lockFlake(
|
|||
const LockFlags & lockFlags)
|
||||
{
|
||||
auto useRegistries = lockFlags.useRegistries.value_or(settings.useRegistries);
|
||||
auto useRegistriesTop = useRegistries ? fetchers::UseRegistries::All : fetchers::UseRegistries::No;
|
||||
auto useRegistriesInputs = useRegistries ? fetchers::UseRegistries::Limited : fetchers::UseRegistries::No;
|
||||
|
||||
auto flake = getFlake(state, topRef, useRegistries, {}, lockFlags.requireLockable);
|
||||
auto flake = getFlake(
|
||||
state,
|
||||
topRef,
|
||||
useRegistriesTop,
|
||||
{},
|
||||
lockFlags.requireLockable);
|
||||
|
||||
if (lockFlags.applyNixConfig) {
|
||||
flake.config.apply(settings);
|
||||
|
|
@ -552,7 +559,12 @@ LockedFlake lockFlake(
|
|||
if (auto resolvedPath = resolveRelativePath()) {
|
||||
return readFlake(state, ref, ref, ref, *resolvedPath, inputAttrPath);
|
||||
} else {
|
||||
return getFlake(state, ref, useRegistries, inputAttrPath, true);
|
||||
return getFlake(
|
||||
state,
|
||||
ref,
|
||||
useRegistriesInputs,
|
||||
inputAttrPath,
|
||||
true);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -660,6 +672,29 @@ LockedFlake lockFlake(
|
|||
use --no-write-lock-file. */
|
||||
auto ref = (input2.ref && explicitCliOverrides.contains(inputAttrPath)) ? *input2.ref : *input.ref;
|
||||
|
||||
/* Warn against the use of indirect flakerefs
|
||||
(but only at top-level since we don't want
|
||||
to annoy users about flakes that are not
|
||||
under their control). */
|
||||
auto warnRegistry = [&](const FlakeRef & resolvedRef)
|
||||
{
|
||||
if (inputAttrPath.size() == 1 && !input.ref->input.isDirect()) {
|
||||
std::ostringstream s;
|
||||
printLiteralString(s, resolvedRef.to_string());
|
||||
warn(
|
||||
"Flake input '%1%' uses the flake registry. "
|
||||
"Using the registry in flake inputs is deprecated in Determinate Nix. "
|
||||
"To make your flake future-proof, add the following to '%2%':\n"
|
||||
"\n"
|
||||
" inputs.%1%.url = %3%;\n"
|
||||
"\n"
|
||||
"For more information, see: https://github.com/DeterminateSystems/nix-src/issues/37",
|
||||
inputAttrPathS,
|
||||
flake.path,
|
||||
s.str());
|
||||
}
|
||||
};
|
||||
|
||||
if (input.isFlake) {
|
||||
auto inputFlake = getInputFlake(*input.ref);
|
||||
|
||||
|
|
@ -691,6 +726,8 @@ LockedFlake lockFlake(
|
|||
oldLock ? followsPrefix : inputAttrPath,
|
||||
inputFlake.path,
|
||||
false);
|
||||
|
||||
warnRegistry(inputFlake.resolvedRef);
|
||||
}
|
||||
|
||||
else {
|
||||
|
|
@ -700,10 +737,13 @@ LockedFlake lockFlake(
|
|||
if (auto resolvedPath = resolveRelativePath()) {
|
||||
return {*resolvedPath, *input.ref};
|
||||
} else {
|
||||
auto cachedInput = state.inputCache->getAccessor(state.store, input.ref->input, useRegistries);
|
||||
auto cachedInput = state.inputCache->getAccessor(state.store, input.ref->input, useRegistriesTop);
|
||||
|
||||
auto resolvedRef = FlakeRef(std::move(cachedInput.resolvedInput), input.ref->subdir);
|
||||
auto lockedRef = FlakeRef(std::move(cachedInput.lockedInput), input.ref->subdir);
|
||||
|
||||
warnRegistry(resolvedRef);
|
||||
|
||||
return {
|
||||
state.storePath(state.mountInput(lockedRef.input, input.ref->input, cachedInput.accessor, true)),
|
||||
lockedRef
|
||||
|
|
@ -817,7 +857,11 @@ LockedFlake lockFlake(
|
|||
repo, so we should re-read it. FIXME: we could
|
||||
also just clear the 'rev' field... */
|
||||
auto prevLockedRef = flake.lockedRef;
|
||||
flake = getFlake(state, topRef, useRegistries, lockFlags.requireLockable);
|
||||
flake = getFlake(
|
||||
state,
|
||||
topRef,
|
||||
useRegistriesTop,
|
||||
lockFlags.requireLockable);
|
||||
|
||||
if (lockFlags.commitLockFile &&
|
||||
flake.lockedRef.input.getRev() &&
|
||||
|
|
@ -37,9 +37,9 @@ std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef)
|
|||
|
||||
FlakeRef FlakeRef::resolve(
|
||||
ref<Store> store,
|
||||
const fetchers::RegistryFilter & filter) const
|
||||
fetchers::UseRegistries useRegistries) const
|
||||
{
|
||||
auto [input2, extraAttrs] = lookupInRegistries(store, input, filter);
|
||||
auto [input2, extraAttrs] = lookupInRegistries(store, input, useRegistries);
|
||||
return FlakeRef(std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir));
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ struct Flake
|
|||
Flake getFlake(
|
||||
EvalState & state,
|
||||
const FlakeRef & flakeRef,
|
||||
bool useRegistries,
|
||||
fetchers::UseRegistries useRegistries,
|
||||
bool requireLockable = true);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ struct FlakeRef
|
|||
|
||||
FlakeRef resolve(
|
||||
ref<Store> store,
|
||||
const fetchers::RegistryFilter & filter = {}) const;
|
||||
fetchers::UseRegistries useRegistries = fetchers::UseRegistries::All) const;
|
||||
|
||||
static FlakeRef fromAttrs(
|
||||
const fetchers::Settings & fetchSettings,
|
||||
|
|
|
|||
|
|
@ -39,13 +39,13 @@ foreach header : [
|
|||
endforeach
|
||||
|
||||
sources = files(
|
||||
'flake/config.cc',
|
||||
'flake/flake.cc',
|
||||
'flake/flakeref.cc',
|
||||
'flake/lockfile.cc',
|
||||
'flake/flake-primops.cc',
|
||||
'flake/settings.cc',
|
||||
'flake/url-name.cc',
|
||||
'config.cc',
|
||||
'flake.cc',
|
||||
'flakeref.cc',
|
||||
'lockfile.cc',
|
||||
'flake-primops.cc',
|
||||
'settings.cc',
|
||||
'url-name.cc',
|
||||
)
|
||||
|
||||
subdir('include/nix/flake')
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "nix/util/file-content-address.hh"
|
||||
|
|
@ -26,8 +27,11 @@ TEST(FileSerialisationMethod, testRoundTripPrintParse_2) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(FileSerialisationMethod, testParseFileSerialisationMethodOptException) {
|
||||
EXPECT_THROW(parseFileSerialisationMethod("narwhal"), UsageError);
|
||||
TEST(FileSerialisationMethod, testParseFileSerialisationMethodOptException)
|
||||
{
|
||||
EXPECT_THAT(
|
||||
[]() { parseFileSerialisationMethod("narwhal"); },
|
||||
testing::ThrowsMessage<UsageError>(testing::HasSubstr("narwhal")));
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
|
|
@ -54,8 +58,11 @@ TEST(FileIngestionMethod, testRoundTripPrintParse_2) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(FileIngestionMethod, testParseFileIngestionMethodOptException) {
|
||||
EXPECT_THROW(parseFileIngestionMethod("narwhal"), UsageError);
|
||||
TEST(FileIngestionMethod, testParseFileIngestionMethodOptException)
|
||||
{
|
||||
EXPECT_THAT(
|
||||
[]() { parseFileIngestionMethod("narwhal"); },
|
||||
testing::ThrowsMessage<UsageError>(testing::HasSubstr("narwhal")));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
#include "nix/util/util.hh"
|
||||
#include "nix/util/monitor-fd.hh"
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <gtest/gtest.h>
|
||||
# include "nix/util/util.hh"
|
||||
# include "nix/util/monitor-fd.hh"
|
||||
|
||||
# include <sys/file.h>
|
||||
# include <gtest/gtest.h>
|
||||
|
||||
namespace nix {
|
||||
TEST(MonitorFdHup, shouldNotBlock)
|
||||
|
|
@ -16,3 +18,5 @@ TEST(MonitorFdHup, shouldNotBlock)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ FileSerialisationMethod parseFileSerialisationMethod(std::string_view input)
|
|||
if (ret)
|
||||
return *ret;
|
||||
else
|
||||
throw UsageError("Unknown file serialiation method '%s', expect `flat` or `nar`");
|
||||
throw UsageError("Unknown file serialiation method '%s', expect `flat` or `nar`", input);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ FileIngestionMethod parseFileIngestionMethod(std::string_view input)
|
|||
if (ret)
|
||||
return static_cast<FileIngestionMethod>(*ret);
|
||||
else
|
||||
throw UsageError("Unknown file ingestion method '%s', expect `flat`, `nar`, or `git`");
|
||||
throw UsageError("Unknown file ingestion method '%s', expect `flat`, `nar`, or `git`", input);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ Path canonPath(PathView path, bool resolveSymlinks)
|
|||
(std::string & result, std::string_view & remaining) {
|
||||
if (resolveSymlinks && fs::is_symlink(result)) {
|
||||
if (++followCount >= maxFollow)
|
||||
throw Error("infinite symlink recursion in path '%0%'", remaining);
|
||||
throw Error("infinite symlink recursion in path '%1%'", remaining);
|
||||
remaining = (temp = concatStrings(readLink(result), remaining));
|
||||
if (isAbsolute(remaining)) {
|
||||
/* restart for symlinks pointing to absolute path */
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ void parseTree(
|
|||
RawMode rawMode = std::stoi(perms, 0, 8);
|
||||
auto modeOpt = decodeMode(rawMode);
|
||||
if (!modeOpt)
|
||||
throw Error("Unknown Git permission: %o", perms);
|
||||
throw Error("Unknown Git permission: %o", rawMode);
|
||||
auto mode = std::move(*modeOpt);
|
||||
|
||||
std::string name = getStringUntil(source, '\0');
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ static int childEntry(void * arg)
|
|||
|
||||
pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
|
||||
{
|
||||
auto newLogger = makeSimpleLogger();
|
||||
ChildWrapperFunction wrapper = [&] {
|
||||
if (!options.allowVfork) {
|
||||
/* Set a simple logger, while releasing (not destroying)
|
||||
|
|
@ -210,7 +211,7 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
|
|||
~ProgressBar() tries to join a thread that doesn't
|
||||
exist. */
|
||||
logger.release();
|
||||
logger = makeSimpleLogger();
|
||||
logger = std::move(newLogger);
|
||||
}
|
||||
try {
|
||||
#ifdef __linux__
|
||||
|
|
|
|||
|
|
@ -164,6 +164,11 @@ static void update(const StringSet & channelNames)
|
|||
|
||||
static int main_nix_channel(int argc, char ** argv)
|
||||
{
|
||||
warn(
|
||||
"nix-channel is deprecated in favor of flakes in Determinate Nix. \
|
||||
See https://zero-to-nix.com for a guide to Nix flakes. \
|
||||
For details and to offer feedback on the deprecation process, see: https://github.com/DeterminateSystems/nix-src/issues/34.");
|
||||
|
||||
{
|
||||
// Figure out the name of the `.nix-channels' file to use
|
||||
auto home = getHome();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "nix/util/config-global.hh"
|
||||
#include "nix/expr/eval.hh"
|
||||
#include "nix/fetchers/fetch-settings.hh"
|
||||
#include "nix/cmd/installable-flake.hh"
|
||||
#include "nix/cmd/command-installable-value.hh"
|
||||
#include "nix/main/common-args.hh"
|
||||
|
|
@ -583,6 +584,11 @@ struct CmdDevelop : Common, MixEnvironment
|
|||
;
|
||||
}
|
||||
|
||||
void preRun(ref<Store> store) override
|
||||
{
|
||||
fetchSettings.warnDirty = false;
|
||||
}
|
||||
|
||||
void run(ref<Store> store, ref<Installable> installable) override
|
||||
{
|
||||
auto [buildEnvironment, gcroot] = getBuildEnvironment(store, installable);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
stdenv,
|
||||
lib,
|
||||
mkMesonExecutable,
|
||||
|
||||
|
|
@ -94,6 +95,11 @@ mkMesonExecutable (finalAttrs: {
|
|||
mesonFlags = [
|
||||
];
|
||||
|
||||
postInstall = lib.optionalString stdenv.hostPlatform.isStatic ''
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
meta = {
|
||||
mainProgram = "nix";
|
||||
platforms = lib.platforms.unix ++ lib.platforms.windows;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue