Merge remote-tracking branch 'upstream/master' into ca-floating-upstream
This commit is contained in:
commit
b7df353f27
59 changed files with 662 additions and 491 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -12,15 +12,6 @@ perl/Makefile.config
|
|||
/svn-revision
|
||||
/libtool
|
||||
|
||||
/corepkgs/config.nix
|
||||
|
||||
# /corepkgs/channels/
|
||||
/corepkgs/channels/unpack.sh
|
||||
|
||||
# /corepkgs/nar/
|
||||
/corepkgs/nar/nar.sh
|
||||
/corepkgs/nar/unnar.sh
|
||||
|
||||
# /doc/manual/
|
||||
/doc/manual/*.1
|
||||
/doc/manual/*.5
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
# FIXME: remove this file?
|
||||
let
|
||||
fromEnv = var: def:
|
||||
let val = builtins.getEnv var; in
|
||||
if val != "" then val else def;
|
||||
in rec {
|
||||
nixBinDir = fromEnv "NIX_BIN_DIR" "@bindir@";
|
||||
nixPrefix = "@prefix@";
|
||||
nixLibexecDir = fromEnv "NIX_LIBEXEC_DIR" "@libexecdir@";
|
||||
nixLocalstateDir = "@localstatedir@";
|
||||
nixSysconfDir = "@sysconfdir@";
|
||||
nixStoreDir = fromEnv "NIX_STORE_DIR" "@storedir@";
|
||||
}
|
|
@ -1,8 +1,4 @@
|
|||
corepkgs_FILES = \
|
||||
unpack-channel.nix \
|
||||
derivation.nix \
|
||||
fetchurl.nix
|
||||
|
||||
$(foreach file,config.nix $(corepkgs_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/corepkgs)))
|
||||
|
||||
template-files += $(d)/config.nix
|
||||
$(foreach file,$(corepkgs_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/corepkgs)))
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
. | to_entries | sort_by(.key) | map(
|
||||
" - `builtins." + .key + "` "
|
||||
+ (.value.args | map("*" + . + "*") | join(" "))
|
||||
+ " \n\n"
|
||||
+ (.value.doc | split("\n") | map(" " + . + "\n") | join("")) + "\n\n"
|
||||
) | join("")
|
14
doc/manual/generate-builtins.nix
Normal file
14
doc/manual/generate-builtins.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
with builtins;
|
||||
with import ./utils.nix;
|
||||
|
||||
builtins:
|
||||
|
||||
concatStrings (map
|
||||
(name:
|
||||
let builtin = builtins.${name}; in
|
||||
" - `builtins.${name}` " + concatStringsSep " " (map (s: "*${s}*") builtin.args)
|
||||
+ " \n\n"
|
||||
+ concatStrings (map (s: " ${s}\n") (splitLines builtin.doc)) + "\n\n"
|
||||
)
|
||||
(attrNames builtins))
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
def show_flags:
|
||||
.flags
|
||||
| map_values(select(.category != "config"))
|
||||
| to_entries
|
||||
| map(
|
||||
" - `--" + .key + "`"
|
||||
+ (if .value.shortName then " / `" + .value.shortName + "`" else "" end)
|
||||
+ (if .value.labels then " " + (.value.labels | map("*" + . + "*") | join(" ")) else "" end)
|
||||
+ " \n"
|
||||
+ " " + .value.description + "\n\n")
|
||||
| join("")
|
||||
;
|
||||
|
||||
def show_synopsis:
|
||||
"`" + .command + "` [*flags*...] " + (.args | map("*" + .label + "*" + (if has("arity") then "" else "..." end)) | join(" ")) + "\n\n"
|
||||
;
|
||||
|
||||
def show_command:
|
||||
. as $top |
|
||||
.section + " Name\n\n"
|
||||
+ "`" + .command + "` - " + .def.description + "\n\n"
|
||||
+ .section + " Synopsis\n\n"
|
||||
+ ({"command": .command, "args": .def.args} | show_synopsis)
|
||||
+ (if .def | has("doc")
|
||||
then .section + " Description\n\n" + .def.doc + "\n\n"
|
||||
else ""
|
||||
end)
|
||||
+ (if (.def.flags | length) > 0 then
|
||||
.section + " Flags\n\n"
|
||||
+ (.def | show_flags)
|
||||
else "" end)
|
||||
+ (if (.def.examples | length) > 0 then
|
||||
.section + " Examples\n\n"
|
||||
+ (.def.examples | map(.description + "\n\n```console\n" + .command + "\n```\n" ) | join("\n"))
|
||||
+ "\n"
|
||||
else "" end)
|
||||
+ (if .def.commands then .def.commands | to_entries | map(
|
||||
"# Subcommand `" + ($top.command + " " + .key) + "`\n\n"
|
||||
+ ({"command": ($top.command + " " + .key), "section": "##", "def": .value} | show_command)
|
||||
) | join("") else "" end)
|
||||
;
|
||||
|
||||
"Title: nix\n\n"
|
||||
+ ({"command": "nix", "section": "#", "def": .} | show_command)
|
56
doc/manual/generate-manpage.nix
Normal file
56
doc/manual/generate-manpage.nix
Normal file
|
@ -0,0 +1,56 @@
|
|||
with builtins;
|
||||
with import ./utils.nix;
|
||||
|
||||
let
|
||||
|
||||
showCommand =
|
||||
{ command, section, def }:
|
||||
"${section} Name\n\n"
|
||||
+ "`${command}` - ${def.description}\n\n"
|
||||
+ "${section} Synopsis\n\n"
|
||||
+ showSynopsis { inherit command; args = def.args; }
|
||||
+ (if def ? doc
|
||||
then "${section} Description\n\n" + def.doc + "\n\n"
|
||||
else "")
|
||||
+ (let s = showFlags def.flags; in
|
||||
if s != ""
|
||||
then "${section} Flags\n\n${s}"
|
||||
else "")
|
||||
+ (if def.examples or [] != []
|
||||
then
|
||||
"${section} Examples\n\n"
|
||||
+ concatStrings (map ({ description, command }: "${description}\n\n```console\n${command}\n```\n\n") def.examples)
|
||||
else "")
|
||||
+ (if def.commands or [] != []
|
||||
then concatStrings (
|
||||
map (name:
|
||||
"# Subcommand `${command} ${name}`\n\n"
|
||||
+ showCommand { command = command + " " + name; section = "##"; def = def.commands.${name}; })
|
||||
(attrNames def.commands))
|
||||
else "");
|
||||
|
||||
showFlags = flags:
|
||||
concatStrings
|
||||
(map (longName:
|
||||
let flag = flags.${longName}; in
|
||||
if flag.category or "" != "config"
|
||||
then
|
||||
" - `--${longName}`"
|
||||
+ (if flag ? shortName then " / `${flag.shortName}`" else "")
|
||||
+ (if flag ? labels then " " + (concatStringsSep " " (map (s: "*${s}*") flag.labels)) else "")
|
||||
+ " \n"
|
||||
+ " " + flag.description + "\n\n"
|
||||
else "")
|
||||
(attrNames flags));
|
||||
|
||||
showSynopsis =
|
||||
{ command, args }:
|
||||
"`${command}` [*flags*...] ${concatStringsSep " "
|
||||
(map (arg: "*${arg.label}*" + (if arg ? arity then "" else "...")) args)}\n\n";
|
||||
|
||||
in
|
||||
|
||||
command:
|
||||
|
||||
"Title: nix\n\n"
|
||||
+ showCommand { command = "nix"; section = "#"; def = command; }
|
|
@ -1,16 +0,0 @@
|
|||
. | to_entries | sort_by(.key) | map(
|
||||
" - `" + .key + "` \n\n"
|
||||
+ (.value.description | split("\n") | map(" " + . + "\n") | join("")) + "\n\n"
|
||||
+ " **Default:** " + (
|
||||
if .value.value == "" or .value.value == []
|
||||
then "*empty*"
|
||||
elif (.value.value | type) == "array"
|
||||
then "`" + (.value.value | join(" ")) + "`"
|
||||
else "`" + (.value.value | tostring) + "`"
|
||||
end)
|
||||
+ "\n\n"
|
||||
+ (if (.value.aliases | length) > 0
|
||||
then " **Deprecated alias:** " + (.value.aliases | map("`" + . + "`") | join(", ")) + "\n\n"
|
||||
else ""
|
||||
end)
|
||||
) | join("")
|
21
doc/manual/generate-options.nix
Normal file
21
doc/manual/generate-options.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
with builtins;
|
||||
with import ./utils.nix;
|
||||
|
||||
options:
|
||||
|
||||
concatStrings (map
|
||||
(name:
|
||||
let option = options.${name}; in
|
||||
" - `${name}` \n\n"
|
||||
+ concatStrings (map (s: " ${s}\n") (splitLines option.description)) + "\n\n"
|
||||
+ " **Default:** " + (
|
||||
if option.value == "" || option.value == []
|
||||
then "*empty*"
|
||||
else if isBool option.value
|
||||
then (if option.value then "`true`" else "`false`")
|
||||
else "`" + toString option.value + "`") + "\n\n"
|
||||
+ (if option.aliases != []
|
||||
then " **Deprecated alias:** " + (concatStringsSep ", " (map (s: "`${s}`") option.aliases)) + "\n\n"
|
||||
else "")
|
||||
)
|
||||
(attrNames options))
|
|
@ -15,6 +15,8 @@ clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8
|
|||
|
||||
dist-files += $(man-pages)
|
||||
|
||||
nix-eval = $(bindir)/nix eval --experimental-features nix-command -I nix/corepkgs=corepkgs --store dummy:// --impure --raw --expr
|
||||
|
||||
$(d)/%.1: $(d)/src/command-ref/%.md
|
||||
$(trace-gen) lowdown -sT man $^ -o $@
|
||||
|
||||
|
@ -24,25 +26,31 @@ $(d)/%.8: $(d)/src/command-ref/%.md
|
|||
$(d)/nix.conf.5: $(d)/src/command-ref/conf-file.md
|
||||
$(trace-gen) lowdown -sT man $^ -o $@
|
||||
|
||||
$(d)/src/command-ref/nix.md: $(d)/nix.json $(d)/generate-manpage.jq
|
||||
jq -r -f doc/manual/generate-manpage.jq $< > $@
|
||||
$(d)/src/command-ref/nix.md: $(d)/nix.json $(d)/generate-manpage.nix $(bindir)/nix
|
||||
$(trace-gen) $(nix-eval) 'import doc/manual/generate-manpage.nix (builtins.fromJSON (builtins.readFile $<))' > $@.tmp
|
||||
@mv $@.tmp $@
|
||||
|
||||
$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/generate-options.jq $(d)/src/command-ref/conf-file-prefix.md
|
||||
cat doc/manual/src/command-ref/conf-file-prefix.md > $@
|
||||
jq -r -f doc/manual/generate-options.jq $< >> $@
|
||||
$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/generate-options.nix $(d)/src/command-ref/conf-file-prefix.md $(bindir)/nix
|
||||
@cat doc/manual/src/command-ref/conf-file-prefix.md > $@.tmp
|
||||
$(trace-gen) $(nix-eval) 'import doc/manual/generate-options.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp
|
||||
@mv $@.tmp $@
|
||||
|
||||
$(d)/nix.json: $(bindir)/nix
|
||||
$(trace-gen) $(bindir)/nix __dump-args > $@
|
||||
$(trace-gen) $(bindir)/nix __dump-args > $@.tmp
|
||||
@mv $@.tmp $@
|
||||
|
||||
$(d)/conf-file.json: $(bindir)/nix
|
||||
$(trace-gen) env -i NIX_CONF_DIR=/dummy HOME=/dummy $(bindir)/nix show-config --json --experimental-features nix-command > $@
|
||||
$(trace-gen) env -i NIX_CONF_DIR=/dummy HOME=/dummy $(bindir)/nix show-config --json --experimental-features nix-command > $@.tmp
|
||||
@mv $@.tmp $@
|
||||
|
||||
$(d)/src/expressions/builtins.md: $(d)/builtins.json $(d)/generate-builtins.jq $(d)/src/expressions/builtins-prefix.md
|
||||
cat doc/manual/src/expressions/builtins-prefix.md > $@
|
||||
jq -r -f doc/manual/generate-builtins.jq $< >> $@
|
||||
$(d)/src/expressions/builtins.md: $(d)/builtins.json $(d)/generate-builtins.nix $(d)/src/expressions/builtins-prefix.md $(bindir)/nix
|
||||
@cat doc/manual/src/expressions/builtins-prefix.md > $@.tmp
|
||||
$(trace-gen) $(nix-eval) 'import doc/manual/generate-builtins.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp
|
||||
@mv $@.tmp $@
|
||||
|
||||
$(d)/builtins.json: $(bindir)/nix
|
||||
$(trace-gen) $(bindir)/nix __dump-builtins > $@
|
||||
$(trace-gen) NIX_PATH=nix/corepkgs=corepkgs $(bindir)/nix __dump-builtins > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
# Generate the HTML manual.
|
||||
install: $(docdir)/manual/index.html
|
||||
|
|
7
doc/manual/utils.nix
Normal file
7
doc/manual/utils.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
with builtins;
|
||||
|
||||
{
|
||||
splitLines = s: filter (x: !isList x) (split "\n" s);
|
||||
|
||||
concatStrings = concatStringsSep "";
|
||||
}
|
|
@ -70,19 +70,6 @@ PKG_CHECK_MODULES([NIX], [nix-store])
|
|||
|
||||
NEED_PROG([NIX], [nix])
|
||||
|
||||
# Get nix configure values
|
||||
export NIX_REMOTE=daemon
|
||||
nixbindir=$("$NIX" --experimental-features nix-command eval --raw -f '<nix/config.nix>' nixBinDir)
|
||||
nixlibexecdir=$("$NIX" --experimental-features nix-command eval --raw -f '<nix/config.nix>' nixLibexecDir)
|
||||
nixlocalstatedir=$("$NIX" --experimental-features nix-command eval --raw -f '<nix/config.nix>' nixLocalstateDir)
|
||||
nixsysconfdir=$("$NIX" --experimental-features nix-command eval --raw -f '<nix/config.nix>' nixSysconfDir)
|
||||
nixstoredir=$("$NIX" --experimental-features nix-command eval --raw -f '<nix/config.nix>' nixStoreDir)
|
||||
AC_SUBST(nixbindir)
|
||||
AC_SUBST(nixlibexecdir)
|
||||
AC_SUBST(nixlocalstatedir)
|
||||
AC_SUBST(nixsysconfdir)
|
||||
AC_SUBST(nixstoredir)
|
||||
|
||||
# Expand all variables in config.status.
|
||||
test "$prefix" = NONE && prefix=$ac_default_prefix
|
||||
test "$exec_prefix" = NONE && exec_prefix='${prefix}'
|
||||
|
|
|
@ -4,14 +4,8 @@ use MIME::Base64;
|
|||
|
||||
$version = "@PACKAGE_VERSION@";
|
||||
|
||||
$binDir = $ENV{"NIX_BIN_DIR"} || "@nixbindir@";
|
||||
$libexecDir = $ENV{"NIX_LIBEXEC_DIR"} || "@nixlibexecdir@";
|
||||
$stateDir = $ENV{"NIX_STATE_DIR"} || "@nixlocalstatedir@/nix";
|
||||
$logDir = $ENV{"NIX_LOG_DIR"} || "@nixlocalstatedir@/log/nix";
|
||||
$confDir = $ENV{"NIX_CONF_DIR"} || "@nixsysconfdir@/nix";
|
||||
$storeDir = $ENV{"NIX_STORE_DIR"} || "@nixstoredir@";
|
||||
|
||||
$useBindings = 1;
|
||||
$binDir = Nix::Store::getBinDir;
|
||||
$storeDir = Nix::Store::getStoreDir;
|
||||
|
||||
%config = ();
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package Nix::Store;
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Nix::Config;
|
||||
|
||||
require Exporter;
|
||||
|
||||
|
@ -22,6 +21,7 @@ our @EXPORT = qw(
|
|||
addToStore makeFixedOutputPath
|
||||
derivationFromPath
|
||||
addTempRoot
|
||||
getBinDir getStoreDir
|
||||
);
|
||||
|
||||
our $VERSION = '0.15';
|
||||
|
@ -34,62 +34,8 @@ sub backtick {
|
|||
return $res;
|
||||
}
|
||||
|
||||
if ($Nix::Config::useBindings) {
|
||||
require XSLoader;
|
||||
XSLoader::load('Nix::Store', $VERSION);
|
||||
} else {
|
||||
|
||||
# Provide slow fallbacks of some functions on platforms that don't
|
||||
# support the Perl bindings.
|
||||
|
||||
use File::Temp;
|
||||
use Fcntl qw/F_SETFD/;
|
||||
|
||||
*hashFile = sub {
|
||||
my ($algo, $base32, $path) = @_;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-hash", "--flat", $path, "--type", $algo, $base32 ? "--base32" : ());
|
||||
chomp $res;
|
||||
return $res;
|
||||
};
|
||||
|
||||
*hashPath = sub {
|
||||
my ($algo, $base32, $path) = @_;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-hash", $path, "--type", $algo, $base32 ? "--base32" : ());
|
||||
chomp $res;
|
||||
return $res;
|
||||
};
|
||||
|
||||
*hashString = sub {
|
||||
my ($algo, $base32, $s) = @_;
|
||||
my $fh = File::Temp->new();
|
||||
print $fh $s;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-hash", $fh->filename, "--type", $algo, $base32 ? "--base32" : ());
|
||||
chomp $res;
|
||||
return $res;
|
||||
};
|
||||
|
||||
*addToStore = sub {
|
||||
my ($srcPath, $recursive, $algo) = @_;
|
||||
die "not implemented" if $recursive || $algo ne "sha256";
|
||||
my $res = backtick("$Nix::Config::binDir/nix-store", "--add", $srcPath);
|
||||
chomp $res;
|
||||
return $res;
|
||||
};
|
||||
|
||||
*isValidPath = sub {
|
||||
my ($path) = @_;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-store", "--check-validity", "--print-invalid", $path);
|
||||
chomp $res;
|
||||
return $res ne $path;
|
||||
};
|
||||
|
||||
*queryPathHash = sub {
|
||||
my ($path) = @_;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-store", "--query", "--hash", $path);
|
||||
chomp $res;
|
||||
return $res;
|
||||
};
|
||||
}
|
||||
require XSLoader;
|
||||
XSLoader::load('Nix::Store', $VERSION);
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
|
|
@ -351,3 +351,13 @@ void addTempRoot(char * storePath)
|
|||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * getBinDir()
|
||||
PPCODE:
|
||||
XPUSHs(sv_2mortal(newSVpv(settings.nixBinDir.c_str(), 0)));
|
||||
|
||||
|
||||
SV * getStoreDir()
|
||||
PPCODE:
|
||||
XPUSHs(sv_2mortal(newSVpv(settings.nixStore.c_str(), 0)));
|
||||
|
|
|
@ -370,7 +370,11 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
|
|||
for (auto & i : _searchPath) addToSearchPath(i);
|
||||
for (auto & i : evalSettings.nixPath.get()) addToSearchPath(i);
|
||||
}
|
||||
addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs", true));
|
||||
|
||||
try {
|
||||
addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs", true));
|
||||
} catch (Error &) {
|
||||
}
|
||||
|
||||
if (evalSettings.restrictEval || evalSettings.pureEval) {
|
||||
allowedPaths = PathSet();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace nix {
|
||||
class Store;
|
||||
struct StorePath;
|
||||
class StorePath;
|
||||
}
|
||||
|
||||
namespace nix::flake {
|
||||
|
|
|
@ -42,6 +42,6 @@ $(eval $(call install-file-in, $(d)/nix-expr.pc, $(prefix)/lib/pkgconfig, 0644))
|
|||
$(foreach i, $(wildcard src/libexpr/flake/*.hh), \
|
||||
$(eval $(call install-file-in, $(i), $(includedir)/nix/flake, 0644)))
|
||||
|
||||
$(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh
|
||||
$(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh $(d)/primops/derivation.nix.gen.hh
|
||||
|
||||
$(d)/flake/flake.cc: $(d)/flake/call-flake.nix.gen.hh
|
||||
|
|
|
@ -1704,7 +1704,7 @@ static RegisterPrimOp primop_toFile({
|
|||
...
|
||||
cp ${configFile} $out/etc/foo.conf
|
||||
";
|
||||
```
|
||||
```
|
||||
|
||||
Note that `${configFile}` is an
|
||||
[antiquotation](language-values.md), so the result of the
|
||||
|
@ -3565,9 +3565,10 @@ void EvalState::createBaseEnv()
|
|||
|
||||
/* Add a wrapper around the derivation primop that computes the
|
||||
`drvPath' and `outPath' attributes lazily. */
|
||||
string path = canonPath(settings.nixDataDir + "/nix/corepkgs/derivation.nix", true);
|
||||
sDerivationNix = symbols.create(path);
|
||||
evalFile(path, v);
|
||||
sDerivationNix = symbols.create("//builtin/derivation.nix");
|
||||
eval(parse(
|
||||
#include "primops/derivation.nix.gen.hh"
|
||||
, foFile, sDerivationNix, "/", staticBaseEnv), v);
|
||||
addConstant("derivation", v);
|
||||
|
||||
/* Now that we've added all primops, sort the `builtins' set,
|
||||
|
|
|
@ -23,7 +23,7 @@ struct InputScheme;
|
|||
|
||||
struct Input
|
||||
{
|
||||
friend class InputScheme;
|
||||
friend struct InputScheme;
|
||||
|
||||
std::shared_ptr<InputScheme> scheme; // note: can be null
|
||||
Attrs attrs;
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
namespace nix {
|
||||
|
||||
BinaryCacheStore::BinaryCacheStore(const Params & params)
|
||||
: Store(params)
|
||||
: BinaryCacheStoreConfig(params)
|
||||
, Store(params)
|
||||
{
|
||||
if (secretKeyFile != "")
|
||||
secretKey = std::unique_ptr<SecretKey>(new SecretKey(readFile(secretKeyFile)));
|
||||
|
|
|
@ -11,17 +11,21 @@ namespace nix {
|
|||
|
||||
struct NarInfo;
|
||||
|
||||
class BinaryCacheStore : public Store
|
||||
struct BinaryCacheStoreConfig : virtual StoreConfig
|
||||
{
|
||||
public:
|
||||
using StoreConfig::StoreConfig;
|
||||
|
||||
const Setting<std::string> compression{this, "xz", "compression", "NAR compression method ('xz', 'bzip2', or 'none')"};
|
||||
const Setting<bool> writeNARListing{this, false, "write-nar-listing", "whether to write a JSON file listing the files in each NAR"};
|
||||
const Setting<bool> writeDebugInfo{this, false, "index-debug-info", "whether to index DWARF debug info files by build ID"};
|
||||
const Setting<Path> secretKeyFile{this, "", "secret-key", "path to secret key used to sign the binary cache"};
|
||||
const Setting<Path> localNarCache{this, "", "local-nar-cache", "path to a local cache of NARs"};
|
||||
const Setting<bool> parallelCompression{this, false, "parallel-compression",
|
||||
const Setting<std::string> compression{(StoreConfig*) this, "xz", "compression", "NAR compression method ('xz', 'bzip2', or 'none')"};
|
||||
const Setting<bool> writeNARListing{(StoreConfig*) this, false, "write-nar-listing", "whether to write a JSON file listing the files in each NAR"};
|
||||
const Setting<bool> writeDebugInfo{(StoreConfig*) this, false, "index-debug-info", "whether to index DWARF debug info files by build ID"};
|
||||
const Setting<Path> secretKeyFile{(StoreConfig*) this, "", "secret-key", "path to secret key used to sign the binary cache"};
|
||||
const Setting<Path> localNarCache{(StoreConfig*) this, "", "local-nar-cache", "path to a local cache of NARs"};
|
||||
const Setting<bool> parallelCompression{(StoreConfig*) this, false, "parallel-compression",
|
||||
"enable multi-threading compression, available for xz only currently"};
|
||||
};
|
||||
|
||||
class BinaryCacheStore : public Store, public virtual BinaryCacheStoreConfig
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
|
@ -58,7 +62,7 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
virtual void init();
|
||||
virtual void init() override;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -2910,18 +2910,23 @@ void DerivationGoal::writeStructuredAttrs()
|
|||
chownToBuilder(tmpDir + "/.attrs.sh");
|
||||
}
|
||||
|
||||
struct RestrictedStoreConfig : LocalFSStoreConfig
|
||||
{
|
||||
using LocalFSStoreConfig::LocalFSStoreConfig;
|
||||
const std::string name() { return "Restricted Store"; }
|
||||
};
|
||||
|
||||
/* A wrapper around LocalStore that only allows building/querying of
|
||||
paths that are in the input closures of the build or were added via
|
||||
recursive Nix calls. */
|
||||
struct RestrictedStore : public LocalFSStore
|
||||
struct RestrictedStore : public LocalFSStore, public virtual RestrictedStoreConfig
|
||||
{
|
||||
ref<LocalStore> next;
|
||||
|
||||
DerivationGoal & goal;
|
||||
|
||||
RestrictedStore(const Params & params, ref<LocalStore> next, DerivationGoal & goal)
|
||||
: Store(params), LocalFSStore(params), next(next), goal(goal)
|
||||
: StoreConfig(params), Store(params), LocalFSStore(params), next(next), goal(goal)
|
||||
{ }
|
||||
|
||||
Path getRealStoreDir() override
|
||||
|
|
|
@ -2,17 +2,27 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
static std::string uriScheme = "dummy://";
|
||||
struct DummyStoreConfig : virtual StoreConfig {
|
||||
using StoreConfig::StoreConfig;
|
||||
|
||||
struct DummyStore : public Store
|
||||
const std::string name() override { return "Dummy Store"; }
|
||||
};
|
||||
|
||||
struct DummyStore : public Store, public virtual DummyStoreConfig
|
||||
{
|
||||
DummyStore(const Params & params)
|
||||
: Store(params)
|
||||
DummyStore(const std::string scheme, const std::string uri, const Params & params)
|
||||
: DummyStore(params)
|
||||
{ }
|
||||
|
||||
DummyStore(const Params & params)
|
||||
: StoreConfig(params)
|
||||
, Store(params)
|
||||
{
|
||||
}
|
||||
|
||||
string getUri() override
|
||||
{
|
||||
return uriScheme;
|
||||
return *uriSchemes().begin();
|
||||
}
|
||||
|
||||
void queryPathInfoUncached(const StorePath & path,
|
||||
|
@ -21,6 +31,10 @@ struct DummyStore : public Store
|
|||
callback(nullptr);
|
||||
}
|
||||
|
||||
static std::set<std::string> uriSchemes() {
|
||||
return {"dummy"};
|
||||
}
|
||||
|
||||
std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override
|
||||
{ unsupported("queryPathFromHashPart"); }
|
||||
|
||||
|
@ -48,12 +62,6 @@ struct DummyStore : public Store
|
|||
{ unsupported("buildDerivation"); }
|
||||
};
|
||||
|
||||
static RegisterStoreImplementation regStore([](
|
||||
const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
{
|
||||
if (uri != uriScheme) return nullptr;
|
||||
return std::make_shared<DummyStore>(params);
|
||||
});
|
||||
static RegisterStoreImplementation<DummyStore, DummyStoreConfig> regStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -574,9 +574,12 @@ bool LocalStore::canReachRoot(GCState & state, StorePathSet & visited, const Sto
|
|||
/* If keep-derivations is set and this is a derivation, then
|
||||
don't delete the derivation if any of the outputs are alive. */
|
||||
if (state.gcKeepDerivations && path.isDerivation()) {
|
||||
for (auto & i : queryDerivationOutputs(path))
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path)
|
||||
incoming.insert(i);
|
||||
for (auto & [name, maybeOutPath] : queryPartialDerivationOutputMap(path))
|
||||
if (maybeOutPath &&
|
||||
isValidPath(*maybeOutPath) &&
|
||||
queryPathInfo(*maybeOutPath)->deriver == path
|
||||
)
|
||||
incoming.insert(*maybeOutPath);
|
||||
}
|
||||
|
||||
/* If keep-outputs is set, then don't delete this path if there
|
||||
|
|
|
@ -162,11 +162,6 @@ template<> std::string BaseSetting<SandboxMode>::to_string() const
|
|||
else abort();
|
||||
}
|
||||
|
||||
template<> nlohmann::json BaseSetting<SandboxMode>::toJSON()
|
||||
{
|
||||
return AbstractSetting::toJSON();
|
||||
}
|
||||
|
||||
template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::string & category)
|
||||
{
|
||||
args.addFlag({
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "types.hh"
|
||||
#include "config.hh"
|
||||
#include "abstractsettingtojson.hh"
|
||||
#include "util.hh"
|
||||
|
||||
#include <map>
|
||||
|
|
|
@ -7,7 +7,14 @@ namespace nix {
|
|||
|
||||
MakeError(UploadToHTTP, Error);
|
||||
|
||||
class HttpBinaryCacheStore : public BinaryCacheStore
|
||||
struct HttpBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
|
||||
{
|
||||
using BinaryCacheStoreConfig::BinaryCacheStoreConfig;
|
||||
|
||||
const std::string name() override { return "Http Binary Cache Store"; }
|
||||
};
|
||||
|
||||
class HttpBinaryCacheStore : public BinaryCacheStore, public HttpBinaryCacheStoreConfig
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -24,9 +31,12 @@ private:
|
|||
public:
|
||||
|
||||
HttpBinaryCacheStore(
|
||||
const Params & params, const Path & _cacheUri)
|
||||
: BinaryCacheStore(params)
|
||||
, cacheUri(_cacheUri)
|
||||
const std::string & scheme,
|
||||
const Path & _cacheUri,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, BinaryCacheStore(params)
|
||||
, cacheUri(scheme + "://" + _cacheUri)
|
||||
{
|
||||
if (cacheUri.back() == '/')
|
||||
cacheUri.pop_back();
|
||||
|
@ -55,6 +65,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static std::set<std::string> uriSchemes()
|
||||
{
|
||||
static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1";
|
||||
auto ret = std::set<std::string>({"http", "https"});
|
||||
if (forceHttp) ret.insert("file");
|
||||
return ret;
|
||||
}
|
||||
protected:
|
||||
|
||||
void maybeDisable()
|
||||
|
@ -162,18 +179,6 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
static RegisterStoreImplementation regStore([](
|
||||
const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
{
|
||||
static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1";
|
||||
if (std::string(uri, 0, 7) != "http://" &&
|
||||
std::string(uri, 0, 8) != "https://" &&
|
||||
(!forceHttp || std::string(uri, 0, 7) != "file://"))
|
||||
return 0;
|
||||
auto store = std::make_shared<HttpBinaryCacheStore>(params, uri);
|
||||
store->init();
|
||||
return store;
|
||||
});
|
||||
static RegisterStoreImplementation<HttpBinaryCacheStore, HttpBinaryCacheStoreConfig> regStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -9,18 +9,24 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
static std::string uriScheme = "ssh://";
|
||||
|
||||
struct LegacySSHStore : public Store
|
||||
struct LegacySSHStoreConfig : virtual StoreConfig
|
||||
{
|
||||
const Setting<int> maxConnections{this, 1, "max-connections", "maximum number of concurrent SSH connections"};
|
||||
const Setting<Path> sshKey{this, "", "ssh-key", "path to an SSH private key"};
|
||||
const Setting<bool> compress{this, false, "compress", "whether to compress the connection"};
|
||||
const Setting<Path> remoteProgram{this, "nix-store", "remote-program", "path to the nix-store executable on the remote system"};
|
||||
const Setting<std::string> remoteStore{this, "", "remote-store", "URI of the store on the remote system"};
|
||||
using StoreConfig::StoreConfig;
|
||||
const Setting<int> maxConnections{(StoreConfig*) this, 1, "max-connections", "maximum number of concurrent SSH connections"};
|
||||
const Setting<Path> sshKey{(StoreConfig*) this, "", "ssh-key", "path to an SSH private key"};
|
||||
const Setting<bool> compress{(StoreConfig*) this, false, "compress", "whether to compress the connection"};
|
||||
const Setting<Path> remoteProgram{(StoreConfig*) this, "nix-store", "remote-program", "path to the nix-store executable on the remote system"};
|
||||
const Setting<std::string> remoteStore{(StoreConfig*) this, "", "remote-store", "URI of the store on the remote system"};
|
||||
|
||||
const std::string name() override { return "Legacy SSH Store"; }
|
||||
};
|
||||
|
||||
struct LegacySSHStore : public Store, public virtual LegacySSHStoreConfig
|
||||
{
|
||||
// Hack for getting remote build log output.
|
||||
const Setting<int> logFD{this, -1, "log-fd", "file descriptor to which SSH's stderr is connected"};
|
||||
// Intentionally not in `LegacySSHStoreConfig` so that it doesn't appear in
|
||||
// the documentation
|
||||
const Setting<int> logFD{(StoreConfig*) this, -1, "log-fd", "file descriptor to which SSH's stderr is connected"};
|
||||
|
||||
struct Connection
|
||||
{
|
||||
|
@ -37,8 +43,11 @@ struct LegacySSHStore : public Store
|
|||
|
||||
SSHMaster master;
|
||||
|
||||
LegacySSHStore(const string & host, const Params & params)
|
||||
: Store(params)
|
||||
static std::set<std::string> uriSchemes() { return {"ssh"}; }
|
||||
|
||||
LegacySSHStore(const string & scheme, const string & host, const Params & params)
|
||||
: StoreConfig(params)
|
||||
, Store(params)
|
||||
, host(host)
|
||||
, connections(make_ref<Pool<Connection>>(
|
||||
std::max(1, (int) maxConnections),
|
||||
|
@ -84,7 +93,7 @@ struct LegacySSHStore : public Store
|
|||
|
||||
string getUri() override
|
||||
{
|
||||
return uriScheme + host;
|
||||
return *uriSchemes().begin() + "://" + host;
|
||||
}
|
||||
|
||||
void queryPathInfoUncached(const StorePath & path,
|
||||
|
@ -325,12 +334,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
static RegisterStoreImplementation regStore([](
|
||||
const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
{
|
||||
if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0;
|
||||
return std::make_shared<LegacySSHStore>(std::string(uri, uriScheme.size()), params);
|
||||
});
|
||||
static RegisterStoreImplementation<LegacySSHStore, LegacySSHStoreConfig> regStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,14 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
class LocalBinaryCacheStore : public BinaryCacheStore
|
||||
struct LocalBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
|
||||
{
|
||||
using BinaryCacheStoreConfig::BinaryCacheStoreConfig;
|
||||
|
||||
const std::string name() override { return "Local Binary Cache Store"; }
|
||||
};
|
||||
|
||||
class LocalBinaryCacheStore : public BinaryCacheStore, public virtual LocalBinaryCacheStoreConfig
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -13,8 +20,11 @@ private:
|
|||
public:
|
||||
|
||||
LocalBinaryCacheStore(
|
||||
const Params & params, const Path & binaryCacheDir)
|
||||
: BinaryCacheStore(params)
|
||||
const std::string scheme,
|
||||
const Path & binaryCacheDir,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, BinaryCacheStore(params)
|
||||
, binaryCacheDir(binaryCacheDir)
|
||||
{
|
||||
}
|
||||
|
@ -26,6 +36,8 @@ public:
|
|||
return "file://" + binaryCacheDir;
|
||||
}
|
||||
|
||||
static std::set<std::string> uriSchemes();
|
||||
|
||||
protected:
|
||||
|
||||
bool fileExists(const std::string & path) override;
|
||||
|
@ -85,16 +97,14 @@ bool LocalBinaryCacheStore::fileExists(const std::string & path)
|
|||
return pathExists(binaryCacheDir + "/" + path);
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation regStore([](
|
||||
const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
std::set<std::string> LocalBinaryCacheStore::uriSchemes()
|
||||
{
|
||||
if (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") == "1" ||
|
||||
std::string(uri, 0, 7) != "file://")
|
||||
return 0;
|
||||
auto store = std::make_shared<LocalBinaryCacheStore>(params, std::string(uri, 7));
|
||||
store->init();
|
||||
return store;
|
||||
});
|
||||
if (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") == "1")
|
||||
return {};
|
||||
else
|
||||
return {"file"};
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation<LocalBinaryCacheStore, LocalBinaryCacheStoreConfig> regStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@ namespace nix {
|
|||
|
||||
|
||||
LocalStore::LocalStore(const Params & params)
|
||||
: Store(params)
|
||||
: StoreConfig(params)
|
||||
, Store(params)
|
||||
, LocalFSStore(params)
|
||||
, realStoreDir_{this, false, rootDir != "" ? rootDir + "/nix/store" : storeDir, "real",
|
||||
"physical path to the Nix store"}
|
||||
|
|
|
@ -30,8 +30,19 @@ struct OptimiseStats
|
|||
uint64_t blocksFreed = 0;
|
||||
};
|
||||
|
||||
struct LocalStoreConfig : virtual LocalFSStoreConfig
|
||||
{
|
||||
using LocalFSStoreConfig::LocalFSStoreConfig;
|
||||
|
||||
class LocalStore : public LocalFSStore
|
||||
Setting<bool> requireSigs{(StoreConfig*) this,
|
||||
settings.requireSigs,
|
||||
"require-sigs", "whether store paths should have a trusted signature on import"};
|
||||
|
||||
const std::string name() override { return "Local Store"; }
|
||||
};
|
||||
|
||||
|
||||
class LocalStore : public LocalFSStore, public virtual LocalStoreConfig
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -95,10 +106,6 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
Setting<bool> requireSigs{(Store*) this,
|
||||
settings.requireSigs,
|
||||
"require-sigs", "whether store paths should have a trusted signature on import"};
|
||||
|
||||
const PublicKeys & getPublicKeys();
|
||||
|
||||
public:
|
||||
|
|
|
@ -94,9 +94,19 @@ void write(const Store & store, Sink & out, const std::optional<StorePath> & sto
|
|||
/* TODO: Separate these store impls into different files, give them better names */
|
||||
RemoteStore::RemoteStore(const Params & params)
|
||||
: Store(params)
|
||||
, RemoteStoreConfig(params)
|
||||
, connections(make_ref<Pool<Connection>>(
|
||||
std::max(1, (int) maxConnections),
|
||||
[this]() { return openConnectionWrapper(); },
|
||||
[this]() {
|
||||
auto conn = openConnectionWrapper();
|
||||
try {
|
||||
initConnection(*conn);
|
||||
} catch (...) {
|
||||
failed = true;
|
||||
throw;
|
||||
}
|
||||
return conn;
|
||||
},
|
||||
[this](const ref<Connection> & r) {
|
||||
return
|
||||
r->to.good()
|
||||
|
@ -123,19 +133,21 @@ ref<RemoteStore::Connection> RemoteStore::openConnectionWrapper()
|
|||
|
||||
|
||||
UDSRemoteStore::UDSRemoteStore(const Params & params)
|
||||
: Store(params)
|
||||
: StoreConfig(params)
|
||||
, Store(params)
|
||||
, LocalFSStore(params)
|
||||
, RemoteStore(params)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
UDSRemoteStore::UDSRemoteStore(std::string socket_path, const Params & params)
|
||||
: Store(params)
|
||||
, LocalFSStore(params)
|
||||
, RemoteStore(params)
|
||||
, path(socket_path)
|
||||
UDSRemoteStore::UDSRemoteStore(
|
||||
const std::string scheme,
|
||||
std::string socket_path,
|
||||
const Params & params)
|
||||
: UDSRemoteStore(params)
|
||||
{
|
||||
path.emplace(socket_path);
|
||||
}
|
||||
|
||||
|
||||
|
@ -179,8 +191,6 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
|
|||
|
||||
conn->startTime = std::chrono::steady_clock::now();
|
||||
|
||||
initConnection(*conn);
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
@ -982,14 +992,6 @@ std::exception_ptr RemoteStore::Connection::processStderr(Sink * sink, Source *
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static std::string uriScheme = "unix://";
|
||||
|
||||
static RegisterStoreImplementation regStore([](
|
||||
const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
{
|
||||
if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0;
|
||||
return std::make_shared<UDSRemoteStore>(std::string(uri, uriScheme.size()), params);
|
||||
});
|
||||
static RegisterStoreImplementation<UDSRemoteStore, UDSRemoteStoreConfig> regStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -16,19 +16,23 @@ struct FdSource;
|
|||
template<typename T> class Pool;
|
||||
struct ConnectionHandle;
|
||||
|
||||
struct RemoteStoreConfig : virtual StoreConfig
|
||||
{
|
||||
using StoreConfig::StoreConfig;
|
||||
|
||||
const Setting<int> maxConnections{(StoreConfig*) this, 1,
|
||||
"max-connections", "maximum number of concurrent connections to the Nix daemon"};
|
||||
|
||||
const Setting<unsigned int> maxConnectionAge{(StoreConfig*) this, std::numeric_limits<unsigned int>::max(),
|
||||
"max-connection-age", "number of seconds to reuse a connection"};
|
||||
};
|
||||
|
||||
/* FIXME: RemoteStore is a misnomer - should be something like
|
||||
DaemonStore. */
|
||||
class RemoteStore : public virtual Store
|
||||
class RemoteStore : public virtual Store, public virtual RemoteStoreConfig
|
||||
{
|
||||
public:
|
||||
|
||||
const Setting<int> maxConnections{(Store*) this, 1,
|
||||
"max-connections", "maximum number of concurrent connections to the Nix daemon"};
|
||||
|
||||
const Setting<unsigned int> maxConnectionAge{(Store*) this, std::numeric_limits<unsigned int>::max(),
|
||||
"max-connection-age", "number of seconds to reuse a connection"};
|
||||
|
||||
virtual bool sameMachine() = 0;
|
||||
|
||||
RemoteStore(const Params & params);
|
||||
|
@ -102,8 +106,6 @@ public:
|
|||
|
||||
void flushBadConnections();
|
||||
|
||||
protected:
|
||||
|
||||
struct Connection
|
||||
{
|
||||
AutoCloseFD fd;
|
||||
|
@ -119,6 +121,8 @@ protected:
|
|||
|
||||
ref<Connection> openConnectionWrapper();
|
||||
|
||||
protected:
|
||||
|
||||
virtual ref<Connection> openConnection() = 0;
|
||||
|
||||
void initConnection(Connection & conn);
|
||||
|
@ -141,15 +145,35 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class UDSRemoteStore : public LocalFSStore, public RemoteStore
|
||||
struct UDSRemoteStoreConfig : virtual LocalFSStoreConfig, virtual RemoteStoreConfig
|
||||
{
|
||||
UDSRemoteStoreConfig(const Store::Params & params)
|
||||
: StoreConfig(params)
|
||||
, LocalFSStoreConfig(params)
|
||||
, RemoteStoreConfig(params)
|
||||
{
|
||||
}
|
||||
|
||||
UDSRemoteStoreConfig()
|
||||
: UDSRemoteStoreConfig(Store::Params({}))
|
||||
{
|
||||
}
|
||||
|
||||
const std::string name() override { return "Local Daemon Store"; }
|
||||
};
|
||||
|
||||
class UDSRemoteStore : public LocalFSStore, public RemoteStore, public virtual UDSRemoteStoreConfig
|
||||
{
|
||||
public:
|
||||
|
||||
UDSRemoteStore(const Params & params);
|
||||
UDSRemoteStore(std::string path, const Params & params);
|
||||
UDSRemoteStore(const std::string scheme, std::string path, const Params & params);
|
||||
|
||||
std::string getUri() override;
|
||||
|
||||
static std::set<std::string> uriSchemes()
|
||||
{ return {"unix"}; }
|
||||
|
||||
bool sameMachine() override
|
||||
{ return true; }
|
||||
|
||||
|
|
|
@ -172,20 +172,26 @@ S3Helper::FileTransferResult S3Helper::getObject(
|
|||
return res;
|
||||
}
|
||||
|
||||
struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
|
||||
struct S3BinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
|
||||
{
|
||||
const Setting<std::string> profile{this, "", "profile", "The name of the AWS configuration profile to use."};
|
||||
const Setting<std::string> region{this, Aws::Region::US_EAST_1, "region", {"aws-region"}};
|
||||
const Setting<std::string> scheme{this, "", "scheme", "The scheme to use for S3 requests, https by default."};
|
||||
const Setting<std::string> endpoint{this, "", "endpoint", "An optional override of the endpoint to use when talking to S3."};
|
||||
const Setting<std::string> narinfoCompression{this, "", "narinfo-compression", "compression method for .narinfo files"};
|
||||
const Setting<std::string> lsCompression{this, "", "ls-compression", "compression method for .ls files"};
|
||||
const Setting<std::string> logCompression{this, "", "log-compression", "compression method for log/* files"};
|
||||
using BinaryCacheStoreConfig::BinaryCacheStoreConfig;
|
||||
const Setting<std::string> profile{(StoreConfig*) this, "", "profile", "The name of the AWS configuration profile to use."};
|
||||
const Setting<std::string> region{(StoreConfig*) this, Aws::Region::US_EAST_1, "region", {"aws-region"}};
|
||||
const Setting<std::string> scheme{(StoreConfig*) this, "", "scheme", "The scheme to use for S3 requests, https by default."};
|
||||
const Setting<std::string> endpoint{(StoreConfig*) this, "", "endpoint", "An optional override of the endpoint to use when talking to S3."};
|
||||
const Setting<std::string> narinfoCompression{(StoreConfig*) this, "", "narinfo-compression", "compression method for .narinfo files"};
|
||||
const Setting<std::string> lsCompression{(StoreConfig*) this, "", "ls-compression", "compression method for .ls files"};
|
||||
const Setting<std::string> logCompression{(StoreConfig*) this, "", "log-compression", "compression method for log/* files"};
|
||||
const Setting<bool> multipartUpload{
|
||||
this, false, "multipart-upload", "whether to use multi-part uploads"};
|
||||
(StoreConfig*) this, false, "multipart-upload", "whether to use multi-part uploads"};
|
||||
const Setting<uint64_t> bufferSize{
|
||||
this, 5 * 1024 * 1024, "buffer-size", "size (in bytes) of each part in multi-part uploads"};
|
||||
(StoreConfig*) this, 5 * 1024 * 1024, "buffer-size", "size (in bytes) of each part in multi-part uploads"};
|
||||
|
||||
const std::string name() override { return "S3 Binary Cache Store"; }
|
||||
};
|
||||
|
||||
struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore, virtual S3BinaryCacheStoreConfig
|
||||
{
|
||||
std::string bucketName;
|
||||
|
||||
Stats stats;
|
||||
|
@ -193,8 +199,11 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
|
|||
S3Helper s3Helper;
|
||||
|
||||
S3BinaryCacheStoreImpl(
|
||||
const Params & params, const std::string & bucketName)
|
||||
: S3BinaryCacheStore(params)
|
||||
const std::string & scheme,
|
||||
const std::string & bucketName,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, S3BinaryCacheStore(params)
|
||||
, bucketName(bucketName)
|
||||
, s3Helper(profile, region, scheme, endpoint)
|
||||
{
|
||||
|
@ -426,17 +435,11 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
|
|||
return paths;
|
||||
}
|
||||
|
||||
static std::set<std::string> uriSchemes() { return {"s3"}; }
|
||||
|
||||
};
|
||||
|
||||
static RegisterStoreImplementation regStore([](
|
||||
const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
{
|
||||
if (std::string(uri, 0, 5) != "s3://") return 0;
|
||||
auto store = std::make_shared<S3BinaryCacheStoreImpl>(params, std::string(uri, 5));
|
||||
store->init();
|
||||
return store;
|
||||
});
|
||||
static RegisterStoreImplementation<S3BinaryCacheStoreImpl, S3BinaryCacheStoreConfig> regStore;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -8,19 +8,25 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
static std::string uriScheme = "ssh-ng://";
|
||||
struct SSHStoreConfig : virtual RemoteStoreConfig
|
||||
{
|
||||
using RemoteStoreConfig::RemoteStoreConfig;
|
||||
|
||||
class SSHStore : public RemoteStore
|
||||
const Setting<Path> sshKey{(StoreConfig*) this, "", "ssh-key", "path to an SSH private key"};
|
||||
const Setting<bool> compress{(StoreConfig*) this, false, "compress", "whether to compress the connection"};
|
||||
const Setting<Path> remoteProgram{(StoreConfig*) this, "nix-daemon", "remote-program", "path to the nix-daemon executable on the remote system"};
|
||||
const Setting<std::string> remoteStore{(StoreConfig*) this, "", "remote-store", "URI of the store on the remote system"};
|
||||
|
||||
const std::string name() override { return "SSH Store"; }
|
||||
};
|
||||
|
||||
class SSHStore : public virtual RemoteStore, public virtual SSHStoreConfig
|
||||
{
|
||||
public:
|
||||
|
||||
const Setting<Path> sshKey{(Store*) this, "", "ssh-key", "path to an SSH private key"};
|
||||
const Setting<bool> compress{(Store*) this, false, "compress", "whether to compress the connection"};
|
||||
const Setting<Path> remoteProgram{(Store*) this, "nix-daemon", "remote-program", "path to the nix-daemon executable on the remote system"};
|
||||
const Setting<std::string> remoteStore{(Store*) this, "", "remote-store", "URI of the store on the remote system"};
|
||||
|
||||
SSHStore(const std::string & host, const Params & params)
|
||||
: Store(params)
|
||||
SSHStore(const std::string & scheme, const std::string & host, const Params & params)
|
||||
: StoreConfig(params)
|
||||
, Store(params)
|
||||
, RemoteStore(params)
|
||||
, host(host)
|
||||
, master(
|
||||
|
@ -32,9 +38,11 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
static std::set<std::string> uriSchemes() { return {"ssh-ng"}; }
|
||||
|
||||
std::string getUri() override
|
||||
{
|
||||
return uriScheme + host;
|
||||
return *uriSchemes().begin() + "://" + host;
|
||||
}
|
||||
|
||||
bool sameMachine() override
|
||||
|
@ -72,16 +80,9 @@ ref<RemoteStore::Connection> SSHStore::openConnection()
|
|||
+ (remoteStore.get() == "" ? "" : " --store " + shellEscape(remoteStore.get())));
|
||||
conn->to = FdSink(conn->sshConn->in.get());
|
||||
conn->from = FdSource(conn->sshConn->out.get());
|
||||
initConnection(*conn);
|
||||
return conn;
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation regStore([](
|
||||
const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
{
|
||||
if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0;
|
||||
return std::make_shared<SSHStore>(std::string(uri, uriScheme.size()), params);
|
||||
});
|
||||
static RegisterStoreImplementation<SSHStore, SSHStoreConfig> regStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -346,7 +346,7 @@ ValidPathInfo Store::addToStoreSlow(std::string_view name, const Path & srcPath,
|
|||
|
||||
|
||||
Store::Store(const Params & params)
|
||||
: Config(params)
|
||||
: StoreConfig(params)
|
||||
, state({(size_t) pathInfoCacheSize})
|
||||
{
|
||||
}
|
||||
|
@ -1009,7 +1009,6 @@ Derivation Store::readDerivation(const StorePath & drvPath)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1019,9 +1018,6 @@ Derivation Store::readDerivation(const StorePath & drvPath)
|
|||
|
||||
namespace nix {
|
||||
|
||||
|
||||
RegisterStoreImplementation::Implementations * RegisterStoreImplementation::implementations = 0;
|
||||
|
||||
/* Split URI into protocol+hierarchy part and its parameter set. */
|
||||
std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri_)
|
||||
{
|
||||
|
@ -1035,24 +1031,6 @@ std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri_
|
|||
return {uri, params};
|
||||
}
|
||||
|
||||
ref<Store> openStore(const std::string & uri_,
|
||||
const Store::Params & extraParams)
|
||||
{
|
||||
auto [uri, uriParams] = splitUriAndParams(uri_);
|
||||
auto params = extraParams;
|
||||
params.insert(uriParams.begin(), uriParams.end());
|
||||
|
||||
for (auto fun : *RegisterStoreImplementation::implementations) {
|
||||
auto store = fun(uri, params);
|
||||
if (store) {
|
||||
store->warnUnknownSettings();
|
||||
return ref<Store>(store);
|
||||
}
|
||||
}
|
||||
|
||||
throw Error("don't know how to open Nix store '%s'", uri);
|
||||
}
|
||||
|
||||
static bool isNonUriPath(const std::string & spec) {
|
||||
return
|
||||
// is not a URL
|
||||
|
@ -1062,44 +1040,62 @@ static bool isNonUriPath(const std::string & spec) {
|
|||
&& spec.find("/") != std::string::npos;
|
||||
}
|
||||
|
||||
StoreType getStoreType(const std::string & uri, const std::string & stateDir)
|
||||
std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Params & params)
|
||||
{
|
||||
if (uri == "daemon") {
|
||||
return tDaemon;
|
||||
} else if (uri == "local" || isNonUriPath(uri)) {
|
||||
return tLocal;
|
||||
} else if (uri == "" || uri == "auto") {
|
||||
if (uri == "" || uri == "auto") {
|
||||
auto stateDir = get(params, "state").value_or(settings.nixStateDir);
|
||||
if (access(stateDir.c_str(), R_OK | W_OK) == 0)
|
||||
return tLocal;
|
||||
return std::make_shared<LocalStore>(params);
|
||||
else if (pathExists(settings.nixDaemonSocketFile))
|
||||
return tDaemon;
|
||||
return std::make_shared<UDSRemoteStore>(params);
|
||||
else
|
||||
return tLocal;
|
||||
return std::make_shared<LocalStore>(params);
|
||||
} else if (uri == "daemon") {
|
||||
return std::make_shared<UDSRemoteStore>(params);
|
||||
} else if (uri == "local") {
|
||||
return std::make_shared<LocalStore>(params);
|
||||
} else if (isNonUriPath(uri)) {
|
||||
Store::Params params2 = params;
|
||||
params2["root"] = absPath(uri);
|
||||
return std::make_shared<LocalStore>(params2);
|
||||
} else {
|
||||
return tOther;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static RegisterStoreImplementation regStore([](
|
||||
const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
ref<Store> openStore(const std::string & uri_,
|
||||
const Store::Params & extraParams)
|
||||
{
|
||||
switch (getStoreType(uri, get(params, "state").value_or(settings.nixStateDir))) {
|
||||
case tDaemon:
|
||||
return std::shared_ptr<Store>(std::make_shared<UDSRemoteStore>(params));
|
||||
case tLocal: {
|
||||
Store::Params params2 = params;
|
||||
if (isNonUriPath(uri)) {
|
||||
params2["root"] = absPath(uri);
|
||||
}
|
||||
return std::shared_ptr<Store>(std::make_shared<LocalStore>(params2));
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
});
|
||||
auto params = extraParams;
|
||||
try {
|
||||
auto parsedUri = parseURL(uri_);
|
||||
params.insert(parsedUri.query.begin(), parsedUri.query.end());
|
||||
|
||||
auto baseURI = parsedUri.authority.value_or("") + parsedUri.path;
|
||||
|
||||
for (auto implem : *Implementations::registered) {
|
||||
if (implem.uriSchemes.count(parsedUri.scheme)) {
|
||||
auto store = implem.create(parsedUri.scheme, baseURI, params);
|
||||
if (store) {
|
||||
store->init();
|
||||
store->warnUnknownSettings();
|
||||
return ref<Store>(store);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (BadURL &) {
|
||||
auto [uri, uriParams] = splitUriAndParams(uri_);
|
||||
params.insert(uriParams.begin(), uriParams.end());
|
||||
|
||||
if (auto store = openFromNonUri(uri, params)) {
|
||||
store->warnUnknownSettings();
|
||||
return ref<Store>(store);
|
||||
}
|
||||
}
|
||||
|
||||
throw Error("don't know how to open Nix store '%s'", uri_);
|
||||
}
|
||||
|
||||
std::list<ref<Store>> getDefaultSubstituters()
|
||||
{
|
||||
|
@ -1133,5 +1129,6 @@ std::list<ref<Store>> getDefaultSubstituters()
|
|||
return stores;
|
||||
}
|
||||
|
||||
std::vector<StoreFactory> * Implementations::registered = 0;
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,31 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
* About the class hierarchy of the store implementations:
|
||||
*
|
||||
* Each store type `Foo` consists of two classes:
|
||||
*
|
||||
* 1. A class `FooConfig : virtual StoreConfig` that contains the configuration
|
||||
* for the store
|
||||
*
|
||||
* It should only contain members of type `const Setting<T>` (or subclasses
|
||||
* of it) and inherit the constructors of `StoreConfig`
|
||||
* (`using StoreConfig::StoreConfig`).
|
||||
*
|
||||
* 2. A class `Foo : virtual Store, virtual FooConfig` that contains the
|
||||
* implementation of the store.
|
||||
*
|
||||
* This class is expected to have a constructor `Foo(const Params & params)`
|
||||
* that calls `StoreConfig(params)` (otherwise you're gonna encounter an
|
||||
* `assertion failure` when trying to instantiate it).
|
||||
*
|
||||
* You can then register the new store using:
|
||||
*
|
||||
* ```
|
||||
* cpp static RegisterStoreImplementation<Foo, FooConfig> regStore;
|
||||
* ```
|
||||
*/
|
||||
|
||||
MakeError(SubstError, Error);
|
||||
MakeError(BuildError, Error); // denotes a permanent build failure
|
||||
|
@ -33,6 +58,7 @@ MakeError(SubstituteGone, Error);
|
|||
MakeError(SubstituterDisabled, Error);
|
||||
MakeError(BadStorePath, Error);
|
||||
|
||||
MakeError(InvalidStoreURI, Error);
|
||||
|
||||
class FSAccessor;
|
||||
class NarInfoDiskCache;
|
||||
|
@ -144,12 +170,31 @@ struct BuildResult
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class Store : public std::enable_shared_from_this<Store>, public Config
|
||||
struct StoreConfig : public Config
|
||||
{
|
||||
public:
|
||||
using Config::Config;
|
||||
|
||||
typedef std::map<std::string, std::string> Params;
|
||||
/**
|
||||
* When constructing a store implementation, we pass in a map `params` of
|
||||
* parameters that's supposed to initialize the associated config.
|
||||
* To do that, we must use the `StoreConfig(StringMap & params)`
|
||||
* constructor, so we'd like to `delete` its default constructor to enforce
|
||||
* it.
|
||||
*
|
||||
* However, actually deleting it means that all the subclasses of
|
||||
* `StoreConfig` will have their default constructor deleted (because it's
|
||||
* supposed to call the deleted default constructor of `StoreConfig`). But
|
||||
* because we're always using virtual inheritance, the constructors of
|
||||
* child classes will never implicitely call this one, so deleting it will
|
||||
* be more painful than anything else.
|
||||
*
|
||||
* So we `assert(false)` here to ensure at runtime that the right
|
||||
* constructor is always called without having to redefine a custom
|
||||
* constructor for each `*Config` class.
|
||||
*/
|
||||
StoreConfig() { assert(false); }
|
||||
|
||||
virtual const std::string name() = 0;
|
||||
|
||||
const PathSetting storeDir_{this, false, settings.nixStore,
|
||||
"store", "path to the Nix store"};
|
||||
|
@ -167,6 +212,14 @@ public:
|
|||
"system-features",
|
||||
"Optional features that the system this store builds on implements (like \"kvm\")."};
|
||||
|
||||
};
|
||||
|
||||
class Store : public std::enable_shared_from_this<Store>, public virtual StoreConfig
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::map<std::string, std::string> Params;
|
||||
|
||||
protected:
|
||||
|
||||
struct PathInfoCacheValue {
|
||||
|
@ -200,6 +253,11 @@ protected:
|
|||
Store(const Params & params);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Perform any necessary effectful operation to make the store up and
|
||||
* running
|
||||
*/
|
||||
virtual void init() {};
|
||||
|
||||
virtual ~Store() { }
|
||||
|
||||
|
@ -626,22 +684,25 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
|
||||
class LocalFSStore : public virtual Store
|
||||
struct LocalFSStoreConfig : virtual StoreConfig
|
||||
{
|
||||
public:
|
||||
|
||||
// FIXME: the (Store*) cast works around a bug in gcc that causes
|
||||
using StoreConfig::StoreConfig;
|
||||
// FIXME: the (StoreConfig*) cast works around a bug in gcc that causes
|
||||
// it to omit the call to the Setting constructor. Clang works fine
|
||||
// either way.
|
||||
const PathSetting rootDir{(Store*) this, true, "",
|
||||
const PathSetting rootDir{(StoreConfig*) this, true, "",
|
||||
"root", "directory prefixed to all other paths"};
|
||||
const PathSetting stateDir{(Store*) this, false,
|
||||
const PathSetting stateDir{(StoreConfig*) this, false,
|
||||
rootDir != "" ? rootDir + "/nix/var/nix" : settings.nixStateDir,
|
||||
"state", "directory where Nix will store state"};
|
||||
const PathSetting logDir{(Store*) this, false,
|
||||
const PathSetting logDir{(StoreConfig*) this, false,
|
||||
rootDir != "" ? rootDir + "/nix/var/log/nix" : settings.nixLogDir,
|
||||
"log", "directory where Nix will store state"};
|
||||
};
|
||||
|
||||
class LocalFSStore : public virtual Store, public virtual LocalFSStoreConfig
|
||||
{
|
||||
public:
|
||||
|
||||
const static string drvsLogDir;
|
||||
|
||||
|
@ -730,37 +791,47 @@ ref<Store> openStore(const std::string & uri = settings.storeUri.get(),
|
|||
const Store::Params & extraParams = Store::Params());
|
||||
|
||||
|
||||
enum StoreType {
|
||||
tDaemon,
|
||||
tLocal,
|
||||
tOther
|
||||
};
|
||||
|
||||
|
||||
StoreType getStoreType(const std::string & uri = settings.storeUri.get(),
|
||||
const std::string & stateDir = settings.nixStateDir);
|
||||
|
||||
/* Return the default substituter stores, defined by the
|
||||
‘substituters’ option and various legacy options. */
|
||||
std::list<ref<Store>> getDefaultSubstituters();
|
||||
|
||||
|
||||
/* Store implementation registration. */
|
||||
typedef std::function<std::shared_ptr<Store>(
|
||||
const std::string & uri, const Store::Params & params)> OpenStore;
|
||||
|
||||
struct RegisterStoreImplementation
|
||||
struct StoreFactory
|
||||
{
|
||||
typedef std::vector<OpenStore> Implementations;
|
||||
static Implementations * implementations;
|
||||
std::set<std::string> uriSchemes;
|
||||
std::function<std::shared_ptr<Store> (const std::string & scheme, const std::string & uri, const Store::Params & params)> create;
|
||||
std::function<std::shared_ptr<StoreConfig> ()> getConfig;
|
||||
};
|
||||
struct Implementations
|
||||
{
|
||||
static std::vector<StoreFactory> * registered;
|
||||
|
||||
RegisterStoreImplementation(OpenStore fun)
|
||||
template<typename T, typename TConfig>
|
||||
static void add()
|
||||
{
|
||||
if (!implementations) implementations = new Implementations;
|
||||
implementations->push_back(fun);
|
||||
if (!registered) registered = new std::vector<StoreFactory>();
|
||||
StoreFactory factory{
|
||||
.uriSchemes = T::uriSchemes(),
|
||||
.create =
|
||||
([](const std::string & scheme, const std::string & uri, const Store::Params & params)
|
||||
-> std::shared_ptr<Store>
|
||||
{ return std::make_shared<T>(scheme, uri, params); }),
|
||||
.getConfig =
|
||||
([]()
|
||||
-> std::shared_ptr<StoreConfig>
|
||||
{ return std::make_shared<TConfig>(StringMap({})); })
|
||||
};
|
||||
registered->push_back(factory);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename TConfig>
|
||||
struct RegisterStoreImplementation
|
||||
{
|
||||
RegisterStoreImplementation()
|
||||
{
|
||||
Implementations::add<T, TConfig>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Display a set of paths in human-readable form (i.e., between quotes
|
||||
|
|
15
src/libutil/abstractsettingtojson.hh
Normal file
15
src/libutil/abstractsettingtojson.hh
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "config.hh"
|
||||
|
||||
namespace nix {
|
||||
template<typename T>
|
||||
std::map<std::string, nlohmann::json> BaseSetting<T>::toJSONObject()
|
||||
{
|
||||
auto obj = AbstractSetting::toJSONObject();
|
||||
obj.emplace("value", value);
|
||||
obj.emplace("defaultValue", defaultValue);
|
||||
return obj;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#include "config.hh"
|
||||
#include "args.hh"
|
||||
#include "abstractsettingtojson.hh"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
|
@ -137,11 +138,7 @@ nlohmann::json Config::toJSON()
|
|||
auto res = nlohmann::json::object();
|
||||
for (auto & s : _settings)
|
||||
if (!s.second.isAlias) {
|
||||
auto obj = nlohmann::json::object();
|
||||
obj.emplace("description", s.second.setting->description);
|
||||
obj.emplace("aliases", s.second.setting->aliases);
|
||||
obj.emplace("value", s.second.setting->toJSON());
|
||||
res.emplace(s.first, obj);
|
||||
res.emplace(s.first, s.second.setting->toJSON());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -168,19 +165,21 @@ void AbstractSetting::setDefault(const std::string & str)
|
|||
|
||||
nlohmann::json AbstractSetting::toJSON()
|
||||
{
|
||||
return to_string();
|
||||
return nlohmann::json(toJSONObject());
|
||||
}
|
||||
|
||||
std::map<std::string, nlohmann::json> AbstractSetting::toJSONObject()
|
||||
{
|
||||
std::map<std::string, nlohmann::json> obj;
|
||||
obj.emplace("description", description);
|
||||
obj.emplace("aliases", aliases);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void AbstractSetting::convertToArg(Args & args, const std::string & category)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
nlohmann::json BaseSetting<T>::toJSON()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BaseSetting<T>::convertToArg(Args & args, const std::string & category)
|
||||
{
|
||||
|
@ -259,11 +258,6 @@ template<> std::string BaseSetting<Strings>::to_string() const
|
|||
return concatStringsSep(" ", value);
|
||||
}
|
||||
|
||||
template<> nlohmann::json BaseSetting<Strings>::toJSON()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
template<> void BaseSetting<StringSet>::set(const std::string & str)
|
||||
{
|
||||
value = tokenizeString<StringSet>(str);
|
||||
|
@ -274,11 +268,6 @@ template<> std::string BaseSetting<StringSet>::to_string() const
|
|||
return concatStringsSep(" ", value);
|
||||
}
|
||||
|
||||
template<> nlohmann::json BaseSetting<StringSet>::toJSON()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
template class BaseSetting<int>;
|
||||
template class BaseSetting<unsigned int>;
|
||||
template class BaseSetting<long>;
|
||||
|
|
|
@ -206,7 +206,9 @@ protected:
|
|||
|
||||
virtual std::string to_string() const = 0;
|
||||
|
||||
virtual nlohmann::json toJSON();
|
||||
nlohmann::json toJSON();
|
||||
|
||||
virtual std::map<std::string, nlohmann::json> toJSONObject();
|
||||
|
||||
virtual void convertToArg(Args & args, const std::string & category);
|
||||
|
||||
|
@ -220,6 +222,7 @@ class BaseSetting : public AbstractSetting
|
|||
protected:
|
||||
|
||||
T value;
|
||||
const T defaultValue;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -229,6 +232,7 @@ public:
|
|||
const std::set<std::string> & aliases = {})
|
||||
: AbstractSetting(name, description, aliases)
|
||||
, value(def)
|
||||
, defaultValue(def)
|
||||
{ }
|
||||
|
||||
operator const T &() const { return value; }
|
||||
|
@ -251,7 +255,7 @@ public:
|
|||
|
||||
void convertToArg(Args & args, const std::string & category) override;
|
||||
|
||||
nlohmann::json toJSON() override;
|
||||
std::map<std::string, nlohmann::json> toJSONObject() override;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -161,7 +161,7 @@ namespace nix {
|
|||
Setting<std::string> setting{&config, "", "name-of-the-setting", "description"};
|
||||
setting.assign("value");
|
||||
|
||||
ASSERT_EQ(config.toJSON().dump(), R"#({"name-of-the-setting":{"aliases":[],"description":"description\n","value":"value"}})#");
|
||||
ASSERT_EQ(config.toJSON().dump(), R"#({"name-of-the-setting":{"aliases":[],"defaultValue":"","description":"description\n","value":"value"}})#");
|
||||
}
|
||||
|
||||
TEST(Config, setSettingAlias) {
|
||||
|
|
|
@ -31,7 +31,7 @@ ParsedURL parseURL(const std::string & url);
|
|||
|
||||
// URI stuff.
|
||||
const static std::string pctEncoded = "(?:%[0-9a-fA-F][0-9a-fA-F])";
|
||||
const static std::string schemeRegex = "(?:[a-z+]+)";
|
||||
const static std::string schemeRegex = "(?:[a-z+.-]+)";
|
||||
const static std::string ipv6AddressRegex = "(?:\\[[0-9a-fA-F:]+\\])";
|
||||
const static std::string unreservedRegex = "(?:[a-zA-Z0-9-._~])";
|
||||
const static std::string subdelimsRegex = "(?:[!$&'\"()*+,;=])";
|
||||
|
|
|
@ -76,6 +76,13 @@ static void update(const StringSet & channelNames)
|
|||
|
||||
auto store = openStore();
|
||||
|
||||
auto [fd, unpackChannelPath] = createTempFile();
|
||||
writeFull(fd.get(),
|
||||
#include "unpack-channel.nix.gen.hh"
|
||||
);
|
||||
fd = -1;
|
||||
AutoDelete del(unpackChannelPath, false);
|
||||
|
||||
// Download each channel.
|
||||
Strings exprs;
|
||||
for (const auto & channel : channels) {
|
||||
|
@ -104,7 +111,7 @@ static void update(const StringSet & channelNames)
|
|||
|
||||
bool unpacked = false;
|
||||
if (std::regex_search(filename, std::regex("\\.tar\\.(gz|bz2|xz)$"))) {
|
||||
runProgram(settings.nixBinDir + "/nix-build", false, { "--no-out-link", "--expr", "import <nix/unpack-channel.nix> "
|
||||
runProgram(settings.nixBinDir + "/nix-build", false, { "--no-out-link", "--expr", "import " + unpackChannelPath +
|
||||
"{ name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \"" + filename + "\"; }" });
|
||||
unpacked = true;
|
||||
}
|
||||
|
@ -125,7 +132,7 @@ static void update(const StringSet & channelNames)
|
|||
// Unpack the channel tarballs into the Nix store and install them
|
||||
// into the channels profile.
|
||||
std::cerr << "unpacking channels...\n";
|
||||
Strings envArgs{ "--profile", profile, "--file", "<nix/unpack-channel.nix>", "--install", "--from-expression" };
|
||||
Strings envArgs{ "--profile", profile, "--file", unpackChannelPath, "--install", "--from-expression" };
|
||||
for (auto & expr : exprs)
|
||||
envArgs.push_back(std::move(expr));
|
||||
envArgs.push_back("--quiet");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "shared.hh"
|
||||
#include "local-store.hh"
|
||||
#include "remote-store.hh"
|
||||
#include "util.hh"
|
||||
#include "serialise.hh"
|
||||
#include "archive.hh"
|
||||
|
@ -285,44 +286,28 @@ static int _main(int argc, char * * argv)
|
|||
initPlugins();
|
||||
|
||||
if (stdio) {
|
||||
if (getStoreType() == tDaemon) {
|
||||
// Forward on this connection to the real daemon
|
||||
auto socketPath = settings.nixDaemonSocketFile;
|
||||
auto s = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (s == -1)
|
||||
throw SysError("creating Unix domain socket");
|
||||
if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) {
|
||||
auto conn = store->openConnectionWrapper();
|
||||
int from = conn->from.fd;
|
||||
int to = conn->to.fd;
|
||||
|
||||
auto socketDir = dirOf(socketPath);
|
||||
if (chdir(socketDir.c_str()) == -1)
|
||||
throw SysError("changing to socket directory '%1%'", socketDir);
|
||||
|
||||
auto socketName = std::string(baseNameOf(socketPath));
|
||||
auto addr = sockaddr_un{};
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (socketName.size() + 1 >= sizeof(addr.sun_path))
|
||||
throw Error("socket name %1% is too long", socketName);
|
||||
strcpy(addr.sun_path, socketName.c_str());
|
||||
|
||||
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
throw SysError("cannot connect to daemon at %1%", socketPath);
|
||||
|
||||
auto nfds = (s > STDIN_FILENO ? s : STDIN_FILENO) + 1;
|
||||
auto nfds = std::max(from, STDIN_FILENO) + 1;
|
||||
while (true) {
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s, &fds);
|
||||
FD_SET(from, &fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1)
|
||||
throw SysError("waiting for data from client or server");
|
||||
if (FD_ISSET(s, &fds)) {
|
||||
auto res = splice(s, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
|
||||
if (FD_ISSET(from, &fds)) {
|
||||
auto res = splice(from, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
|
||||
if (res == -1)
|
||||
throw SysError("splicing data from daemon socket to stdout");
|
||||
else if (res == 0)
|
||||
throw EndOfFile("unexpected EOF from daemon socket");
|
||||
}
|
||||
if (FD_ISSET(STDIN_FILENO, &fds)) {
|
||||
auto res = splice(STDIN_FILENO, nullptr, s, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
|
||||
auto res = splice(STDIN_FILENO, nullptr, to, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
|
||||
if (res == -1)
|
||||
throw SysError("splicing data from stdin to daemon socket");
|
||||
else if (res == 0)
|
||||
|
|
44
src/nix/describe-stores.cc
Normal file
44
src/nix/describe-stores.cc
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "command.hh"
|
||||
#include "common-args.hh"
|
||||
#include "shared.hh"
|
||||
#include "store-api.hh"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using namespace nix;
|
||||
|
||||
struct CmdDescribeStores : Command, MixJSON
|
||||
{
|
||||
std::string description() override
|
||||
{
|
||||
return "show registered store types and their available options";
|
||||
}
|
||||
|
||||
Category category() override { return catUtility; }
|
||||
|
||||
void run() override
|
||||
{
|
||||
auto res = nlohmann::json::object();
|
||||
for (auto & implem : *Implementations::registered) {
|
||||
auto storeConfig = implem.getConfig();
|
||||
auto storeName = storeConfig->name();
|
||||
res[storeName] = storeConfig->toJSON();
|
||||
}
|
||||
if (json) {
|
||||
std::cout << res;
|
||||
} else {
|
||||
for (auto & [storeName, storeConfig] : res.items()) {
|
||||
std::cout << "## " << storeName << std::endl << std::endl;
|
||||
for (auto & [optionName, optionDesc] : storeConfig.items()) {
|
||||
std::cout << "### " << optionName << std::endl << std::endl;
|
||||
std::cout << optionDesc["description"].get<std::string>() << std::endl;
|
||||
std::cout << "default: " << optionDesc["defaultValue"] << std::endl <<std::endl;
|
||||
if (!optionDesc["aliases"].empty())
|
||||
std::cout << "aliases: " << optionDesc["aliases"] << std::endl << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static auto r1 = registerCommand<CmdDescribeStores>("describe-stores");
|
|
@ -392,7 +392,7 @@ struct CmdDevelop : Common, MixEnvironment
|
|||
|
||||
auto bashInstallable = std::make_shared<InstallableFlake>(
|
||||
state,
|
||||
std::move(installable->nixpkgsFlakeRef()),
|
||||
installable->nixpkgsFlakeRef(),
|
||||
Strings{"bashInteractive"},
|
||||
Strings{"legacyPackages." + settings.thisSystem.get() + "."},
|
||||
lockFlags);
|
||||
|
|
|
@ -81,7 +81,7 @@ void printClosureDiff(
|
|||
auto beforeSize = totalSize(beforeVersions);
|
||||
auto afterSize = totalSize(afterVersions);
|
||||
auto sizeDelta = (int64_t) afterSize - (int64_t) beforeSize;
|
||||
auto showDelta = abs(sizeDelta) >= 8 * 1024;
|
||||
auto showDelta = std::abs(sizeDelta) >= 8 * 1024;
|
||||
|
||||
std::set<std::string> removed, unchanged;
|
||||
for (auto & [version, _] : beforeVersions)
|
||||
|
|
|
@ -49,9 +49,7 @@ struct CmdDoctor : StoreCommand
|
|||
{
|
||||
logger->log("Running checks against store uri: " + store->getUri());
|
||||
|
||||
auto type = getStoreType();
|
||||
|
||||
if (type < tOther) {
|
||||
if (store.dynamic_pointer_cast<LocalFSStore>()) {
|
||||
success &= checkNixInPath();
|
||||
success &= checkProfileRoots(store);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ struct Installable
|
|||
|
||||
virtual FlakeRef nixpkgsFlakeRef() const
|
||||
{
|
||||
return std::move(FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}}));
|
||||
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -29,3 +29,5 @@ $(eval $(call install-symlink, $(bindir)/nix, $(libexecdir)/nix/build-remote))
|
|||
src/nix-env/user-env.cc: src/nix-env/buildenv.nix.gen.hh
|
||||
|
||||
src/nix/develop.cc: src/nix/get-env.sh.gen.hh
|
||||
|
||||
src/nix-channel/nix-channel.cc: src/nix-channel/unpack-channel.nix.gen.hh
|
||||
|
|
|
@ -185,6 +185,7 @@ void mainWrapped(int argc, char * * argv)
|
|||
}
|
||||
|
||||
if (argc == 2 && std::string(argv[1]) == "__dump-builtins") {
|
||||
evalSettings.pureEval = false;
|
||||
EvalState state({}, openStore("dummy://"));
|
||||
auto res = nlohmann::json::object();
|
||||
auto builtins = state.baseEnv.values[0]->attrs;
|
||||
|
|
|
@ -22,3 +22,6 @@ secondSeedArgs=(-j0)
|
|||
# dependent derivations always being already built.
|
||||
#testDerivation dependentCA
|
||||
testDerivation transitivelyDependentCA
|
||||
|
||||
nix-instantiate --experimental-features ca-derivations ./content-addressed.nix -A rootCA --arg seed 5
|
||||
nix-collect-garbage --experimental-features ca-derivations --option keep-derivations true
|
||||
|
|
8
tests/describe-stores.sh
Normal file
8
tests/describe-stores.sh
Normal file
|
@ -0,0 +1,8 @@
|
|||
source common.sh
|
||||
|
||||
# Query an arbitrary value in `nix describe-stores --json`'s output just to
|
||||
# check that it has the right structure
|
||||
[[ $(nix --experimental-features 'nix-command flakes' describe-stores --json | jq '.["SSH Store"]["compress"]["defaultValue"]') == false ]]
|
||||
|
||||
# Ensure that the output of `nix describe-stores` isn't empty
|
||||
[[ -n $(nix --experimental-features 'nix-command flakes' describe-stores) ]]
|
|
@ -15,6 +15,7 @@ nix_tests = \
|
|||
linux-sandbox.sh \
|
||||
build-dry.sh \
|
||||
build-remote-input-addressed.sh \
|
||||
ssh-relay.sh \
|
||||
nar-access.sh \
|
||||
structured-attrs.sh \
|
||||
fetchGit.sh \
|
||||
|
@ -32,6 +33,7 @@ nix_tests = \
|
|||
post-hook.sh \
|
||||
function-trace.sh \
|
||||
recursive.sh \
|
||||
describe-stores.sh \
|
||||
flakes.sh \
|
||||
content-addressed.sh
|
||||
# parallel.sh
|
||||
|
|
|
@ -9,9 +9,8 @@ rm -f $TEST_ROOT/result
|
|||
|
||||
export unreachable=$(nix add-to-store ./recursive.sh)
|
||||
|
||||
nix --experimental-features 'nix-command recursive-nix' build -o $TEST_ROOT/result -L --impure --expr '
|
||||
NIX_BIN_DIR=$(dirname $(type -p nix)) nix --experimental-features 'nix-command recursive-nix' build -o $TEST_ROOT/result -L --impure --expr '
|
||||
with import ./config.nix;
|
||||
with import <nix/config.nix>;
|
||||
mkDerivation {
|
||||
name = "recursive";
|
||||
dummy = builtins.toFile "dummy" "bla bla";
|
||||
|
@ -24,9 +23,10 @@ nix --experimental-features 'nix-command recursive-nix' build -o $TEST_ROOT/resu
|
|||
|
||||
buildCommand = '\'\''
|
||||
mkdir $out
|
||||
PATH=${nixBinDir}:$PATH
|
||||
opts="--experimental-features nix-command"
|
||||
|
||||
PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH
|
||||
|
||||
# Check that we can query/build paths in our input closure.
|
||||
nix $opts path-info $dummy
|
||||
nix $opts build $dummy
|
||||
|
|
16
tests/ssh-relay.sh
Normal file
16
tests/ssh-relay.sh
Normal file
|
@ -0,0 +1,16 @@
|
|||
source common.sh
|
||||
|
||||
echo foo > $TEST_ROOT/hello.sh
|
||||
|
||||
ssh_localhost=ssh://localhost
|
||||
remote_store=?remote-store=$ssh_localhost
|
||||
|
||||
store=$ssh_localhost
|
||||
|
||||
store+=$remote_store
|
||||
store+=$remote_store
|
||||
store+=$remote_store
|
||||
|
||||
out=$(nix add-to-store --store "$store" $TEST_ROOT/hello.sh)
|
||||
|
||||
[ foo = $(< $out) ]
|
Loading…
Reference in a new issue