mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-27 16:16:16 +02:00
Merge remote-tracking branch 'upstream/master' into path-info
This commit is contained in:
commit
a0f369aa3f
127 changed files with 650 additions and 549 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,7 +5,6 @@ perl/Makefile.config
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
/autom4te.cache
|
/autom4te.cache
|
||||||
/precompiled-headers.h.gch
|
/precompiled-headers.h.gch
|
||||||
/precompiled-headers.h.pch
|
|
||||||
/config.*
|
/config.*
|
||||||
/configure
|
/configure
|
||||||
/stamp-h1
|
/stamp-h1
|
||||||
|
|
|
@ -52,5 +52,4 @@ in
|
||||||
|
|
||||||
command:
|
command:
|
||||||
|
|
||||||
"Title: nix\n\n"
|
showCommand { command = "nix"; section = "#"; def = command; }
|
||||||
+ showCommand { command = "nix"; section = "#"; def = command; }
|
|
||||||
|
|
|
@ -18,13 +18,22 @@ dist-files += $(man-pages)
|
||||||
nix-eval = $(bindir)/nix eval --experimental-features nix-command -I nix/corepkgs=corepkgs --store dummy:// --impure --raw --expr
|
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
|
$(d)/%.1: $(d)/src/command-ref/%.md
|
||||||
$(trace-gen) lowdown -sT man $^ -o $@
|
@printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp
|
||||||
|
@cat $^ >> $^.tmp
|
||||||
|
$(trace-gen) lowdown -sT man $^.tmp -o $@
|
||||||
|
@rm $^.tmp
|
||||||
|
|
||||||
$(d)/%.8: $(d)/src/command-ref/%.md
|
$(d)/%.8: $(d)/src/command-ref/%.md
|
||||||
$(trace-gen) lowdown -sT man $^ -o $@
|
@printf "Title: %s\n\n" "$$(basename $@ .8)" > $^.tmp
|
||||||
|
@cat $^ >> $^.tmp
|
||||||
|
$(trace-gen) lowdown -sT man $^.tmp -o $@
|
||||||
|
@rm $^.tmp
|
||||||
|
|
||||||
$(d)/nix.conf.5: $(d)/src/command-ref/conf-file.md
|
$(d)/nix.conf.5: $(d)/src/command-ref/conf-file.md
|
||||||
$(trace-gen) lowdown -sT man $^ -o $@
|
@printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp
|
||||||
|
@cat $^ >> $^.tmp
|
||||||
|
$(trace-gen) lowdown -sT man $^.tmp -o $@
|
||||||
|
@rm $^.tmp
|
||||||
|
|
||||||
$(d)/src/command-ref/nix.md: $(d)/nix.json $(d)/generate-manpage.nix $(bindir)/nix
|
$(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
|
$(trace-gen) $(nix-eval) 'import doc/manual/generate-manpage.nix (builtins.fromJSON (builtins.readFile $<))' > $@.tmp
|
||||||
|
@ -40,7 +49,7 @@ $(d)/nix.json: $(bindir)/nix
|
||||||
@mv $@.tmp $@
|
@mv $@.tmp $@
|
||||||
|
|
||||||
$(d)/conf-file.json: $(bindir)/nix
|
$(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 > $@.tmp
|
$(trace-gen) env -i NIX_CONF_DIR=/dummy HOME=/dummy NIX_SSL_CERT_FILE=/dummy/no-ca-bundle.crt $(bindir)/nix show-config --json --experimental-features nix-command > $@.tmp
|
||||||
@mv $@.tmp $@
|
@mv $@.tmp $@
|
||||||
|
|
||||||
$(d)/src/expressions/builtins.md: $(d)/builtins.json $(d)/generate-builtins.nix $(d)/src/expressions/builtins-prefix.md $(bindir)/nix
|
$(d)/src/expressions/builtins.md: $(d)/builtins.json $(d)/generate-builtins.nix $(d)/src/expressions/builtins-prefix.md $(bindir)/nix
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix.conf
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix.conf` - Nix configuration file
|
`nix.conf` - Nix configuration file
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-build
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-build` - build a Nix expression
|
`nix-build` - build a Nix expression
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-channel
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-channel` - manage Nix channels
|
`nix-channel` - manage Nix channels
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-collect-garbage
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-collect-garbage` - delete unreachable store paths
|
`nix-collect-garbage` - delete unreachable store paths
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-copy-closure
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-copy-closure` - copy a closure to or from a remote machine via SSH
|
`nix-copy-closure` - copy a closure to or from a remote machine via SSH
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-daemon
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-daemon` - Nix multi-user support daemon
|
`nix-daemon` - Nix multi-user support daemon
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-env
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-env` - manipulate or query Nix user environments
|
`nix-env` - manipulate or query Nix user environments
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-hash
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-hash` - compute the cryptographic hash of a path
|
`nix-hash` - compute the cryptographic hash of a path
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-instantiate
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-instantiate` - instantiate store derivations from Nix expressions
|
`nix-instantiate` - instantiate store derivations from Nix expressions
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-prefetch-url
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-prefetch-url` - copy a file from a URL into the store and print its hash
|
`nix-prefetch-url` - copy a file from a URL into the store and print its hash
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-shell
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-shell` - start an interactive shell based on a Nix expression
|
`nix-shell` - start an interactive shell based on a Nix expression
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Title: nix-store
|
|
||||||
|
|
||||||
# Name
|
# Name
|
||||||
|
|
||||||
`nix-store` - manipulate or query the Nix store
|
`nix-store` - manipulate or query the Nix store
|
||||||
|
|
2
local.mk
2
local.mk
|
@ -11,6 +11,6 @@ GLOBAL_CXXFLAGS += -Wno-deprecated-declarations
|
||||||
$(foreach i, config.h $(wildcard src/lib*/*.hh), \
|
$(foreach i, config.h $(wildcard src/lib*/*.hh), \
|
||||||
$(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))
|
$(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))
|
||||||
|
|
||||||
$(GCH) $(PCH): src/libutil/util.hh config.h
|
$(GCH): src/libutil/util.hh config.h
|
||||||
|
|
||||||
GCH_CXXFLAGS = -I src/libutil
|
GCH_CXXFLAGS = -I src/libutil
|
||||||
|
|
|
@ -4,13 +4,14 @@ function _complete_nix {
|
||||||
_get_comp_words_by_ref -n ':=&' words cword cur
|
_get_comp_words_by_ref -n ':=&' words cword cur
|
||||||
local have_type
|
local have_type
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
|
local completion=${line%% *}
|
||||||
if [[ -z $have_type ]]; then
|
if [[ -z $have_type ]]; then
|
||||||
have_type=1
|
have_type=1
|
||||||
if [[ $line = filenames ]]; then
|
if [[ $completion = filenames ]]; then
|
||||||
compopt -o filenames
|
compopt -o filenames
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
COMPREPLY+=("$line")
|
COMPREPLY+=("$completion")
|
||||||
fi
|
fi
|
||||||
done < <(NIX_GET_COMPLETIONS=$cword "${words[@]}")
|
done < <(NIX_GET_COMPLETIONS=$cword "${words[@]}")
|
||||||
__ltrim_colon_completions "$cur"
|
__ltrim_colon_completions "$cur"
|
||||||
|
|
21
misc/zsh/completion.zsh
Normal file
21
misc/zsh/completion.zsh
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
function _nix() {
|
||||||
|
local ifs_bk="$IFS"
|
||||||
|
local input=("${(Q)words[@]}")
|
||||||
|
IFS=$'\n'
|
||||||
|
local res=($(NIX_GET_COMPLETIONS=$((CURRENT - 1)) "$input[@]"))
|
||||||
|
IFS="$ifs_bk"
|
||||||
|
local tpe="${${res[1]}%%> *}"
|
||||||
|
local -a suggestions
|
||||||
|
declare -a suggestions
|
||||||
|
for suggestion in ${res:1}; do
|
||||||
|
# FIXME: This doesn't work properly if the suggestion word contains a `:`
|
||||||
|
# itself
|
||||||
|
suggestions+="${suggestion/ /:}"
|
||||||
|
done
|
||||||
|
if [[ "$tpe" == filenames ]]; then
|
||||||
|
compadd -f
|
||||||
|
fi
|
||||||
|
_describe 'nix' suggestions
|
||||||
|
}
|
||||||
|
|
||||||
|
compdef _nix nix
|
|
@ -10,33 +10,12 @@ $(GCH): precompiled-headers.h
|
||||||
@mkdir -p "$(dir $@)"
|
@mkdir -p "$(dir $@)"
|
||||||
$(trace-gen) $(CXX) -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS)
|
$(trace-gen) $(CXX) -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS)
|
||||||
|
|
||||||
PCH = $(buildprefix)precompiled-headers.h.pch
|
clean-files += $(GCH)
|
||||||
|
|
||||||
$(PCH): precompiled-headers.h
|
|
||||||
@rm -f $@
|
|
||||||
@mkdir -p "$(dir $@)"
|
|
||||||
$(trace-gen) $(CXX) -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS)
|
|
||||||
|
|
||||||
clean-files += $(GCH) $(PCH)
|
|
||||||
|
|
||||||
ifeq ($(PRECOMPILE_HEADERS), 1)
|
ifeq ($(PRECOMPILE_HEADERS), 1)
|
||||||
|
|
||||||
ifeq ($(findstring g++,$(CXX)), g++)
|
GLOBAL_CXXFLAGS_PCH += -include $(buildprefix)precompiled-headers.h -Winvalid-pch
|
||||||
|
|
||||||
GLOBAL_CXXFLAGS_PCH += -include $(buildprefix)precompiled-headers.h -Winvalid-pch
|
GLOBAL_ORDER_AFTER += $(GCH)
|
||||||
|
|
||||||
GLOBAL_ORDER_AFTER += $(GCH)
|
|
||||||
|
|
||||||
else ifeq ($(findstring clang++,$(CXX)), clang++)
|
|
||||||
|
|
||||||
GLOBAL_CXXFLAGS_PCH += -include-pch $(PCH) -Winvalid-pch
|
|
||||||
|
|
||||||
GLOBAL_ORDER_AFTER += $(PCH)
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
$(error Don't know how to precompile headers on $(CXX))
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[allow(improper_ctypes_definitions)]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
mod c;
|
mod c;
|
||||||
mod error;
|
mod error;
|
||||||
|
|
|
@ -19,9 +19,9 @@ impl StorePath {
|
||||||
}
|
}
|
||||||
Self::new_from_base_name(
|
Self::new_from_base_name(
|
||||||
path.file_name()
|
path.file_name()
|
||||||
.ok_or(Error::BadStorePath(path.into()))?
|
.ok_or_else(|| Error::BadStorePath(path.into()))?
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok_or(Error::BadStorePath(path.into()))?,
|
.ok_or_else(|| Error::BadStorePath(path.into()))?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ impl StorePath {
|
||||||
|
|
||||||
pub fn new_from_base_name(base_name: &str) -> Result<Self, Error> {
|
pub fn new_from_base_name(base_name: &str) -> Result<Self, Error> {
|
||||||
if base_name.len() < STORE_PATH_HASH_CHARS + 1
|
if base_name.len() < STORE_PATH_HASH_CHARS + 1
|
||||||
|| base_name.as_bytes()[STORE_PATH_HASH_CHARS] != '-' as u8
|
|| base_name.as_bytes()[STORE_PATH_HASH_CHARS] != b'-'
|
||||||
{
|
{
|
||||||
return Err(Error::BadStorePath(base_name.into()));
|
return Err(Error::BadStorePath(base_name.into()));
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ impl StorePathHash {
|
||||||
Ok(Self(bytes))
|
Ok(Self(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash<'a>(&'a self) -> &'a [u8; STORE_PATH_HASH_BYTES] {
|
pub fn hash(&self) -> &[u8; STORE_PATH_HASH_BYTES] {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ pub struct StorePathName(String);
|
||||||
|
|
||||||
impl StorePathName {
|
impl StorePathName {
|
||||||
pub fn new(s: &str) -> Result<Self, Error> {
|
pub fn new(s: &str) -> Result<Self, Error> {
|
||||||
if s.len() == 0 {
|
if s.is_empty() {
|
||||||
return Err(Error::StorePathNameEmpty);
|
return Err(Error::StorePathNameEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,25 +106,24 @@ impl StorePathName {
|
||||||
return Err(Error::StorePathNameTooLong);
|
return Err(Error::StorePathNameTooLong);
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.starts_with('.')
|
let is_good_path_name = s.chars().all(|c| {
|
||||||
|| !s.chars().all(|c| {
|
c.is_ascii_alphabetic()
|
||||||
c.is_ascii_alphabetic()
|
|| c.is_ascii_digit()
|
||||||
|| c.is_ascii_digit()
|
|| c == '+'
|
||||||
|| c == '+'
|
|| c == '-'
|
||||||
|| c == '-'
|
|| c == '.'
|
||||||
|| c == '.'
|
|| c == '_'
|
||||||
|| c == '_'
|
|| c == '?'
|
||||||
|| c == '?'
|
|| c == '='
|
||||||
|| c == '='
|
});
|
||||||
})
|
if s.starts_with('.') || !is_good_path_name {
|
||||||
{
|
|
||||||
return Err(Error::BadStorePathName);
|
return Err(Error::BadStorePathName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self(s.to_string()))
|
Ok(Self(s.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name<'a>(&'a self) -> &'a str {
|
pub fn name(&self) -> &str {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub fn decoded_len(input_len: usize) -> usize {
|
||||||
input_len * 5 / 8
|
input_len * 5 / 8
|
||||||
}
|
}
|
||||||
|
|
||||||
static BASE32_CHARS: &'static [u8; 32] = &b"0123456789abcdfghijklmnpqrsvwxyz";
|
static BASE32_CHARS: &[u8; 32] = &b"0123456789abcdfghijklmnpqrsvwxyz";
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref BASE32_CHARS_REVERSE: Box<[u8; 256]> = {
|
static ref BASE32_CHARS_REVERSE: Box<[u8; 256]> = {
|
||||||
|
|
|
@ -44,7 +44,7 @@ static bool allSupportedLocally(Store & store, const std::set<std::string>& requ
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _main(int argc, char * * argv)
|
static int main_build_remote(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
logger = makeJSONLogger(*logger);
|
logger = makeJSONLogger(*logger);
|
||||||
|
@ -297,4 +297,4 @@ connected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("build-remote", _main);
|
static RegisterLegacyCommand r_build_remote("build-remote", main_build_remote);
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace nix::eval_cache {
|
||||||
|
|
||||||
MakeError(CachedEvalError, EvalError);
|
MakeError(CachedEvalError, EvalError);
|
||||||
|
|
||||||
class AttrDb;
|
struct AttrDb;
|
||||||
class AttrCursor;
|
class AttrCursor;
|
||||||
|
|
||||||
class EvalCache : public std::enable_shared_from_this<EvalCache>
|
class EvalCache : public std::enable_shared_from_this<EvalCache>
|
||||||
|
|
|
@ -2081,7 +2081,7 @@ Strings EvalSettings::getDefaultNixPath()
|
||||||
|
|
||||||
EvalSettings evalSettings;
|
EvalSettings evalSettings;
|
||||||
|
|
||||||
static GlobalConfig::Register r1(&evalSettings);
|
static GlobalConfig::Register rEvalSettings(&evalSettings);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ using namespace flake;
|
||||||
|
|
||||||
namespace flake {
|
namespace flake {
|
||||||
|
|
||||||
typedef std::pair<Tree, FlakeRef> FetchedFlake;
|
typedef std::pair<fetchers::Tree, FlakeRef> FetchedFlake;
|
||||||
typedef std::vector<std::pair<FlakeRef, FetchedFlake>> FlakeCache;
|
typedef std::vector<std::pair<FlakeRef, FetchedFlake>> FlakeCache;
|
||||||
|
|
||||||
static std::optional<FetchedFlake> lookupInFlakeCache(
|
static std::optional<FetchedFlake> lookupInFlakeCache(
|
||||||
|
|
|
@ -13,12 +13,12 @@ FlakeRef getFlakeRef(
|
||||||
{
|
{
|
||||||
auto i = json.find(attr);
|
auto i = json.find(attr);
|
||||||
if (i != json.end()) {
|
if (i != json.end()) {
|
||||||
auto attrs = jsonToAttrs(*i);
|
auto attrs = fetchers::jsonToAttrs(*i);
|
||||||
// FIXME: remove when we drop support for version 5.
|
// FIXME: remove when we drop support for version 5.
|
||||||
if (info) {
|
if (info) {
|
||||||
auto j = json.find(info);
|
auto j = json.find(info);
|
||||||
if (j != json.end()) {
|
if (j != json.end()) {
|
||||||
for (auto k : jsonToAttrs(*j))
|
for (auto k : fetchers::jsonToAttrs(*j))
|
||||||
attrs.insert_or_assign(k.first, k.second);
|
attrs.insert_or_assign(k.first, k.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,6 @@ class StorePath;
|
||||||
|
|
||||||
namespace nix::flake {
|
namespace nix::flake {
|
||||||
|
|
||||||
using namespace fetchers;
|
|
||||||
|
|
||||||
typedef std::vector<FlakeId> InputPath;
|
typedef std::vector<FlakeId> InputPath;
|
||||||
|
|
||||||
struct LockedNode;
|
struct LockedNode;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
|
@ -11,7 +11,7 @@ static void prim_unsafeDiscardStringContext(EvalState & state, const Pos & pos,
|
||||||
mkString(v, s, PathSet());
|
mkString(v, s, PathSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r1("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
|
static RegisterPrimOp primop_unsafeDiscardStringContext("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
|
||||||
|
|
||||||
|
|
||||||
static void prim_hasContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_hasContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
@ -21,7 +21,7 @@ static void prim_hasContext(EvalState & state, const Pos & pos, Value * * args,
|
||||||
mkBool(v, !context.empty());
|
mkBool(v, !context.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r2("__hasContext", 1, prim_hasContext);
|
static RegisterPrimOp primop_hasContext("__hasContext", 1, prim_hasContext);
|
||||||
|
|
||||||
|
|
||||||
/* Sometimes we want to pass a derivation path (i.e. pkg.drvPath) to a
|
/* Sometimes we want to pass a derivation path (i.e. pkg.drvPath) to a
|
||||||
|
@ -42,7 +42,7 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & po
|
||||||
mkString(v, s, context2);
|
mkString(v, s, context2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r3("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency);
|
static RegisterPrimOp primop_unsafeDiscardOutputDependency("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency);
|
||||||
|
|
||||||
|
|
||||||
/* Extract the context of a string as a structured Nix value.
|
/* Extract the context of a string as a structured Nix value.
|
||||||
|
@ -127,7 +127,7 @@ static void prim_getContext(EvalState & state, const Pos & pos, Value * * args,
|
||||||
v.attrs->sort();
|
v.attrs->sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r4("__getContext", 1, prim_getContext);
|
static RegisterPrimOp primop_getContext("__getContext", 1, prim_getContext);
|
||||||
|
|
||||||
|
|
||||||
/* Append the given context to a given string.
|
/* Append the given context to a given string.
|
||||||
|
@ -191,6 +191,6 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
|
||||||
mkString(v, orig, context);
|
mkString(v, orig, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r5("__appendContext", 2, prim_appendContext);
|
static RegisterPrimOp primop_appendContext("__appendContext", 2, prim_appendContext);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,6 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
|
||||||
state.allowedPaths->insert(tree.actualPath);
|
state.allowedPaths->insert(tree.actualPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r("fetchMercurial", 1, prim_fetchMercurial);
|
static RegisterPrimOp r_fetchMercurial("fetchMercurial", 1, prim_fetchMercurial);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
fetchTree(state, pos, args, v, std::nullopt);
|
fetchTree(state, pos, args, v, std::nullopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r("fetchTree", 1, prim_fetchTree);
|
static RegisterPrimOp primop_fetchTree("fetchTree", 1, prim_fetchTree);
|
||||||
|
|
||||||
static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
||||||
const string & who, bool unpack, std::string name)
|
const string & who, bool unpack, std::string name)
|
||||||
|
|
|
@ -88,6 +88,6 @@ static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r("fromTOML", 1, prim_fromTOML);
|
static RegisterPrimOp primop_fromTOML("fromTOML", 1, prim_fromTOML);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,9 @@ public:
|
||||||
|
|
||||||
struct InputScheme
|
struct InputScheme
|
||||||
{
|
{
|
||||||
|
virtual ~InputScheme()
|
||||||
|
{ }
|
||||||
|
|
||||||
virtual std::optional<Input> inputFromURL(const ParsedURL & url) = 0;
|
virtual std::optional<Input> inputFromURL(const ParsedURL & url) = 0;
|
||||||
|
|
||||||
virtual std::optional<Input> inputFromAttrs(const Attrs & attrs) = 0;
|
virtual std::optional<Input> inputFromAttrs(const Attrs & attrs) = 0;
|
||||||
|
|
|
@ -452,6 +452,6 @@ struct GitInputScheme : InputScheme
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = OnStartup([] { registerInputScheme(std::make_unique<GitInputScheme>()); });
|
static auto rGitInputScheme = OnStartup([] { registerInputScheme(std::make_unique<GitInputScheme>()); });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
virtual std::string type() = 0;
|
virtual std::string type() = 0;
|
||||||
|
|
||||||
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) override
|
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
||||||
{
|
{
|
||||||
|
@ -215,7 +215,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
||||||
{
|
{
|
||||||
std::string type() override { return "github"; }
|
std::string type() override { return "github"; }
|
||||||
|
|
||||||
std::optional<std::pair<std::string, std::string> > accessHeaderFromToken(const std::string & token) const
|
std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
|
||||||
{
|
{
|
||||||
// Github supports PAT/OAuth2 tokens and HTTP Basic
|
// Github supports PAT/OAuth2 tokens and HTTP Basic
|
||||||
// Authentication. The former simply specifies the token, the
|
// Authentication. The former simply specifies the token, the
|
||||||
|
@ -270,7 +270,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
||||||
{
|
{
|
||||||
std::string type() override { return "gitlab"; }
|
std::string type() override { return "gitlab"; }
|
||||||
|
|
||||||
std::optional<std::pair<std::string, std::string> > accessHeaderFromToken(const std::string & token) const
|
std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
|
||||||
{
|
{
|
||||||
// Gitlab supports 4 kinds of authorization, two of which are
|
// Gitlab supports 4 kinds of authorization, two of which are
|
||||||
// relevant here: OAuth2 and PAT (Private Access Token). The
|
// relevant here: OAuth2 and PAT (Private Access Token). The
|
||||||
|
@ -334,7 +334,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = OnStartup([] { registerInputScheme(std::make_unique<GitHubInputScheme>()); });
|
static auto rGitHubInputScheme = OnStartup([] { registerInputScheme(std::make_unique<GitHubInputScheme>()); });
|
||||||
static auto r2 = OnStartup([] { registerInputScheme(std::make_unique<GitLabInputScheme>()); });
|
static auto rGitLabInputScheme = OnStartup([] { registerInputScheme(std::make_unique<GitLabInputScheme>()); });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,6 @@ struct IndirectInputScheme : InputScheme
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = OnStartup([] { registerInputScheme(std::make_unique<IndirectInputScheme>()); });
|
static auto rIndirectInputScheme = OnStartup([] { registerInputScheme(std::make_unique<IndirectInputScheme>()); });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -293,6 +293,6 @@ struct MercurialInputScheme : InputScheme
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = OnStartup([] { registerInputScheme(std::make_unique<MercurialInputScheme>()); });
|
static auto rMercurialInputScheme = OnStartup([] { registerInputScheme(std::make_unique<MercurialInputScheme>()); });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,6 @@ struct PathInputScheme : InputScheme
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = OnStartup([] { registerInputScheme(std::make_unique<PathInputScheme>()); });
|
static auto rPathInputScheme = OnStartup([] { registerInputScheme(std::make_unique<PathInputScheme>()); });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
|
|
@ -237,6 +237,6 @@ struct TarballInputScheme : InputScheme
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = OnStartup([] { registerInputScheme(std::make_unique<TarballInputScheme>()); });
|
static auto rTarballInputScheme = OnStartup([] { registerInputScheme(std::make_unique<TarballInputScheme>()); });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ MixCommonArgs::MixCommonArgs(const string & programName)
|
||||||
globalConfig.getSettings(settings);
|
globalConfig.getSettings(settings);
|
||||||
for (auto & s : settings)
|
for (auto & s : settings)
|
||||||
if (hasPrefix(s.first, prefix))
|
if (hasPrefix(s.first, prefix))
|
||||||
completions->insert(s.first);
|
completions->add(s.first, s.second.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -386,18 +386,12 @@ RunPager::~RunPager()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string showBytes(uint64_t bytes)
|
|
||||||
{
|
|
||||||
return (format("%.2f MiB") % (bytes / (1024.0 * 1024.0))).str();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PrintFreed::~PrintFreed()
|
PrintFreed::~PrintFreed()
|
||||||
{
|
{
|
||||||
if (show)
|
if (show)
|
||||||
std::cout << format("%1% store paths deleted, %2% freed\n")
|
std::cout << fmt("%d store paths deleted, %s freed\n",
|
||||||
% results.paths.size()
|
results.paths.size(),
|
||||||
% showBytes(results.bytesFreed);
|
showBytes(results.bytesFreed));
|
||||||
}
|
}
|
||||||
|
|
||||||
Exit::~Exit() { }
|
Exit::~Exit() { }
|
||||||
|
|
|
@ -831,6 +831,10 @@ private:
|
||||||
paths to the sandbox as a result of recursive Nix calls. */
|
paths to the sandbox as a result of recursive Nix calls. */
|
||||||
AutoCloseFD sandboxMountNamespace;
|
AutoCloseFD sandboxMountNamespace;
|
||||||
|
|
||||||
|
/* On Linux, whether we're doing the build in its own user
|
||||||
|
namespace. */
|
||||||
|
bool usingUserNamespace = true;
|
||||||
|
|
||||||
/* The build hook. */
|
/* The build hook. */
|
||||||
std::unique_ptr<HookInstance> hook;
|
std::unique_ptr<HookInstance> hook;
|
||||||
|
|
||||||
|
@ -920,8 +924,8 @@ private:
|
||||||
result. */
|
result. */
|
||||||
std::map<Path, ValidPathInfo> prevInfos;
|
std::map<Path, ValidPathInfo> prevInfos;
|
||||||
|
|
||||||
const uid_t sandboxUid = 1000;
|
uid_t sandboxUid() { return usingUserNamespace ? 1000 : buildUser->getUID(); }
|
||||||
const gid_t sandboxGid = 100;
|
gid_t sandboxGid() { return usingUserNamespace ? 100 : buildUser->getGID(); }
|
||||||
|
|
||||||
const static Path homeDir;
|
const static Path homeDir;
|
||||||
|
|
||||||
|
@ -2355,7 +2359,8 @@ void DerivationGoal::startBuilder()
|
||||||
worker.store.computeFSClosure(worker.store.toStorePath(i.second.source).first, closure);
|
worker.store.computeFSClosure(worker.store.toStorePath(i.second.source).first, closure);
|
||||||
} catch (InvalidPath & e) {
|
} catch (InvalidPath & e) {
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
throw Error("while processing 'sandbox-paths': %s", e.what());
|
e.addTrace({}, "while processing 'sandbox-paths'");
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
for (auto & i : closure) {
|
for (auto & i : closure) {
|
||||||
auto p = worker.store.printStorePath(i);
|
auto p = worker.store.printStorePath(i);
|
||||||
|
@ -2423,15 +2428,14 @@ void DerivationGoal::startBuilder()
|
||||||
"root:x:0:0:Nix build user:%3%:/noshell\n"
|
"root:x:0:0:Nix build user:%3%:/noshell\n"
|
||||||
"nixbld:x:%1%:%2%:Nix build user:%3%:/noshell\n"
|
"nixbld:x:%1%:%2%:Nix build user:%3%:/noshell\n"
|
||||||
"nobody:x:65534:65534:Nobody:/:/noshell\n",
|
"nobody:x:65534:65534:Nobody:/:/noshell\n",
|
||||||
sandboxUid, sandboxGid, settings.sandboxBuildDir));
|
sandboxUid(), sandboxGid(), settings.sandboxBuildDir));
|
||||||
|
|
||||||
/* Declare the build user's group so that programs get a consistent
|
/* Declare the build user's group so that programs get a consistent
|
||||||
view of the system (e.g., "id -gn"). */
|
view of the system (e.g., "id -gn"). */
|
||||||
writeFile(chrootRootDir + "/etc/group",
|
writeFile(chrootRootDir + "/etc/group",
|
||||||
(format(
|
fmt("root:x:0:\n"
|
||||||
"root:x:0:\n"
|
|
||||||
"nixbld:!:%1%:\n"
|
"nixbld:!:%1%:\n"
|
||||||
"nogroup:x:65534:\n") % sandboxGid).str());
|
"nogroup:x:65534:\n", sandboxGid()));
|
||||||
|
|
||||||
/* Create /etc/hosts with localhost entry. */
|
/* Create /etc/hosts with localhost entry. */
|
||||||
if (!(derivationIsImpure(derivationType)))
|
if (!(derivationIsImpure(derivationType)))
|
||||||
|
@ -2628,6 +2632,13 @@ void DerivationGoal::startBuilder()
|
||||||
|
|
||||||
options.allowVfork = false;
|
options.allowVfork = false;
|
||||||
|
|
||||||
|
Path maxUserNamespaces = "/proc/sys/user/max_user_namespaces";
|
||||||
|
static bool userNamespacesEnabled =
|
||||||
|
pathExists(maxUserNamespaces)
|
||||||
|
&& trim(readFile(maxUserNamespaces)) != "0";
|
||||||
|
|
||||||
|
usingUserNamespace = userNamespacesEnabled;
|
||||||
|
|
||||||
Pid helper = startProcess([&]() {
|
Pid helper = startProcess([&]() {
|
||||||
|
|
||||||
/* Drop additional groups here because we can't do it
|
/* Drop additional groups here because we can't do it
|
||||||
|
@ -2646,9 +2657,11 @@ void DerivationGoal::startBuilder()
|
||||||
PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||||
if (stack == MAP_FAILED) throw SysError("allocating stack");
|
if (stack == MAP_FAILED) throw SysError("allocating stack");
|
||||||
|
|
||||||
int flags = CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD;
|
int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD;
|
||||||
if (privateNetwork)
|
if (privateNetwork)
|
||||||
flags |= CLONE_NEWNET;
|
flags |= CLONE_NEWNET;
|
||||||
|
if (usingUserNamespace)
|
||||||
|
flags |= CLONE_NEWUSER;
|
||||||
|
|
||||||
pid_t child = clone(childEntry, stack + stackSize, flags, this);
|
pid_t child = clone(childEntry, stack + stackSize, flags, this);
|
||||||
if (child == -1 && errno == EINVAL) {
|
if (child == -1 && errno == EINVAL) {
|
||||||
|
@ -2657,11 +2670,12 @@ void DerivationGoal::startBuilder()
|
||||||
flags &= ~CLONE_NEWPID;
|
flags &= ~CLONE_NEWPID;
|
||||||
child = clone(childEntry, stack + stackSize, flags, this);
|
child = clone(childEntry, stack + stackSize, flags, this);
|
||||||
}
|
}
|
||||||
if (child == -1 && (errno == EPERM || errno == EINVAL)) {
|
if (usingUserNamespace && child == -1 && (errno == EPERM || errno == EINVAL)) {
|
||||||
/* Some distros patch Linux to not allow unprivileged
|
/* Some distros patch Linux to not allow unprivileged
|
||||||
* user namespaces. If we get EPERM or EINVAL, try
|
* user namespaces. If we get EPERM or EINVAL, try
|
||||||
* without CLONE_NEWUSER and see if that works.
|
* without CLONE_NEWUSER and see if that works.
|
||||||
*/
|
*/
|
||||||
|
usingUserNamespace = false;
|
||||||
flags &= ~CLONE_NEWUSER;
|
flags &= ~CLONE_NEWUSER;
|
||||||
child = clone(childEntry, stack + stackSize, flags, this);
|
child = clone(childEntry, stack + stackSize, flags, this);
|
||||||
}
|
}
|
||||||
|
@ -2672,7 +2686,8 @@ void DerivationGoal::startBuilder()
|
||||||
_exit(1);
|
_exit(1);
|
||||||
if (child == -1) throw SysError("cloning builder process");
|
if (child == -1) throw SysError("cloning builder process");
|
||||||
|
|
||||||
writeFull(builderOut.writeSide.get(), std::to_string(child) + "\n");
|
writeFull(builderOut.writeSide.get(),
|
||||||
|
fmt("%d %d\n", usingUserNamespace, child));
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
|
@ -2686,23 +2701,38 @@ void DerivationGoal::startBuilder()
|
||||||
|
|
||||||
userNamespaceSync.readSide = -1;
|
userNamespaceSync.readSide = -1;
|
||||||
|
|
||||||
|
/* Close the write side to prevent runChild() from hanging
|
||||||
|
reading from this. */
|
||||||
|
Finally cleanup([&]() {
|
||||||
|
userNamespaceSync.writeSide = -1;
|
||||||
|
});
|
||||||
|
|
||||||
pid_t tmp;
|
pid_t tmp;
|
||||||
if (!string2Int<pid_t>(readLine(builderOut.readSide.get()), tmp)) abort();
|
auto ss = tokenizeString<std::vector<std::string>>(readLine(builderOut.readSide.get()));
|
||||||
|
assert(ss.size() == 2);
|
||||||
|
usingUserNamespace = ss[0] == "1";
|
||||||
|
if (!string2Int<pid_t>(ss[1], tmp)) abort();
|
||||||
pid = tmp;
|
pid = tmp;
|
||||||
|
|
||||||
/* Set the UID/GID mapping of the builder's user namespace
|
if (usingUserNamespace) {
|
||||||
such that the sandbox user maps to the build user, or to
|
/* Set the UID/GID mapping of the builder's user namespace
|
||||||
the calling user (if build users are disabled). */
|
such that the sandbox user maps to the build user, or to
|
||||||
uid_t hostUid = buildUser ? buildUser->getUID() : getuid();
|
the calling user (if build users are disabled). */
|
||||||
uid_t hostGid = buildUser ? buildUser->getGID() : getgid();
|
uid_t hostUid = buildUser ? buildUser->getUID() : getuid();
|
||||||
|
uid_t hostGid = buildUser ? buildUser->getGID() : getgid();
|
||||||
|
|
||||||
writeFile("/proc/" + std::to_string(pid) + "/uid_map",
|
writeFile("/proc/" + std::to_string(pid) + "/uid_map",
|
||||||
(format("%d %d 1") % sandboxUid % hostUid).str());
|
fmt("%d %d 1", sandboxUid(), hostUid));
|
||||||
|
|
||||||
writeFile("/proc/" + std::to_string(pid) + "/setgroups", "deny");
|
writeFile("/proc/" + std::to_string(pid) + "/setgroups", "deny");
|
||||||
|
|
||||||
writeFile("/proc/" + std::to_string(pid) + "/gid_map",
|
writeFile("/proc/" + std::to_string(pid) + "/gid_map",
|
||||||
(format("%d %d 1") % sandboxGid % hostGid).str());
|
fmt("%d %d 1", sandboxGid(), hostGid));
|
||||||
|
} else {
|
||||||
|
debug("note: not using a user namespace");
|
||||||
|
if (!buildUser)
|
||||||
|
throw Error("cannot perform a sandboxed build because user namespaces are not enabled; check /proc/sys/user/max_user_namespaces");
|
||||||
|
}
|
||||||
|
|
||||||
/* Save the mount namespace of the child. We have to do this
|
/* Save the mount namespace of the child. We have to do this
|
||||||
*before* the child does a chroot. */
|
*before* the child does a chroot. */
|
||||||
|
@ -2712,7 +2742,6 @@ void DerivationGoal::startBuilder()
|
||||||
|
|
||||||
/* Signal the builder that we've updated its user namespace. */
|
/* Signal the builder that we've updated its user namespace. */
|
||||||
writeFull(userNamespaceSync.writeSide.get(), "1");
|
writeFull(userNamespaceSync.writeSide.get(), "1");
|
||||||
userNamespaceSync.writeSide = -1;
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -2732,11 +2761,14 @@ void DerivationGoal::startBuilder()
|
||||||
/* Check if setting up the build environment failed. */
|
/* Check if setting up the build environment failed. */
|
||||||
while (true) {
|
while (true) {
|
||||||
string msg = readLine(builderOut.readSide.get());
|
string msg = readLine(builderOut.readSide.get());
|
||||||
|
if (string(msg, 0, 1) == "\2") break;
|
||||||
if (string(msg, 0, 1) == "\1") {
|
if (string(msg, 0, 1) == "\1") {
|
||||||
if (msg.size() == 1) break;
|
FdSource source(builderOut.readSide.get());
|
||||||
throw Error(string(msg, 1));
|
auto ex = readError(source);
|
||||||
|
ex.addTrace({}, "while setting up the build environment");
|
||||||
|
throw ex;
|
||||||
}
|
}
|
||||||
debug(msg);
|
debug("sandbox setup: " + msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3560,9 +3592,9 @@ void DerivationGoal::runChild()
|
||||||
/* Switch to the sandbox uid/gid in the user namespace,
|
/* Switch to the sandbox uid/gid in the user namespace,
|
||||||
which corresponds to the build user or calling user in
|
which corresponds to the build user or calling user in
|
||||||
the parent namespace. */
|
the parent namespace. */
|
||||||
if (setgid(sandboxGid) == -1)
|
if (setgid(sandboxGid()) == -1)
|
||||||
throw SysError("setgid failed");
|
throw SysError("setgid failed");
|
||||||
if (setuid(sandboxUid) == -1)
|
if (setuid(sandboxUid()) == -1)
|
||||||
throw SysError("setuid failed");
|
throw SysError("setuid failed");
|
||||||
|
|
||||||
setUser = false;
|
setUser = false;
|
||||||
|
@ -3780,7 +3812,7 @@ void DerivationGoal::runChild()
|
||||||
args.push_back(rewriteStrings(i, inputRewrites));
|
args.push_back(rewriteStrings(i, inputRewrites));
|
||||||
|
|
||||||
/* Indicate that we managed to set up the build environment. */
|
/* Indicate that we managed to set up the build environment. */
|
||||||
writeFull(STDERR_FILENO, string("\1\n"));
|
writeFull(STDERR_FILENO, string("\2\n"));
|
||||||
|
|
||||||
/* Execute the program. This should not return. */
|
/* Execute the program. This should not return. */
|
||||||
if (drv->isBuiltin()) {
|
if (drv->isBuiltin()) {
|
||||||
|
@ -3801,7 +3833,7 @@ void DerivationGoal::runChild()
|
||||||
throw Error("unsupported builtin function '%1%'", string(drv->builder, 8));
|
throw Error("unsupported builtin function '%1%'", string(drv->builder, 8));
|
||||||
_exit(0);
|
_exit(0);
|
||||||
} catch (std::exception & e) {
|
} catch (std::exception & e) {
|
||||||
writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n");
|
writeFull(STDERR_FILENO, e.what() + std::string("\n"));
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3810,8 +3842,11 @@ void DerivationGoal::runChild()
|
||||||
|
|
||||||
throw SysError("executing '%1%'", drv->builder);
|
throw SysError("executing '%1%'", drv->builder);
|
||||||
|
|
||||||
} catch (std::exception & e) {
|
} catch (Error & e) {
|
||||||
writeFull(STDERR_FILENO, "\1while setting up the build environment: " + string(e.what()) + "\n");
|
writeFull(STDERR_FILENO, "\1\n");
|
||||||
|
FdSink sink(STDERR_FILENO);
|
||||||
|
sink << e;
|
||||||
|
sink.flush();
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,17 +101,20 @@ struct TunnelLogger : public Logger
|
||||||
|
|
||||||
/* stopWork() means that we're done; stop sending stderr to the
|
/* stopWork() means that we're done; stop sending stderr to the
|
||||||
client. */
|
client. */
|
||||||
void stopWork(bool success = true, const string & msg = "", unsigned int status = 0)
|
void stopWork(const Error * ex = nullptr)
|
||||||
{
|
{
|
||||||
auto state(state_.lock());
|
auto state(state_.lock());
|
||||||
|
|
||||||
state->canSendStderr = false;
|
state->canSendStderr = false;
|
||||||
|
|
||||||
if (success)
|
if (!ex)
|
||||||
to << STDERR_LAST;
|
to << STDERR_LAST;
|
||||||
else {
|
else {
|
||||||
to << STDERR_ERROR << msg;
|
if (GET_PROTOCOL_MINOR(clientVersion) >= 26) {
|
||||||
if (status != 0) to << status;
|
to << STDERR_ERROR << *ex;
|
||||||
|
} else {
|
||||||
|
to << STDERR_ERROR << ex->what() << ex->status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,10 +938,11 @@ void processConnection(
|
||||||
during addTextToStore() / importPath(). If that
|
during addTextToStore() / importPath(). If that
|
||||||
happens, just send the error message and exit. */
|
happens, just send the error message and exit. */
|
||||||
bool errorAllowed = tunnelLogger->state_.lock()->canSendStderr;
|
bool errorAllowed = tunnelLogger->state_.lock()->canSendStderr;
|
||||||
tunnelLogger->stopWork(false, e.msg(), e.status);
|
tunnelLogger->stopWork(&e);
|
||||||
if (!errorAllowed) throw;
|
if (!errorAllowed) throw;
|
||||||
} catch (std::bad_alloc & e) {
|
} catch (std::bad_alloc & e) {
|
||||||
tunnelLogger->stopWork(false, "Nix daemon out of memory", 1);
|
auto ex = Error("Nix daemon out of memory");
|
||||||
|
tunnelLogger->stopWork(&ex);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,8 +951,13 @@ void processConnection(
|
||||||
assert(!tunnelLogger->state_.lock()->canSendStderr);
|
assert(!tunnelLogger->state_.lock()->canSendStderr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} catch (Error & e) {
|
||||||
|
tunnelLogger->stopWork(&e);
|
||||||
|
to.flush();
|
||||||
|
return;
|
||||||
} catch (std::exception & e) {
|
} catch (std::exception & e) {
|
||||||
tunnelLogger->stopWork(false, e.what(), 1);
|
auto ex = Error(e.what());
|
||||||
|
tunnelLogger->stopWork(&ex);
|
||||||
to.flush();
|
to.flush();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "serialise.hh"
|
#include "serialise.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,6 @@ typedef std::map<string, DerivationOutput> DerivationOutputs;
|
||||||
also contains, for each output, the (optional) store path in which it would
|
also contains, for each output, the (optional) store path in which it would
|
||||||
be written. To calculate values of these types, see the corresponding
|
be written. To calculate values of these types, see the corresponding
|
||||||
functions in BasicDerivation */
|
functions in BasicDerivation */
|
||||||
typedef std::map<string, std::pair<DerivationOutput, StorePath>>
|
|
||||||
DerivationOutputsAndPaths;
|
|
||||||
typedef std::map<string, std::pair<DerivationOutput, std::optional<StorePath>>>
|
typedef std::map<string, std::pair<DerivationOutput, std::optional<StorePath>>>
|
||||||
DerivationOutputsAndOptPaths;
|
DerivationOutputsAndOptPaths;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,7 @@ struct DummyStore : public Store, public virtual DummyStoreConfig
|
||||||
DummyStore(const Params & params)
|
DummyStore(const Params & params)
|
||||||
: StoreConfig(params)
|
: StoreConfig(params)
|
||||||
, Store(params)
|
, Store(params)
|
||||||
{
|
{ }
|
||||||
}
|
|
||||||
|
|
||||||
string getUri() override
|
string getUri() override
|
||||||
{
|
{
|
||||||
|
@ -63,6 +62,6 @@ struct DummyStore : public Store, public virtual DummyStoreConfig
|
||||||
{ unsupported("buildDerivation"); }
|
{ unsupported("buildDerivation"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static RegisterStoreImplementation<DummyStore, DummyStoreConfig> regStore;
|
static RegisterStoreImplementation<DummyStore, DummyStoreConfig> regDummyStore;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace nix {
|
||||||
|
|
||||||
FileTransferSettings fileTransferSettings;
|
FileTransferSettings fileTransferSettings;
|
||||||
|
|
||||||
static GlobalConfig::Register r1(&fileTransferSettings);
|
static GlobalConfig::Register rFileTransferSettings(&fileTransferSettings);
|
||||||
|
|
||||||
std::string resolveUri(const std::string & uri)
|
std::string resolveUri(const std::string & uri)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "local-store.hh"
|
#include "local-store.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace nix {
|
||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
static GlobalConfig::Register r1(&settings);
|
static GlobalConfig::Register rSettings(&settings);
|
||||||
|
|
||||||
Settings::Settings()
|
Settings::Settings()
|
||||||
: nixPrefix(NIX_PREFIX)
|
: nixPrefix(NIX_PREFIX)
|
||||||
|
|
|
@ -181,6 +181,6 @@ protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static RegisterStoreImplementation<HttpBinaryCacheStore, HttpBinaryCacheStoreConfig> regStore;
|
static RegisterStoreImplementation<HttpBinaryCacheStore, HttpBinaryCacheStoreConfig> regHttpBinaryCacheStore;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,6 +334,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static RegisterStoreImplementation<LegacySSHStore, LegacySSHStoreConfig> regStore;
|
static RegisterStoreImplementation<LegacySSHStore, LegacySSHStoreConfig> regLegacySSHStore;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,6 @@ std::set<std::string> LocalBinaryCacheStore::uriSchemes()
|
||||||
return {"file"};
|
return {"file"};
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterStoreImplementation<LocalBinaryCacheStore, LocalBinaryCacheStoreConfig> regStore;
|
static RegisterStoreImplementation<LocalBinaryCacheStore, LocalBinaryCacheStoreConfig> regLocalBinaryCacheStore;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "fs-accessor.hh"
|
#include "fs-accessor.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "compression.hh"
|
#include "compression.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
|
|
48
src/libstore/local-fs-store.hh
Normal file
48
src/libstore/local-fs-store.hh
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "store-api.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
struct LocalFSStoreConfig : virtual StoreConfig
|
||||||
|
{
|
||||||
|
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{(StoreConfig*) this, true, "",
|
||||||
|
"root", "directory prefixed to all other paths"};
|
||||||
|
const PathSetting stateDir{(StoreConfig*) this, false,
|
||||||
|
rootDir != "" ? rootDir + "/nix/var/nix" : settings.nixStateDir,
|
||||||
|
"state", "directory where Nix will store state"};
|
||||||
|
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;
|
||||||
|
|
||||||
|
LocalFSStore(const Params & params);
|
||||||
|
|
||||||
|
void narFromPath(const StorePath & path, Sink & sink) override;
|
||||||
|
ref<FSAccessor> getFSAccessor() override;
|
||||||
|
|
||||||
|
/* Register a permanent GC root. */
|
||||||
|
Path addPermRoot(const StorePath & storePath, const Path & gcRoot);
|
||||||
|
|
||||||
|
virtual Path getRealStoreDir() { return storeDir; }
|
||||||
|
|
||||||
|
Path toRealPath(const Path & storePath) override
|
||||||
|
{
|
||||||
|
assert(isInStore(storePath));
|
||||||
|
return getRealStoreDir() + "/" + std::string(storePath, storeDir.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<std::string> getBuildLog(const StorePath & path) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "sync.hh"
|
#include "sync.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
|
|
|
@ -276,21 +276,15 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static string showBytes(uint64_t bytes)
|
|
||||||
{
|
|
||||||
return (format("%.2f MiB") % (bytes / (1024.0 * 1024.0))).str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalStore::optimiseStore()
|
void LocalStore::optimiseStore()
|
||||||
{
|
{
|
||||||
OptimiseStats stats;
|
OptimiseStats stats;
|
||||||
|
|
||||||
optimiseStore(stats);
|
optimiseStore(stats);
|
||||||
|
|
||||||
printInfo(
|
printInfo("%s freed by hard-linking %d files",
|
||||||
format("%1% freed by hard-linking %2% files")
|
showBytes(stats.bytesFreed),
|
||||||
% showBytes(stats.bytesFreed)
|
stats.filesLinked);
|
||||||
% stats.filesLinked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalStore::optimisePath(const Path & path)
|
void LocalStore::optimisePath(const Path & path)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "profiles.hh"
|
#include "profiles.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
@ -12,16 +12,6 @@
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
#include "callback.hh"
|
#include "callback.hh"
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
namespace worker_proto {
|
namespace worker_proto {
|
||||||
|
@ -125,69 +115,6 @@ ref<RemoteStore::Connection> RemoteStore::openConnectionWrapper()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UDSRemoteStore::UDSRemoteStore(const Params & params)
|
|
||||||
: StoreConfig(params)
|
|
||||||
, Store(params)
|
|
||||||
, LocalFSStore(params)
|
|
||||||
, RemoteStore(params)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
UDSRemoteStore::UDSRemoteStore(
|
|
||||||
const std::string scheme,
|
|
||||||
std::string socket_path,
|
|
||||||
const Params & params)
|
|
||||||
: UDSRemoteStore(params)
|
|
||||||
{
|
|
||||||
path.emplace(socket_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string UDSRemoteStore::getUri()
|
|
||||||
{
|
|
||||||
if (path) {
|
|
||||||
return std::string("unix://") + *path;
|
|
||||||
} else {
|
|
||||||
return "daemon";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
|
|
||||||
{
|
|
||||||
auto conn = make_ref<Connection>();
|
|
||||||
|
|
||||||
/* Connect to a daemon that does the privileged work for us. */
|
|
||||||
conn->fd = socket(PF_UNIX, SOCK_STREAM
|
|
||||||
#ifdef SOCK_CLOEXEC
|
|
||||||
| SOCK_CLOEXEC
|
|
||||||
#endif
|
|
||||||
, 0);
|
|
||||||
if (!conn->fd)
|
|
||||||
throw SysError("cannot create Unix domain socket");
|
|
||||||
closeOnExec(conn->fd.get());
|
|
||||||
|
|
||||||
string socketPath = path ? *path : settings.nixDaemonSocketFile;
|
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
if (socketPath.size() + 1 >= sizeof(addr.sun_path))
|
|
||||||
throw Error("socket path '%1%' is too long", socketPath);
|
|
||||||
strcpy(addr.sun_path, socketPath.c_str());
|
|
||||||
|
|
||||||
if (::connect(conn->fd.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
|
||||||
throw SysError("cannot connect to daemon at '%1%'", socketPath);
|
|
||||||
|
|
||||||
conn->from.fd = conn->fd.get();
|
|
||||||
conn->to.fd = conn->fd.get();
|
|
||||||
|
|
||||||
conn->startTime = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void RemoteStore::initConnection(Connection & conn)
|
void RemoteStore::initConnection(Connection & conn)
|
||||||
{
|
{
|
||||||
/* Send the magic greeting, check for the reply. */
|
/* Send the magic greeting, check for the reply. */
|
||||||
|
@ -926,9 +853,13 @@ std::exception_ptr RemoteStore::Connection::processStderr(Sink * sink, Source *
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (msg == STDERR_ERROR) {
|
else if (msg == STDERR_ERROR) {
|
||||||
string error = readString(from);
|
if (GET_PROTOCOL_MINOR(daemonVersion) >= 26) {
|
||||||
unsigned int status = readInt(from);
|
return std::make_exception_ptr(readError(from));
|
||||||
return std::make_exception_ptr(Error(status, error));
|
} else {
|
||||||
|
string error = readString(from);
|
||||||
|
unsigned int status = readInt(from);
|
||||||
|
return std::make_exception_ptr(Error(status, error));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (msg == STDERR_NEXT)
|
else if (msg == STDERR_NEXT)
|
||||||
|
@ -1009,6 +940,4 @@ void ConnectionHandle::withFramedSink(std::function<void(Sink &sink)> fun)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterStoreImplementation<UDSRemoteStore, UDSRemoteStoreConfig> regStore;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,49 +155,5 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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(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; }
|
|
||||||
|
|
||||||
ref<FSAccessor> getFSAccessor() override
|
|
||||||
{ return LocalFSStore::getFSAccessor(); }
|
|
||||||
|
|
||||||
void narFromPath(const StorePath & path, Sink & sink) override
|
|
||||||
{ LocalFSStore::narFromPath(path, sink); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
ref<RemoteStore::Connection> openConnection() override;
|
|
||||||
std::optional<std::string> path;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -439,7 +439,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore, virtual S3BinaryCache
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static RegisterStoreImplementation<S3BinaryCacheStoreImpl, S3BinaryCacheStoreConfig> regStore;
|
static RegisterStoreImplementation<S3BinaryCacheStoreImpl, S3BinaryCacheStoreConfig> regS3BinaryCacheStore;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,6 @@ ref<RemoteStore::Connection> SSHStore::openConnection()
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterStoreImplementation<SSHStore, SSHStoreConfig> regStore;
|
static RegisterStoreImplementation<SSHStore, SSHStoreConfig> regSSHStore;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1077,7 +1077,7 @@ Derivation Store::readDerivation(const StorePath & drvPath)
|
||||||
|
|
||||||
|
|
||||||
#include "local-store.hh"
|
#include "local-store.hh"
|
||||||
#include "remote-store.hh"
|
#include "uds-remote-store.hh"
|
||||||
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
|
@ -196,6 +196,8 @@ struct StoreConfig : public Config
|
||||||
*/
|
*/
|
||||||
StoreConfig() { assert(false); }
|
StoreConfig() { assert(false); }
|
||||||
|
|
||||||
|
virtual ~StoreConfig() { }
|
||||||
|
|
||||||
virtual const std::string name() = 0;
|
virtual const std::string name() = 0;
|
||||||
|
|
||||||
const PathSetting storeDir_{this, false, settings.nixStore,
|
const PathSetting storeDir_{this, false, settings.nixStore,
|
||||||
|
@ -709,47 +711,6 @@ protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LocalFSStoreConfig : virtual StoreConfig
|
|
||||||
{
|
|
||||||
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{(StoreConfig*) this, true, "",
|
|
||||||
"root", "directory prefixed to all other paths"};
|
|
||||||
const PathSetting stateDir{(StoreConfig*) this, false,
|
|
||||||
rootDir != "" ? rootDir + "/nix/var/nix" : settings.nixStateDir,
|
|
||||||
"state", "directory where Nix will store state"};
|
|
||||||
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;
|
|
||||||
|
|
||||||
LocalFSStore(const Params & params);
|
|
||||||
|
|
||||||
void narFromPath(const StorePath & path, Sink & sink) override;
|
|
||||||
ref<FSAccessor> getFSAccessor() override;
|
|
||||||
|
|
||||||
/* Register a permanent GC root. */
|
|
||||||
Path addPermRoot(const StorePath & storePath, const Path & gcRoot);
|
|
||||||
|
|
||||||
virtual Path getRealStoreDir() { return storeDir; }
|
|
||||||
|
|
||||||
Path toRealPath(const Path & storePath) override
|
|
||||||
{
|
|
||||||
assert(isInStore(storePath));
|
|
||||||
return getRealStoreDir() + "/" + std::string(storePath, storeDir.size() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<std::string> getBuildLog(const StorePath & path) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Copy a path from one store to another. */
|
/* Copy a path from one store to another. */
|
||||||
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
|
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
|
||||||
|
|
81
src/libstore/uds-remote-store.cc
Normal file
81
src/libstore/uds-remote-store.cc
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#include "uds-remote-store.hh"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
UDSRemoteStore::UDSRemoteStore(const Params & params)
|
||||||
|
: StoreConfig(params)
|
||||||
|
, Store(params)
|
||||||
|
, LocalFSStore(params)
|
||||||
|
, RemoteStore(params)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UDSRemoteStore::UDSRemoteStore(
|
||||||
|
const std::string scheme,
|
||||||
|
std::string socket_path,
|
||||||
|
const Params & params)
|
||||||
|
: UDSRemoteStore(params)
|
||||||
|
{
|
||||||
|
path.emplace(socket_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string UDSRemoteStore::getUri()
|
||||||
|
{
|
||||||
|
if (path) {
|
||||||
|
return std::string("unix://") + *path;
|
||||||
|
} else {
|
||||||
|
return "daemon";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
|
||||||
|
{
|
||||||
|
auto conn = make_ref<Connection>();
|
||||||
|
|
||||||
|
/* Connect to a daemon that does the privileged work for us. */
|
||||||
|
conn->fd = socket(PF_UNIX, SOCK_STREAM
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
|
| SOCK_CLOEXEC
|
||||||
|
#endif
|
||||||
|
, 0);
|
||||||
|
if (!conn->fd)
|
||||||
|
throw SysError("cannot create Unix domain socket");
|
||||||
|
closeOnExec(conn->fd.get());
|
||||||
|
|
||||||
|
string socketPath = path ? *path : settings.nixDaemonSocketFile;
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
if (socketPath.size() + 1 >= sizeof(addr.sun_path))
|
||||||
|
throw Error("socket path '%1%' is too long", socketPath);
|
||||||
|
strcpy(addr.sun_path, socketPath.c_str());
|
||||||
|
|
||||||
|
if (::connect(conn->fd.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||||
|
throw SysError("cannot connect to daemon at '%1%'", socketPath);
|
||||||
|
|
||||||
|
conn->from.fd = conn->fd.get();
|
||||||
|
conn->to.fd = conn->fd.get();
|
||||||
|
|
||||||
|
conn->startTime = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static RegisterStoreImplementation<UDSRemoteStore, UDSRemoteStoreConfig> regUDSRemoteStore;
|
||||||
|
|
||||||
|
}
|
52
src/libstore/uds-remote-store.hh
Normal file
52
src/libstore/uds-remote-store.hh
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "remote-store.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
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(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; }
|
||||||
|
|
||||||
|
ref<FSAccessor> getFSAccessor() override
|
||||||
|
{ return LocalFSStore::getFSAccessor(); }
|
||||||
|
|
||||||
|
void narFromPath(const StorePath & path, Sink & sink) override
|
||||||
|
{ LocalFSStore::narFromPath(path, sink); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ref<RemoteStore::Connection> openConnection() override;
|
||||||
|
std::optional<std::string> path;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ namespace nix {
|
||||||
#define WORKER_MAGIC_1 0x6e697863
|
#define WORKER_MAGIC_1 0x6e697863
|
||||||
#define WORKER_MAGIC_2 0x6478696f
|
#define WORKER_MAGIC_2 0x6478696f
|
||||||
|
|
||||||
#define PROTOCOL_VERSION 0x119
|
#define PROTOCOL_VERSION 0x11a
|
||||||
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
|
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
|
||||||
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
|
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
|
||||||
|
|
||||||
|
@ -83,7 +83,6 @@ MAKE_WORKER_PROTO(, StorePath);
|
||||||
MAKE_WORKER_PROTO(, ContentAddress);
|
MAKE_WORKER_PROTO(, ContentAddress);
|
||||||
|
|
||||||
MAKE_WORKER_PROTO(template<typename T>, std::set<T>);
|
MAKE_WORKER_PROTO(template<typename T>, std::set<T>);
|
||||||
MAKE_WORKER_PROTO(template<typename T>, std::optional<T>);
|
|
||||||
|
|
||||||
#define X_ template<typename K, typename V>
|
#define X_ template<typename K, typename V>
|
||||||
#define Y_ std::map<K, V>
|
#define Y_ std::map<K, V>
|
||||||
|
@ -91,6 +90,22 @@ MAKE_WORKER_PROTO(X_, Y_);
|
||||||
#undef X_
|
#undef X_
|
||||||
#undef Y_
|
#undef Y_
|
||||||
|
|
||||||
|
/* These use the empty string for the null case, relying on the fact
|
||||||
|
that the underlying types never serialize to the empty string.
|
||||||
|
|
||||||
|
We do this instead of a generic std::optional<T> instance because
|
||||||
|
ordinal tags (0 or 1, here) are a bit of a compatability hazard. For
|
||||||
|
the same reason, we don't have a std::variant<T..> instances (ordinal
|
||||||
|
tags 0...n).
|
||||||
|
|
||||||
|
We could the generic instances and then these as specializations for
|
||||||
|
compatability, but that's proven a bit finnicky, and also makes the
|
||||||
|
worker protocol harder to implement in other languages where such
|
||||||
|
specializations may not be allowed.
|
||||||
|
*/
|
||||||
|
MAKE_WORKER_PROTO(, std::optional<StorePath>);
|
||||||
|
MAKE_WORKER_PROTO(, std::optional<ContentAddress>);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::set<T> read(const Store & store, Source & from, Phantom<std::set<T>> _)
|
std::set<T> read(const Store & store, Source & from, Phantom<std::set<T>> _)
|
||||||
{
|
{
|
||||||
|
@ -134,37 +149,6 @@ void write(const Store & store, Sink & out, const std::map<K, V> & resMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
std::optional<T> read(const Store & store, Source & from, Phantom<std::optional<T>> _)
|
|
||||||
{
|
|
||||||
auto tag = readNum<uint8_t>(from);
|
|
||||||
switch (tag) {
|
|
||||||
case 0:
|
|
||||||
return std::nullopt;
|
|
||||||
case 1:
|
|
||||||
return read(store, from, Phantom<T> {});
|
|
||||||
default:
|
|
||||||
throw Error("got an invalid tag bit for std::optional: %#04x", (size_t)tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void write(const Store & store, Sink & out, const std::optional<T> & optVal)
|
|
||||||
{
|
|
||||||
out << (uint64_t) (optVal ? 1 : 0);
|
|
||||||
if (optVal)
|
|
||||||
worker_proto::write(store, out, *optVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Specialization which uses and empty string for the empty case, taking
|
|
||||||
advantage of the fact these types always serialize to non-empty strings.
|
|
||||||
This is done primarily for backwards compatability, so that T <=
|
|
||||||
std::optional<T>, where <= is the compatability partial order, T is one of
|
|
||||||
the types below.
|
|
||||||
*/
|
|
||||||
MAKE_WORKER_PROTO(, std::optional<StorePath>);
|
|
||||||
MAKE_WORKER_PROTO(, std::optional<ContentAddress>);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct ArchiveSettings : Config
|
||||||
|
|
||||||
static ArchiveSettings archiveSettings;
|
static ArchiveSettings archiveSettings;
|
||||||
|
|
||||||
static GlobalConfig::Register r1(&archiveSettings);
|
static GlobalConfig::Register rArchiveSettings(&archiveSettings);
|
||||||
|
|
||||||
const std::string narVersionMagic1 = "nix-archive-1";
|
const std::string narVersionMagic1 = "nix-archive-1";
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,20 @@ void Args::addFlag(Flag && flag_)
|
||||||
if (flag->shortName) shortFlags[flag->shortName] = flag;
|
if (flag->shortName) shortFlags[flag->shortName] = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Completions::add(std::string completion, std::string description)
|
||||||
|
{
|
||||||
|
assert(description.find('\n') == std::string::npos);
|
||||||
|
insert(Completion {
|
||||||
|
.completion = completion,
|
||||||
|
.description = description
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Completion::operator<(const Completion & other) const
|
||||||
|
{ return completion < other.completion || (completion == other.completion && description < other.description); }
|
||||||
|
|
||||||
bool pathCompletions = false;
|
bool pathCompletions = false;
|
||||||
std::shared_ptr<std::set<std::string>> completions;
|
std::shared_ptr<Completions> completions;
|
||||||
|
|
||||||
std::string completionMarker = "___COMPLETE___";
|
std::string completionMarker = "___COMPLETE___";
|
||||||
|
|
||||||
|
@ -148,7 +160,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
|
||||||
for (auto & [name, flag] : longFlags) {
|
for (auto & [name, flag] : longFlags) {
|
||||||
if (!hiddenCategories.count(flag->category)
|
if (!hiddenCategories.count(flag->category)
|
||||||
&& hasPrefix(name, std::string(*prefix, 2)))
|
&& hasPrefix(name, std::string(*prefix, 2)))
|
||||||
completions->insert("--" + name);
|
completions->add("--" + name, flag->description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto i = longFlags.find(string(*pos, 2));
|
auto i = longFlags.find(string(*pos, 2));
|
||||||
|
@ -165,9 +177,9 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
|
||||||
|
|
||||||
if (auto prefix = needsCompletion(*pos)) {
|
if (auto prefix = needsCompletion(*pos)) {
|
||||||
if (prefix == "-") {
|
if (prefix == "-") {
|
||||||
completions->insert("--");
|
completions->add("--");
|
||||||
for (auto & [flag, _] : shortFlags)
|
for (auto & [flagName, flag] : shortFlags)
|
||||||
completions->insert(std::string("-") + flag);
|
completions->add(std::string("-") + flagName, flag->description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +260,7 @@ static void hashTypeCompleter(size_t index, std::string_view prefix)
|
||||||
{
|
{
|
||||||
for (auto & type : hashTypes)
|
for (auto & type : hashTypes)
|
||||||
if (hasPrefix(type, prefix))
|
if (hasPrefix(type, prefix))
|
||||||
completions->insert(type);
|
completions->add(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Args::Flag Args::Flag::mkHashTypeFlag(std::string && longName, HashType * ht)
|
Args::Flag Args::Flag::mkHashTypeFlag(std::string && longName, HashType * ht)
|
||||||
|
@ -277,7 +289,7 @@ Args::Flag Args::Flag::mkHashTypeOptFlag(std::string && longName, std::optional<
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void completePath(std::string_view prefix, bool onlyDirs)
|
static void _completePath(std::string_view prefix, bool onlyDirs)
|
||||||
{
|
{
|
||||||
pathCompletions = true;
|
pathCompletions = true;
|
||||||
glob_t globbuf;
|
glob_t globbuf;
|
||||||
|
@ -292,7 +304,7 @@ static void completePath(std::string_view prefix, bool onlyDirs)
|
||||||
auto st = lstat(globbuf.gl_pathv[i]);
|
auto st = lstat(globbuf.gl_pathv[i]);
|
||||||
if (!S_ISDIR(st.st_mode)) continue;
|
if (!S_ISDIR(st.st_mode)) continue;
|
||||||
}
|
}
|
||||||
completions->insert(globbuf.gl_pathv[i]);
|
completions->add(globbuf.gl_pathv[i]);
|
||||||
}
|
}
|
||||||
globfree(&globbuf);
|
globfree(&globbuf);
|
||||||
}
|
}
|
||||||
|
@ -300,12 +312,12 @@ static void completePath(std::string_view prefix, bool onlyDirs)
|
||||||
|
|
||||||
void completePath(size_t, std::string_view prefix)
|
void completePath(size_t, std::string_view prefix)
|
||||||
{
|
{
|
||||||
completePath(prefix, false);
|
_completePath(prefix, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void completeDir(size_t, std::string_view prefix)
|
void completeDir(size_t, std::string_view prefix)
|
||||||
{
|
{
|
||||||
completePath(prefix, true);
|
_completePath(prefix, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Strings argvToStrings(int argc, char * * argv)
|
Strings argvToStrings(int argc, char * * argv)
|
||||||
|
@ -385,7 +397,7 @@ MultiCommand::MultiCommand(const Commands & commands)
|
||||||
if (auto prefix = needsCompletion(s)) {
|
if (auto prefix = needsCompletion(s)) {
|
||||||
for (auto & [name, command] : commands)
|
for (auto & [name, command] : commands)
|
||||||
if (hasPrefix(name, *prefix))
|
if (hasPrefix(name, *prefix))
|
||||||
completions->insert(name);
|
completions->add(name);
|
||||||
}
|
}
|
||||||
auto i = commands.find(s);
|
auto i = commands.find(s);
|
||||||
if (i == commands.end())
|
if (i == commands.end())
|
||||||
|
|
|
@ -283,7 +283,17 @@ typedef std::vector<std::pair<std::string, std::string>> Table2;
|
||||||
|
|
||||||
void printTable(std::ostream & out, const Table2 & table);
|
void printTable(std::ostream & out, const Table2 & table);
|
||||||
|
|
||||||
extern std::shared_ptr<std::set<std::string>> completions;
|
struct Completion {
|
||||||
|
std::string completion;
|
||||||
|
std::string description;
|
||||||
|
|
||||||
|
bool operator<(const Completion & other) const;
|
||||||
|
};
|
||||||
|
class Completions : public std::set<Completion> {
|
||||||
|
public:
|
||||||
|
void add(std::string completion, std::string description = "");
|
||||||
|
};
|
||||||
|
extern std::shared_ptr<Completions> completions;
|
||||||
extern bool pathCompletions;
|
extern bool pathCompletions;
|
||||||
|
|
||||||
std::optional<std::string> needsCompletion(std::string_view s);
|
std::optional<std::string> needsCompletion(std::string_view s);
|
||||||
|
|
|
@ -11,13 +11,13 @@ const std::string nativeSystem = SYSTEM;
|
||||||
|
|
||||||
BaseError & BaseError::addTrace(std::optional<ErrPos> e, hintformat hint)
|
BaseError & BaseError::addTrace(std::optional<ErrPos> e, hintformat hint)
|
||||||
{
|
{
|
||||||
err.traces.push_front(Trace { .pos = e, .hint = hint});
|
err.traces.push_front(Trace { .pos = e, .hint = hint });
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// c++ std::exception descendants must have a 'const char* what()' function.
|
// c++ std::exception descendants must have a 'const char* what()' function.
|
||||||
// This stringifies the error and caches it for use by what(), or similarly by msg().
|
// This stringifies the error and caches it for use by what(), or similarly by msg().
|
||||||
const string& BaseError::calcWhat() const
|
const string & BaseError::calcWhat() const
|
||||||
{
|
{
|
||||||
if (what_.has_value())
|
if (what_.has_value())
|
||||||
return *what_;
|
return *what_;
|
||||||
|
@ -34,12 +34,12 @@ const string& BaseError::calcWhat() const
|
||||||
|
|
||||||
std::optional<string> ErrorInfo::programName = std::nullopt;
|
std::optional<string> ErrorInfo::programName = std::nullopt;
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream &os, const hintformat &hf)
|
std::ostream & operator<<(std::ostream & os, const hintformat & hf)
|
||||||
{
|
{
|
||||||
return os << hf.str();
|
return os << hf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
string showErrPos(const ErrPos &errPos)
|
string showErrPos(const ErrPos & errPos)
|
||||||
{
|
{
|
||||||
if (errPos.line > 0) {
|
if (errPos.line > 0) {
|
||||||
if (errPos.column > 0) {
|
if (errPos.column > 0) {
|
||||||
|
@ -53,7 +53,7 @@ string showErrPos(const ErrPos &errPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<LinesOfCode> getCodeLines(const ErrPos &errPos)
|
std::optional<LinesOfCode> getCodeLines(const ErrPos & errPos)
|
||||||
{
|
{
|
||||||
if (errPos.line <= 0)
|
if (errPos.line <= 0)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
@ -92,13 +92,13 @@ std::optional<LinesOfCode> getCodeLines(const ErrPos &errPos)
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (EndOfFile &eof) {
|
catch (EndOfFile & eof) {
|
||||||
if (loc.errLineOfCode.has_value())
|
if (loc.errLineOfCode.has_value())
|
||||||
return loc;
|
return loc;
|
||||||
else
|
else
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
catch (std::exception &e) {
|
catch (std::exception & e) {
|
||||||
printError("error reading nix file: %s\n%s", errPos.file, e.what());
|
printError("error reading nix file: %s\n%s", errPos.file, e.what());
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -137,10 +137,10 @@ std::optional<LinesOfCode> getCodeLines(const ErrPos &errPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
// print lines of code to the ostream, indicating the error column.
|
// print lines of code to the ostream, indicating the error column.
|
||||||
void printCodeLines(std::ostream &out,
|
void printCodeLines(std::ostream & out,
|
||||||
const string &prefix,
|
const string & prefix,
|
||||||
const ErrPos &errPos,
|
const ErrPos & errPos,
|
||||||
const LinesOfCode &loc)
|
const LinesOfCode & loc)
|
||||||
{
|
{
|
||||||
// previous line of code.
|
// previous line of code.
|
||||||
if (loc.prevLineOfCode.has_value()) {
|
if (loc.prevLineOfCode.has_value()) {
|
||||||
|
@ -186,7 +186,7 @@ void printCodeLines(std::ostream &out,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAtPos(const string &prefix, const ErrPos &pos, std::ostream &out)
|
void printAtPos(const string & prefix, const ErrPos & pos, std::ostream & out)
|
||||||
{
|
{
|
||||||
if (pos)
|
if (pos)
|
||||||
{
|
{
|
||||||
|
@ -212,7 +212,7 @@ void printAtPos(const string &prefix, const ErrPos &pos, std::ostream &out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& showErrorInfo(std::ostream &out, const ErrorInfo &einfo, bool showTrace)
|
std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool showTrace)
|
||||||
{
|
{
|
||||||
auto errwidth = std::max<size_t>(getWindowSize().second, 20);
|
auto errwidth = std::max<size_t>(getWindowSize().second, 20);
|
||||||
string prefix = "";
|
string prefix = "";
|
||||||
|
|
|
@ -107,7 +107,7 @@ struct Trace {
|
||||||
struct ErrorInfo {
|
struct ErrorInfo {
|
||||||
Verbosity level;
|
Verbosity level;
|
||||||
string name;
|
string name;
|
||||||
string description;
|
string description; // FIXME: remove? it seems to be barely used
|
||||||
std::optional<hintformat> hint;
|
std::optional<hintformat> hint;
|
||||||
std::optional<ErrPos> errPos;
|
std::optional<ErrPos> errPos;
|
||||||
std::list<Trace> traces;
|
std::list<Trace> traces;
|
||||||
|
@ -169,7 +169,7 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const string & msg() const { return calcWhat(); }
|
const string & msg() const { return calcWhat(); }
|
||||||
const ErrorInfo & info() { calcWhat(); return err; }
|
const ErrorInfo & info() const { calcWhat(); return err; }
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
BaseError & addTrace(std::optional<ErrPos> e, const string &fs, const Args & ... args)
|
BaseError & addTrace(std::optional<ErrPos> e, const string &fs, const Args & ... args)
|
||||||
|
|
|
@ -76,11 +76,11 @@ template <class T>
|
||||||
struct yellowtxt
|
struct yellowtxt
|
||||||
{
|
{
|
||||||
yellowtxt(const T &s) : value(s) {}
|
yellowtxt(const T &s) : value(s) {}
|
||||||
const T &value;
|
const T & value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
std::ostream& operator<<(std::ostream &out, const yellowtxt<T> &y)
|
std::ostream & operator<<(std::ostream & out, const yellowtxt<T> & y)
|
||||||
{
|
{
|
||||||
return out << ANSI_YELLOW << y.value << ANSI_NORMAL;
|
return out << ANSI_YELLOW << y.value << ANSI_NORMAL;
|
||||||
}
|
}
|
||||||
|
@ -88,12 +88,12 @@ std::ostream& operator<<(std::ostream &out, const yellowtxt<T> &y)
|
||||||
template <class T>
|
template <class T>
|
||||||
struct normaltxt
|
struct normaltxt
|
||||||
{
|
{
|
||||||
normaltxt(const T &s) : value(s) {}
|
normaltxt(const T & s) : value(s) {}
|
||||||
const T &value;
|
const T & value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
std::ostream& operator<<(std::ostream &out, const normaltxt<T> &y)
|
std::ostream & operator<<(std::ostream & out, const normaltxt<T> & y)
|
||||||
{
|
{
|
||||||
return out << ANSI_NORMAL << y.value;
|
return out << ANSI_NORMAL << y.value;
|
||||||
}
|
}
|
||||||
|
@ -101,26 +101,30 @@ std::ostream& operator<<(std::ostream &out, const normaltxt<T> &y)
|
||||||
class hintformat
|
class hintformat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
hintformat(const string &format) :fmt(format)
|
hintformat(const string & format) : fmt(format)
|
||||||
{
|
{
|
||||||
fmt.exceptions(boost::io::all_error_bits ^
|
fmt.exceptions(boost::io::all_error_bits ^
|
||||||
boost::io::too_many_args_bit ^
|
boost::io::too_many_args_bit ^
|
||||||
boost::io::too_few_args_bit);
|
boost::io::too_few_args_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
hintformat(const hintformat &hf)
|
hintformat(const hintformat & hf)
|
||||||
: fmt(hf.fmt)
|
: fmt(hf.fmt)
|
||||||
{}
|
{ }
|
||||||
|
|
||||||
|
hintformat(format && fmt)
|
||||||
|
: fmt(std::move(fmt))
|
||||||
|
{ }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
hintformat& operator%(const T &value)
|
hintformat & operator%(const T & value)
|
||||||
{
|
{
|
||||||
fmt % yellowtxt(value);
|
fmt % yellowtxt(value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
hintformat& operator%(const normaltxt<T> &value)
|
hintformat & operator%(const normaltxt<T> & value)
|
||||||
{
|
{
|
||||||
fmt % value.value;
|
fmt % value.value;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -135,7 +139,7 @@ private:
|
||||||
format fmt;
|
format fmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream &os, const hintformat &hf);
|
std::ostream & operator<<(std::ostream & os, const hintformat & hf);
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
inline hintformat hintfmt(const std::string & fs, const Args & ... args)
|
inline hintformat hintfmt(const std::string & fs, const Args & ... args)
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
#include <exception>
|
|
||||||
#include <functional>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace nix {
|
|
||||||
|
|
||||||
/* A helper class for lazily-initialized variables.
|
|
||||||
|
|
||||||
Lazy<T> var([]() { return value; });
|
|
||||||
|
|
||||||
declares a variable of type T that is initialized to 'value' (in a
|
|
||||||
thread-safe way) on first use, that is, when var() is first
|
|
||||||
called. If the initialiser code throws an exception, then all
|
|
||||||
subsequent calls to var() will rethrow that exception. */
|
|
||||||
template<typename T>
|
|
||||||
class Lazy
|
|
||||||
{
|
|
||||||
|
|
||||||
typedef std::function<T()> Init;
|
|
||||||
|
|
||||||
Init init;
|
|
||||||
|
|
||||||
std::once_flag done;
|
|
||||||
|
|
||||||
T value;
|
|
||||||
|
|
||||||
std::exception_ptr ex;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Lazy(Init init) : init(init)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
const T & operator () ()
|
|
||||||
{
|
|
||||||
std::call_once(done, [&]() {
|
|
||||||
try {
|
|
||||||
value = init();
|
|
||||||
} catch (...) {
|
|
||||||
ex = std::current_exception();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (ex) std::rethrow_exception(ex);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -10,7 +10,7 @@ namespace nix {
|
||||||
|
|
||||||
LoggerSettings loggerSettings;
|
LoggerSettings loggerSettings;
|
||||||
|
|
||||||
static GlobalConfig::Register r1(&loggerSettings);
|
static GlobalConfig::Register rLoggerSettings(&loggerSettings);
|
||||||
|
|
||||||
static thread_local ActivityId curActivity = 0;
|
static thread_local ActivityId curActivity = 0;
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,24 @@ Sink & operator << (Sink & sink, const StringSet & s)
|
||||||
return sink;
|
return sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sink & operator << (Sink & sink, const Error & ex)
|
||||||
|
{
|
||||||
|
auto info = ex.info();
|
||||||
|
sink
|
||||||
|
<< "Error"
|
||||||
|
<< info.level
|
||||||
|
<< info.name
|
||||||
|
<< info.description
|
||||||
|
<< (info.hint ? info.hint->str() : "")
|
||||||
|
<< 0 // FIXME: info.errPos
|
||||||
|
<< info.traces.size();
|
||||||
|
for (auto & trace : info.traces) {
|
||||||
|
sink << 0; // FIXME: trace.pos
|
||||||
|
sink << trace.hint.str();
|
||||||
|
}
|
||||||
|
return sink;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void readPadding(size_t len, Source & source)
|
void readPadding(size_t len, Source & source)
|
||||||
{
|
{
|
||||||
|
@ -319,6 +337,30 @@ template Paths readStrings(Source & source);
|
||||||
template PathSet readStrings(Source & source);
|
template PathSet readStrings(Source & source);
|
||||||
|
|
||||||
|
|
||||||
|
Error readError(Source & source)
|
||||||
|
{
|
||||||
|
auto type = readString(source);
|
||||||
|
assert(type == "Error");
|
||||||
|
ErrorInfo info;
|
||||||
|
info.level = (Verbosity) readInt(source);
|
||||||
|
info.name = readString(source);
|
||||||
|
info.description = readString(source);
|
||||||
|
auto hint = readString(source);
|
||||||
|
if (hint != "") info.hint = hintformat(std::move(format("%s") % hint));
|
||||||
|
auto havePos = readNum<size_t>(source);
|
||||||
|
assert(havePos == 0);
|
||||||
|
auto nrTraces = readNum<size_t>(source);
|
||||||
|
for (size_t i = 0; i < nrTraces; ++i) {
|
||||||
|
havePos = readNum<size_t>(source);
|
||||||
|
assert(havePos == 0);
|
||||||
|
info.traces.push_back(Trace {
|
||||||
|
.hint = hintformat(std::move(format("%s") % readString(source)))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Error(std::move(info));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringSink::operator () (const unsigned char * data, size_t len)
|
void StringSink::operator () (const unsigned char * data, size_t len)
|
||||||
{
|
{
|
||||||
static bool warned = false;
|
static bool warned = false;
|
||||||
|
|
|
@ -321,6 +321,7 @@ inline Sink & operator << (Sink & sink, uint64_t n)
|
||||||
Sink & operator << (Sink & sink, const string & s);
|
Sink & operator << (Sink & sink, const string & s);
|
||||||
Sink & operator << (Sink & sink, const Strings & s);
|
Sink & operator << (Sink & sink, const Strings & s);
|
||||||
Sink & operator << (Sink & sink, const StringSet & s);
|
Sink & operator << (Sink & sink, const StringSet & s);
|
||||||
|
Sink & operator << (Sink & in, const Error & ex);
|
||||||
|
|
||||||
|
|
||||||
MakeError(SerialisationError, Error);
|
MakeError(SerialisationError, Error);
|
||||||
|
@ -382,6 +383,8 @@ Source & operator >> (Source & in, bool & b)
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error readError(Source & source);
|
||||||
|
|
||||||
|
|
||||||
/* An adapter that converts a std::basic_istream into a source. */
|
/* An adapter that converts a std::basic_istream into a source. */
|
||||||
struct StreamToSourceAdapter : Source
|
struct StreamToSourceAdapter : Source
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "error.hh"
|
#include "error.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include "lazy.hh"
|
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "affinity.hh"
|
#include "affinity.hh"
|
||||||
#include "sync.hh"
|
#include "sync.hh"
|
||||||
|
@ -326,7 +325,12 @@ void writeFile(const Path & path, const string & s, mode_t mode)
|
||||||
AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode);
|
AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode);
|
||||||
if (!fd)
|
if (!fd)
|
||||||
throw SysError("opening file '%1%'", path);
|
throw SysError("opening file '%1%'", path);
|
||||||
writeFull(fd.get(), s);
|
try {
|
||||||
|
writeFull(fd.get(), s);
|
||||||
|
} catch (Error & e) {
|
||||||
|
e.addTrace({}, "writing file '%1%'", path);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -338,11 +342,16 @@ void writeFile(const Path & path, Source & source, mode_t mode)
|
||||||
|
|
||||||
std::vector<unsigned char> buf(64 * 1024);
|
std::vector<unsigned char> buf(64 * 1024);
|
||||||
|
|
||||||
while (true) {
|
try {
|
||||||
try {
|
while (true) {
|
||||||
auto n = source.read(buf.data(), buf.size());
|
try {
|
||||||
writeFull(fd.get(), (unsigned char *) buf.data(), n);
|
auto n = source.read(buf.data(), buf.size());
|
||||||
} catch (EndOfFile &) { break; }
|
writeFull(fd.get(), (unsigned char *) buf.data(), n);
|
||||||
|
} catch (EndOfFile &) { break; }
|
||||||
|
}
|
||||||
|
} catch (Error & e) {
|
||||||
|
e.addTrace({}, "writing file '%1%'", path);
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,21 +521,24 @@ std::string getUserName()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Lazy<Path> getHome2([]() {
|
Path getHome()
|
||||||
auto homeDir = getEnv("HOME");
|
{
|
||||||
if (!homeDir) {
|
static Path homeDir = []()
|
||||||
std::vector<char> buf(16384);
|
{
|
||||||
struct passwd pwbuf;
|
auto homeDir = getEnv("HOME");
|
||||||
struct passwd * pw;
|
if (!homeDir) {
|
||||||
if (getpwuid_r(geteuid(), &pwbuf, buf.data(), buf.size(), &pw) != 0
|
std::vector<char> buf(16384);
|
||||||
|| !pw || !pw->pw_dir || !pw->pw_dir[0])
|
struct passwd pwbuf;
|
||||||
throw Error("cannot determine user's home directory");
|
struct passwd * pw;
|
||||||
homeDir = pw->pw_dir;
|
if (getpwuid_r(geteuid(), &pwbuf, buf.data(), buf.size(), &pw) != 0
|
||||||
}
|
|| !pw || !pw->pw_dir || !pw->pw_dir[0])
|
||||||
return *homeDir;
|
throw Error("cannot determine user's home directory");
|
||||||
});
|
homeDir = pw->pw_dir;
|
||||||
|
}
|
||||||
Path getHome() { return getHome2(); }
|
return *homeDir;
|
||||||
|
}();
|
||||||
|
return homeDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Path getCacheDir()
|
Path getCacheDir()
|
||||||
|
@ -1641,4 +1653,11 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
|
||||||
return fdSocket;
|
return fdSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string showBytes(uint64_t bytes)
|
||||||
|
{
|
||||||
|
return fmt("%.2f MiB", bytes / (1024.0 * 1024.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -573,4 +573,7 @@ template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||||
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
||||||
|
|
||||||
|
|
||||||
|
std::string showBytes(uint64_t bytes);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "affinity.hh"
|
#include "affinity.hh"
|
||||||
|
@ -67,7 +68,7 @@ std::vector<string> shellwords(const string & s)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _main(int argc, char * * argv)
|
static void main_nix_build(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
auto dryRun = false;
|
auto dryRun = false;
|
||||||
auto runEnv = std::regex_search(argv[0], std::regex("nix-shell$"));
|
auto runEnv = std::regex_search(argv[0], std::regex("nix-shell$"));
|
||||||
|
@ -540,5 +541,5 @@ static void _main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-build", _main);
|
static RegisterLegacyCommand r_nix_build("nix-build", main_nix_build);
|
||||||
static RegisterLegacyCommand s2("nix-shell", _main);
|
static RegisterLegacyCommand r_nix_shell("nix-shell", main_nix_build);
|
||||||
|
|
|
@ -153,7 +153,7 @@ static void update(const StringSet & channelNames)
|
||||||
replaceSymlink(profile, channelLink);
|
replaceSymlink(profile, channelLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _main(int argc, char ** argv)
|
static int main_nix_channel(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
// Figure out the name of the `.nix-channels' file to use
|
// Figure out the name of the `.nix-channels' file to use
|
||||||
|
@ -250,4 +250,4 @@ static int _main(int argc, char ** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-channel", _main);
|
static RegisterLegacyCommand r_nix_channel("nix-channel", main_nix_channel);
|
||||||
|
|
|
@ -49,7 +49,7 @@ void removeOldGenerations(std::string dir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _main(int argc, char * * argv)
|
static int main_nix_collect_garbage(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
bool removeOld = false;
|
bool removeOld = false;
|
||||||
|
@ -92,4 +92,4 @@ static int _main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-collect-garbage", _main);
|
static RegisterLegacyCommand r_nix_collect_garbage("nix-collect-garbage", main_nix_collect_garbage);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
static int _main(int argc, char ** argv)
|
static int main_nix_copy_closure(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto gzip = false;
|
auto gzip = false;
|
||||||
|
@ -65,4 +65,4 @@ static int _main(int argc, char ** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-copy-closure", _main);
|
static RegisterLegacyCommand r_nix_copy_closure("nix-copy-closure", main_nix_copy_closure);
|
||||||
|
|
|
@ -265,7 +265,7 @@ static void daemonLoop(char * * argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _main(int argc, char * * argv)
|
static int main_nix_daemon(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto stdio = false;
|
auto stdio = false;
|
||||||
|
@ -330,4 +330,4 @@ static int _main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-daemon", _main);
|
static RegisterLegacyCommand r_nix_daemon("nix-daemon", main_nix_daemon);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "profiles.hh"
|
#include "profiles.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "user-env.hh"
|
#include "user-env.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "json.hh"
|
#include "json.hh"
|
||||||
|
@ -1330,7 +1331,7 @@ static void opVersion(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _main(int argc, char * * argv)
|
static int main_nix_env(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Strings opFlags, opArgs;
|
Strings opFlags, opArgs;
|
||||||
|
@ -1460,4 +1461,4 @@ static int _main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-env", _main);
|
static RegisterLegacyCommand r_nix_env("nix-env", main_nix_env);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "value-to-json.hh"
|
#include "value-to-json.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "common-eval-args.hh"
|
#include "common-eval-args.hh"
|
||||||
#include "../nix/legacy.hh"
|
#include "../nix/legacy.hh"
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ void processExpr(EvalState & state, const Strings & attrPaths,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _main(int argc, char * * argv)
|
static int main_nix_instantiate(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Strings files;
|
Strings files;
|
||||||
|
@ -192,4 +193,4 @@ static int _main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-instantiate", _main);
|
static RegisterLegacyCommand r_nix_instantiate("nix-instantiate", main_nix_instantiate);
|
||||||
|
|
|
@ -48,7 +48,7 @@ string resolveMirrorUri(EvalState & state, string uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _main(int argc, char * * argv)
|
static int main_nix_prefetch_url(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
HashType ht = htSHA256;
|
HashType ht = htSHA256;
|
||||||
|
@ -235,4 +235,4 @@ static int _main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-prefetch-url", _main);
|
static RegisterLegacyCommand r_nix_prefetch_url("nix-prefetch-url", main_nix_prefetch_url);
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace nix_store {
|
||||||
|
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
using std::cin;
|
using std::cin;
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
@ -1031,7 +1034,7 @@ static void opVersion(Strings opFlags, Strings opArgs)
|
||||||
/* Scan the arguments; find the operation, set global flags, put all
|
/* Scan the arguments; find the operation, set global flags, put all
|
||||||
other flags in a list, and put all other arguments in another
|
other flags in a list, and put all other arguments in another
|
||||||
list. */
|
list. */
|
||||||
static int _main(int argc, char * * argv)
|
static int main_nix_store(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Strings opFlags, opArgs;
|
Strings opFlags, opArgs;
|
||||||
|
@ -1127,4 +1130,6 @@ static int _main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterLegacyCommand s1("nix-store", _main);
|
static RegisterLegacyCommand r_nix_store("nix-store", main_nix_store);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -93,4 +93,4 @@ struct CmdAddToStore : MixDryRun, StoreCommand
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = registerCommand<CmdAddToStore>("add-to-store");
|
static auto rCmdAddToStore = registerCommand<CmdAddToStore>("add-to-store");
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
|
@ -88,4 +89,4 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixProfile
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = registerCommand<CmdBuild>("build");
|
static auto rCmdBuild = registerCommand<CmdBuild>("build");
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "fs-accessor.hh"
|
#include "fs-accessor.hh"
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
|
@ -72,5 +72,5 @@ struct CmdCatNar : StoreCommand, MixCat
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = registerCommand<CmdCatStore>("cat-store");
|
static auto rCmdCatStore = registerCommand<CmdCatStore>("cat-store");
|
||||||
static auto r2 = registerCommand<CmdCatNar>("cat-nar");
|
static auto rCmdCatNar = registerCommand<CmdCatNar>("cat-nar");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "command.hh"
|
#include "command.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "local-fs-store.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "nixexpr.hh"
|
#include "nixexpr.hh"
|
||||||
#include "profiles.hh"
|
#include "profiles.hh"
|
||||||
|
|
|
@ -106,4 +106,4 @@ struct CmdCopy : StorePathsCommand
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = registerCommand<CmdCopy>("copy");
|
static auto rCmdCopy = registerCommand<CmdCopy>("copy");
|
||||||
|
|
|
@ -41,4 +41,4 @@ struct CmdDescribeStores : Command, MixJSON
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = registerCommand<CmdDescribeStores>("describe-stores");
|
static auto rDescribeStore = registerCommand<CmdDescribeStores>("describe-stores");
|
||||||
|
|
|
@ -164,6 +164,7 @@ struct Common : InstallableCommand, MixProfile
|
||||||
"BASHOPTS",
|
"BASHOPTS",
|
||||||
"EUID",
|
"EUID",
|
||||||
"HOME", // FIXME: don't ignore in pure mode?
|
"HOME", // FIXME: don't ignore in pure mode?
|
||||||
|
"HOSTNAME",
|
||||||
"NIX_BUILD_TOP",
|
"NIX_BUILD_TOP",
|
||||||
"NIX_ENFORCE_PURITY",
|
"NIX_ENFORCE_PURITY",
|
||||||
"NIX_LOG_FD",
|
"NIX_LOG_FD",
|
||||||
|
@ -377,6 +378,10 @@ struct CmdDevelop : Common, MixEnvironment
|
||||||
script += fmt("exec %s\n", concatStringsSep(" ", args));
|
script += fmt("exec %s\n", concatStringsSep(" ", args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
script += "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;\n";
|
||||||
|
}
|
||||||
|
|
||||||
writeFull(rcFileFd.get(), script);
|
writeFull(rcFileFd.get(), script);
|
||||||
|
|
||||||
stopProgressBar();
|
stopProgressBar();
|
||||||
|
@ -443,5 +448,5 @@ struct CmdPrintDevEnv : Common
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto r1 = registerCommand<CmdPrintDevEnv>("print-dev-env");
|
static auto rCmdPrintDevEnv = registerCommand<CmdPrintDevEnv>("print-dev-env");
|
||||||
static auto r2 = registerCommand<CmdDevelop>("develop");
|
static auto rCmdDevelop = registerCommand<CmdDevelop>("develop");
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue