forked from LnL7/nix
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 NixOS#9205 is complete. Split `tests.cc` matching split of `util.{cc,hh}` last year. Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
- Loading branch information
1 parent
0836888
commit 6c861b9
Showing
32 changed files
with
616 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#pragma once | ||
///@file | ||
|
||
#include "file-system.hh" | ||
|
||
namespace nix { | ||
|
||
struct ExecutablePath | ||
{ | ||
std::vector<std::filesystem::path> directories; | ||
|
||
constexpr static const OsString::value_type separator = | ||
#ifdef WIN32 | ||
L';' | ||
#else | ||
':' | ||
#endif | ||
; | ||
|
||
/** | ||
* Parse `path` into a list of paths. | ||
* | ||
* On Unix we split on `:`, on Windows we split on `;`. | ||
* | ||
* For Unix, this is according to the POSIX spec for `PATH`. | ||
* https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 | ||
*/ | ||
static ExecutablePath parse(const OsString & path); | ||
|
||
/** | ||
* Load the `PATH` environment variable and `parse` it. | ||
*/ | ||
static ExecutablePath load(); | ||
|
||
/** | ||
* Opposite of `parse` | ||
*/ | ||
OsString render() const; | ||
|
||
/** | ||
* Search for an executable. | ||
* | ||
* For Unix, this is according to the POSIX spec for `PATH`. | ||
* https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 | ||
* | ||
* @param exe This must just be a name, and not contain any `/` (or | ||
* `\` on Windows). in case it does, per the spec no lookup should | ||
* be perfomed, and the path (it is not just a file name) as is. | ||
* This is the caller's respsonsibility. | ||
* | ||
* This is a pure function, except for the default `isExecutable` | ||
* argument, which uses the ambient file system to check if a file is | ||
* executable (and exists). | ||
* | ||
* @return path to a resolved executable | ||
*/ | ||
std::optional<std::filesystem::path> find( | ||
const OsString & exe, | ||
std::function<bool(const std::filesystem::path &)> isExecutableFile = isExecutableFileAmbient) const; | ||
|
||
bool operator==(const ExecutablePath &) const = default; | ||
}; | ||
|
||
} // namespace nix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.