mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-10 00:08:07 +02:00
No global settings in libnixfetchers
and libnixflake
Progress on #5638
There are still a global fetcher and eval settings, but they are pushed
down into `libnixcmd`, which is a lot less bad a place for this sort of
thing.
Continuing process pioneered in
52bfccf8d8
.
This commit is contained in:
parent
b57c361097
commit
3fc77f281e
50 changed files with 401 additions and 271 deletions
|
@ -132,7 +132,7 @@ ref<EvalState> EvalCommand::getEvalState()
|
||||||
#else
|
#else
|
||||||
std::make_shared<EvalState>(
|
std::make_shared<EvalState>(
|
||||||
#endif
|
#endif
|
||||||
lookupPath, getEvalStore(), evalSettings, getStore())
|
lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore())
|
||||||
;
|
;
|
||||||
|
|
||||||
evalState->repair = repair;
|
evalState->repair = repair;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "fetch-settings.hh"
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
#include "common-eval-args.hh"
|
#include "common-eval-args.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
|
@ -7,6 +8,7 @@
|
||||||
#include "fetchers.hh"
|
#include "fetchers.hh"
|
||||||
#include "registry.hh"
|
#include "registry.hh"
|
||||||
#include "flake/flakeref.hh"
|
#include "flake/flakeref.hh"
|
||||||
|
#include "flake/settings.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "command.hh"
|
#include "command.hh"
|
||||||
#include "tarball.hh"
|
#include "tarball.hh"
|
||||||
|
@ -16,6 +18,10 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
fetchers::Settings fetchSettings;
|
||||||
|
|
||||||
|
static GlobalConfig::Register rFetchSettings(&fetchSettings);
|
||||||
|
|
||||||
EvalSettings evalSettings {
|
EvalSettings evalSettings {
|
||||||
settings.readOnlyMode,
|
settings.readOnlyMode,
|
||||||
{
|
{
|
||||||
|
@ -24,7 +30,7 @@ EvalSettings evalSettings {
|
||||||
[](ref<Store> store, std::string_view rest) {
|
[](ref<Store> store, std::string_view rest) {
|
||||||
experimentalFeatureSettings.require(Xp::Flakes);
|
experimentalFeatureSettings.require(Xp::Flakes);
|
||||||
// FIXME `parseFlakeRef` should take a `std::string_view`.
|
// FIXME `parseFlakeRef` should take a `std::string_view`.
|
||||||
auto flakeRef = parseFlakeRef(std::string { rest }, {}, true, false);
|
auto flakeRef = parseFlakeRef(fetchSettings, std::string { rest }, {}, true, false);
|
||||||
debug("fetching flake search path element '%s''", rest);
|
debug("fetching flake search path element '%s''", rest);
|
||||||
auto storePath = flakeRef.resolve(store).fetchTree(store).first;
|
auto storePath = flakeRef.resolve(store).fetchTree(store).first;
|
||||||
return store->toRealPath(storePath);
|
return store->toRealPath(storePath);
|
||||||
|
@ -35,6 +41,12 @@ EvalSettings evalSettings {
|
||||||
|
|
||||||
static GlobalConfig::Register rEvalSettings(&evalSettings);
|
static GlobalConfig::Register rEvalSettings(&evalSettings);
|
||||||
|
|
||||||
|
|
||||||
|
flake::Settings flakeSettings;
|
||||||
|
|
||||||
|
static GlobalConfig::Register rFlakeSettings(&flakeSettings);
|
||||||
|
|
||||||
|
|
||||||
CompatibilitySettings compatibilitySettings {};
|
CompatibilitySettings compatibilitySettings {};
|
||||||
|
|
||||||
static GlobalConfig::Register rCompatibilitySettings(&compatibilitySettings);
|
static GlobalConfig::Register rCompatibilitySettings(&compatibilitySettings);
|
||||||
|
@ -171,8 +183,8 @@ MixEvalArgs::MixEvalArgs()
|
||||||
.category = category,
|
.category = category,
|
||||||
.labels = {"original-ref", "resolved-ref"},
|
.labels = {"original-ref", "resolved-ref"},
|
||||||
.handler = {[&](std::string _from, std::string _to) {
|
.handler = {[&](std::string _from, std::string _to) {
|
||||||
auto from = parseFlakeRef(_from, absPath("."));
|
auto from = parseFlakeRef(fetchSettings, _from, absPath("."));
|
||||||
auto to = parseFlakeRef(_to, absPath("."));
|
auto to = parseFlakeRef(fetchSettings, _to, absPath("."));
|
||||||
fetchers::Attrs extraAttrs;
|
fetchers::Attrs extraAttrs;
|
||||||
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
|
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
|
||||||
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
|
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
|
||||||
|
@ -230,7 +242,7 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas
|
||||||
|
|
||||||
else if (hasPrefix(s, "flake:")) {
|
else if (hasPrefix(s, "flake:")) {
|
||||||
experimentalFeatureSettings.require(Xp::Flakes);
|
experimentalFeatureSettings.require(Xp::Flakes);
|
||||||
auto flakeRef = parseFlakeRef(std::string(s.substr(6)), {}, true, false);
|
auto flakeRef = parseFlakeRef(fetchSettings, std::string(s.substr(6)), {}, true, false);
|
||||||
auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first;
|
auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first;
|
||||||
return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
|
return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,32 @@
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
class Store;
|
class Store;
|
||||||
|
|
||||||
|
namespace fetchers { struct Settings; }
|
||||||
|
|
||||||
class EvalState;
|
class EvalState;
|
||||||
struct EvalSettings;
|
struct EvalSettings;
|
||||||
struct CompatibilitySettings;
|
struct CompatibilitySettings;
|
||||||
class Bindings;
|
class Bindings;
|
||||||
struct SourcePath;
|
struct SourcePath;
|
||||||
|
|
||||||
|
namespace flake { struct Settings; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Get rid of global setttings variables
|
||||||
|
*/
|
||||||
|
extern fetchers::Settings fetchSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Get rid of global setttings variables
|
* @todo Get rid of global setttings variables
|
||||||
*/
|
*/
|
||||||
extern EvalSettings evalSettings;
|
extern EvalSettings evalSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Get rid of global setttings variables
|
||||||
|
*/
|
||||||
|
extern flake::Settings flakeSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings that control behaviors that have changed since Nix 2.3.
|
* Settings that control behaviors that have changed since Nix 2.3.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -196,7 +196,8 @@ std::shared_ptr<flake::LockedFlake> InstallableFlake::getLockedFlake() const
|
||||||
flake::LockFlags lockFlagsApplyConfig = lockFlags;
|
flake::LockFlags lockFlagsApplyConfig = lockFlags;
|
||||||
// FIXME why this side effect?
|
// FIXME why this side effect?
|
||||||
lockFlagsApplyConfig.applyNixConfig = true;
|
lockFlagsApplyConfig.applyNixConfig = true;
|
||||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlagsApplyConfig));
|
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(
|
||||||
|
flakeSettings, *state, flakeRef, lockFlagsApplyConfig));
|
||||||
}
|
}
|
||||||
return _lockedFlake;
|
return _lockedFlake;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
///@file
|
///@file
|
||||||
|
|
||||||
|
#include "common-eval-args.hh"
|
||||||
#include "installable-value.hh"
|
#include "installable-value.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -78,7 +79,7 @@ struct InstallableFlake : InstallableValue
|
||||||
*/
|
*/
|
||||||
static inline FlakeRef defaultNixpkgsFlakeRef()
|
static inline FlakeRef defaultNixpkgsFlakeRef()
|
||||||
{
|
{
|
||||||
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
|
return FlakeRef::fromAttrs(fetchSettings, {{"type","indirect"}, {"id", "nixpkgs"}});
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<eval_cache::EvalCache> openEvalCache(
|
ref<eval_cache::EvalCache> openEvalCache(
|
||||||
|
|
|
@ -129,7 +129,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
lockFlags.writeLockFile = false;
|
lockFlags.writeLockFile = false;
|
||||||
lockFlags.inputOverrides.insert_or_assign(
|
lockFlags.inputOverrides.insert_or_assign(
|
||||||
flake::parseInputPath(inputPath),
|
flake::parseInputPath(inputPath),
|
||||||
parseFlakeRef(flakeRef, absPath(getCommandBaseDir()), true));
|
parseFlakeRef(fetchSettings, flakeRef, absPath(getCommandBaseDir()), true));
|
||||||
}},
|
}},
|
||||||
.completer = {[&](AddCompletions & completions, size_t n, std::string_view prefix) {
|
.completer = {[&](AddCompletions & completions, size_t n, std::string_view prefix) {
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
|
@ -170,14 +170,15 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
.handler = {[&](std::string flakeRef) {
|
.handler = {[&](std::string flakeRef) {
|
||||||
auto evalState = getEvalState();
|
auto evalState = getEvalState();
|
||||||
auto flake = flake::lockFlake(
|
auto flake = flake::lockFlake(
|
||||||
|
flakeSettings,
|
||||||
*evalState,
|
*evalState,
|
||||||
parseFlakeRef(flakeRef, absPath(getCommandBaseDir())),
|
parseFlakeRef(fetchSettings, flakeRef, absPath(getCommandBaseDir())),
|
||||||
{ .writeLockFile = false });
|
{ .writeLockFile = false });
|
||||||
for (auto & [inputName, input] : flake.lockFile.root->inputs) {
|
for (auto & [inputName, input] : flake.lockFile.root->inputs) {
|
||||||
auto input2 = flake.lockFile.findInput({inputName}); // resolve 'follows' nodes
|
auto input2 = flake.lockFile.findInput({inputName}); // resolve 'follows' nodes
|
||||||
if (auto input3 = std::dynamic_pointer_cast<const flake::LockedNode>(input2)) {
|
if (auto input3 = std::dynamic_pointer_cast<const flake::LockedNode>(input2)) {
|
||||||
overrideRegistry(
|
overrideRegistry(
|
||||||
fetchers::Input::fromAttrs({{"type","indirect"}, {"id", inputName}}),
|
fetchers::Input::fromAttrs(fetchSettings, {{"type","indirect"}, {"id", inputName}}),
|
||||||
input3->lockedRef.input,
|
input3->lockedRef.input,
|
||||||
{});
|
{});
|
||||||
}
|
}
|
||||||
|
@ -338,10 +339,11 @@ void completeFlakeRefWithFragment(
|
||||||
auto flakeRefS = std::string(prefix.substr(0, hash));
|
auto flakeRefS = std::string(prefix.substr(0, hash));
|
||||||
|
|
||||||
// TODO: ideally this would use the command base directory instead of assuming ".".
|
// TODO: ideally this would use the command base directory instead of assuming ".".
|
||||||
auto flakeRef = parseFlakeRef(expandTilde(flakeRefS), absPath("."));
|
auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), absPath("."));
|
||||||
|
|
||||||
auto evalCache = openEvalCache(*evalState,
|
auto evalCache = openEvalCache(*evalState,
|
||||||
std::make_shared<flake::LockedFlake>(lockFlake(*evalState, flakeRef, lockFlags)));
|
std::make_shared<flake::LockedFlake>(lockFlake(
|
||||||
|
flakeSettings, *evalState, flakeRef, lockFlags)));
|
||||||
|
|
||||||
auto root = evalCache->getRoot();
|
auto root = evalCache->getRoot();
|
||||||
|
|
||||||
|
@ -403,7 +405,7 @@ void completeFlakeRef(AddCompletions & completions, ref<Store> store, std::strin
|
||||||
Args::completeDir(completions, 0, prefix);
|
Args::completeDir(completions, 0, prefix);
|
||||||
|
|
||||||
/* Look for registry entries that match the prefix. */
|
/* Look for registry entries that match the prefix. */
|
||||||
for (auto & registry : fetchers::getRegistries(store)) {
|
for (auto & registry : fetchers::getRegistries(fetchSettings, store)) {
|
||||||
for (auto & entry : registry->entries) {
|
for (auto & entry : registry->entries) {
|
||||||
auto from = entry.from.to_string();
|
auto from = entry.from.to_string();
|
||||||
if (!hasPrefix(prefix, "flake:") && hasPrefix(from, "flake:")) {
|
if (!hasPrefix(prefix, "flake:") && hasPrefix(from, "flake:")) {
|
||||||
|
@ -534,7 +536,8 @@ Installables SourceExprCommand::parseInstallables(
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(std::string { prefix }, absPath(getCommandBaseDir()));
|
auto [flakeRef, fragment] = parseFlakeRefWithFragment(
|
||||||
|
fetchSettings, std::string { prefix }, absPath(getCommandBaseDir()));
|
||||||
result.push_back(make_ref<InstallableFlake>(
|
result.push_back(make_ref<InstallableFlake>(
|
||||||
this,
|
this,
|
||||||
getEvalState(),
|
getEvalState(),
|
||||||
|
@ -851,6 +854,7 @@ std::vector<FlakeRef> RawInstallablesCommand::getFlakeRefsForCompletion()
|
||||||
std::vector<FlakeRef> res;
|
std::vector<FlakeRef> res;
|
||||||
for (auto i : rawInstallables)
|
for (auto i : rawInstallables)
|
||||||
res.push_back(parseFlakeRefWithFragment(
|
res.push_back(parseFlakeRefWithFragment(
|
||||||
|
fetchSettings,
|
||||||
expandTilde(i),
|
expandTilde(i),
|
||||||
absPath(getCommandBaseDir())).first);
|
absPath(getCommandBaseDir())).first);
|
||||||
return res;
|
return res;
|
||||||
|
@ -873,6 +877,7 @@ std::vector<FlakeRef> InstallableCommand::getFlakeRefsForCompletion()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
parseFlakeRefWithFragment(
|
parseFlakeRefWithFragment(
|
||||||
|
fetchSettings,
|
||||||
expandTilde(_installable),
|
expandTilde(_installable),
|
||||||
absPath(getCommandBaseDir())).first
|
absPath(getCommandBaseDir())).first
|
||||||
};
|
};
|
||||||
|
|
|
@ -690,14 +690,14 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
|
||||||
if (flakeRefS.empty())
|
if (flakeRefS.empty())
|
||||||
throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");
|
throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");
|
||||||
|
|
||||||
auto flakeRef = parseFlakeRef(flakeRefS, absPath("."), true);
|
auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, absPath("."), true);
|
||||||
if (evalSettings.pureEval && !flakeRef.input.isLocked())
|
if (evalSettings.pureEval && !flakeRef.input.isLocked())
|
||||||
throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);
|
throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);
|
||||||
|
|
||||||
Value v;
|
Value v;
|
||||||
|
|
||||||
flake::callFlake(*state,
|
flake::callFlake(*state,
|
||||||
flake::lockFlake(*state, flakeRef,
|
flake::lockFlake(flakeSettings, *state, flakeRef,
|
||||||
flake::LockFlags {
|
flake::LockFlags {
|
||||||
.updateLockFile = false,
|
.updateLockFile = false,
|
||||||
.useRegistries = !evalSettings.pureEval,
|
.useRegistries = !evalSettings.pureEval,
|
||||||
|
|
|
@ -15,7 +15,7 @@ libexprc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \
|
||||||
$(INCLUDE_libstore) $(INCLUDE_libstorec) \
|
$(INCLUDE_libstore) $(INCLUDE_libstorec) \
|
||||||
$(INCLUDE_libexpr) $(INCLUDE_libexprc)
|
$(INCLUDE_libexpr) $(INCLUDE_libexprc)
|
||||||
|
|
||||||
libexprc_LIBS = libutil libutilc libstore libstorec libexpr
|
libexprc_LIBS = libutil libutilc libstore libstorec libfetchers libexpr
|
||||||
|
|
||||||
libexprc_LDFLAGS += $(THREAD_LDFLAGS)
|
libexprc_LDFLAGS += $(THREAD_LDFLAGS)
|
||||||
|
|
||||||
|
|
|
@ -112,12 +112,14 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c
|
||||||
static_cast<std::align_val_t>(alignof(EvalState)));
|
static_cast<std::align_val_t>(alignof(EvalState)));
|
||||||
auto * p2 = static_cast<EvalState *>(p);
|
auto * p2 = static_cast<EvalState *>(p);
|
||||||
new (p) EvalState {
|
new (p) EvalState {
|
||||||
|
.fetchSettings = nix::fetchers::Settings{},
|
||||||
.settings = nix::EvalSettings{
|
.settings = nix::EvalSettings{
|
||||||
nix::settings.readOnlyMode,
|
nix::settings.readOnlyMode,
|
||||||
},
|
},
|
||||||
.state = nix::EvalState(
|
.state = nix::EvalState(
|
||||||
nix::LookupPath::parse(lookupPath),
|
nix::LookupPath::parse(lookupPath),
|
||||||
store->ptr,
|
store->ptr,
|
||||||
|
p2->fetchSettings,
|
||||||
p2->settings),
|
p2->settings),
|
||||||
};
|
};
|
||||||
loadConfFile(p2->settings);
|
loadConfFile(p2->settings);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef NIX_API_EXPR_INTERNAL_H
|
#ifndef NIX_API_EXPR_INTERNAL_H
|
||||||
#define NIX_API_EXPR_INTERNAL_H
|
#define NIX_API_EXPR_INTERNAL_H
|
||||||
|
|
||||||
|
#include "fetch-settings.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
#include "attr-set.hh"
|
#include "attr-set.hh"
|
||||||
|
@ -8,6 +9,7 @@
|
||||||
|
|
||||||
struct EvalState
|
struct EvalState
|
||||||
{
|
{
|
||||||
|
nix::fetchers::Settings fetchSettings;
|
||||||
nix::EvalSettings settings;
|
nix::EvalSettings settings;
|
||||||
nix::EvalState state;
|
nix::EvalState state;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
#include "config-global.hh"
|
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "profiles.hh"
|
#include "profiles.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
|
|
@ -217,9 +217,11 @@ static constexpr size_t BASE_ENV_SIZE = 128;
|
||||||
EvalState::EvalState(
|
EvalState::EvalState(
|
||||||
const LookupPath & _lookupPath,
|
const LookupPath & _lookupPath,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const EvalSettings & settings,
|
const EvalSettings & settings,
|
||||||
std::shared_ptr<Store> buildStore)
|
std::shared_ptr<Store> buildStore)
|
||||||
: settings{settings}
|
: fetchSettings{fetchSettings}
|
||||||
|
, settings{settings}
|
||||||
, sWith(symbols.create("<with>"))
|
, sWith(symbols.create("<with>"))
|
||||||
, sOutPath(symbols.create("outPath"))
|
, sOutPath(symbols.create("outPath"))
|
||||||
, sDrvPath(symbols.create("drvPath"))
|
, sDrvPath(symbols.create("drvPath"))
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace nix {
|
||||||
constexpr size_t maxPrimOpArity = 8;
|
constexpr size_t maxPrimOpArity = 8;
|
||||||
|
|
||||||
class Store;
|
class Store;
|
||||||
|
namespace fetchers { struct Settings; }
|
||||||
struct EvalSettings;
|
struct EvalSettings;
|
||||||
class EvalState;
|
class EvalState;
|
||||||
class StorePath;
|
class StorePath;
|
||||||
|
@ -43,7 +44,7 @@ namespace eval_cache {
|
||||||
/**
|
/**
|
||||||
* Function that implements a primop.
|
* Function that implements a primop.
|
||||||
*/
|
*/
|
||||||
typedef void (* PrimOpFun) (EvalState & state, const PosIdx pos, Value * * args, Value & v);
|
using PrimOpFun = void(EvalState & state, const PosIdx pos, Value * * args, Value & v);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Info about a primitive operation, and its implementation
|
* Info about a primitive operation, and its implementation
|
||||||
|
@ -84,7 +85,7 @@ struct PrimOp
|
||||||
/**
|
/**
|
||||||
* Implementation of the primop.
|
* Implementation of the primop.
|
||||||
*/
|
*/
|
||||||
std::function<std::remove_pointer<PrimOpFun>::type> fun;
|
std::function<PrimOpFun> fun;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional experimental for this to be gated on.
|
* Optional experimental for this to be gated on.
|
||||||
|
@ -162,6 +163,7 @@ struct DebugTrace {
|
||||||
class EvalState : public std::enable_shared_from_this<EvalState>
|
class EvalState : public std::enable_shared_from_this<EvalState>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
const fetchers::Settings & fetchSettings;
|
||||||
const EvalSettings & settings;
|
const EvalSettings & settings;
|
||||||
SymbolTable symbols;
|
SymbolTable symbols;
|
||||||
PosTable positions;
|
PosTable positions;
|
||||||
|
@ -353,6 +355,7 @@ public:
|
||||||
EvalState(
|
EvalState(
|
||||||
const LookupPath & _lookupPath,
|
const LookupPath & _lookupPath,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const EvalSettings & settings,
|
const EvalSettings & settings,
|
||||||
std::shared_ptr<Store> buildStore = nullptr);
|
std::shared_ptr<Store> buildStore = nullptr);
|
||||||
~EvalState();
|
~EvalState();
|
||||||
|
|
|
@ -62,7 +62,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
|
||||||
attrs.insert_or_assign("name", std::string(name));
|
attrs.insert_or_assign("name", std::string(name));
|
||||||
if (ref) attrs.insert_or_assign("ref", *ref);
|
if (ref) attrs.insert_or_assign("ref", *ref);
|
||||||
if (rev) attrs.insert_or_assign("rev", rev->gitRev());
|
if (rev) attrs.insert_or_assign("rev", rev->gitRev());
|
||||||
auto input = fetchers::Input::fromAttrs(std::move(attrs));
|
auto input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs));
|
||||||
|
|
||||||
auto [storePath, input2] = input.fetchToStore(state.store);
|
auto [storePath, input2] = input.fetchToStore(state.store);
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ static void fetchTree(
|
||||||
Value & v,
|
Value & v,
|
||||||
const FetchTreeParams & params = FetchTreeParams{}
|
const FetchTreeParams & params = FetchTreeParams{}
|
||||||
) {
|
) {
|
||||||
fetchers::Input input;
|
fetchers::Input input { state.fetchSettings };
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
std::optional<std::string> type;
|
std::optional<std::string> type;
|
||||||
if (params.isFetchGit) type = "git";
|
if (params.isFetchGit) type = "git";
|
||||||
|
@ -148,7 +148,7 @@ static void fetchTree(
|
||||||
"attribute 'name' isn’t supported in call to 'fetchTree'"
|
"attribute 'name' isn’t supported in call to 'fetchTree'"
|
||||||
).atPos(pos).debugThrow();
|
).atPos(pos).debugThrow();
|
||||||
|
|
||||||
input = fetchers::Input::fromAttrs(std::move(attrs));
|
input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs));
|
||||||
} else {
|
} else {
|
||||||
auto url = state.coerceToString(pos, *args[0], context,
|
auto url = state.coerceToString(pos, *args[0], context,
|
||||||
"while evaluating the first argument passed to the fetcher",
|
"while evaluating the first argument passed to the fetcher",
|
||||||
|
@ -161,13 +161,13 @@ static void fetchTree(
|
||||||
if (!attrs.contains("exportIgnore") && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) {
|
if (!attrs.contains("exportIgnore") && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) {
|
||||||
attrs.emplace("exportIgnore", Explicit<bool>{true});
|
attrs.emplace("exportIgnore", Explicit<bool>{true});
|
||||||
}
|
}
|
||||||
input = fetchers::Input::fromAttrs(std::move(attrs));
|
input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs));
|
||||||
} else {
|
} else {
|
||||||
if (!experimentalFeatureSettings.isEnabled(Xp::Flakes))
|
if (!experimentalFeatureSettings.isEnabled(Xp::Flakes))
|
||||||
state.error<EvalError>(
|
state.error<EvalError>(
|
||||||
"passing a string argument to 'fetchTree' requires the 'flakes' experimental feature"
|
"passing a string argument to 'fetchTree' requires the 'flakes' experimental feature"
|
||||||
).atPos(pos).debugThrow();
|
).atPos(pos).debugThrow();
|
||||||
input = fetchers::Input::fromURL(url);
|
input = fetchers::Input::fromURL(state.fetchSettings, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
#include "fetch-settings.hh"
|
#include "fetch-settings.hh"
|
||||||
#include "config-global.hh"
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix::fetchers {
|
||||||
|
|
||||||
FetchSettings::FetchSettings()
|
Settings::Settings()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchSettings fetchSettings;
|
|
||||||
|
|
||||||
static GlobalConfig::Register rFetchSettings(&fetchSettings);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix::fetchers {
|
||||||
|
|
||||||
struct FetchSettings : public Config
|
struct Settings : public Config
|
||||||
{
|
{
|
||||||
FetchSettings();
|
Settings();
|
||||||
|
|
||||||
Setting<StringMap> accessTokens{this, {}, "access-tokens",
|
Setting<StringMap> accessTokens{this, {}, "access-tokens",
|
||||||
R"(
|
R"(
|
||||||
|
@ -84,9 +84,14 @@ struct FetchSettings : public Config
|
||||||
`narHash` attribute is specified,
|
`narHash` attribute is specified,
|
||||||
e.g. `github:NixOS/patchelf/7c2f768bf9601268a4e71c2ebe91e2011918a70f?narHash=sha256-PPXqKY2hJng4DBVE0I4xshv/vGLUskL7jl53roB8UdU%3D`.
|
e.g. `github:NixOS/patchelf/7c2f768bf9601268a4e71c2ebe91e2011918a70f?narHash=sha256-PPXqKY2hJng4DBVE0I4xshv/vGLUskL7jl53roB8UdU%3D`.
|
||||||
)"};
|
)"};
|
||||||
|
|
||||||
|
Setting<std::string> flakeRegistry{this, "https://channels.nixos.org/flake-registry.json", "flake-registry",
|
||||||
|
R"(
|
||||||
|
Path or URI of the global flake registry.
|
||||||
|
|
||||||
|
When empty, disables the global flake registry.
|
||||||
|
)",
|
||||||
|
{}, true, Xp::Flakes};
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: don't use a global variable.
|
|
||||||
extern FetchSettings fetchSettings;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,11 @@ nlohmann::json dumpRegisterInputSchemeInfo() {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Input Input::fromURL(const std::string & url, bool requireTree)
|
Input Input::fromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const std::string & url, bool requireTree)
|
||||||
{
|
{
|
||||||
return fromURL(parseURL(url), requireTree);
|
return fromURL(settings, parseURL(url), requireTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fixupInput(Input & input)
|
static void fixupInput(Input & input)
|
||||||
|
@ -49,10 +51,12 @@ static void fixupInput(Input & input)
|
||||||
input.getLastModified();
|
input.getLastModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
Input Input::fromURL(const ParsedURL & url, bool requireTree)
|
Input Input::fromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const ParsedURL & url, bool requireTree)
|
||||||
{
|
{
|
||||||
for (auto & [_, inputScheme] : *inputSchemes) {
|
for (auto & [_, inputScheme] : *inputSchemes) {
|
||||||
auto res = inputScheme->inputFromURL(url, requireTree);
|
auto res = inputScheme->inputFromURL(settings, url, requireTree);
|
||||||
if (res) {
|
if (res) {
|
||||||
experimentalFeatureSettings.require(inputScheme->experimentalFeature());
|
experimentalFeatureSettings.require(inputScheme->experimentalFeature());
|
||||||
res->scheme = inputScheme;
|
res->scheme = inputScheme;
|
||||||
|
@ -64,7 +68,7 @@ Input Input::fromURL(const ParsedURL & url, bool requireTree)
|
||||||
throw Error("input '%s' is unsupported", url.url);
|
throw Error("input '%s' is unsupported", url.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
Input Input::fromAttrs(Attrs && attrs)
|
Input Input::fromAttrs(const Settings & settings, Attrs && attrs)
|
||||||
{
|
{
|
||||||
auto schemeName = ({
|
auto schemeName = ({
|
||||||
auto schemeNameOpt = maybeGetStrAttr(attrs, "type");
|
auto schemeNameOpt = maybeGetStrAttr(attrs, "type");
|
||||||
|
@ -78,7 +82,7 @@ Input Input::fromAttrs(Attrs && attrs)
|
||||||
// but not all of them. Doing this is to support those other
|
// but not all of them. Doing this is to support those other
|
||||||
// operations which are supposed to be robust on
|
// operations which are supposed to be robust on
|
||||||
// unknown/uninterpretable inputs.
|
// unknown/uninterpretable inputs.
|
||||||
Input input;
|
Input input { settings };
|
||||||
input.attrs = attrs;
|
input.attrs = attrs;
|
||||||
fixupInput(input);
|
fixupInput(input);
|
||||||
return input;
|
return input;
|
||||||
|
@ -99,7 +103,7 @@ Input Input::fromAttrs(Attrs && attrs)
|
||||||
if (name != "type" && allowedAttrs.count(name) == 0)
|
if (name != "type" && allowedAttrs.count(name) == 0)
|
||||||
throw Error("input attribute '%s' not supported by scheme '%s'", name, schemeName);
|
throw Error("input attribute '%s' not supported by scheme '%s'", name, schemeName);
|
||||||
|
|
||||||
auto res = inputScheme->inputFromAttrs(attrs);
|
auto res = inputScheme->inputFromAttrs(settings, attrs);
|
||||||
if (!res) return raw();
|
if (!res) return raw();
|
||||||
res->scheme = inputScheme;
|
res->scheme = inputScheme;
|
||||||
fixupInput(*res);
|
fixupInput(*res);
|
||||||
|
|
|
@ -17,6 +17,8 @@ namespace nix::fetchers {
|
||||||
|
|
||||||
struct InputScheme;
|
struct InputScheme;
|
||||||
|
|
||||||
|
struct Settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Input` object is generated by a specific fetcher, based on
|
* The `Input` object is generated by a specific fetcher, based on
|
||||||
* user-supplied information, and contains
|
* user-supplied information, and contains
|
||||||
|
@ -28,6 +30,12 @@ struct Input
|
||||||
{
|
{
|
||||||
friend struct InputScheme;
|
friend struct InputScheme;
|
||||||
|
|
||||||
|
const Settings * settings;
|
||||||
|
|
||||||
|
Input(const Settings & settings)
|
||||||
|
: settings{&settings}
|
||||||
|
{ }
|
||||||
|
|
||||||
std::shared_ptr<InputScheme> scheme; // note: can be null
|
std::shared_ptr<InputScheme> scheme; // note: can be null
|
||||||
Attrs attrs;
|
Attrs attrs;
|
||||||
|
|
||||||
|
@ -42,16 +50,22 @@ public:
|
||||||
*
|
*
|
||||||
* The URL indicate which sort of fetcher, and provides information to that fetcher.
|
* The URL indicate which sort of fetcher, and provides information to that fetcher.
|
||||||
*/
|
*/
|
||||||
static Input fromURL(const std::string & url, bool requireTree = true);
|
static Input fromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const std::string & url, bool requireTree = true);
|
||||||
|
|
||||||
static Input fromURL(const ParsedURL & url, bool requireTree = true);
|
static Input fromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const ParsedURL & url, bool requireTree = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an `Input` from a an `Attrs`.
|
* Create an `Input` from a an `Attrs`.
|
||||||
*
|
*
|
||||||
* The URL indicate which sort of fetcher, and provides information to that fetcher.
|
* The URL indicate which sort of fetcher, and provides information to that fetcher.
|
||||||
*/
|
*/
|
||||||
static Input fromAttrs(Attrs && attrs);
|
static Input fromAttrs(
|
||||||
|
const Settings & settings,
|
||||||
|
Attrs && attrs);
|
||||||
|
|
||||||
ParsedURL toURL() const;
|
ParsedURL toURL() const;
|
||||||
|
|
||||||
|
@ -146,9 +160,13 @@ struct InputScheme
|
||||||
virtual ~InputScheme()
|
virtual ~InputScheme()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const = 0;
|
virtual std::optional<Input> inputFromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const ParsedURL & url, bool requireTree) const = 0;
|
||||||
|
|
||||||
virtual std::optional<Input> inputFromAttrs(const Attrs & attrs) const = 0;
|
virtual std::optional<Input> inputFromAttrs(
|
||||||
|
const Settings & settings,
|
||||||
|
const Attrs & attrs) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What is the name of the scheme?
|
* What is the name of the scheme?
|
||||||
|
|
|
@ -164,7 +164,9 @@ static const Hash nullRev{HashAlgorithm::SHA1};
|
||||||
|
|
||||||
struct GitInputScheme : InputScheme
|
struct GitInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
std::optional<Input> inputFromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const ParsedURL & url, bool requireTree) const override
|
||||||
{
|
{
|
||||||
if (url.scheme != "git" &&
|
if (url.scheme != "git" &&
|
||||||
url.scheme != "git+http" &&
|
url.scheme != "git+http" &&
|
||||||
|
@ -190,7 +192,7 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
attrs.emplace("url", url2.to_string());
|
attrs.emplace("url", url2.to_string());
|
||||||
|
|
||||||
return inputFromAttrs(attrs);
|
return inputFromAttrs(settings, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -222,7 +224,9 @@ struct GitInputScheme : InputScheme
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
std::optional<Input> inputFromAttrs(
|
||||||
|
const Settings & settings,
|
||||||
|
const Attrs & attrs) const override
|
||||||
{
|
{
|
||||||
for (auto & [name, _] : attrs)
|
for (auto & [name, _] : attrs)
|
||||||
if (name == "verifyCommit"
|
if (name == "verifyCommit"
|
||||||
|
@ -238,7 +242,7 @@ struct GitInputScheme : InputScheme
|
||||||
throw BadURL("invalid Git branch/tag name '%s'", *ref);
|
throw BadURL("invalid Git branch/tag name '%s'", *ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs = attrs;
|
input.attrs = attrs;
|
||||||
auto url = fixGitURL(getStrAttr(attrs, "url"));
|
auto url = fixGitURL(getStrAttr(attrs, "url"));
|
||||||
parseURL(url);
|
parseURL(url);
|
||||||
|
@ -366,13 +370,13 @@ struct GitInputScheme : InputScheme
|
||||||
/* URL of the repo, or its path if isLocal. Never a `file` URL. */
|
/* URL of the repo, or its path if isLocal. Never a `file` URL. */
|
||||||
std::string url;
|
std::string url;
|
||||||
|
|
||||||
void warnDirty() const
|
void warnDirty(const Settings & settings) const
|
||||||
{
|
{
|
||||||
if (workdirInfo.isDirty) {
|
if (workdirInfo.isDirty) {
|
||||||
if (!fetchSettings.allowDirty)
|
if (!settings.allowDirty)
|
||||||
throw Error("Git tree '%s' is dirty", url);
|
throw Error("Git tree '%s' is dirty", url);
|
||||||
|
|
||||||
if (fetchSettings.warnDirty)
|
if (settings.warnDirty)
|
||||||
warn("Git tree '%s' is dirty", url);
|
warn("Git tree '%s' is dirty", url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,7 +657,7 @@ struct GitInputScheme : InputScheme
|
||||||
attrs.insert_or_assign("exportIgnore", Explicit<bool>{ exportIgnore });
|
attrs.insert_or_assign("exportIgnore", Explicit<bool>{ exportIgnore });
|
||||||
attrs.insert_or_assign("submodules", Explicit<bool>{ true });
|
attrs.insert_or_assign("submodules", Explicit<bool>{ true });
|
||||||
attrs.insert_or_assign("allRefs", Explicit<bool>{ true });
|
attrs.insert_or_assign("allRefs", Explicit<bool>{ true });
|
||||||
auto submoduleInput = fetchers::Input::fromAttrs(std::move(attrs));
|
auto submoduleInput = fetchers::Input::fromAttrs(*input.settings, std::move(attrs));
|
||||||
auto [submoduleAccessor, submoduleInput2] =
|
auto [submoduleAccessor, submoduleInput2] =
|
||||||
submoduleInput.getAccessor(store);
|
submoduleInput.getAccessor(store);
|
||||||
submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»");
|
submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»");
|
||||||
|
@ -711,7 +715,7 @@ struct GitInputScheme : InputScheme
|
||||||
// TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out
|
// TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out
|
||||||
// attrs.insert_or_assign("allRefs", Explicit<bool>{ true });
|
// attrs.insert_or_assign("allRefs", Explicit<bool>{ true });
|
||||||
|
|
||||||
auto submoduleInput = fetchers::Input::fromAttrs(std::move(attrs));
|
auto submoduleInput = fetchers::Input::fromAttrs(*input.settings, std::move(attrs));
|
||||||
auto [submoduleAccessor, submoduleInput2] =
|
auto [submoduleAccessor, submoduleInput2] =
|
||||||
submoduleInput.getAccessor(store);
|
submoduleInput.getAccessor(store);
|
||||||
submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»");
|
submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»");
|
||||||
|
@ -743,7 +747,7 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
verifyCommit(input, repo);
|
verifyCommit(input, repo);
|
||||||
} else {
|
} else {
|
||||||
repoInfo.warnDirty();
|
repoInfo.warnDirty(*input.settings);
|
||||||
|
|
||||||
if (repoInfo.workdirInfo.headRev) {
|
if (repoInfo.workdirInfo.headRev) {
|
||||||
input.attrs.insert_or_assign("dirtyRev",
|
input.attrs.insert_or_assign("dirtyRev",
|
||||||
|
|
|
@ -31,7 +31,9 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
virtual std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const = 0;
|
virtual std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const = 0;
|
||||||
|
|
||||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
std::optional<Input> inputFromURL(
|
||||||
|
const fetchers::Settings & settings,
|
||||||
|
const ParsedURL & url, bool requireTree) const override
|
||||||
{
|
{
|
||||||
if (url.scheme != schemeName()) return {};
|
if (url.scheme != schemeName()) return {};
|
||||||
|
|
||||||
|
@ -90,7 +92,7 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
if (ref && rev)
|
if (ref && rev)
|
||||||
throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url.url, *ref, rev->gitRev());
|
throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url.url, *ref, rev->gitRev());
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs.insert_or_assign("type", std::string { schemeName() });
|
input.attrs.insert_or_assign("type", std::string { schemeName() });
|
||||||
input.attrs.insert_or_assign("owner", path[0]);
|
input.attrs.insert_or_assign("owner", path[0]);
|
||||||
input.attrs.insert_or_assign("repo", path[1]);
|
input.attrs.insert_or_assign("repo", path[1]);
|
||||||
|
@ -119,12 +121,14 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
std::optional<Input> inputFromAttrs(
|
||||||
|
const fetchers::Settings & settings,
|
||||||
|
const Attrs & attrs) const override
|
||||||
{
|
{
|
||||||
getStrAttr(attrs, "owner");
|
getStrAttr(attrs, "owner");
|
||||||
getStrAttr(attrs, "repo");
|
getStrAttr(attrs, "repo");
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs = attrs;
|
input.attrs = attrs;
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
@ -168,18 +172,20 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> getAccessToken(const std::string & host) const
|
std::optional<std::string> getAccessToken(const fetchers::Settings & settings, const std::string & host) const
|
||||||
{
|
{
|
||||||
auto tokens = fetchSettings.accessTokens.get();
|
auto tokens = settings.accessTokens.get();
|
||||||
if (auto token = get(tokens, host))
|
if (auto token = get(tokens, host))
|
||||||
return *token;
|
return *token;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Headers makeHeadersWithAuthTokens(const std::string & host) const
|
Headers makeHeadersWithAuthTokens(
|
||||||
|
const fetchers::Settings & settings,
|
||||||
|
const std::string & host) const
|
||||||
{
|
{
|
||||||
Headers headers;
|
Headers headers;
|
||||||
auto accessToken = getAccessToken(host);
|
auto accessToken = getAccessToken(settings, host);
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
auto hdr = accessHeaderFromToken(*accessToken);
|
auto hdr = accessHeaderFromToken(*accessToken);
|
||||||
if (hdr)
|
if (hdr)
|
||||||
|
@ -295,7 +301,7 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
locking. FIXME: in the future, we may want to require a Git
|
locking. FIXME: in the future, we may want to require a Git
|
||||||
tree hash instead of a NAR hash. */
|
tree hash instead of a NAR hash. */
|
||||||
return input.getRev().has_value()
|
return input.getRev().has_value()
|
||||||
&& (fetchSettings.trustTarballsFromGitForges ||
|
&& (input.settings->trustTarballsFromGitForges ||
|
||||||
input.getNarHash().has_value());
|
input.getNarHash().has_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +358,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
||||||
: "https://%s/api/v3/repos/%s/%s/commits/%s",
|
: "https://%s/api/v3/repos/%s/%s/commits/%s",
|
||||||
host, getOwner(input), getRepo(input), *input.getRef());
|
host, getOwner(input), getRepo(input), *input.getRef());
|
||||||
|
|
||||||
Headers headers = makeHeadersWithAuthTokens(host);
|
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||||
|
|
||||||
auto json = nlohmann::json::parse(
|
auto json = nlohmann::json::parse(
|
||||||
readFile(
|
readFile(
|
||||||
|
@ -369,7 +375,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
||||||
{
|
{
|
||||||
auto host = getHost(input);
|
auto host = getHost(input);
|
||||||
|
|
||||||
Headers headers = makeHeadersWithAuthTokens(host);
|
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||||
|
|
||||||
// If we have no auth headers then we default to the public archive
|
// If we have no auth headers then we default to the public archive
|
||||||
// urls so we do not run into rate limits.
|
// urls so we do not run into rate limits.
|
||||||
|
@ -389,7 +395,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
||||||
void clone(const Input & input, const Path & destDir) const override
|
void clone(const Input & input, const Path & destDir) const override
|
||||||
{
|
{
|
||||||
auto host = getHost(input);
|
auto host = getHost(input);
|
||||||
Input::fromURL(fmt("git+https://%s/%s/%s.git",
|
Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s.git",
|
||||||
host, getOwner(input), getRepo(input)))
|
host, getOwner(input), getRepo(input)))
|
||||||
.applyOverrides(input.getRef(), input.getRev())
|
.applyOverrides(input.getRef(), input.getRev())
|
||||||
.clone(destDir);
|
.clone(destDir);
|
||||||
|
@ -426,7 +432,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
||||||
auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/commits?ref_name=%s",
|
auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/commits?ref_name=%s",
|
||||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), *input.getRef());
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), *input.getRef());
|
||||||
|
|
||||||
Headers headers = makeHeadersWithAuthTokens(host);
|
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||||
|
|
||||||
auto json = nlohmann::json::parse(
|
auto json = nlohmann::json::parse(
|
||||||
readFile(
|
readFile(
|
||||||
|
@ -456,7 +462,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
||||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
||||||
input.getRev()->to_string(HashFormat::Base16, false));
|
input.getRev()->to_string(HashFormat::Base16, false));
|
||||||
|
|
||||||
Headers headers = makeHeadersWithAuthTokens(host);
|
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||||
return DownloadUrl { url, headers };
|
return DownloadUrl { url, headers };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,7 +470,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
||||||
{
|
{
|
||||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
||||||
// FIXME: get username somewhere
|
// FIXME: get username somewhere
|
||||||
Input::fromURL(fmt("git+https://%s/%s/%s.git",
|
Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s.git",
|
||||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
||||||
.applyOverrides(input.getRef(), input.getRev())
|
.applyOverrides(input.getRef(), input.getRev())
|
||||||
.clone(destDir);
|
.clone(destDir);
|
||||||
|
@ -496,7 +502,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
|
||||||
auto base_url = fmt("https://%s/%s/%s",
|
auto base_url = fmt("https://%s/%s/%s",
|
||||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"));
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"));
|
||||||
|
|
||||||
Headers headers = makeHeadersWithAuthTokens(host);
|
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||||
|
|
||||||
std::string refUri;
|
std::string refUri;
|
||||||
if (ref == "HEAD") {
|
if (ref == "HEAD") {
|
||||||
|
@ -543,14 +549,14 @@ struct SourceHutInputScheme : GitArchiveInputScheme
|
||||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
||||||
input.getRev()->to_string(HashFormat::Base16, false));
|
input.getRev()->to_string(HashFormat::Base16, false));
|
||||||
|
|
||||||
Headers headers = makeHeadersWithAuthTokens(host);
|
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||||
return DownloadUrl { url, headers };
|
return DownloadUrl { url, headers };
|
||||||
}
|
}
|
||||||
|
|
||||||
void clone(const Input & input, const Path & destDir) const override
|
void clone(const Input & input, const Path & destDir) const override
|
||||||
{
|
{
|
||||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
||||||
Input::fromURL(fmt("git+https://%s/%s/%s",
|
Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s",
|
||||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
||||||
.applyOverrides(input.getRef(), input.getRev())
|
.applyOverrides(input.getRef(), input.getRev())
|
||||||
.clone(destDir);
|
.clone(destDir);
|
||||||
|
|
|
@ -8,7 +8,9 @@ std::regex flakeRegex("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript);
|
||||||
|
|
||||||
struct IndirectInputScheme : InputScheme
|
struct IndirectInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
std::optional<Input> inputFromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const ParsedURL & url, bool requireTree) const override
|
||||||
{
|
{
|
||||||
if (url.scheme != "flake") return {};
|
if (url.scheme != "flake") return {};
|
||||||
|
|
||||||
|
@ -41,7 +43,7 @@ struct IndirectInputScheme : InputScheme
|
||||||
|
|
||||||
// FIXME: forbid query params?
|
// FIXME: forbid query params?
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs.insert_or_assign("type", "indirect");
|
input.attrs.insert_or_assign("type", "indirect");
|
||||||
input.attrs.insert_or_assign("id", id);
|
input.attrs.insert_or_assign("id", id);
|
||||||
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
||||||
|
@ -65,13 +67,15 @@ struct IndirectInputScheme : InputScheme
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
std::optional<Input> inputFromAttrs(
|
||||||
|
const Settings & settings,
|
||||||
|
const Attrs & attrs) const override
|
||||||
{
|
{
|
||||||
auto id = getStrAttr(attrs, "id");
|
auto id = getStrAttr(attrs, "id");
|
||||||
if (!std::regex_match(id, flakeRegex))
|
if (!std::regex_match(id, flakeRegex))
|
||||||
throw BadURL("'%s' is not a valid flake ID", id);
|
throw BadURL("'%s' is not a valid flake ID", id);
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs = attrs;
|
input.attrs = attrs;
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,9 @@ static std::string runHg(const Strings & args, const std::optional<std::string>
|
||||||
|
|
||||||
struct MercurialInputScheme : InputScheme
|
struct MercurialInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
std::optional<Input> inputFromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const ParsedURL & url, bool requireTree) const override
|
||||||
{
|
{
|
||||||
if (url.scheme != "hg+http" &&
|
if (url.scheme != "hg+http" &&
|
||||||
url.scheme != "hg+https" &&
|
url.scheme != "hg+https" &&
|
||||||
|
@ -68,7 +70,7 @@ struct MercurialInputScheme : InputScheme
|
||||||
|
|
||||||
attrs.emplace("url", url2.to_string());
|
attrs.emplace("url", url2.to_string());
|
||||||
|
|
||||||
return inputFromAttrs(attrs);
|
return inputFromAttrs(settings, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view schemeName() const override
|
std::string_view schemeName() const override
|
||||||
|
@ -88,7 +90,9 @@ struct MercurialInputScheme : InputScheme
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
std::optional<Input> inputFromAttrs(
|
||||||
|
const Settings & settings,
|
||||||
|
const Attrs & attrs) const override
|
||||||
{
|
{
|
||||||
parseURL(getStrAttr(attrs, "url"));
|
parseURL(getStrAttr(attrs, "url"));
|
||||||
|
|
||||||
|
@ -97,7 +101,7 @@ struct MercurialInputScheme : InputScheme
|
||||||
throw BadURL("invalid Mercurial branch/tag name '%s'", *ref);
|
throw BadURL("invalid Mercurial branch/tag name '%s'", *ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs = attrs;
|
input.attrs = attrs;
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
@ -182,10 +186,10 @@ struct MercurialInputScheme : InputScheme
|
||||||
/* This is an unclean working tree. So copy all tracked
|
/* This is an unclean working tree. So copy all tracked
|
||||||
files. */
|
files. */
|
||||||
|
|
||||||
if (!fetchSettings.allowDirty)
|
if (!input.settings->allowDirty)
|
||||||
throw Error("Mercurial tree '%s' is unclean", actualUrl);
|
throw Error("Mercurial tree '%s' is unclean", actualUrl);
|
||||||
|
|
||||||
if (fetchSettings.warnDirty)
|
if (input.settings->warnDirty)
|
||||||
warn("Mercurial tree '%s' is unclean", actualUrl);
|
warn("Mercurial tree '%s' is unclean", actualUrl);
|
||||||
|
|
||||||
input.attrs.insert_or_assign("ref", chomp(runHg({ "branch", "-R", actualUrl })));
|
input.attrs.insert_or_assign("ref", chomp(runHg({ "branch", "-R", actualUrl })));
|
||||||
|
|
|
@ -7,14 +7,16 @@ namespace nix::fetchers {
|
||||||
|
|
||||||
struct PathInputScheme : InputScheme
|
struct PathInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
std::optional<Input> inputFromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const ParsedURL & url, bool requireTree) const override
|
||||||
{
|
{
|
||||||
if (url.scheme != "path") return {};
|
if (url.scheme != "path") return {};
|
||||||
|
|
||||||
if (url.authority && *url.authority != "")
|
if (url.authority && *url.authority != "")
|
||||||
throw Error("path URL '%s' should not have an authority ('%s')", url.url, *url.authority);
|
throw Error("path URL '%s' should not have an authority ('%s')", url.url, *url.authority);
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs.insert_or_assign("type", "path");
|
input.attrs.insert_or_assign("type", "path");
|
||||||
input.attrs.insert_or_assign("path", url.path);
|
input.attrs.insert_or_assign("path", url.path);
|
||||||
|
|
||||||
|
@ -54,11 +56,13 @@ struct PathInputScheme : InputScheme
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
std::optional<Input> inputFromAttrs(
|
||||||
|
const Settings & settings,
|
||||||
|
const Attrs & attrs) const override
|
||||||
{
|
{
|
||||||
getStrAttr(attrs, "path");
|
getStrAttr(attrs, "path");
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs = attrs;
|
input.attrs = attrs;
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
#include "fetch-settings.hh"
|
||||||
#include "registry.hh"
|
#include "registry.hh"
|
||||||
#include "tarball.hh"
|
#include "tarball.hh"
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
#include "config-global.hh"
|
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "local-fs-store.hh"
|
#include "local-fs-store.hh"
|
||||||
|
@ -11,12 +11,13 @@
|
||||||
namespace nix::fetchers {
|
namespace nix::fetchers {
|
||||||
|
|
||||||
std::shared_ptr<Registry> Registry::read(
|
std::shared_ptr<Registry> Registry::read(
|
||||||
|
const Settings & settings,
|
||||||
const Path & path, RegistryType type)
|
const Path & path, RegistryType type)
|
||||||
{
|
{
|
||||||
auto registry = std::make_shared<Registry>(type);
|
auto registry = std::make_shared<Registry>(settings, type);
|
||||||
|
|
||||||
if (!pathExists(path))
|
if (!pathExists(path))
|
||||||
return std::make_shared<Registry>(type);
|
return std::make_shared<Registry>(settings, type);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -36,8 +37,8 @@ std::shared_ptr<Registry> Registry::read(
|
||||||
auto exact = i.find("exact");
|
auto exact = i.find("exact");
|
||||||
registry->entries.push_back(
|
registry->entries.push_back(
|
||||||
Entry {
|
Entry {
|
||||||
.from = Input::fromAttrs(jsonToAttrs(i["from"])),
|
.from = Input::fromAttrs(settings, jsonToAttrs(i["from"])),
|
||||||
.to = Input::fromAttrs(std::move(toAttrs)),
|
.to = Input::fromAttrs(settings, std::move(toAttrs)),
|
||||||
.extraAttrs = extraAttrs,
|
.extraAttrs = extraAttrs,
|
||||||
.exact = exact != i.end() && exact.value()
|
.exact = exact != i.end() && exact.value()
|
||||||
});
|
});
|
||||||
|
@ -106,10 +107,10 @@ static Path getSystemRegistryPath()
|
||||||
return settings.nixConfDir + "/registry.json";
|
return settings.nixConfDir + "/registry.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<Registry> getSystemRegistry()
|
static std::shared_ptr<Registry> getSystemRegistry(const Settings & settings)
|
||||||
{
|
{
|
||||||
static auto systemRegistry =
|
static auto systemRegistry =
|
||||||
Registry::read(getSystemRegistryPath(), Registry::System);
|
Registry::read(settings, getSystemRegistryPath(), Registry::System);
|
||||||
return systemRegistry;
|
return systemRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,25 +119,24 @@ Path getUserRegistryPath()
|
||||||
return getConfigDir() + "/nix/registry.json";
|
return getConfigDir() + "/nix/registry.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Registry> getUserRegistry()
|
std::shared_ptr<Registry> getUserRegistry(const Settings & settings)
|
||||||
{
|
{
|
||||||
static auto userRegistry =
|
static auto userRegistry =
|
||||||
Registry::read(getUserRegistryPath(), Registry::User);
|
Registry::read(settings, getUserRegistryPath(), Registry::User);
|
||||||
return userRegistry;
|
return userRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Registry> getCustomRegistry(const Path & p)
|
std::shared_ptr<Registry> getCustomRegistry(const Settings & settings, const Path & p)
|
||||||
{
|
{
|
||||||
static auto customRegistry =
|
static auto customRegistry =
|
||||||
Registry::read(p, Registry::Custom);
|
Registry::read(settings, p, Registry::Custom);
|
||||||
return customRegistry;
|
return customRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<Registry> flagRegistry =
|
std::shared_ptr<Registry> getFlagRegistry(const Settings & settings)
|
||||||
std::make_shared<Registry>(Registry::Flag);
|
|
||||||
|
|
||||||
std::shared_ptr<Registry> getFlagRegistry()
|
|
||||||
{
|
{
|
||||||
|
static auto flagRegistry =
|
||||||
|
std::make_shared<Registry>(settings, Registry::Flag);
|
||||||
return flagRegistry;
|
return flagRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,30 +145,15 @@ void overrideRegistry(
|
||||||
const Input & to,
|
const Input & to,
|
||||||
const Attrs & extraAttrs)
|
const Attrs & extraAttrs)
|
||||||
{
|
{
|
||||||
flagRegistry->add(from, to, extraAttrs);
|
getFlagRegistry(*from.settings)->add(from, to, extraAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RegistrySettings : Config
|
static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, ref<Store> store)
|
||||||
{
|
|
||||||
Setting<std::string> flakeRegistry{this, "https://channels.nixos.org/flake-registry.json", "flake-registry",
|
|
||||||
R"(
|
|
||||||
Path or URI of the global flake registry.
|
|
||||||
|
|
||||||
When empty, disables the global flake registry.
|
|
||||||
)",
|
|
||||||
{}, true, Xp::Flakes};
|
|
||||||
};
|
|
||||||
|
|
||||||
RegistrySettings registrySettings;
|
|
||||||
|
|
||||||
static GlobalConfig::Register rRegistrySettings(®istrySettings);
|
|
||||||
|
|
||||||
static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
|
|
||||||
{
|
{
|
||||||
static auto reg = [&]() {
|
static auto reg = [&]() {
|
||||||
auto path = registrySettings.flakeRegistry.get();
|
auto path = settings.flakeRegistry.get();
|
||||||
if (path == "") {
|
if (path == "") {
|
||||||
return std::make_shared<Registry>(Registry::Global); // empty registry
|
return std::make_shared<Registry>(settings, Registry::Global); // empty registry
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasPrefix(path, "/")) {
|
if (!hasPrefix(path, "/")) {
|
||||||
|
@ -178,19 +163,19 @@ static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
|
||||||
path = store->toRealPath(storePath);
|
path = store->toRealPath(storePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Registry::read(path, Registry::Global);
|
return Registry::read(settings, path, Registry::Global);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
Registries getRegistries(ref<Store> store)
|
Registries getRegistries(const Settings & settings, ref<Store> store)
|
||||||
{
|
{
|
||||||
Registries registries;
|
Registries registries;
|
||||||
registries.push_back(getFlagRegistry());
|
registries.push_back(getFlagRegistry(settings));
|
||||||
registries.push_back(getUserRegistry());
|
registries.push_back(getUserRegistry(settings));
|
||||||
registries.push_back(getSystemRegistry());
|
registries.push_back(getSystemRegistry(settings));
|
||||||
registries.push_back(getGlobalRegistry(store));
|
registries.push_back(getGlobalRegistry(settings, store));
|
||||||
return registries;
|
return registries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +192,7 @@ std::pair<Input, Attrs> lookupInRegistries(
|
||||||
n++;
|
n++;
|
||||||
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());
|
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());
|
||||||
|
|
||||||
for (auto & registry : getRegistries(store)) {
|
for (auto & registry : getRegistries(*input.settings, store)) {
|
||||||
// FIXME: O(n)
|
// FIXME: O(n)
|
||||||
for (auto & entry : registry->entries) {
|
for (auto & entry : registry->entries) {
|
||||||
if (entry.exact) {
|
if (entry.exact) {
|
||||||
|
|
|
@ -10,6 +10,8 @@ namespace nix::fetchers {
|
||||||
|
|
||||||
struct Registry
|
struct Registry
|
||||||
{
|
{
|
||||||
|
const Settings & settings;
|
||||||
|
|
||||||
enum RegistryType {
|
enum RegistryType {
|
||||||
Flag = 0,
|
Flag = 0,
|
||||||
User = 1,
|
User = 1,
|
||||||
|
@ -29,11 +31,13 @@ struct Registry
|
||||||
|
|
||||||
std::vector<Entry> entries;
|
std::vector<Entry> entries;
|
||||||
|
|
||||||
Registry(RegistryType type)
|
Registry(const Settings & settings, RegistryType type)
|
||||||
: type(type)
|
: settings{settings}
|
||||||
|
, type{type}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
static std::shared_ptr<Registry> read(
|
static std::shared_ptr<Registry> read(
|
||||||
|
const Settings & settings,
|
||||||
const Path & path, RegistryType type);
|
const Path & path, RegistryType type);
|
||||||
|
|
||||||
void write(const Path & path);
|
void write(const Path & path);
|
||||||
|
@ -48,13 +52,13 @@ struct Registry
|
||||||
|
|
||||||
typedef std::vector<std::shared_ptr<Registry>> Registries;
|
typedef std::vector<std::shared_ptr<Registry>> Registries;
|
||||||
|
|
||||||
std::shared_ptr<Registry> getUserRegistry();
|
std::shared_ptr<Registry> getUserRegistry(const Settings & settings);
|
||||||
|
|
||||||
std::shared_ptr<Registry> getCustomRegistry(const Path & p);
|
std::shared_ptr<Registry> getCustomRegistry(const Settings & settings, const Path & p);
|
||||||
|
|
||||||
Path getUserRegistryPath();
|
Path getUserRegistryPath();
|
||||||
|
|
||||||
Registries getRegistries(ref<Store> store);
|
Registries getRegistries(const Settings & settings, ref<Store> store);
|
||||||
|
|
||||||
void overrideRegistry(
|
void overrideRegistry(
|
||||||
const Input & from,
|
const Input & from,
|
||||||
|
|
|
@ -214,12 +214,14 @@ struct CurlInputScheme : InputScheme
|
||||||
|
|
||||||
static const std::set<std::string> specialParams;
|
static const std::set<std::string> specialParams;
|
||||||
|
|
||||||
std::optional<Input> inputFromURL(const ParsedURL & _url, bool requireTree) const override
|
std::optional<Input> inputFromURL(
|
||||||
|
const Settings & settings,
|
||||||
|
const ParsedURL & _url, bool requireTree) const override
|
||||||
{
|
{
|
||||||
if (!isValidURL(_url, requireTree))
|
if (!isValidURL(_url, requireTree))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
Input input;
|
Input input{settings};
|
||||||
|
|
||||||
auto url = _url;
|
auto url = _url;
|
||||||
|
|
||||||
|
@ -267,9 +269,11 @@ struct CurlInputScheme : InputScheme
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
std::optional<Input> inputFromAttrs(
|
||||||
|
const Settings & settings,
|
||||||
|
const Attrs & attrs) const override
|
||||||
{
|
{
|
||||||
Input input;
|
Input input{settings};
|
||||||
input.attrs = attrs;
|
input.attrs = attrs;
|
||||||
|
|
||||||
//input.locked = (bool) maybeGetStrAttr(input.attrs, "hash");
|
//input.locked = (bool) maybeGetStrAttr(input.attrs, "hash");
|
||||||
|
@ -349,7 +353,7 @@ struct TarballInputScheme : CurlInputScheme
|
||||||
result.accessor->setPathDisplay("«" + input.to_string() + "»");
|
result.accessor->setPathDisplay("«" + input.to_string() + "»");
|
||||||
|
|
||||||
if (result.immutableUrl) {
|
if (result.immutableUrl) {
|
||||||
auto immutableInput = Input::fromURL(*result.immutableUrl);
|
auto immutableInput = Input::fromURL(*input.settings, *result.immutableUrl);
|
||||||
// FIXME: would be nice to support arbitrary flakerefs
|
// FIXME: would be nice to support arbitrary flakerefs
|
||||||
// here, e.g. git flakes.
|
// here, e.g. git flakes.
|
||||||
if (immutableInput.getType() != "tarball")
|
if (immutableInput.getType() != "tarball")
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#include "flake-settings.hh"
|
|
||||||
#include "config-global.hh"
|
|
||||||
|
|
||||||
namespace nix {
|
|
||||||
|
|
||||||
FlakeSettings::FlakeSettings() {}
|
|
||||||
|
|
||||||
FlakeSettings flakeSettings;
|
|
||||||
|
|
||||||
static GlobalConfig::Register rFlakeSettings(&flakeSettings);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
#include "config-global.hh"
|
#include "config-global.hh"
|
||||||
#include "flake-settings.hh"
|
#include "flake/settings.hh"
|
||||||
#include "flake.hh"
|
#include "flake.hh"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
@ -30,7 +30,7 @@ static void writeTrustedList(const TrustedList & trustedList)
|
||||||
writeFile(path, nlohmann::json(trustedList).dump());
|
writeFile(path, nlohmann::json(trustedList).dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigFile::apply()
|
void ConfigFile::apply(const Settings & flakeSettings)
|
||||||
{
|
{
|
||||||
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lock-file-summary", "commit-lockfile-summary"};
|
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lock-file-summary", "commit-lockfile-summary"};
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ void ConfigFile::apply()
|
||||||
else
|
else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
||||||
if (!whitelist.count(baseName) && !nix::flakeSettings.acceptFlakeConfig) {
|
if (!whitelist.count(baseName) && !flakeSettings.acceptFlakeConfig) {
|
||||||
bool trusted = false;
|
bool trusted = false;
|
||||||
auto trustedList = readTrustedList();
|
auto trustedList = readTrustedList();
|
||||||
auto tlname = get(trustedList, name);
|
auto tlname = get(trustedList, name);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "fetchers.hh"
|
#include "fetchers.hh"
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
#include "fetch-settings.hh"
|
#include "fetch-settings.hh"
|
||||||
#include "flake-settings.hh"
|
#include "flake/settings.hh"
|
||||||
#include "value-to-json.hh"
|
#include "value-to-json.hh"
|
||||||
#include "local-fs-store.hh"
|
#include "local-fs-store.hh"
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ static FlakeInput parseFlakeInput(EvalState & state,
|
||||||
|
|
||||||
if (attrs.count("type"))
|
if (attrs.count("type"))
|
||||||
try {
|
try {
|
||||||
input.ref = FlakeRef::fromAttrs(attrs);
|
input.ref = FlakeRef::fromAttrs(state.fetchSettings, attrs);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(state.positions[pos], HintFmt("while evaluating flake input"));
|
e.addTrace(state.positions[pos], HintFmt("while evaluating flake input"));
|
||||||
throw;
|
throw;
|
||||||
|
@ -174,11 +174,11 @@ static FlakeInput parseFlakeInput(EvalState & state,
|
||||||
if (!attrs.empty())
|
if (!attrs.empty())
|
||||||
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, state.positions[pos]);
|
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, state.positions[pos]);
|
||||||
if (url)
|
if (url)
|
||||||
input.ref = parseFlakeRef(*url, baseDir, true, input.isFlake);
|
input.ref = parseFlakeRef(state.fetchSettings, *url, baseDir, true, input.isFlake);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!input.follows && !input.ref)
|
if (!input.follows && !input.ref)
|
||||||
input.ref = FlakeRef::fromAttrs({{"type", "indirect"}, {"id", std::string(inputName)}});
|
input.ref = FlakeRef::fromAttrs(state.fetchSettings, {{"type", "indirect"}, {"id", std::string(inputName)}});
|
||||||
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ static Flake readFlake(
|
||||||
for (auto & formal : outputs->value->payload.lambda.fun->formals->formals) {
|
for (auto & formal : outputs->value->payload.lambda.fun->formals->formals) {
|
||||||
if (formal.name != state.sSelf)
|
if (formal.name != state.sSelf)
|
||||||
flake.inputs.emplace(state.symbols[formal.name], FlakeInput {
|
flake.inputs.emplace(state.symbols[formal.name], FlakeInput {
|
||||||
.ref = parseFlakeRef(std::string(state.symbols[formal.name]))
|
.ref = parseFlakeRef(state.fetchSettings, std::string(state.symbols[formal.name]))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,16 +329,19 @@ Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup
|
||||||
return getFlake(state, originalRef, allowLookup, flakeCache);
|
return getFlake(state, originalRef, allowLookup, flakeCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LockFile readLockFile(const SourcePath & lockFilePath)
|
static LockFile readLockFile(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
|
const SourcePath & lockFilePath)
|
||||||
{
|
{
|
||||||
return lockFilePath.pathExists()
|
return lockFilePath.pathExists()
|
||||||
? LockFile(lockFilePath.readFile(), fmt("%s", lockFilePath))
|
? LockFile(fetchSettings, lockFilePath.readFile(), fmt("%s", lockFilePath))
|
||||||
: LockFile();
|
: LockFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute an in-memory lock file for the specified top-level flake,
|
/* Compute an in-memory lock file for the specified top-level flake,
|
||||||
and optionally write it to file, if the flake is writable. */
|
and optionally write it to file, if the flake is writable. */
|
||||||
LockedFlake lockFlake(
|
LockedFlake lockFlake(
|
||||||
|
const Settings & settings,
|
||||||
EvalState & state,
|
EvalState & state,
|
||||||
const FlakeRef & topRef,
|
const FlakeRef & topRef,
|
||||||
const LockFlags & lockFlags)
|
const LockFlags & lockFlags)
|
||||||
|
@ -347,21 +350,22 @@ LockedFlake lockFlake(
|
||||||
|
|
||||||
FlakeCache flakeCache;
|
FlakeCache flakeCache;
|
||||||
|
|
||||||
auto useRegistries = lockFlags.useRegistries.value_or(flakeSettings.useRegistries);
|
auto useRegistries = lockFlags.useRegistries.value_or(settings.useRegistries);
|
||||||
|
|
||||||
auto flake = getFlake(state, topRef, useRegistries, flakeCache);
|
auto flake = getFlake(state, topRef, useRegistries, flakeCache);
|
||||||
|
|
||||||
if (lockFlags.applyNixConfig) {
|
if (lockFlags.applyNixConfig) {
|
||||||
flake.config.apply();
|
flake.config.apply(settings);
|
||||||
state.store->setOptions();
|
state.store->setOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!fetchSettings.allowDirty && lockFlags.referenceLockFilePath) {
|
if (!state.fetchSettings.allowDirty && lockFlags.referenceLockFilePath) {
|
||||||
throw Error("reference lock file was provided, but the `allow-dirty` setting is set to false");
|
throw Error("reference lock file was provided, but the `allow-dirty` setting is set to false");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto oldLockFile = readLockFile(
|
auto oldLockFile = readLockFile(
|
||||||
|
state.fetchSettings,
|
||||||
lockFlags.referenceLockFilePath.value_or(
|
lockFlags.referenceLockFilePath.value_or(
|
||||||
flake.lockFilePath()));
|
flake.lockFilePath()));
|
||||||
|
|
||||||
|
@ -597,7 +601,7 @@ LockedFlake lockFlake(
|
||||||
inputFlake.inputs, childNode, inputPath,
|
inputFlake.inputs, childNode, inputPath,
|
||||||
oldLock
|
oldLock
|
||||||
? std::dynamic_pointer_cast<const Node>(oldLock)
|
? std::dynamic_pointer_cast<const Node>(oldLock)
|
||||||
: readLockFile(inputFlake.lockFilePath()).root.get_ptr(),
|
: readLockFile(state.fetchSettings, inputFlake.lockFilePath()).root.get_ptr(),
|
||||||
oldLock ? lockRootPath : inputPath,
|
oldLock ? lockRootPath : inputPath,
|
||||||
localPath,
|
localPath,
|
||||||
false);
|
false);
|
||||||
|
@ -660,7 +664,7 @@ LockedFlake lockFlake(
|
||||||
if (lockFlags.writeLockFile) {
|
if (lockFlags.writeLockFile) {
|
||||||
if (sourcePath || lockFlags.outputLockFilePath) {
|
if (sourcePath || lockFlags.outputLockFilePath) {
|
||||||
if (auto unlockedInput = newLockFile.isUnlocked()) {
|
if (auto unlockedInput = newLockFile.isUnlocked()) {
|
||||||
if (fetchSettings.warnDirty)
|
if (state.fetchSettings.warnDirty)
|
||||||
warn("will not write lock file of flake '%s' because it has an unlocked input ('%s')", topRef, *unlockedInput);
|
warn("will not write lock file of flake '%s' because it has an unlocked input ('%s')", topRef, *unlockedInput);
|
||||||
} else {
|
} else {
|
||||||
if (!lockFlags.updateLockFile)
|
if (!lockFlags.updateLockFile)
|
||||||
|
@ -692,7 +696,7 @@ LockedFlake lockFlake(
|
||||||
if (lockFlags.commitLockFile) {
|
if (lockFlags.commitLockFile) {
|
||||||
std::string cm;
|
std::string cm;
|
||||||
|
|
||||||
cm = flakeSettings.commitLockFileSummary.get();
|
cm = settings.commitLockFileSummary.get();
|
||||||
|
|
||||||
if (cm == "") {
|
if (cm == "") {
|
||||||
cm = fmt("%s: %s", relPath, lockFileExists ? "Update" : "Add");
|
cm = fmt("%s: %s", relPath, lockFileExists ? "Update" : "Add");
|
||||||
|
@ -800,46 +804,49 @@ void callFlake(EvalState & state,
|
||||||
state.callFunction(*vTmp1, vOverrides, vRes, noPos);
|
state.callFunction(*vTmp1, vOverrides, vRes, noPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prim_getFlake(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
void initLib(const Settings & settings)
|
||||||
{
|
{
|
||||||
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
|
auto prim_getFlake = [&settings](EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
|
{
|
||||||
if (state.settings.pureEval && !flakeRef.input.isLocked())
|
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
|
||||||
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.positions[pos]);
|
auto flakeRef = parseFlakeRef(state.fetchSettings, flakeRefS, {}, true);
|
||||||
|
if (state.settings.pureEval && !flakeRef.input.isLocked())
|
||||||
|
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.positions[pos]);
|
||||||
|
|
||||||
callFlake(state,
|
callFlake(state,
|
||||||
lockFlake(state, flakeRef,
|
lockFlake(settings, state, flakeRef,
|
||||||
LockFlags {
|
LockFlags {
|
||||||
.updateLockFile = false,
|
.updateLockFile = false,
|
||||||
.writeLockFile = false,
|
.writeLockFile = false,
|
||||||
.useRegistries = !state.settings.pureEval && flakeSettings.useRegistries,
|
.useRegistries = !state.settings.pureEval && settings.useRegistries,
|
||||||
.allowUnlocked = !state.settings.pureEval,
|
.allowUnlocked = !state.settings.pureEval,
|
||||||
}),
|
}),
|
||||||
v);
|
v);
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterPrimOp::primOps->push_back({
|
||||||
|
.name = "__getFlake",
|
||||||
|
.args = {"args"},
|
||||||
|
.doc = R"(
|
||||||
|
Fetch a flake from a flake reference, and return its output attributes and some metadata. For example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
(builtins.getFlake "nix/55bc52401966fbffa525c574c14f67b00bc4fb3a").packages.x86_64-linux.nix
|
||||||
|
```
|
||||||
|
|
||||||
|
Unless impure evaluation is allowed (`--impure`), the flake reference
|
||||||
|
must be "locked", e.g. contain a Git revision or content hash. An
|
||||||
|
example of an unlocked usage is:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
(builtins.getFlake "github:edolstra/dwarffs").rev
|
||||||
|
```
|
||||||
|
)",
|
||||||
|
.fun = prim_getFlake,
|
||||||
|
.experimentalFeature = Xp::Flakes,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r2({
|
|
||||||
.name = "__getFlake",
|
|
||||||
.args = {"args"},
|
|
||||||
.doc = R"(
|
|
||||||
Fetch a flake from a flake reference, and return its output attributes and some metadata. For example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
(builtins.getFlake "nix/55bc52401966fbffa525c574c14f67b00bc4fb3a").packages.x86_64-linux.nix
|
|
||||||
```
|
|
||||||
|
|
||||||
Unless impure evaluation is allowed (`--impure`), the flake reference
|
|
||||||
must be "locked", e.g. contain a Git revision or content hash. An
|
|
||||||
example of an unlocked usage is:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
(builtins.getFlake "github:edolstra/dwarffs").rev
|
|
||||||
```
|
|
||||||
)",
|
|
||||||
.fun = prim_getFlake,
|
|
||||||
.experimentalFeature = Xp::Flakes,
|
|
||||||
});
|
|
||||||
|
|
||||||
static void prim_parseFlakeRef(
|
static void prim_parseFlakeRef(
|
||||||
EvalState & state,
|
EvalState & state,
|
||||||
const PosIdx pos,
|
const PosIdx pos,
|
||||||
|
@ -848,7 +855,7 @@ static void prim_parseFlakeRef(
|
||||||
{
|
{
|
||||||
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos,
|
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos,
|
||||||
"while evaluating the argument passed to builtins.parseFlakeRef"));
|
"while evaluating the argument passed to builtins.parseFlakeRef"));
|
||||||
auto attrs = parseFlakeRef(flakeRefS, {}, true).toAttrs();
|
auto attrs = parseFlakeRef(state.fetchSettings, flakeRefS, {}, true).toAttrs();
|
||||||
auto binds = state.buildBindings(attrs.size());
|
auto binds = state.buildBindings(attrs.size());
|
||||||
for (const auto & [key, value] : attrs) {
|
for (const auto & [key, value] : attrs) {
|
||||||
auto s = state.symbols.create(key);
|
auto s = state.symbols.create(key);
|
||||||
|
@ -913,7 +920,7 @@ static void prim_flakeRefToString(
|
||||||
showType(*attr.value)).debugThrow();
|
showType(*attr.value)).debugThrow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto flakeRef = FlakeRef::fromAttrs(attrs);
|
auto flakeRef = FlakeRef::fromAttrs(state.fetchSettings, attrs);
|
||||||
v.mkString(flakeRef.to_string());
|
v.mkString(flakeRef.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,16 @@ class EvalState;
|
||||||
|
|
||||||
namespace flake {
|
namespace flake {
|
||||||
|
|
||||||
|
struct Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize `libnixflake`
|
||||||
|
*
|
||||||
|
* So far, this registers the `builtins.getFlake` primop, which depends
|
||||||
|
* on the choice of `flake:Settings`.
|
||||||
|
*/
|
||||||
|
void initLib(const Settings & settings);
|
||||||
|
|
||||||
struct FlakeInput;
|
struct FlakeInput;
|
||||||
|
|
||||||
typedef std::map<FlakeId, FlakeInput> FlakeInputs;
|
typedef std::map<FlakeId, FlakeInput> FlakeInputs;
|
||||||
|
@ -57,7 +67,7 @@ struct ConfigFile
|
||||||
|
|
||||||
std::map<std::string, ConfigValue> settings;
|
std::map<std::string, ConfigValue> settings;
|
||||||
|
|
||||||
void apply();
|
void apply(const Settings & settings);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,6 +204,7 @@ struct LockFlags
|
||||||
};
|
};
|
||||||
|
|
||||||
LockedFlake lockFlake(
|
LockedFlake lockFlake(
|
||||||
|
const Settings & settings,
|
||||||
EvalState & state,
|
EvalState & state,
|
||||||
const FlakeRef & flakeRef,
|
const FlakeRef & flakeRef,
|
||||||
const LockFlags & lockFlags);
|
const LockFlags & lockFlags);
|
||||||
|
|
|
@ -48,28 +48,32 @@ FlakeRef FlakeRef::resolve(ref<Store> store) const
|
||||||
}
|
}
|
||||||
|
|
||||||
FlakeRef parseFlakeRef(
|
FlakeRef parseFlakeRef(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const std::optional<Path> & baseDir,
|
const std::optional<Path> & baseDir,
|
||||||
bool allowMissing,
|
bool allowMissing,
|
||||||
bool isFlake)
|
bool isFlake)
|
||||||
{
|
{
|
||||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir, allowMissing, isFlake);
|
auto [flakeRef, fragment] = parseFlakeRefWithFragment(fetchSettings, url, baseDir, allowMissing, isFlake);
|
||||||
if (fragment != "")
|
if (fragment != "")
|
||||||
throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url);
|
throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url);
|
||||||
return flakeRef;
|
return flakeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<FlakeRef> maybeParseFlakeRef(
|
std::optional<FlakeRef> maybeParseFlakeRef(
|
||||||
const std::string & url, const std::optional<Path> & baseDir)
|
const fetchers::Settings & fetchSettings,
|
||||||
|
const std::string & url,
|
||||||
|
const std::optional<Path> & baseDir)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return parseFlakeRef(url, baseDir);
|
return parseFlakeRef(fetchSettings, url, baseDir);
|
||||||
} catch (Error &) {
|
} catch (Error &) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
|
std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const std::optional<Path> & baseDir,
|
const std::optional<Path> & baseDir,
|
||||||
bool allowMissing,
|
bool allowMissing,
|
||||||
|
@ -166,7 +170,7 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
|
||||||
parsedURL.query.insert_or_assign("shallow", "1");
|
parsedURL.query.insert_or_assign("shallow", "1");
|
||||||
|
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
FlakeRef(fetchers::Input::fromURL(parsedURL), getOr(parsedURL.query, "dir", "")),
|
FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL), getOr(parsedURL.query, "dir", "")),
|
||||||
fragment);
|
fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,13 +189,14 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
|
||||||
attrs.insert_or_assign("type", "path");
|
attrs.insert_or_assign("type", "path");
|
||||||
attrs.insert_or_assign("path", path);
|
attrs.insert_or_assign("path", path);
|
||||||
|
|
||||||
return std::make_pair(FlakeRef(fetchers::Input::fromAttrs(std::move(attrs)), ""), fragment);
|
return std::make_pair(FlakeRef(fetchers::Input::fromAttrs(fetchSettings, std::move(attrs)), ""), fragment);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Check if 'url' is a flake ID. This is an abbreviated syntax for
|
/* Check if 'url' is a flake ID. This is an abbreviated syntax for
|
||||||
'flake:<flake-id>?ref=<ref>&rev=<rev>'. */
|
'flake:<flake-id>?ref=<ref>&rev=<rev>'. */
|
||||||
std::optional<std::pair<FlakeRef, std::string>> parseFlakeIdRef(
|
static std::optional<std::pair<FlakeRef, std::string>> parseFlakeIdRef(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
bool isFlake
|
bool isFlake
|
||||||
)
|
)
|
||||||
|
@ -213,7 +218,7 @@ std::optional<std::pair<FlakeRef, std::string>> parseFlakeIdRef(
|
||||||
};
|
};
|
||||||
|
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
FlakeRef(fetchers::Input::fromURL(parsedURL, isFlake), ""),
|
FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake), ""),
|
||||||
percentDecode(match.str(6)));
|
percentDecode(match.str(6)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +226,7 @@ std::optional<std::pair<FlakeRef, std::string>> parseFlakeIdRef(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::pair<FlakeRef, std::string>> parseURLFlakeRef(
|
std::optional<std::pair<FlakeRef, std::string>> parseURLFlakeRef(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const std::optional<Path> & baseDir,
|
const std::optional<Path> & baseDir,
|
||||||
bool isFlake
|
bool isFlake
|
||||||
|
@ -236,7 +242,7 @@ std::optional<std::pair<FlakeRef, std::string>> parseURLFlakeRef(
|
||||||
std::string fragment;
|
std::string fragment;
|
||||||
std::swap(fragment, parsedURL.fragment);
|
std::swap(fragment, parsedURL.fragment);
|
||||||
|
|
||||||
auto input = fetchers::Input::fromURL(parsedURL, isFlake);
|
auto input = fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake);
|
||||||
input.parent = baseDir;
|
input.parent = baseDir;
|
||||||
|
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
|
@ -245,6 +251,7 @@ std::optional<std::pair<FlakeRef, std::string>> parseURLFlakeRef(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const std::optional<Path> & baseDir,
|
const std::optional<Path> & baseDir,
|
||||||
bool allowMissing,
|
bool allowMissing,
|
||||||
|
@ -254,31 +261,34 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||||
|
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
|
|
||||||
if (auto res = parseFlakeIdRef(url, isFlake)) {
|
if (auto res = parseFlakeIdRef(fetchSettings, url, isFlake)) {
|
||||||
return *res;
|
return *res;
|
||||||
} else if (auto res = parseURLFlakeRef(url, baseDir, isFlake)) {
|
} else if (auto res = parseURLFlakeRef(fetchSettings, url, baseDir, isFlake)) {
|
||||||
return *res;
|
return *res;
|
||||||
} else {
|
} else {
|
||||||
return parsePathFlakeRefWithFragment(url, baseDir, allowMissing, isFlake);
|
return parsePathFlakeRefWithFragment(fetchSettings, url, baseDir, allowMissing, isFlake);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
|
std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url, const std::optional<Path> & baseDir)
|
const std::string & url, const std::optional<Path> & baseDir)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return parseFlakeRefWithFragment(url, baseDir);
|
return parseFlakeRefWithFragment(fetchSettings, url, baseDir);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlakeRef FlakeRef::fromAttrs(const fetchers::Attrs & attrs)
|
FlakeRef FlakeRef::fromAttrs(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
|
const fetchers::Attrs & attrs)
|
||||||
{
|
{
|
||||||
auto attrs2(attrs);
|
auto attrs2(attrs);
|
||||||
attrs2.erase("dir");
|
attrs2.erase("dir");
|
||||||
return FlakeRef(
|
return FlakeRef(
|
||||||
fetchers::Input::fromAttrs(std::move(attrs2)),
|
fetchers::Input::fromAttrs(fetchSettings, std::move(attrs2)),
|
||||||
fetchers::maybeGetStrAttr(attrs, "dir").value_or(""));
|
fetchers::maybeGetStrAttr(attrs, "dir").value_or(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,13 +299,16 @@ std::pair<StorePath, FlakeRef> FlakeRef::fetchTree(ref<Store> store) const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragmentAndExtendedOutputsSpec(
|
std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragmentAndExtendedOutputsSpec(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const std::optional<Path> & baseDir,
|
const std::optional<Path> & baseDir,
|
||||||
bool allowMissing,
|
bool allowMissing,
|
||||||
bool isFlake)
|
bool isFlake)
|
||||||
{
|
{
|
||||||
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(url);
|
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(url);
|
||||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(std::string { prefix }, baseDir, allowMissing, isFlake);
|
auto [flakeRef, fragment] = parseFlakeRefWithFragment(
|
||||||
|
fetchSettings,
|
||||||
|
std::string { prefix }, baseDir, allowMissing, isFlake);
|
||||||
return {std::move(flakeRef), fragment, std::move(extendedOutputsSpec)};
|
return {std::move(flakeRef), fragment, std::move(extendedOutputsSpec)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,9 @@ struct FlakeRef
|
||||||
|
|
||||||
FlakeRef resolve(ref<Store> store) const;
|
FlakeRef resolve(ref<Store> store) const;
|
||||||
|
|
||||||
static FlakeRef fromAttrs(const fetchers::Attrs & attrs);
|
static FlakeRef fromAttrs(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
|
const fetchers::Attrs & attrs);
|
||||||
|
|
||||||
std::pair<StorePath, FlakeRef> fetchTree(ref<Store> store) const;
|
std::pair<StorePath, FlakeRef> fetchTree(ref<Store> store) const;
|
||||||
};
|
};
|
||||||
|
@ -72,6 +74,7 @@ std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef);
|
||||||
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
||||||
*/
|
*/
|
||||||
FlakeRef parseFlakeRef(
|
FlakeRef parseFlakeRef(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const std::optional<Path> & baseDir = {},
|
const std::optional<Path> & baseDir = {},
|
||||||
bool allowMissing = false,
|
bool allowMissing = false,
|
||||||
|
@ -81,12 +84,15 @@ FlakeRef parseFlakeRef(
|
||||||
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
||||||
*/
|
*/
|
||||||
std::optional<FlakeRef> maybeParseFlake(
|
std::optional<FlakeRef> maybeParseFlake(
|
||||||
const std::string & url, const std::optional<Path> & baseDir = {});
|
const fetchers::Settings & fetchSettings,
|
||||||
|
const std::string & url,
|
||||||
|
const std::optional<Path> & baseDir = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
||||||
*/
|
*/
|
||||||
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const std::optional<Path> & baseDir = {},
|
const std::optional<Path> & baseDir = {},
|
||||||
bool allowMissing = false,
|
bool allowMissing = false,
|
||||||
|
@ -96,12 +102,15 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||||
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
||||||
*/
|
*/
|
||||||
std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
|
std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
|
||||||
const std::string & url, const std::optional<Path> & baseDir = {});
|
const fetchers::Settings & fetchSettings,
|
||||||
|
const std::string & url,
|
||||||
|
const std::optional<Path> & baseDir = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
* @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory)
|
||||||
*/
|
*/
|
||||||
std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragmentAndExtendedOutputsSpec(
|
std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragmentAndExtendedOutputsSpec(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const std::optional<Path> & baseDir = {},
|
const std::optional<Path> & baseDir = {},
|
||||||
bool allowMissing = false,
|
bool allowMissing = false,
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
namespace nix::flake {
|
namespace nix::flake {
|
||||||
|
|
||||||
FlakeRef getFlakeRef(
|
static FlakeRef getFlakeRef(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
const nlohmann::json & json,
|
const nlohmann::json & json,
|
||||||
const char * attr,
|
const char * attr,
|
||||||
const char * info)
|
const char * info)
|
||||||
|
@ -26,15 +27,17 @@ FlakeRef getFlakeRef(
|
||||||
attrs.insert_or_assign(k.first, k.second);
|
attrs.insert_or_assign(k.first, k.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FlakeRef::fromAttrs(attrs);
|
return FlakeRef::fromAttrs(fetchSettings, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Error("attribute '%s' missing in lock file", attr);
|
throw Error("attribute '%s' missing in lock file", attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
LockedNode::LockedNode(const nlohmann::json & json)
|
LockedNode::LockedNode(
|
||||||
: lockedRef(getFlakeRef(json, "locked", "info")) // FIXME: remove "info"
|
const fetchers::Settings & fetchSettings,
|
||||||
, originalRef(getFlakeRef(json, "original", nullptr))
|
const nlohmann::json & json)
|
||||||
|
: lockedRef(getFlakeRef(fetchSettings, json, "locked", "info")) // FIXME: remove "info"
|
||||||
|
, originalRef(getFlakeRef(fetchSettings, json, "original", nullptr))
|
||||||
, isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true)
|
, isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true)
|
||||||
{
|
{
|
||||||
if (!lockedRef.input.isLocked())
|
if (!lockedRef.input.isLocked())
|
||||||
|
@ -84,7 +87,9 @@ std::shared_ptr<Node> LockFile::findInput(const InputPath & path)
|
||||||
return doFind(root, path, visited);
|
return doFind(root, path, visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
LockFile::LockFile(std::string_view contents, std::string_view path)
|
LockFile::LockFile(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
|
std::string_view contents, std::string_view path)
|
||||||
{
|
{
|
||||||
auto json = nlohmann::json::parse(contents);
|
auto json = nlohmann::json::parse(contents);
|
||||||
|
|
||||||
|
@ -113,7 +118,7 @@ LockFile::LockFile(std::string_view contents, std::string_view path)
|
||||||
auto jsonNode2 = nodes.find(inputKey);
|
auto jsonNode2 = nodes.find(inputKey);
|
||||||
if (jsonNode2 == nodes.end())
|
if (jsonNode2 == nodes.end())
|
||||||
throw Error("lock file references missing node '%s'", inputKey);
|
throw Error("lock file references missing node '%s'", inputKey);
|
||||||
auto input = make_ref<LockedNode>(*jsonNode2);
|
auto input = make_ref<LockedNode>(fetchSettings, *jsonNode2);
|
||||||
k = nodeMap.insert_or_assign(inputKey, input).first;
|
k = nodeMap.insert_or_assign(inputKey, input).first;
|
||||||
getInputs(*input, *jsonNode2);
|
getInputs(*input, *jsonNode2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,9 @@ struct LockedNode : Node
|
||||||
: lockedRef(lockedRef), originalRef(originalRef), isFlake(isFlake)
|
: lockedRef(lockedRef), originalRef(originalRef), isFlake(isFlake)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
LockedNode(const nlohmann::json & json);
|
LockedNode(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
|
const nlohmann::json & json);
|
||||||
|
|
||||||
StorePath computeStorePath(Store & store) const;
|
StorePath computeStorePath(Store & store) const;
|
||||||
};
|
};
|
||||||
|
@ -55,7 +57,9 @@ struct LockFile
|
||||||
ref<Node> root = make_ref<Node>();
|
ref<Node> root = make_ref<Node>();
|
||||||
|
|
||||||
LockFile() {};
|
LockFile() {};
|
||||||
LockFile(std::string_view contents, std::string_view path);
|
LockFile(
|
||||||
|
const fetchers::Settings & fetchSettings,
|
||||||
|
std::string_view contents, std::string_view path);
|
||||||
|
|
||||||
typedef std::map<ref<const Node>, std::string> KeyMap;
|
typedef std::map<ref<const Node>, std::string> KeyMap;
|
||||||
|
|
||||||
|
|
7
src/libflake/flake/settings.cc
Normal file
7
src/libflake/flake/settings.cc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#include "flake/settings.hh"
|
||||||
|
|
||||||
|
namespace nix::flake {
|
||||||
|
|
||||||
|
Settings::Settings() {}
|
||||||
|
|
||||||
|
}
|
|
@ -10,11 +10,11 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix::flake {
|
||||||
|
|
||||||
struct FlakeSettings : public Config
|
struct Settings : public Config
|
||||||
{
|
{
|
||||||
FlakeSettings();
|
Settings();
|
||||||
|
|
||||||
Setting<bool> useRegistries{
|
Setting<bool> useRegistries{
|
||||||
this,
|
this,
|
||||||
|
@ -47,7 +47,4 @@ struct FlakeSettings : public Config
|
||||||
Xp::Flakes};
|
Xp::Flakes};
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: don't use a global variable.
|
|
||||||
extern FlakeSettings flakeSettings;
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -42,21 +42,21 @@ add_project_arguments(
|
||||||
subdir('build-utils-meson/diagnostics')
|
subdir('build-utils-meson/diagnostics')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
'flake-settings.cc',
|
|
||||||
'flake/config.cc',
|
'flake/config.cc',
|
||||||
'flake/flake.cc',
|
'flake/flake.cc',
|
||||||
'flake/flakeref.cc',
|
'flake/flakeref.cc',
|
||||||
'flake/url-name.cc',
|
|
||||||
'flake/lockfile.cc',
|
'flake/lockfile.cc',
|
||||||
|
'flake/settings.cc',
|
||||||
|
'flake/url-name.cc',
|
||||||
)
|
)
|
||||||
|
|
||||||
include_dirs = [include_directories('.')]
|
include_dirs = [include_directories('.')]
|
||||||
|
|
||||||
headers = files(
|
headers = files(
|
||||||
'flake-settings.hh',
|
|
||||||
'flake/flake.hh',
|
'flake/flake.hh',
|
||||||
'flake/flakeref.hh',
|
'flake/flakeref.hh',
|
||||||
'flake/lockfile.hh',
|
'flake/lockfile.hh',
|
||||||
|
'flake/settings.hh',
|
||||||
'flake/url-name.hh',
|
'flake/url-name.hh',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,7 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
auto store = openStore();
|
auto store = openStore();
|
||||||
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
|
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
|
||||||
|
|
||||||
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, evalSettings, store);
|
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, fetchSettings, evalSettings, store);
|
||||||
state->repair = myArgs.repair;
|
state->repair = myArgs.repair;
|
||||||
if (myArgs.repair) buildMode = bmRepair;
|
if (myArgs.repair) buildMode = bmRepair;
|
||||||
|
|
||||||
|
|
|
@ -1525,7 +1525,7 @@ static int main_nix_env(int argc, char * * argv)
|
||||||
|
|
||||||
auto store = openStore();
|
auto store = openStore();
|
||||||
|
|
||||||
globals.state = std::shared_ptr<EvalState>(new EvalState(myArgs.lookupPath, store, evalSettings));
|
globals.state = std::shared_ptr<EvalState>(new EvalState(myArgs.lookupPath, store, fetchSettings, evalSettings));
|
||||||
globals.state->repair = myArgs.repair;
|
globals.state->repair = myArgs.repair;
|
||||||
|
|
||||||
globals.instSource.nixExprPath = std::make_shared<SourcePath>(
|
globals.instSource.nixExprPath = std::make_shared<SourcePath>(
|
||||||
|
|
|
@ -157,7 +157,7 @@ static int main_nix_instantiate(int argc, char * * argv)
|
||||||
auto store = openStore();
|
auto store = openStore();
|
||||||
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
|
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
|
||||||
|
|
||||||
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, evalSettings, store);
|
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, fetchSettings, evalSettings, store);
|
||||||
state->repair = myArgs.repair;
|
state->repair = myArgs.repair;
|
||||||
|
|
||||||
Bindings & autoArgs = *myArgs.getAutoArgs(*state);
|
Bindings & autoArgs = *myArgs.getAutoArgs(*state);
|
||||||
|
|
|
@ -76,7 +76,9 @@ struct CmdBundle : InstallableValueCommand
|
||||||
|
|
||||||
auto val = installable->toValue(*evalState).first;
|
auto val = installable->toValue(*evalState).first;
|
||||||
|
|
||||||
auto [bundlerFlakeRef, bundlerName, extendedOutputsSpec] = parseFlakeRefWithFragmentAndExtendedOutputsSpec(bundler, absPath("."));
|
auto [bundlerFlakeRef, bundlerName, extendedOutputsSpec] =
|
||||||
|
parseFlakeRefWithFragmentAndExtendedOutputsSpec(
|
||||||
|
fetchSettings, bundler, absPath("."));
|
||||||
const flake::LockFlags lockFlags{ .writeLockFile = false };
|
const flake::LockFlags lockFlags{ .writeLockFile = false };
|
||||||
InstallableFlake bundler{this,
|
InstallableFlake bundler{this,
|
||||||
evalState, std::move(bundlerFlakeRef), bundlerName, std::move(extendedOutputsSpec),
|
evalState, std::move(bundlerFlakeRef), bundlerName, std::move(extendedOutputsSpec),
|
||||||
|
|
|
@ -48,19 +48,19 @@ public:
|
||||||
|
|
||||||
FlakeRef getFlakeRef()
|
FlakeRef getFlakeRef()
|
||||||
{
|
{
|
||||||
return parseFlakeRef(flakeUrl, absPath(".")); //FIXME
|
return parseFlakeRef(fetchSettings, flakeUrl, absPath(".")); //FIXME
|
||||||
}
|
}
|
||||||
|
|
||||||
LockedFlake lockFlake()
|
LockedFlake lockFlake()
|
||||||
{
|
{
|
||||||
return flake::lockFlake(*getEvalState(), getFlakeRef(), lockFlags);
|
return flake::lockFlake(flakeSettings, *getEvalState(), getFlakeRef(), lockFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<FlakeRef> getFlakeRefsForCompletion() override
|
std::vector<FlakeRef> getFlakeRefsForCompletion() override
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
// Like getFlakeRef but with expandTilde calld first
|
// Like getFlakeRef but with expandTilde calld first
|
||||||
parseFlakeRef(expandTilde(flakeUrl), absPath("."))
|
parseFlakeRef(fetchSettings, expandTilde(flakeUrl), absPath("."))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -848,7 +848,8 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
|
||||||
|
|
||||||
auto evalState = getEvalState();
|
auto evalState = getEvalState();
|
||||||
|
|
||||||
auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(templateUrl, absPath("."));
|
auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(
|
||||||
|
fetchSettings, templateUrl, absPath("."));
|
||||||
|
|
||||||
auto installable = InstallableFlake(nullptr,
|
auto installable = InstallableFlake(nullptr,
|
||||||
evalState, std::move(templateFlakeRef), templateName, ExtendedOutputsSpec::Default(),
|
evalState, std::move(templateFlakeRef), templateName, ExtendedOutputsSpec::Default(),
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
#include "network-proxy.hh"
|
#include "network-proxy.hh"
|
||||||
#include "eval-cache.hh"
|
#include "eval-cache.hh"
|
||||||
|
#include "flake/flake.hh"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
@ -242,7 +243,7 @@ static void showHelp(std::vector<std::string> subcommand, NixArgs & toplevel)
|
||||||
|
|
||||||
evalSettings.restrictEval = false;
|
evalSettings.restrictEval = false;
|
||||||
evalSettings.pureEval = false;
|
evalSettings.pureEval = false;
|
||||||
EvalState state({}, openStore("dummy://"), evalSettings);
|
EvalState state({}, openStore("dummy://"), fetchSettings, evalSettings);
|
||||||
|
|
||||||
auto vGenerateManpage = state.allocValue();
|
auto vGenerateManpage = state.allocValue();
|
||||||
state.eval(state.parseExprFromString(
|
state.eval(state.parseExprFromString(
|
||||||
|
@ -362,6 +363,7 @@ void mainWrapped(int argc, char * * argv)
|
||||||
|
|
||||||
initNix();
|
initNix();
|
||||||
initGC();
|
initGC();
|
||||||
|
flake::initLib(flakeSettings);
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
if (isRootUser()) {
|
if (isRootUser()) {
|
||||||
|
@ -418,7 +420,7 @@ void mainWrapped(int argc, char * * argv)
|
||||||
Xp::FetchTree,
|
Xp::FetchTree,
|
||||||
};
|
};
|
||||||
evalSettings.pureEval = false;
|
evalSettings.pureEval = false;
|
||||||
EvalState state({}, openStore("dummy://"), evalSettings);
|
EvalState state({}, openStore("dummy://"), fetchSettings, evalSettings);
|
||||||
auto builtinsJson = nlohmann::json::object();
|
auto builtinsJson = nlohmann::json::object();
|
||||||
for (auto & builtin : *state.baseEnv.values[0]->attrs()) {
|
for (auto & builtin : *state.baseEnv.values[0]->attrs()) {
|
||||||
auto b = nlohmann::json::object();
|
auto b = nlohmann::json::object();
|
||||||
|
|
|
@ -195,7 +195,7 @@ static int main_nix_prefetch_url(int argc, char * * argv)
|
||||||
startProgressBar();
|
startProgressBar();
|
||||||
|
|
||||||
auto store = openStore();
|
auto store = openStore();
|
||||||
auto state = std::make_unique<EvalState>(myArgs.lookupPath, store, evalSettings);
|
auto state = std::make_unique<EvalState>(myArgs.lookupPath, store, fetchSettings, evalSettings);
|
||||||
|
|
||||||
Bindings & autoArgs = *myArgs.getAutoArgs(*state);
|
Bindings & autoArgs = *myArgs.getAutoArgs(*state);
|
||||||
|
|
||||||
|
|
|
@ -154,8 +154,8 @@ struct ProfileManifest
|
||||||
}
|
}
|
||||||
if (e.value(sUrl, "") != "") {
|
if (e.value(sUrl, "") != "") {
|
||||||
element.source = ProfileElementSource {
|
element.source = ProfileElementSource {
|
||||||
parseFlakeRef(e[sOriginalUrl]),
|
parseFlakeRef(fetchSettings, e[sOriginalUrl]),
|
||||||
parseFlakeRef(e[sUrl]),
|
parseFlakeRef(fetchSettings, e[sUrl]),
|
||||||
e["attrPath"],
|
e["attrPath"],
|
||||||
e["outputs"].get<ExtendedOutputsSpec>()
|
e["outputs"].get<ExtendedOutputsSpec>()
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,9 +33,9 @@ public:
|
||||||
{
|
{
|
||||||
if (registry) return registry;
|
if (registry) return registry;
|
||||||
if (registry_path.empty()) {
|
if (registry_path.empty()) {
|
||||||
registry = fetchers::getUserRegistry();
|
registry = fetchers::getUserRegistry(fetchSettings);
|
||||||
} else {
|
} else {
|
||||||
registry = fetchers::getCustomRegistry(registry_path);
|
registry = fetchers::getCustomRegistry(fetchSettings, registry_path);
|
||||||
}
|
}
|
||||||
return registry;
|
return registry;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ struct CmdRegistryList : StoreCommand
|
||||||
{
|
{
|
||||||
using namespace fetchers;
|
using namespace fetchers;
|
||||||
|
|
||||||
auto registries = getRegistries(store);
|
auto registries = getRegistries(fetchSettings, store);
|
||||||
|
|
||||||
for (auto & registry : registries) {
|
for (auto & registry : registries) {
|
||||||
for (auto & entry : registry->entries) {
|
for (auto & entry : registry->entries) {
|
||||||
|
@ -109,8 +109,8 @@ struct CmdRegistryAdd : MixEvalArgs, Command, RegistryCommand
|
||||||
|
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
auto fromRef = parseFlakeRef(fromUrl);
|
auto fromRef = parseFlakeRef(fetchSettings, fromUrl);
|
||||||
auto toRef = parseFlakeRef(toUrl);
|
auto toRef = parseFlakeRef(fetchSettings, toUrl);
|
||||||
auto registry = getRegistry();
|
auto registry = getRegistry();
|
||||||
fetchers::Attrs extraAttrs;
|
fetchers::Attrs extraAttrs;
|
||||||
if (toRef.subdir != "") extraAttrs["dir"] = toRef.subdir;
|
if (toRef.subdir != "") extraAttrs["dir"] = toRef.subdir;
|
||||||
|
@ -144,7 +144,7 @@ struct CmdRegistryRemove : RegistryCommand, Command
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
auto registry = getRegistry();
|
auto registry = getRegistry();
|
||||||
registry->remove(parseFlakeRef(url).input);
|
registry->remove(parseFlakeRef(fetchSettings, url).input);
|
||||||
registry->write(getRegistryPath());
|
registry->write(getRegistryPath());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -185,8 +185,8 @@ struct CmdRegistryPin : RegistryCommand, EvalCommand
|
||||||
{
|
{
|
||||||
if (locked.empty()) locked = url;
|
if (locked.empty()) locked = url;
|
||||||
auto registry = getRegistry();
|
auto registry = getRegistry();
|
||||||
auto ref = parseFlakeRef(url);
|
auto ref = parseFlakeRef(fetchSettings, url);
|
||||||
auto lockedRef = parseFlakeRef(locked);
|
auto lockedRef = parseFlakeRef(fetchSettings, locked);
|
||||||
registry->remove(ref.input);
|
registry->remove(ref.input);
|
||||||
auto resolved = lockedRef.resolve(store).input.getAccessor(store).second;
|
auto resolved = lockedRef.resolve(store).input.getAccessor(store).second;
|
||||||
if (!resolved.isLocked())
|
if (!resolved.isLocked())
|
||||||
|
|
|
@ -147,7 +147,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
|
||||||
auto req = FileTransferRequest((std::string&) settings.upgradeNixStorePathUrl);
|
auto req = FileTransferRequest((std::string&) settings.upgradeNixStorePathUrl);
|
||||||
auto res = getFileTransfer()->download(req);
|
auto res = getFileTransfer()->download(req);
|
||||||
|
|
||||||
auto state = std::make_unique<EvalState>(LookupPath{}, store, evalSettings);
|
auto state = std::make_unique<EvalState>(LookupPath{}, store, fetchSettings, evalSettings);
|
||||||
auto v = state->allocValue();
|
auto v = state->allocValue();
|
||||||
state->eval(state->parseExprFromString(res.data, state->rootPath(CanonPath("/no-such-path"))), *v);
|
state->eval(state->parseExprFromString(res.data, state->rootPath(CanonPath("/no-such-path"))), *v);
|
||||||
Bindings & bindings(*state->allocBindings(0));
|
Bindings & bindings(*state->allocBindings(0));
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#include "fetch-settings.hh"
|
||||||
#include "value.hh"
|
#include "value.hh"
|
||||||
#include "nixexpr.hh"
|
#include "nixexpr.hh"
|
||||||
|
#include "nixexpr.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
|
@ -24,7 +26,7 @@ namespace nix {
|
||||||
protected:
|
protected:
|
||||||
LibExprTest()
|
LibExprTest()
|
||||||
: LibStoreTest()
|
: LibStoreTest()
|
||||||
, state({}, store, evalSettings, nullptr)
|
, state({}, store, fetchSettings, evalSettings, nullptr)
|
||||||
{
|
{
|
||||||
evalSettings.nixPath = {};
|
evalSettings.nixPath = {};
|
||||||
}
|
}
|
||||||
|
@ -43,6 +45,7 @@ namespace nix {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readOnlyMode = true;
|
bool readOnlyMode = true;
|
||||||
|
fetchers::Settings fetchSettings{};
|
||||||
EvalSettings evalSettings{readOnlyMode};
|
EvalSettings evalSettings{readOnlyMode};
|
||||||
EvalState state;
|
EvalState state;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "fetch-settings.hh"
|
||||||
#include "flake/flakeref.hh"
|
#include "flake/flakeref.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -11,8 +12,9 @@ namespace nix {
|
||||||
* --------------------------------------------------------------------------*/
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TEST(to_string, doesntReencodeUrl) {
|
TEST(to_string, doesntReencodeUrl) {
|
||||||
|
fetchers::Settings fetchSettings;
|
||||||
auto s = "http://localhost:8181/test/+3d.tar.gz";
|
auto s = "http://localhost:8181/test/+3d.tar.gz";
|
||||||
auto flakeref = parseFlakeRef(s);
|
auto flakeref = parseFlakeRef(fetchSettings, s);
|
||||||
auto parsed = flakeref.to_string();
|
auto parsed = flakeref.to_string();
|
||||||
auto expected = "http://localhost:8181/test/%2B3d.tar.gz";
|
auto expected = "http://localhost:8181/test/%2B3d.tar.gz";
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue