mirror of
https://github.com/NixOS/nix
synced 2025-06-25 14:51:16 +02:00
Factor out lookupExecutable
and other PATH improvments
This ended up motivating a good deal of other infra improvements in order to get Windows right: - `OsString` to complement `std::filesystem::path` - env var code for working with the underlying `OsString`s - Rename `PATHNG_LITERAL` to `OS_STR` - `NativePathTrait` renamed to `OsPathTrait`, given a character template parameter until #9205 is complete. Split `tests.cc` matching split of `util.{cc,hh}` last year. Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
This commit is contained in:
parent
0836888002
commit
6c861b9c51
32 changed files with 616 additions and 97 deletions
79
src/libutil/executable-path.cc
Normal file
79
src/libutil/executable-path.cc
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "environment-variables.hh"
|
||||
#include "executable-path.hh"
|
||||
#include "strings-inline.hh"
|
||||
#include "util.hh"
|
||||
#include "file-path-impl.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
constexpr static const OsStringView path_var_separator{
|
||||
&ExecutablePath::separator,
|
||||
1,
|
||||
};
|
||||
|
||||
ExecutablePath ExecutablePath::load()
|
||||
{
|
||||
// "If PATH is unset or is set to null, the path search is
|
||||
// implementation-defined."
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
|
||||
return ExecutablePath::parse(getEnvOs(OS_STR("PATH")).value_or(OS_STR("")));
|
||||
}
|
||||
|
||||
ExecutablePath ExecutablePath::parse(const OsString & path)
|
||||
{
|
||||
auto strings = path.empty() ? (std::list<OsString>{})
|
||||
: basicSplitString<std::list<OsString>, OsString::value_type>(path, path_var_separator);
|
||||
|
||||
std::vector<fs::path> ret;
|
||||
ret.reserve(strings.size());
|
||||
|
||||
std::transform(
|
||||
std::make_move_iterator(strings.begin()),
|
||||
std::make_move_iterator(strings.end()),
|
||||
std::back_inserter(ret),
|
||||
[](auto && str) {
|
||||
return fs::path{
|
||||
str.empty()
|
||||
// "A zero-length prefix is a legacy feature that
|
||||
// indicates the current working directory. It
|
||||
// appears as two adjacent <colon> characters
|
||||
// ("::"), as an initial <colon> preceding the rest
|
||||
// of the list, or as a trailing <colon> following
|
||||
// the rest of the list."
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
|
||||
? OS_STR(".")
|
||||
: std::move(str),
|
||||
};
|
||||
});
|
||||
|
||||
return {ret};
|
||||
}
|
||||
|
||||
OsString ExecutablePath::render() const
|
||||
{
|
||||
std::vector<PathViewNG> path2;
|
||||
for (auto & p : directories)
|
||||
path2.push_back(p.native());
|
||||
return basicConcatStringsSep(path_var_separator, path2);
|
||||
}
|
||||
|
||||
std::optional<fs::path>
|
||||
ExecutablePath::find(const OsString & exe, std::function<bool(const fs::path &)> isExecutable) const
|
||||
{
|
||||
// "If the pathname being sought contains a <slash>, the search
|
||||
// through the path prefixes shall not be performed."
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
|
||||
assert(OsPathTrait<fs::path::value_type>::rfindPathSep(exe) == exe.npos);
|
||||
|
||||
for (auto & dir : directories) {
|
||||
auto candidate = dir / exe;
|
||||
if (isExecutable(candidate))
|
||||
return std::filesystem::canonical(candidate);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace nix
|
Loading…
Add table
Add a link
Reference in a new issue