mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-15 10:46:15 +02:00
Merge pull request #11362 from siddhantk232/path-in-exec
More `std::filesystem::path` in end executables
This commit is contained in:
commit
2a1a26f8fc
41 changed files with 274 additions and 121 deletions
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
namespace fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
fetchers::Settings fetchSettings;
|
fetchers::Settings fetchSettings;
|
||||||
|
|
||||||
static GlobalConfig::Register rFetchSettings(&fetchSettings);
|
static GlobalConfig::Register rFetchSettings(&fetchSettings);
|
||||||
|
@ -119,8 +121,8 @@ MixEvalArgs::MixEvalArgs()
|
||||||
.category = category,
|
.category = category,
|
||||||
.labels = {"original-ref", "resolved-ref"},
|
.labels = {"original-ref", "resolved-ref"},
|
||||||
.handler = {[&](std::string _from, std::string _to) {
|
.handler = {[&](std::string _from, std::string _to) {
|
||||||
auto from = parseFlakeRef(fetchSettings, _from, absPath("."));
|
auto from = parseFlakeRef(fetchSettings, _from, fs::current_path().string());
|
||||||
auto to = parseFlakeRef(fetchSettings, _to, absPath("."));
|
auto to = parseFlakeRef(fetchSettings, _to, fs::current_path().string());
|
||||||
fetchers::Attrs extraAttrs;
|
fetchers::Attrs extraAttrs;
|
||||||
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
|
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
|
||||||
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
|
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
namespace fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
void completeFlakeInputPath(
|
void completeFlakeInputPath(
|
||||||
AddCompletions & completions,
|
AddCompletions & completions,
|
||||||
ref<EvalState> evalState,
|
ref<EvalState> evalState,
|
||||||
|
@ -341,7 +343,7 @@ void completeFlakeRefWithFragment(
|
||||||
auto flakeRefS = std::string(prefix.substr(0, hash));
|
auto flakeRefS = std::string(prefix.substr(0, hash));
|
||||||
|
|
||||||
// TODO: ideally this would use the command base directory instead of assuming ".".
|
// TODO: ideally this would use the command base directory instead of assuming ".".
|
||||||
auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), absPath("."));
|
auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), fs::current_path().string());
|
||||||
|
|
||||||
auto evalCache = openEvalCache(*evalState,
|
auto evalCache = openEvalCache(*evalState,
|
||||||
std::make_shared<flake::LockedFlake>(lockFlake(
|
std::make_shared<flake::LockedFlake>(lockFlake(
|
||||||
|
|
|
@ -622,7 +622,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||||
// When missing, trigger the normal exception
|
// When missing, trigger the normal exception
|
||||||
// e.g. :doc builtins.foo
|
// e.g. :doc builtins.foo
|
||||||
// behaves like
|
// behaves like
|
||||||
// nix-repl> builtins.foo
|
// nix-repl> builtins.foo<tab>
|
||||||
// error: attribute 'foo' missing
|
// error: attribute 'foo' missing
|
||||||
evalString(arg, v);
|
evalString(arg, v);
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -720,7 +720,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
|
||||||
if (flakeRefS.empty())
|
if (flakeRefS.empty())
|
||||||
throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");
|
throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");
|
||||||
|
|
||||||
auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, absPath("."), true);
|
auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, std::filesystem::current_path().string(), true);
|
||||||
if (evalSettings.pureEval && !flakeRef.input.isLocked())
|
if (evalSettings.pureEval && !flakeRef.input.isLocked())
|
||||||
throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);
|
throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ string_parts_interpolated
|
||||||
|
|
||||||
path_start
|
path_start
|
||||||
: PATH {
|
: PATH {
|
||||||
Path path(absPath({$1.p, $1.l}, state->basePath.path.abs()));
|
Path path(absPath(std::string_view{$1.p, $1.l}, state->basePath.path.abs()));
|
||||||
/* add back in the trailing '/' to the first segment */
|
/* add back in the trailing '/' to the first segment */
|
||||||
if ($1.p[$1.l-1] == '/' && $1.l > 1)
|
if ($1.p[$1.l-1] == '/' && $1.l > 1)
|
||||||
path += "/";
|
path += "/";
|
||||||
|
|
|
@ -333,7 +333,7 @@ static std::string quoteRegexChars(const std::string & raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
static void readFileRoots(const char * path, UncheckedRoots & roots)
|
static void readFileRoots(const std::filesystem::path & path, UncheckedRoots & roots)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
roots[readFile(path)].emplace(path);
|
roots[readFile(path)].emplace(path);
|
||||||
|
|
|
@ -31,7 +31,7 @@ LocalOverlayStore::LocalOverlayStore(std::string_view scheme, PathView path, con
|
||||||
if (checkMount.get()) {
|
if (checkMount.get()) {
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
std::string mountInfo;
|
std::string mountInfo;
|
||||||
auto mounts = readFile("/proc/self/mounts");
|
auto mounts = readFile(std::filesystem::path{"/proc/self/mounts"});
|
||||||
auto regex = std::regex(R"((^|\n)overlay )" + realStoreDir.get() + R"( .*(\n|$))");
|
auto regex = std::regex(R"((^|\n)overlay )" + realStoreDir.get() + R"( .*(\n|$))");
|
||||||
|
|
||||||
// Mount points can be stacked, so there might be multiple matching entries.
|
// Mount points can be stacked, so there might be multiple matching entries.
|
||||||
|
|
|
@ -113,6 +113,16 @@ protected:
|
||||||
, arity(1)
|
, arity(1)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
Handler(std::filesystem::path * dest)
|
||||||
|
: fun([dest](std::vector<std::string> ss) { *dest = ss[0]; })
|
||||||
|
, arity(1)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Handler(std::optional<std::filesystem::path> * dest)
|
||||||
|
: fun([dest](std::vector<std::string> ss) { *dest = ss[0]; })
|
||||||
|
, arity(1)
|
||||||
|
{ }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Handler(T * dest, const T & val)
|
Handler(T * dest, const T & val)
|
||||||
: fun([dest, val](std::vector<std::string> ss) { *dest = val; })
|
: fun([dest, val](std::vector<std::string> ss) { *dest = val; })
|
||||||
|
@ -283,6 +293,18 @@ public:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect a path argument.
|
||||||
|
*/
|
||||||
|
void expectArg(const std::string & label, std::filesystem::path * dest, bool optional = false)
|
||||||
|
{
|
||||||
|
expectArgs({
|
||||||
|
.label = label,
|
||||||
|
.optional = optional,
|
||||||
|
.handler = {dest}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expect 0 or more arguments.
|
* Expect 0 or more arguments.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "os-string.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +10,6 @@ namespace nix {
|
||||||
*
|
*
|
||||||
* We use our own implementation unconditionally for consistency.
|
* We use our own implementation unconditionally for consistency.
|
||||||
*/
|
*/
|
||||||
int execvpe(const char * file0, char * const argv[], char * const envp[]);
|
int execvpe(const OsChar * file0, const OsChar * const argv[], const OsChar * const envp[]);
|
||||||
|
|
||||||
}
|
}
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr static const OsStringView path_var_separator{
|
constexpr static const OsStringView path_var_separator{
|
||||||
&ExecutablePath::separator,
|
&ExecutablePath::separator,
|
||||||
|
@ -24,7 +26,7 @@ ExecutablePath ExecutablePath::load()
|
||||||
ExecutablePath ExecutablePath::parse(const OsString & path)
|
ExecutablePath ExecutablePath::parse(const OsString & path)
|
||||||
{
|
{
|
||||||
auto strings = path.empty() ? (std::list<OsString>{})
|
auto strings = path.empty() ? (std::list<OsString>{})
|
||||||
: basicSplitString<std::list<OsString>, OsString::value_type>(path, path_var_separator);
|
: basicSplitString<std::list<OsString>, OsChar>(path, path_var_separator);
|
||||||
|
|
||||||
std::vector<fs::path> ret;
|
std::vector<fs::path> ret;
|
||||||
ret.reserve(strings.size());
|
ret.reserve(strings.size());
|
||||||
|
|
|
@ -7,11 +7,15 @@ namespace nix {
|
||||||
|
|
||||||
MakeError(ExecutableLookupError, Error);
|
MakeError(ExecutableLookupError, Error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo rename, it is not just good for execuatable paths, but also
|
||||||
|
* other lists of paths.
|
||||||
|
*/
|
||||||
struct ExecutablePath
|
struct ExecutablePath
|
||||||
{
|
{
|
||||||
std::vector<std::filesystem::path> directories;
|
std::vector<std::filesystem::path> directories;
|
||||||
|
|
||||||
constexpr static const OsString::value_type separator =
|
constexpr static const OsChar separator =
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
L';'
|
L';'
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
|
|
||||||
#include "strings-inline.hh"
|
#include "strings-inline.hh"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
namespace fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Treat the string as possibly an absolute path, by inspecting the
|
* Treat the string as possibly an absolute path, by inspecting the
|
||||||
* start of it. Return whether it was probably intended to be
|
* start of it. Return whether it was probably intended to be
|
||||||
|
@ -73,6 +73,10 @@ Path absPath(PathView path, std::optional<PathView> dir, bool resolveSymlinks)
|
||||||
return canonPath(path, resolveSymlinks);
|
return canonPath(path, resolveSymlinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::filesystem::path absPath(const std::filesystem::path & path, bool resolveSymlinks)
|
||||||
|
{
|
||||||
|
return absPath(path.string(), std::nullopt, resolveSymlinks);
|
||||||
|
}
|
||||||
|
|
||||||
Path canonPath(PathView path, bool resolveSymlinks)
|
Path canonPath(PathView path, bool resolveSymlinks)
|
||||||
{
|
{
|
||||||
|
@ -206,10 +210,10 @@ bool pathExists(const Path & path)
|
||||||
return maybeLstat(path).has_value();
|
return maybeLstat(path).has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pathAccessible(const Path & path)
|
bool pathAccessible(const std::filesystem::path & path)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return pathExists(path);
|
return pathExists(path.string());
|
||||||
} catch (SysError & e) {
|
} catch (SysError & e) {
|
||||||
// swallow EPERM
|
// swallow EPERM
|
||||||
if (e.errNo == EPERM) return false;
|
if (e.errNo == EPERM) return false;
|
||||||
|
@ -238,6 +242,11 @@ std::string readFile(const Path & path)
|
||||||
return readFile(fd.get());
|
return readFile(fd.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string readFile(const std::filesystem::path & path)
|
||||||
|
{
|
||||||
|
return readFile(os_string_to_string(PathViewNG { path }));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void readFile(const Path & path, Sink & sink)
|
void readFile(const Path & path, Sink & sink)
|
||||||
{
|
{
|
||||||
|
@ -324,7 +333,7 @@ void recursiveSync(const Path & path)
|
||||||
/* If it's a file, just fsync and return. */
|
/* If it's a file, just fsync and return. */
|
||||||
auto st = lstat(path);
|
auto st = lstat(path);
|
||||||
if (S_ISREG(st.st_mode)) {
|
if (S_ISREG(st.st_mode)) {
|
||||||
AutoCloseFD fd = open(path.c_str(), O_RDONLY, 0);
|
AutoCloseFD fd = toDescriptor(open(path.c_str(), O_RDONLY, 0));
|
||||||
if (!fd)
|
if (!fd)
|
||||||
throw SysError("opening file '%1%'", path);
|
throw SysError("opening file '%1%'", path);
|
||||||
fd.fsync();
|
fd.fsync();
|
||||||
|
@ -344,7 +353,7 @@ void recursiveSync(const Path & path)
|
||||||
if (fs::is_directory(st)) {
|
if (fs::is_directory(st)) {
|
||||||
dirsToEnumerate.emplace_back(entry.path());
|
dirsToEnumerate.emplace_back(entry.path());
|
||||||
} else if (fs::is_regular_file(st)) {
|
} else if (fs::is_regular_file(st)) {
|
||||||
AutoCloseFD fd = open(entry.path().c_str(), O_RDONLY, 0);
|
AutoCloseFD fd = toDescriptor(open(entry.path().string().c_str(), O_RDONLY, 0));
|
||||||
if (!fd)
|
if (!fd)
|
||||||
throw SysError("opening file '%1%'", entry.path());
|
throw SysError("opening file '%1%'", entry.path());
|
||||||
fd.fsync();
|
fd.fsync();
|
||||||
|
@ -355,7 +364,7 @@ void recursiveSync(const Path & path)
|
||||||
|
|
||||||
/* Fsync all the directories. */
|
/* Fsync all the directories. */
|
||||||
for (auto dir = dirsToFsync.rbegin(); dir != dirsToFsync.rend(); ++dir) {
|
for (auto dir = dirsToFsync.rbegin(); dir != dirsToFsync.rend(); ++dir) {
|
||||||
AutoCloseFD fd = open(dir->c_str(), O_RDONLY, 0);
|
AutoCloseFD fd = toDescriptor(open(dir->string().c_str(), O_RDONLY, 0));
|
||||||
if (!fd)
|
if (!fd)
|
||||||
throw SysError("opening directory '%1%'", *dir);
|
throw SysError("opening directory '%1%'", *dir);
|
||||||
fd.fsync();
|
fd.fsync();
|
||||||
|
@ -595,19 +604,20 @@ void createSymlink(const Path & target, const Path & link)
|
||||||
fs::create_symlink(target, link);
|
fs::create_symlink(target, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceSymlink(const Path & target, const Path & link)
|
void replaceSymlink(const fs::path & target, const fs::path & link)
|
||||||
{
|
{
|
||||||
for (unsigned int n = 0; true; n++) {
|
for (unsigned int n = 0; true; n++) {
|
||||||
Path tmp = canonPath(fmt("%s/.%d_%s", dirOf(link), n, baseNameOf(link)));
|
auto tmp = link.parent_path() / fs::path{fmt(".%d_%s", n, link.filename().string())};
|
||||||
|
tmp = tmp.lexically_normal();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
createSymlink(target, tmp);
|
fs::create_symlink(target, tmp);
|
||||||
} catch (fs::filesystem_error & e) {
|
} catch (fs::filesystem_error & e) {
|
||||||
if (e.code() == std::errc::file_exists) continue;
|
if (e.code() == std::errc::file_exists) continue;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::rename(tmp, link);
|
fs::rename(tmp, link);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,16 +46,33 @@ struct Source;
|
||||||
* @return An absolutized path, resolving paths relative to the
|
* @return An absolutized path, resolving paths relative to the
|
||||||
* specified directory, or the current directory otherwise. The path
|
* specified directory, or the current directory otherwise. The path
|
||||||
* is also canonicalised.
|
* is also canonicalised.
|
||||||
|
*
|
||||||
|
* In the process of being deprecated for `std::filesystem::absolute`.
|
||||||
*/
|
*/
|
||||||
Path absPath(PathView path,
|
Path absPath(PathView path,
|
||||||
std::optional<PathView> dir = {},
|
std::optional<PathView> dir = {},
|
||||||
bool resolveSymlinks = false);
|
bool resolveSymlinks = false);
|
||||||
|
|
||||||
|
inline Path absPath(const Path & path,
|
||||||
|
std::optional<PathView> dir = {},
|
||||||
|
bool resolveSymlinks = false)
|
||||||
|
{
|
||||||
|
return absPath(PathView{path}, dir, resolveSymlinks);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::path absPath(const std::filesystem::path & path,
|
||||||
|
bool resolveSymlinks = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Canonicalise a path by removing all `.` or `..` components and
|
* Canonicalise a path by removing all `.` or `..` components and
|
||||||
* double or trailing slashes. Optionally resolves all symlink
|
* double or trailing slashes. Optionally resolves all symlink
|
||||||
* components such that each component of the resulting path is *not*
|
* components such that each component of the resulting path is *not*
|
||||||
* a symbolic link.
|
* a symbolic link.
|
||||||
|
*
|
||||||
|
* In the process of being deprecated for
|
||||||
|
* `std::filesystem::path::lexically_normal` (for the `resolveSymlinks =
|
||||||
|
* false` case), and `std::filesystem::weakly_canonical` (for the
|
||||||
|
* `resolveSymlinks = true` case).
|
||||||
*/
|
*/
|
||||||
Path canonPath(PathView path, bool resolveSymlinks = false);
|
Path canonPath(PathView path, bool resolveSymlinks = false);
|
||||||
|
|
||||||
|
@ -64,12 +81,18 @@ Path canonPath(PathView path, bool resolveSymlinks = false);
|
||||||
* everything before the final `/`. If the path is the root or an
|
* everything before the final `/`. If the path is the root or an
|
||||||
* immediate child thereof (e.g., `/foo`), this means `/`
|
* immediate child thereof (e.g., `/foo`), this means `/`
|
||||||
* is returned.
|
* is returned.
|
||||||
|
*
|
||||||
|
* In the process of being deprecated for
|
||||||
|
* `std::filesystem::path::parent_path`.
|
||||||
*/
|
*/
|
||||||
Path dirOf(const PathView path);
|
Path dirOf(const PathView path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the base name of the given canonical path, i.e., everything
|
* @return the base name of the given canonical path, i.e., everything
|
||||||
* following the final `/` (trailing slashes are removed).
|
* following the final `/` (trailing slashes are removed).
|
||||||
|
*
|
||||||
|
* In the process of being deprecated for
|
||||||
|
* `std::filesystem::path::filename`.
|
||||||
*/
|
*/
|
||||||
std::string_view baseNameOf(std::string_view path);
|
std::string_view baseNameOf(std::string_view path);
|
||||||
|
|
||||||
|
@ -98,20 +121,42 @@ std::optional<struct stat> maybeLstat(const Path & path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true iff the given path exists.
|
* @return true iff the given path exists.
|
||||||
|
*
|
||||||
|
* In the process of being deprecated for `fs::symlink_exists`.
|
||||||
*/
|
*/
|
||||||
bool pathExists(const Path & path);
|
bool pathExists(const Path & path);
|
||||||
|
|
||||||
|
namespace fs {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ```
|
||||||
|
* symlink_exists(p) = std::filesystem::exists(std::filesystem::symlink_status(p))
|
||||||
|
* ```
|
||||||
|
* Missing convenience analogous to
|
||||||
|
* ```
|
||||||
|
* std::filesystem::exists(p) = std::filesystem::exists(std::filesystem::status(p))
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
inline bool symlink_exists(const std::filesystem::path & path) {
|
||||||
|
return std::filesystem::exists(std::filesystem::symlink_status(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fs
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A version of pathExists that returns false on a permission error.
|
* A version of pathExists that returns false on a permission error.
|
||||||
* Useful for inferring default paths across directories that might not
|
* Useful for inferring default paths across directories that might not
|
||||||
* be readable.
|
* be readable.
|
||||||
* @return true iff the given path can be accessed and exists
|
* @return true iff the given path can be accessed and exists
|
||||||
*/
|
*/
|
||||||
bool pathAccessible(const Path & path);
|
bool pathAccessible(const std::filesystem::path & path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the contents (target) of a symbolic link. The result is not
|
* Read the contents (target) of a symbolic link. The result is not
|
||||||
* in any way canonicalised.
|
* in any way canonicalised.
|
||||||
|
*
|
||||||
|
* In the process of being deprecated for
|
||||||
|
* `std::filesystem::read_symlink`.
|
||||||
*/
|
*/
|
||||||
Path readLink(const Path & path);
|
Path readLink(const Path & path);
|
||||||
|
|
||||||
|
@ -124,14 +169,23 @@ Descriptor openDirectory(const std::filesystem::path & path);
|
||||||
* Read the contents of a file into a string.
|
* Read the contents of a file into a string.
|
||||||
*/
|
*/
|
||||||
std::string readFile(const Path & path);
|
std::string readFile(const Path & path);
|
||||||
|
std::string readFile(const std::filesystem::path & path);
|
||||||
void readFile(const Path & path, Sink & sink);
|
void readFile(const Path & path, Sink & sink);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a string to a file.
|
* Write a string to a file.
|
||||||
*/
|
*/
|
||||||
void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool sync = false);
|
void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool sync = false);
|
||||||
|
static inline void writeFile(const std::filesystem::path & path, std::string_view s, mode_t mode = 0666, bool sync = false)
|
||||||
|
{
|
||||||
|
return writeFile(path.string(), s, mode, sync);
|
||||||
|
}
|
||||||
|
|
||||||
void writeFile(const Path & path, Source & source, mode_t mode = 0666, bool sync = false);
|
void writeFile(const Path & path, Source & source, mode_t mode = 0666, bool sync = false);
|
||||||
|
static inline void writeFile(const std::filesystem::path & path, Source & source, mode_t mode = 0666, bool sync = false)
|
||||||
|
{
|
||||||
|
return writeFile(path.string(), source, mode, sync);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush a path's parent directory to disk.
|
* Flush a path's parent directory to disk.
|
||||||
|
@ -154,6 +208,9 @@ void deletePath(const std::filesystem::path & path, uint64_t & bytesFreed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a directory and all its parents, if necessary.
|
* Create a directory and all its parents, if necessary.
|
||||||
|
*
|
||||||
|
* In the process of being deprecated for
|
||||||
|
* `std::filesystem::create_directories`.
|
||||||
*/
|
*/
|
||||||
void createDirs(const Path & path);
|
void createDirs(const Path & path);
|
||||||
inline void createDirs(PathView path)
|
inline void createDirs(PathView path)
|
||||||
|
@ -192,13 +249,21 @@ void setWriteTime(const std::filesystem::path & path, const struct stat & st);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a symlink.
|
* Create a symlink.
|
||||||
|
*
|
||||||
|
* In the process of being deprecated for
|
||||||
|
* `std::filesystem::create_symlink`.
|
||||||
*/
|
*/
|
||||||
void createSymlink(const Path & target, const Path & link);
|
void createSymlink(const Path & target, const Path & link);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomically create or replace a symlink.
|
* Atomically create or replace a symlink.
|
||||||
*/
|
*/
|
||||||
void replaceSymlink(const Path & target, const Path & link);
|
void replaceSymlink(const std::filesystem::path & target, const std::filesystem::path & link);
|
||||||
|
|
||||||
|
inline void replaceSymlink(const Path & target, const Path & link)
|
||||||
|
{
|
||||||
|
return replaceSymlink(std::filesystem::path{target}, std::filesystem::path{link});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to 'renameFile', but fallback to a copy+remove if `src` and `dst`
|
* Similar to 'renameFile', but fallback to a copy+remove if `src` and `dst`
|
||||||
|
|
|
@ -118,7 +118,7 @@ void saveMountNamespace()
|
||||||
void restoreMountNamespace()
|
void restoreMountNamespace()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
auto savedCwd = absPath(".");
|
auto savedCwd = std::filesystem::current_path();
|
||||||
|
|
||||||
if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1)
|
if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1)
|
||||||
throw SysError("restoring parent mount namespace");
|
throw SysError("restoring parent mount namespace");
|
||||||
|
|
|
@ -129,6 +129,7 @@ sources = files(
|
||||||
'english.cc',
|
'english.cc',
|
||||||
'environment-variables.cc',
|
'environment-variables.cc',
|
||||||
'error.cc',
|
'error.cc',
|
||||||
|
'exec.hh',
|
||||||
'executable-path.cc',
|
'executable-path.cc',
|
||||||
'exit.cc',
|
'exit.cc',
|
||||||
'experimental-features.cc',
|
'experimental-features.cc',
|
||||||
|
|
|
@ -11,21 +11,30 @@ namespace nix {
|
||||||
* Named because it is similar to the Rust type, except it is in the
|
* Named because it is similar to the Rust type, except it is in the
|
||||||
* native encoding not WTF-8.
|
* native encoding not WTF-8.
|
||||||
*
|
*
|
||||||
* Same as `std::filesystem::path::string_type`, but manually defined to
|
* Same as `std::filesystem::path::value_type`, but manually defined to
|
||||||
* avoid including a much more complex header.
|
* avoid including a much more complex header.
|
||||||
*/
|
*/
|
||||||
using OsString = std::basic_string<
|
using OsChar =
|
||||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
wchar_t
|
wchar_t
|
||||||
#else
|
#else
|
||||||
char
|
char
|
||||||
#endif
|
#endif
|
||||||
>;
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Named because it is similar to the Rust type, except it is in the
|
||||||
|
* native encoding not WTF-8.
|
||||||
|
*
|
||||||
|
* Same as `std::filesystem::path::string_type`, but manually defined
|
||||||
|
* for the same reason as `OsChar`.
|
||||||
|
*/
|
||||||
|
using OsString = std::basic_string<OsChar>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `std::string_view` counterpart for `OsString`.
|
* `std::string_view` counterpart for `OsString`.
|
||||||
*/
|
*/
|
||||||
using OsStringView = std::basic_string_view<OsString::value_type>;
|
using OsStringView = std::basic_string_view<OsChar>;
|
||||||
|
|
||||||
std::string os_string_to_string(OsStringView path);
|
std::string os_string_to_string(OsStringView path);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ PosixSourceAccessor::PosixSourceAccessor()
|
||||||
|
|
||||||
SourcePath PosixSourceAccessor::createAtRoot(const std::filesystem::path & path)
|
SourcePath PosixSourceAccessor::createAtRoot(const std::filesystem::path & path)
|
||||||
{
|
{
|
||||||
std::filesystem::path path2 = absPath(path.string());
|
std::filesystem::path path2 = absPath(path);
|
||||||
return {
|
return {
|
||||||
make_ref<PosixSourceAccessor>(path2.root_path()),
|
make_ref<PosixSourceAccessor>(path2.root_path()),
|
||||||
CanonPath { path2.relative_path().string() },
|
CanonPath { path2.relative_path().string() },
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <fileapi.h>
|
# include <fileapi.h>
|
||||||
|
# include <winsock2.h>
|
||||||
# include "windows-error.hh"
|
# include "windows-error.hh"
|
||||||
#else
|
#else
|
||||||
# include <poll.h>
|
# include <poll.h>
|
||||||
|
@ -167,13 +168,14 @@ bool FdSource::hasData()
|
||||||
while (true) {
|
while (true) {
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(fd, &fds);
|
int fd_ = fromDescriptorReadOnly(fd);
|
||||||
|
FD_SET(fd_, &fds);
|
||||||
|
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
auto n = select(fd + 1, &fds, nullptr, nullptr, &timeout);
|
auto n = select(fd_ + 1, &fds, nullptr, nullptr, &timeout);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
throw SysError("polling file descriptor");
|
throw SysError("polling file descriptor");
|
||||||
|
|
|
@ -14,8 +14,8 @@ template std::list<std::string> splitString(std::string_view s, std::string_view
|
||||||
template std::set<std::string> splitString(std::string_view s, std::string_view separators);
|
template std::set<std::string> splitString(std::string_view s, std::string_view separators);
|
||||||
template std::vector<std::string> splitString(std::string_view s, std::string_view separators);
|
template std::vector<std::string> splitString(std::string_view s, std::string_view separators);
|
||||||
|
|
||||||
template std::list<OsString> basicSplitString(
|
template std::list<OsString>
|
||||||
std::basic_string_view<OsString::value_type> s, std::basic_string_view<OsString::value_type> separators);
|
basicSplitString(std::basic_string_view<OsChar> s, std::basic_string_view<OsChar> separators);
|
||||||
|
|
||||||
template std::string concatStringsSep(std::string_view, const std::list<std::string> &);
|
template std::string concatStringsSep(std::string_view, const std::list<std::string> &);
|
||||||
template std::string concatStringsSep(std::string_view, const std::set<std::string> &);
|
template std::string concatStringsSep(std::string_view, const std::set<std::string> &);
|
||||||
|
|
|
@ -13,7 +13,6 @@ sources += files(
|
||||||
include_dirs += include_directories('.')
|
include_dirs += include_directories('.')
|
||||||
|
|
||||||
headers += files(
|
headers += files(
|
||||||
'exec.hh',
|
|
||||||
'monitor-fd.hh',
|
'monitor-fd.hh',
|
||||||
'signals-impl.hh',
|
'signals-impl.hh',
|
||||||
)
|
)
|
||||||
|
|
|
@ -420,10 +420,12 @@ bool statusOk(int status)
|
||||||
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int execvpe(const char * file0, char * const argv[], char * const envp[])
|
int execvpe(const char * file0, const char * const argv[], const char * const envp[])
|
||||||
{
|
{
|
||||||
auto file = ExecutablePath::load().findPath(file0).string();
|
auto file = ExecutablePath::load().findPath(file0);
|
||||||
return execve(file.c_str(), argv, envp);
|
// `const_cast` is safe. See the note in
|
||||||
|
// https://pubs.opengroup.org/onlinepubs/9799919799/functions/exec.html
|
||||||
|
return execve(file.c_str(), const_cast<char *const *>(argv), const_cast<char *const *>(envp));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
namespace fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
std::string getUserName()
|
std::string getUserName()
|
||||||
{
|
{
|
||||||
auto pw = getpwuid(geteuid());
|
auto pw = getpwuid(geteuid());
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "current-process.hh"
|
#include "current-process.hh"
|
||||||
#include "environment-variables.hh"
|
#include "environment-variables.hh"
|
||||||
#include "error.hh"
|
#include "error.hh"
|
||||||
|
#include "executable-path.hh"
|
||||||
#include "file-descriptor.hh"
|
#include "file-descriptor.hh"
|
||||||
#include "file-path.hh"
|
#include "file-path.hh"
|
||||||
#include "signals.hh"
|
#include "signals.hh"
|
||||||
|
@ -377,4 +378,11 @@ bool statusOk(int status)
|
||||||
{
|
{
|
||||||
return status == 0;
|
return status == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int execvpe(const wchar_t * file0, const wchar_t * const argv[], const wchar_t * const envp[])
|
||||||
|
{
|
||||||
|
auto file = ExecutablePath::load().findPath(file0);
|
||||||
|
return _wexecve(file.c_str(), argv, envp);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "local-fs-store.hh"
|
#include "local-fs-store.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
|
|
||||||
|
namespace nix::fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
struct CmdBundle : InstallableValueCommand
|
struct CmdBundle : InstallableValueCommand
|
||||||
|
@ -78,7 +80,7 @@ struct CmdBundle : InstallableValueCommand
|
||||||
|
|
||||||
auto [bundlerFlakeRef, bundlerName, extendedOutputsSpec] =
|
auto [bundlerFlakeRef, bundlerName, extendedOutputsSpec] =
|
||||||
parseFlakeRefWithFragmentAndExtendedOutputsSpec(
|
parseFlakeRefWithFragmentAndExtendedOutputsSpec(
|
||||||
fetchSettings, bundler, absPath("."));
|
fetchSettings, bundler, fs::current_path().string());
|
||||||
const flake::LockFlags lockFlags{ .writeLockFile = false };
|
const flake::LockFlags lockFlags{ .writeLockFile = false };
|
||||||
InstallableFlake bundler{this,
|
InstallableFlake bundler{this,
|
||||||
evalState, std::move(bundlerFlakeRef), bundlerName, std::move(extendedOutputsSpec),
|
evalState, std::move(bundlerFlakeRef), bundlerName, std::move(extendedOutputsSpec),
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "worker-protocol.hh"
|
#include "worker-protocol.hh"
|
||||||
#include "executable-path.hh"
|
#include "executable-path.hh"
|
||||||
|
|
||||||
|
namespace nix::fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -40,8 +42,6 @@ void checkInfo(const std::string & msg) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
struct CmdConfigCheck : StoreCommand
|
struct CmdConfigCheck : StoreCommand
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include "strings.hh"
|
#include "strings.hh"
|
||||||
|
|
||||||
|
namespace nix::fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
struct DevelopSettings : Config
|
struct DevelopSettings : Config
|
||||||
|
@ -341,7 +343,7 @@ struct Common : InstallableCommand, MixProfile
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
const BuildEnvironment & buildEnvironment,
|
const BuildEnvironment & buildEnvironment,
|
||||||
const std::filesystem::path & tmpDir,
|
const std::filesystem::path & tmpDir,
|
||||||
const std::filesystem::path & outputsDir = std::filesystem::path { absPath(".") } / "outputs")
|
const std::filesystem::path & outputsDir = fs::path { fs::current_path() } / "outputs")
|
||||||
{
|
{
|
||||||
// A list of colon-separated environment variables that should be
|
// A list of colon-separated environment variables that should be
|
||||||
// prepended to, rather than overwritten, in order to keep the shell usable.
|
// prepended to, rather than overwritten, in order to keep the shell usable.
|
||||||
|
@ -450,7 +452,7 @@ struct Common : InstallableCommand, MixProfile
|
||||||
auto targetFilePath = tmpDir / OS_STR(".attrs.");
|
auto targetFilePath = tmpDir / OS_STR(".attrs.");
|
||||||
targetFilePath += ext;
|
targetFilePath += ext;
|
||||||
|
|
||||||
writeFile(targetFilePath.string(), content);
|
writeFile(targetFilePath, content);
|
||||||
|
|
||||||
auto fileInBuilderEnv = buildEnvironment.vars.find(envVar);
|
auto fileInBuilderEnv = buildEnvironment.vars.find(envVar);
|
||||||
assert(fileInBuilderEnv != buildEnvironment.vars.end());
|
assert(fileInBuilderEnv != buildEnvironment.vars.end());
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include "strings-inline.hh"
|
#include "strings-inline.hh"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace nix::fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
using namespace nix::flake;
|
using namespace nix::flake;
|
||||||
|
@ -53,7 +53,7 @@ public:
|
||||||
|
|
||||||
FlakeRef getFlakeRef()
|
FlakeRef getFlakeRef()
|
||||||
{
|
{
|
||||||
return parseFlakeRef(fetchSettings, flakeUrl, absPath(".")); //FIXME
|
return parseFlakeRef(fetchSettings, flakeUrl, fs::current_path().string()); //FIXME
|
||||||
}
|
}
|
||||||
|
|
||||||
LockedFlake lockFlake()
|
LockedFlake lockFlake()
|
||||||
|
@ -65,7 +65,7 @@ public:
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
// Like getFlakeRef but with expandTilde calld first
|
// Like getFlakeRef but with expandTilde calld first
|
||||||
parseFlakeRef(fetchSettings, expandTilde(flakeUrl), absPath("."))
|
parseFlakeRef(fetchSettings, expandTilde(flakeUrl), fs::current_path().string())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -880,7 +880,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
|
||||||
auto evalState = getEvalState();
|
auto evalState = getEvalState();
|
||||||
|
|
||||||
auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(
|
auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(
|
||||||
fetchSettings, templateUrl, absPath("."));
|
fetchSettings, templateUrl, fs::current_path().string());
|
||||||
|
|
||||||
auto installable = InstallableFlake(nullptr,
|
auto installable = InstallableFlake(nullptr,
|
||||||
evalState, std::move(templateFlakeRef), templateName, ExtendedOutputsSpec::Default(),
|
evalState, std::move(templateFlakeRef), templateName, ExtendedOutputsSpec::Default(),
|
||||||
|
@ -927,7 +927,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
writeFile(to2.string(), contents);
|
writeFile(to2, contents);
|
||||||
}
|
}
|
||||||
else if (fs::is_symlink(st)) {
|
else if (fs::is_symlink(st)) {
|
||||||
auto target = fs::read_symlink(from2);
|
auto target = fs::read_symlink(from2);
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
namespace nix::fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
std::string chrootHelperName = "__run_in_chroot";
|
std::string chrootHelperName = "__run_in_chroot";
|
||||||
|
@ -170,25 +172,25 @@ void chrootHelper(int argc, char * * argv)
|
||||||
if (!pathExists(storeDir)) {
|
if (!pathExists(storeDir)) {
|
||||||
// FIXME: Use overlayfs?
|
// FIXME: Use overlayfs?
|
||||||
|
|
||||||
std::filesystem::path tmpDir = createTempDir();
|
fs::path tmpDir = createTempDir();
|
||||||
|
|
||||||
createDirs(tmpDir + storeDir);
|
createDirs(tmpDir + storeDir);
|
||||||
|
|
||||||
if (mount(realStoreDir.c_str(), (tmpDir + storeDir).c_str(), "", MS_BIND, 0) == -1)
|
if (mount(realStoreDir.c_str(), (tmpDir + storeDir).c_str(), "", MS_BIND, 0) == -1)
|
||||||
throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);
|
throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);
|
||||||
|
|
||||||
for (auto entry : std::filesystem::directory_iterator{"/"}) {
|
for (auto entry : fs::directory_iterator{"/"}) {
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
auto src = entry.path();
|
auto src = entry.path();
|
||||||
Path dst = tmpDir / entry.path().filename();
|
fs::path dst = tmpDir / entry.path().filename();
|
||||||
if (pathExists(dst)) continue;
|
if (pathExists(dst)) continue;
|
||||||
auto st = entry.symlink_status();
|
auto st = entry.symlink_status();
|
||||||
if (std::filesystem::is_directory(st)) {
|
if (fs::is_directory(st)) {
|
||||||
if (mkdir(dst.c_str(), 0700) == -1)
|
if (mkdir(dst.c_str(), 0700) == -1)
|
||||||
throw SysError("creating directory '%s'", dst);
|
throw SysError("creating directory '%s'", dst);
|
||||||
if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, 0) == -1)
|
if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, 0) == -1)
|
||||||
throw SysError("mounting '%s' on '%s'", src, dst);
|
throw SysError("mounting '%s' on '%s'", src, dst);
|
||||||
} else if (std::filesystem::is_symlink(st))
|
} else if (fs::is_symlink(st))
|
||||||
createSymlink(readLink(src), dst);
|
createSymlink(readLink(src), dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,9 +207,9 @@ void chrootHelper(int argc, char * * argv)
|
||||||
if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1)
|
if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1)
|
||||||
throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);
|
throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);
|
||||||
|
|
||||||
writeFile("/proc/self/setgroups", "deny");
|
writeFile(fs::path{"/proc/self/setgroups"}, "deny");
|
||||||
writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1));
|
writeFile(fs::path{"/proc/self/uid_map"}, fmt("%d %d %d", uid, uid, 1));
|
||||||
writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1));
|
writeFile(fs::path{"/proc/self/gid_map"}, fmt("%d %d %d", gid, gid, 1));
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
if (system != "")
|
if (system != "")
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
}
|
||||||
|
|
||||||
fs::path getNixBin(std::optional<std::string_view> binaryNameOpt)
|
fs::path getNixBin(std::optional<std::string_view> binaryNameOpt)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,11 +10,11 @@ using nlohmann::json;
|
||||||
|
|
||||||
class PublicKeyTest : public CharacterizationTest
|
class PublicKeyTest : public CharacterizationTest
|
||||||
{
|
{
|
||||||
Path unitTestData = getUnitTestData() + "/public-key";
|
std::filesystem::path unitTestData = getUnitTestData() / "public-key";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Path goldenMaster(std::string_view testStem) const override {
|
std::filesystem::path goldenMaster(std::string_view testStem) const override {
|
||||||
return unitTestData + "/" + testStem;
|
return unitTestData / testStem;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
namespace nixC {
|
namespace nixC {
|
||||||
class nix_api_store_test : public nix_api_util_context
|
class nix_api_store_test : public nix_api_util_context
|
||||||
|
|
|
@ -12,10 +12,10 @@ namespace nix {
|
||||||
template<class Proto, const char * protocolDir>
|
template<class Proto, const char * protocolDir>
|
||||||
class ProtoTest : public CharacterizationTest, public LibStoreTest
|
class ProtoTest : public CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
Path unitTestData = getUnitTestData() + "/" + protocolDir;
|
std::filesystem::path unitTestData = getUnitTestData() / protocolDir;
|
||||||
|
|
||||||
Path goldenMaster(std::string_view testStem) const override {
|
std::filesystem::path goldenMaster(std::string_view testStem) const override {
|
||||||
return unitTestData + "/" + testStem + ".bin";
|
return unitTestData / (std::string { testStem + ".bin" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,12 @@ using nlohmann::json;
|
||||||
|
|
||||||
class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest
|
class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
Path unitTestData = getUnitTestData() + "/derivation";
|
std::filesystem::path unitTestData = getUnitTestData() / "derivation";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Path goldenMaster(std::string_view testStem) const override
|
std::filesystem::path goldenMaster(std::string_view testStem) const override
|
||||||
{
|
{
|
||||||
return unitTestData + "/" + testStem;
|
return unitTestData / testStem;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@ using nlohmann::json;
|
||||||
|
|
||||||
class DerivationTest : public CharacterizationTest, public LibStoreTest
|
class DerivationTest : public CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
Path unitTestData = getUnitTestData() + "/derivation";
|
std::filesystem::path unitTestData = getUnitTestData() / "derivation";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Path goldenMaster(std::string_view testStem) const override {
|
std::filesystem::path goldenMaster(std::string_view testStem) const override {
|
||||||
return unitTestData + "/" + testStem;
|
return unitTestData / testStem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,6 +13,8 @@ using testing::Eq;
|
||||||
using testing::Field;
|
using testing::Field;
|
||||||
using testing::SizeIs;
|
using testing::SizeIs;
|
||||||
|
|
||||||
|
namespace nix::fs { using namespace std::filesystem; }
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
TEST(machines, getMachinesWithEmptyBuilders) {
|
TEST(machines, getMachinesWithEmptyBuilders) {
|
||||||
|
@ -135,10 +137,10 @@ TEST(machines, getMachinesWithIncorrectFormat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(machines, getMachinesWithCorrectFileReference) {
|
TEST(machines, getMachinesWithCorrectFileReference) {
|
||||||
auto path = absPath(getUnitTestData() + "/machines/valid");
|
auto path = fs::weakly_canonical(getUnitTestData() / "machines/valid");
|
||||||
ASSERT_TRUE(pathExists(path));
|
ASSERT_TRUE(fs::exists(path));
|
||||||
|
|
||||||
auto actual = Machine::parseConfig({}, "@" + path);
|
auto actual = Machine::parseConfig({}, "@" + path.string());
|
||||||
ASSERT_THAT(actual, SizeIs(3));
|
ASSERT_THAT(actual, SizeIs(3));
|
||||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
|
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
|
||||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
|
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
|
||||||
|
@ -146,20 +148,22 @@ TEST(machines, getMachinesWithCorrectFileReference) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) {
|
TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) {
|
||||||
auto path = "/dev/null";
|
fs::path path = "/dev/null";
|
||||||
ASSERT_TRUE(pathExists(path));
|
ASSERT_TRUE(fs::exists(path));
|
||||||
|
|
||||||
auto actual = Machine::parseConfig({}, std::string{"@"} + path);
|
auto actual = Machine::parseConfig({}, "@" + path.string());
|
||||||
ASSERT_THAT(actual, SizeIs(0));
|
ASSERT_THAT(actual, SizeIs(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(machines, getMachinesWithIncorrectFileReference) {
|
TEST(machines, getMachinesWithIncorrectFileReference) {
|
||||||
auto actual = Machine::parseConfig({}, "@" + absPath("/not/a/file"));
|
auto path = fs::weakly_canonical("/not/a/file");
|
||||||
|
ASSERT_TRUE(!fs::exists(path));
|
||||||
|
auto actual = Machine::parseConfig({}, "@" + path.string());
|
||||||
ASSERT_THAT(actual, SizeIs(0));
|
ASSERT_THAT(actual, SizeIs(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) {
|
TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) {
|
||||||
EXPECT_THROW(
|
EXPECT_THROW(
|
||||||
Machine::parseConfig({}, "@" + absPath(getUnitTestData() + "/machines/bad_format")),
|
Machine::parseConfig({}, "@" + fs::weakly_canonical(getUnitTestData() / "machines" / "bad_format").string()),
|
||||||
FormatError);
|
FormatError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,10 @@ using nlohmann::json;
|
||||||
|
|
||||||
class NarInfoTest : public CharacterizationTest, public LibStoreTest
|
class NarInfoTest : public CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
Path unitTestData = getUnitTestData() + "/nar-info";
|
std::filesystem::path unitTestData = getUnitTestData() / "nar-info";
|
||||||
|
|
||||||
Path goldenMaster(PathView testStem) const override {
|
std::filesystem::path goldenMaster(PathView testStem) const override {
|
||||||
return unitTestData + "/" + testStem + ".json";
|
return unitTestData / (testStem + ".json");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,10 @@ using nlohmann::json;
|
||||||
|
|
||||||
class PathInfoTest : public CharacterizationTest, public LibStoreTest
|
class PathInfoTest : public CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
Path unitTestData = getUnitTestData() + "/path-info";
|
std::filesystem::path unitTestData = getUnitTestData() / "path-info";
|
||||||
|
|
||||||
Path goldenMaster(PathView testStem) const override {
|
std::filesystem::path goldenMaster(PathView testStem) const override {
|
||||||
return unitTestData + "/" + testStem + ".json";
|
return unitTestData / (testStem + ".json");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@ using nlohmann::json;
|
||||||
|
|
||||||
class StoreReferenceTest : public CharacterizationTest, public LibStoreTest
|
class StoreReferenceTest : public CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
Path unitTestData = getUnitTestData() + "/store-reference";
|
std::filesystem::path unitTestData = getUnitTestData() / "store-reference";
|
||||||
|
|
||||||
Path goldenMaster(PathView testStem) const override
|
std::filesystem::path goldenMaster(PathView testStem) const override
|
||||||
{
|
{
|
||||||
return unitTestData + "/" + testStem + ".txt";
|
return unitTestData / (testStem + ".txt");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace nix {
|
||||||
* The path to the unit test data directory. See the contributing guide
|
* The path to the unit test data directory. See the contributing guide
|
||||||
* in the manual for further details.
|
* in the manual for further details.
|
||||||
*/
|
*/
|
||||||
static inline Path getUnitTestData() {
|
static inline std::filesystem::path getUnitTestData() {
|
||||||
return getEnv("_NIX_TEST_UNIT_DATA").value();
|
return getEnv("_NIX_TEST_UNIT_DATA").value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ protected:
|
||||||
* While the "golden master" for this characterization test is
|
* While the "golden master" for this characterization test is
|
||||||
* located. It should not be shared with any other test.
|
* located. It should not be shared with any other test.
|
||||||
*/
|
*/
|
||||||
virtual Path goldenMaster(PathView testStem) const = 0;
|
virtual std::filesystem::path goldenMaster(PathView testStem) const = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -77,7 +77,7 @@ public:
|
||||||
|
|
||||||
if (testAccept())
|
if (testAccept())
|
||||||
{
|
{
|
||||||
createDirs(dirOf(file));
|
std::filesystem::create_directories(file.parent_path());
|
||||||
writeFile2(file, got);
|
writeFile2(file, got);
|
||||||
GTEST_SKIP()
|
GTEST_SKIP()
|
||||||
<< "Updating golden master "
|
<< "Updating golden master "
|
||||||
|
@ -97,10 +97,10 @@ public:
|
||||||
{
|
{
|
||||||
writeTest(
|
writeTest(
|
||||||
testStem, test,
|
testStem, test,
|
||||||
[](const Path & f) -> std::string {
|
[](const std::filesystem::path & f) -> std::string {
|
||||||
return readFile(f);
|
return readFile(f);
|
||||||
},
|
},
|
||||||
[](const Path & f, const std::string & c) {
|
[](const std::filesystem::path & f, const std::string & c) {
|
||||||
return writeFile(f, c);
|
return writeFile(f, c);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define FS_SEP "\\"
|
# define FS_SEP L"\\"
|
||||||
# define FS_ROOT "C:" FS_SEP // Need a mounted one, C drive is likely
|
# define FS_ROOT L"C:" FS_SEP // Need a mounted one, C drive is likely
|
||||||
#else
|
#else
|
||||||
# define FS_SEP "/"
|
# define FS_SEP "/"
|
||||||
# define FS_ROOT FS_SEP
|
# define FS_ROOT FS_SEP
|
||||||
|
@ -23,6 +23,12 @@
|
||||||
# define PATH_MAX 4096
|
# define PATH_MAX 4096
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define GET_CWD _wgetcwd
|
||||||
|
#else
|
||||||
|
# define GET_CWD getcwd
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
/* ----------- tests for file-system.hh -------------------------------------*/
|
/* ----------- tests for file-system.hh -------------------------------------*/
|
||||||
|
@ -33,34 +39,34 @@ namespace nix {
|
||||||
|
|
||||||
TEST(absPath, doesntChangeRoot)
|
TEST(absPath, doesntChangeRoot)
|
||||||
{
|
{
|
||||||
auto p = absPath(FS_ROOT);
|
auto p = absPath(std::filesystem::path{FS_ROOT});
|
||||||
|
|
||||||
ASSERT_EQ(p, FS_ROOT);
|
ASSERT_EQ(p, FS_ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(absPath, turnsEmptyPathIntoCWD)
|
TEST(absPath, turnsEmptyPathIntoCWD)
|
||||||
{
|
{
|
||||||
char cwd[PATH_MAX + 1];
|
OsChar cwd[PATH_MAX + 1];
|
||||||
auto p = absPath("");
|
auto p = absPath(std::filesystem::path{""});
|
||||||
|
|
||||||
ASSERT_EQ(p, getcwd((char *) &cwd, PATH_MAX));
|
ASSERT_EQ(p, GET_CWD((OsChar *) &cwd, PATH_MAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(absPath, usesOptionalBasePathWhenGiven)
|
TEST(absPath, usesOptionalBasePathWhenGiven)
|
||||||
{
|
{
|
||||||
char _cwd[PATH_MAX + 1];
|
OsChar _cwd[PATH_MAX + 1];
|
||||||
char * cwd = getcwd((char *) &_cwd, PATH_MAX);
|
OsChar * cwd = GET_CWD((OsChar *) &_cwd, PATH_MAX);
|
||||||
|
|
||||||
auto p = absPath("", cwd);
|
auto p = absPath(std::filesystem::path{""}.string(), std::filesystem::path{cwd}.string());
|
||||||
|
|
||||||
ASSERT_EQ(p, cwd);
|
ASSERT_EQ(p, std::filesystem::path{cwd}.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(absPath, isIdempotent)
|
TEST(absPath, isIdempotent)
|
||||||
{
|
{
|
||||||
char _cwd[PATH_MAX + 1];
|
OsChar _cwd[PATH_MAX + 1];
|
||||||
char * cwd = getcwd((char *) &_cwd, PATH_MAX);
|
OsChar * cwd = GET_CWD((OsChar *) &_cwd, PATH_MAX);
|
||||||
auto p1 = absPath(cwd);
|
auto p1 = absPath(std::filesystem::path{cwd});
|
||||||
auto p2 = absPath(p1);
|
auto p2 = absPath(p1);
|
||||||
|
|
||||||
ASSERT_EQ(p1, p2);
|
ASSERT_EQ(p1, p2);
|
||||||
|
@ -68,8 +74,8 @@ TEST(absPath, isIdempotent)
|
||||||
|
|
||||||
TEST(absPath, pathIsCanonicalised)
|
TEST(absPath, pathIsCanonicalised)
|
||||||
{
|
{
|
||||||
auto path = FS_ROOT "some/path/with/trailing/dot/.";
|
auto path = FS_ROOT OS_STR("some/path/with/trailing/dot/.");
|
||||||
auto p1 = absPath(path);
|
auto p1 = absPath(std::filesystem::path{path});
|
||||||
auto p2 = absPath(p1);
|
auto p2 = absPath(p1);
|
||||||
|
|
||||||
ASSERT_EQ(p1, FS_ROOT "some" FS_SEP "path" FS_SEP "with" FS_SEP "trailing" FS_SEP "dot");
|
ASSERT_EQ(p1, FS_ROOT "some" FS_SEP "path" FS_SEP "with" FS_SEP "trailing" FS_SEP "dot");
|
||||||
|
@ -82,26 +88,26 @@ TEST(absPath, pathIsCanonicalised)
|
||||||
|
|
||||||
TEST(canonPath, removesTrailingSlashes)
|
TEST(canonPath, removesTrailingSlashes)
|
||||||
{
|
{
|
||||||
auto path = FS_ROOT "this/is/a/path//";
|
std::filesystem::path path = FS_ROOT "this/is/a/path//";
|
||||||
auto p = canonPath(path);
|
auto p = canonPath(path.string());
|
||||||
|
|
||||||
ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path");
|
ASSERT_EQ(p, std::filesystem::path{FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"}.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(canonPath, removesDots)
|
TEST(canonPath, removesDots)
|
||||||
{
|
{
|
||||||
auto path = FS_ROOT "this/./is/a/path/./";
|
std::filesystem::path path = FS_ROOT "this/./is/a/path/./";
|
||||||
auto p = canonPath(path);
|
auto p = canonPath(path.string());
|
||||||
|
|
||||||
ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path");
|
ASSERT_EQ(p, std::filesystem::path{FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"}.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(canonPath, removesDots2)
|
TEST(canonPath, removesDots2)
|
||||||
{
|
{
|
||||||
auto path = FS_ROOT "this/a/../is/a////path/foo/..";
|
std::filesystem::path path = FS_ROOT "this/a/../is/a////path/foo/..";
|
||||||
auto p = canonPath(path);
|
auto p = canonPath(path.string());
|
||||||
|
|
||||||
ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path");
|
ASSERT_EQ(p, std::filesystem::path{FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"}.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(canonPath, requiresAbsolutePath)
|
TEST(canonPath, requiresAbsolutePath)
|
||||||
|
@ -243,7 +249,7 @@ TEST(isDirOrInDir, DISABLED_shouldWork)
|
||||||
|
|
||||||
TEST(pathExists, rootExists)
|
TEST(pathExists, rootExists)
|
||||||
{
|
{
|
||||||
ASSERT_TRUE(pathExists(FS_ROOT));
|
ASSERT_TRUE(pathExists(std::filesystem::path{FS_ROOT}.string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pathExists, cwdExists)
|
TEST(pathExists, cwdExists)
|
||||||
|
|
|
@ -11,12 +11,12 @@ using namespace git;
|
||||||
|
|
||||||
class GitTest : public CharacterizationTest
|
class GitTest : public CharacterizationTest
|
||||||
{
|
{
|
||||||
Path unitTestData = getUnitTestData() + "/git";
|
std::filesystem::path unitTestData = getUnitTestData() / "git";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Path goldenMaster(std::string_view testStem) const override {
|
std::filesystem::path goldenMaster(std::string_view testStem) const override {
|
||||||
return unitTestData + "/" + testStem;
|
return unitTestData / std::string(testStem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,12 +48,14 @@ subdir('build-utils-meson/diagnostics')
|
||||||
sources = files(
|
sources = files(
|
||||||
'args.cc',
|
'args.cc',
|
||||||
'canon-path.cc',
|
'canon-path.cc',
|
||||||
|
'checked-arithmetic.cc',
|
||||||
'chunked-vector.cc',
|
'chunked-vector.cc',
|
||||||
'closure.cc',
|
'closure.cc',
|
||||||
'compression.cc',
|
'compression.cc',
|
||||||
'config.cc',
|
'config.cc',
|
||||||
'executable-path.cc',
|
'executable-path.cc',
|
||||||
'file-content-address.cc',
|
'file-content-address.cc',
|
||||||
|
'file-system.cc',
|
||||||
'git.cc',
|
'git.cc',
|
||||||
'hash.cc',
|
'hash.cc',
|
||||||
'hilite.cc',
|
'hilite.cc',
|
||||||
|
@ -62,6 +64,7 @@ sources = files(
|
||||||
'lru-cache.cc',
|
'lru-cache.cc',
|
||||||
'nix_api_util.cc',
|
'nix_api_util.cc',
|
||||||
'pool.cc',
|
'pool.cc',
|
||||||
|
'position.cc',
|
||||||
'processes.cc',
|
'processes.cc',
|
||||||
'references.cc',
|
'references.cc',
|
||||||
'spawn.cc',
|
'spawn.cc',
|
||||||
|
|
Loading…
Reference in a new issue