2024-08-05 19:05:29 +03:00
|
|
|
#pragma once
|
|
|
|
///@file
|
|
|
|
|
|
|
|
#include "file-system.hh"
|
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2024-07-25 06:14:36 +03:00
|
|
|
MakeError(ExecutableLookupError, Error);
|
|
|
|
|
2024-08-26 19:24:37 +03:00
|
|
|
/**
|
|
|
|
* @todo rename, it is not just good for execuatable paths, but also
|
|
|
|
* other lists of paths.
|
|
|
|
*/
|
2024-08-05 19:05:29 +03:00
|
|
|
struct ExecutablePath
|
|
|
|
{
|
|
|
|
std::vector<std::filesystem::path> directories;
|
|
|
|
|
2024-08-26 19:24:37 +03:00
|
|
|
constexpr static const OsChar separator =
|
2024-08-05 19:05:29 +03:00
|
|
|
#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
|
|
|
|
*/
|
2024-07-25 06:14:36 +03:00
|
|
|
std::optional<std::filesystem::path> findName(
|
2024-08-05 19:05:29 +03:00
|
|
|
const OsString & exe,
|
|
|
|
std::function<bool(const std::filesystem::path &)> isExecutableFile = isExecutableFileAmbient) const;
|
|
|
|
|
2024-07-25 06:14:36 +03:00
|
|
|
/**
|
|
|
|
* Like the `findName` but also allows a file path as input.
|
|
|
|
*
|
|
|
|
* This implements the full POSIX spec: if the path is just a name,
|
|
|
|
* it searches like the above. Otherwise, it returns the path as is.
|
|
|
|
* If (in the name case) the search fails, an exception is thrown.
|
|
|
|
*/
|
|
|
|
std::filesystem::path findPath(
|
|
|
|
const std::filesystem::path & exe,
|
|
|
|
std::function<bool(const std::filesystem::path &)> isExecutable = isExecutableFileAmbient) const;
|
|
|
|
|
2024-08-05 19:05:29 +03:00
|
|
|
bool operator==(const ExecutablePath &) const = default;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace nix
|