mirror of
https://github.com/NixOS/nix
synced 2025-06-30 03:23:16 +02:00
Merge remote-tracking branch 'origin/master' into flakes
This commit is contained in:
commit
c3c23a52ee
76 changed files with 1387 additions and 631 deletions
|
@ -70,23 +70,23 @@ public:
|
|||
Args & args;
|
||||
Flag::ptr flag;
|
||||
friend class Args;
|
||||
FlagMaker(Args & args) : args(args), flag(std::make_shared<Flag>()) { };
|
||||
FlagMaker(Args & args) : args(args), flag(std::make_shared<Flag>()) { }
|
||||
public:
|
||||
~FlagMaker();
|
||||
FlagMaker & longName(const std::string & s) { flag->longName = s; return *this; };
|
||||
FlagMaker & shortName(char s) { flag->shortName = s; return *this; };
|
||||
FlagMaker & description(const std::string & s) { flag->description = s; return *this; };
|
||||
FlagMaker & label(const std::string & l) { flag->arity = 1; flag->labels = {l}; return *this; };
|
||||
FlagMaker & labels(const Strings & ls) { flag->arity = ls.size(); flag->labels = ls; return *this; };
|
||||
FlagMaker & arity(size_t arity) { flag->arity = arity; return *this; };
|
||||
FlagMaker & handler(std::function<void(std::vector<std::string>)> handler) { flag->handler = handler; return *this; };
|
||||
FlagMaker & handler(std::function<void()> handler) { flag->handler = [handler](std::vector<std::string>) { handler(); }; return *this; };
|
||||
FlagMaker & longName(const std::string & s) { flag->longName = s; return *this; }
|
||||
FlagMaker & shortName(char s) { flag->shortName = s; return *this; }
|
||||
FlagMaker & description(const std::string & s) { flag->description = s; return *this; }
|
||||
FlagMaker & label(const std::string & l) { flag->arity = 1; flag->labels = {l}; return *this; }
|
||||
FlagMaker & labels(const Strings & ls) { flag->arity = ls.size(); flag->labels = ls; return *this; }
|
||||
FlagMaker & arity(size_t arity) { flag->arity = arity; return *this; }
|
||||
FlagMaker & handler(std::function<void(std::vector<std::string>)> handler) { flag->handler = handler; return *this; }
|
||||
FlagMaker & handler(std::function<void()> handler) { flag->handler = [handler](std::vector<std::string>) { handler(); }; return *this; }
|
||||
FlagMaker & handler(std::function<void(std::string)> handler) {
|
||||
flag->arity = 1;
|
||||
flag->handler = [handler](std::vector<std::string> ss) { handler(std::move(ss[0])); };
|
||||
return *this;
|
||||
};
|
||||
FlagMaker & category(const std::string & s) { flag->category = s; return *this; };
|
||||
}
|
||||
FlagMaker & category(const std::string & s) { flag->category = s; return *this; }
|
||||
|
||||
template<class T>
|
||||
FlagMaker & dest(T * dest)
|
||||
|
@ -94,7 +94,7 @@ public:
|
|||
flag->arity = 1;
|
||||
flag->handler = [=](std::vector<std::string> ss) { *dest = ss[0]; };
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
FlagMaker & set(T * dest, const T & val)
|
||||
|
@ -102,7 +102,7 @@ public:
|
|||
flag->arity = 0;
|
||||
flag->handler = [=](std::vector<std::string> ss) { *dest = val; };
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
FlagMaker & mkHashTypeFlag(HashType * ht);
|
||||
};
|
||||
|
|
|
@ -7,3 +7,5 @@ libutil_DIR := $(d)
|
|||
libutil_SOURCES := $(wildcard $(d)/*.cc)
|
||||
|
||||
libutil_LDFLAGS = $(LIBLZMA_LIBS) -lbz2 -pthread $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(BOOST_LDFLAGS) -lboost_context
|
||||
|
||||
libutil_LIBS = libnixrust
|
||||
|
|
12
src/libutil/rust-ffi.cc
Normal file
12
src/libutil/rust-ffi.cc
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "logging.hh"
|
||||
#include "rust-ffi.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
extern "C" std::exception_ptr * make_error(rust::StringSlice s)
|
||||
{
|
||||
// FIXME: leak
|
||||
return new std::exception_ptr(std::make_exception_ptr(Error(std::string(s.ptr, s.size))));
|
||||
}
|
||||
|
||||
}
|
84
src/libutil/rust-ffi.hh
Normal file
84
src/libutil/rust-ffi.hh
Normal file
|
@ -0,0 +1,84 @@
|
|||
#include "serialise.hh"
|
||||
|
||||
namespace rust {
|
||||
|
||||
// Depending on the internal representation of Rust slices is slightly
|
||||
// evil...
|
||||
template<typename T>
|
||||
struct Slice
|
||||
{
|
||||
T * ptr;
|
||||
size_t size;
|
||||
|
||||
Slice(T * ptr, size_t size) : ptr(ptr), size(size)
|
||||
{
|
||||
assert(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
struct StringSlice : Slice<char>
|
||||
{
|
||||
StringSlice(const std::string & s): Slice((char *) s.data(), s.size()) {}
|
||||
};
|
||||
|
||||
struct Source
|
||||
{
|
||||
size_t (*fun)(void * source_this, rust::Slice<uint8_t> data);
|
||||
nix::Source * _this;
|
||||
|
||||
Source(nix::Source & _this)
|
||||
: fun(sourceWrapper), _this(&_this)
|
||||
{}
|
||||
|
||||
// FIXME: how to propagate exceptions?
|
||||
static size_t sourceWrapper(void * _this, rust::Slice<uint8_t> data)
|
||||
{
|
||||
auto n = ((nix::Source *) _this)->read(data.ptr, data.size);
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
/* C++ representation of Rust's Result<T, CppException>. */
|
||||
template<typename T>
|
||||
struct Result
|
||||
{
|
||||
unsigned int tag;
|
||||
|
||||
union {
|
||||
T data;
|
||||
std::exception_ptr * exc;
|
||||
};
|
||||
|
||||
/* Rethrow the wrapped exception or return the wrapped value. */
|
||||
T unwrap()
|
||||
{
|
||||
if (tag == 0)
|
||||
return data;
|
||||
else if (tag == 1)
|
||||
std::rethrow_exception(*exc);
|
||||
else
|
||||
abort();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct CBox
|
||||
{
|
||||
T * ptr;
|
||||
|
||||
T * operator ->()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
CBox(T * ptr) : ptr(ptr) { }
|
||||
CBox(const CBox &) = delete;
|
||||
CBox(CBox &&) = delete;
|
||||
|
||||
~CBox()
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -77,7 +77,6 @@ struct BufferedSource : Source
|
|||
|
||||
size_t read(unsigned char * data, size_t len) override;
|
||||
|
||||
|
||||
bool hasData();
|
||||
|
||||
protected:
|
||||
|
@ -274,7 +273,7 @@ Sink & operator << (Sink & sink, const Strings & s);
|
|||
Sink & operator << (Sink & sink, const StringSet & s);
|
||||
|
||||
|
||||
MakeError(SerialisationError, Error)
|
||||
MakeError(SerialisationError, Error);
|
||||
|
||||
|
||||
template<typename T>
|
||||
|
|
36
src/libutil/tarfile.cc
Normal file
36
src/libutil/tarfile.cc
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "rust-ffi.hh"
|
||||
#include "compression.hh"
|
||||
|
||||
extern "C" {
|
||||
rust::Result<std::tuple<>> *
|
||||
unpack_tarfile(rust::Source source, rust::StringSlice dest_dir);
|
||||
}
|
||||
|
||||
namespace nix {
|
||||
|
||||
void unpackTarfile(Source & source, const Path & destDir)
|
||||
{
|
||||
rust::Source source2(source);
|
||||
rust::CBox(unpack_tarfile(source2, destDir))->unwrap();
|
||||
}
|
||||
|
||||
void unpackTarfile(const Path & tarFile, const Path & destDir,
|
||||
std::optional<std::string> baseName)
|
||||
{
|
||||
if (!baseName) baseName = baseNameOf(tarFile);
|
||||
|
||||
auto source = sinkToSource([&](Sink & sink) {
|
||||
// FIXME: look at first few bytes to determine compression type.
|
||||
auto decompressor =
|
||||
// FIXME: add .gz support
|
||||
hasSuffix(*baseName, ".bz2") ? makeDecompressionSink("bzip2", sink) :
|
||||
hasSuffix(*baseName, ".xz") ? makeDecompressionSink("xz", sink) :
|
||||
makeDecompressionSink("none", sink);
|
||||
readFile(tarFile, *decompressor);
|
||||
decompressor->finish();
|
||||
});
|
||||
|
||||
unpackTarfile(*source, destDir);
|
||||
}
|
||||
|
||||
}
|
10
src/libutil/tarfile.hh
Normal file
10
src/libutil/tarfile.hh
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "serialise.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
void unpackTarfile(Source & source, const Path & destDir);
|
||||
|
||||
void unpackTarfile(const Path & tarFile, const Path & destDir,
|
||||
std::optional<std::string> baseName = {});
|
||||
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
MakeError(ThreadPoolShutDown, Error)
|
||||
MakeError(ThreadPoolShutDown, Error);
|
||||
|
||||
/* A simple thread pool that executes a queue of work items
|
||||
(lambdas). */
|
||||
|
|
|
@ -116,9 +116,9 @@ public:
|
|||
{ \
|
||||
public: \
|
||||
using superClass::superClass; \
|
||||
};
|
||||
}
|
||||
|
||||
MakeError(Error, BaseError)
|
||||
MakeError(Error, BaseError);
|
||||
|
||||
class SysError : public Error
|
||||
{
|
||||
|
|
|
@ -59,10 +59,11 @@ std::string SysError::addErrno(const std::string & s)
|
|||
}
|
||||
|
||||
|
||||
string getEnv(const string & key, const string & def)
|
||||
std::optional<std::string> getEnv(const std::string & key)
|
||||
{
|
||||
char * value = getenv(key.c_str());
|
||||
return value ? string(value) : def;
|
||||
if (!value) return {};
|
||||
return std::string(value);
|
||||
}
|
||||
|
||||
|
||||
|
@ -438,7 +439,7 @@ void deletePath(const Path & path, unsigned long long & bytesFreed)
|
|||
static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
|
||||
int & counter)
|
||||
{
|
||||
tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot, true);
|
||||
tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR").value_or("/tmp") : tmpRoot, true);
|
||||
if (includePid)
|
||||
return (format("%1%/%2%-%3%-%4%") % tmpRoot % prefix % getpid() % counter++).str();
|
||||
else
|
||||
|
@ -479,7 +480,7 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
|
|||
|
||||
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
|
||||
{
|
||||
Path tmpl(getEnv("TMPDIR", "/tmp") + "/" + prefix + ".XXXXXX");
|
||||
Path tmpl(getEnv("TMPDIR").value_or("/tmp") + "/" + prefix + ".XXXXXX");
|
||||
// Strictly speaking, this is UB, but who cares...
|
||||
AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
|
||||
if (!fd)
|
||||
|
@ -491,7 +492,7 @@ std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
|
|||
std::string getUserName()
|
||||
{
|
||||
auto pw = getpwuid(geteuid());
|
||||
std::string name = pw ? pw->pw_name : getEnv("USER", "");
|
||||
std::string name = pw ? pw->pw_name : getEnv("USER").value_or("");
|
||||
if (name.empty())
|
||||
throw Error("cannot figure out user name");
|
||||
return name;
|
||||
|
@ -499,8 +500,8 @@ std::string getUserName()
|
|||
|
||||
|
||||
static Lazy<Path> getHome2([]() {
|
||||
Path homeDir = getEnv("HOME");
|
||||
if (homeDir.empty()) {
|
||||
auto homeDir = getEnv("HOME");
|
||||
if (!homeDir) {
|
||||
std::vector<char> buf(16384);
|
||||
struct passwd pwbuf;
|
||||
struct passwd * pw;
|
||||
|
@ -509,7 +510,7 @@ static Lazy<Path> getHome2([]() {
|
|||
throw Error("cannot determine user's home directory");
|
||||
homeDir = pw->pw_dir;
|
||||
}
|
||||
return homeDir;
|
||||
return *homeDir;
|
||||
});
|
||||
|
||||
Path getHome() { return getHome2(); }
|
||||
|
@ -517,25 +518,21 @@ Path getHome() { return getHome2(); }
|
|||
|
||||
Path getCacheDir()
|
||||
{
|
||||
Path cacheDir = getEnv("XDG_CACHE_HOME");
|
||||
if (cacheDir.empty())
|
||||
cacheDir = getHome() + "/.cache";
|
||||
return cacheDir;
|
||||
auto cacheDir = getEnv("XDG_CACHE_HOME");
|
||||
return cacheDir ? *cacheDir : getHome() + "/.cache";
|
||||
}
|
||||
|
||||
|
||||
Path getConfigDir()
|
||||
{
|
||||
Path configDir = getEnv("XDG_CONFIG_HOME");
|
||||
if (configDir.empty())
|
||||
configDir = getHome() + "/.config";
|
||||
return configDir;
|
||||
auto configDir = getEnv("XDG_CONFIG_HOME");
|
||||
return configDir ? *configDir : getHome() + "/.config";
|
||||
}
|
||||
|
||||
std::vector<Path> getConfigDirs()
|
||||
{
|
||||
Path configHome = getConfigDir();
|
||||
string configDirs = getEnv("XDG_CONFIG_DIRS");
|
||||
string configDirs = getEnv("XDG_CONFIG_DIRS").value_or("");
|
||||
std::vector<Path> result = tokenizeString<std::vector<string>>(configDirs, ":");
|
||||
result.insert(result.begin(), configHome);
|
||||
return result;
|
||||
|
@ -544,10 +541,8 @@ std::vector<Path> getConfigDirs()
|
|||
|
||||
Path getDataDir()
|
||||
{
|
||||
Path dataDir = getEnv("XDG_DATA_HOME");
|
||||
if (dataDir.empty())
|
||||
dataDir = getHome() + "/.local/share";
|
||||
return dataDir;
|
||||
auto dataDir = getEnv("XDG_DATA_HOME");
|
||||
return dataDir ? *dataDir : getHome() + "/.local/share";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ extern const std::string nativeSystem;
|
|||
|
||||
|
||||
/* Return an environment variable. */
|
||||
string getEnv(const string & key, const string & def = "");
|
||||
std::optional<std::string> getEnv(const std::string & key);
|
||||
|
||||
/* Get the entire environment. */
|
||||
std::map<std::string, std::string> getEnv();
|
||||
|
@ -158,7 +158,7 @@ void readFull(int fd, unsigned char * buf, size_t count);
|
|||
void writeFull(int fd, const unsigned char * buf, size_t count, bool allowInterrupts = true);
|
||||
void writeFull(int fd, const string & s, bool allowInterrupts = true);
|
||||
|
||||
MakeError(EndOfFile, Error)
|
||||
MakeError(EndOfFile, Error);
|
||||
|
||||
|
||||
/* Read a file descriptor until EOF occurs. */
|
||||
|
@ -339,10 +339,10 @@ void inline checkInterrupt()
|
|||
_interrupted();
|
||||
}
|
||||
|
||||
MakeError(Interrupted, BaseError)
|
||||
MakeError(Interrupted, BaseError);
|
||||
|
||||
|
||||
MakeError(FormatError, Error)
|
||||
MakeError(FormatError, Error);
|
||||
|
||||
|
||||
/* String tokenizer. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue