Skip to content

Commit

Permalink
Clenup env::which
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoinePrv committed Nov 20, 2023
1 parent 7c5f056 commit fa110f0
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 30 deletions.
54 changes: 50 additions & 4 deletions libmamba/include/mamba/core/environment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,60 @@
#ifndef MAMBA_CORE_ENVIRONMENT_HPP
#define MAMBA_CORE_ENVIRONMENT_HPP

#include <string>
#include <vector>
#include <string_view>

#include "mamba/fs/filesystem.hpp"
#include "mamba/util/build.hpp"

namespace mamba::env
{
auto which(const std::string& exe, const std::string& override_path = "") -> fs::u8path;
auto which(const std::string& exe, const std::vector<fs::u8path>& search_paths) -> fs::u8path;
[[nodiscard]] auto which(std::string_view exe, std::string_view override_path = "") -> fs::u8path;

template <typename Iter>
[[nodiscard]] auto which_in(std::string_view exe, Iter search_path_first, Iter search_path_last)
-> fs::u8path;

template <typename Range>
[[nodiscard]] auto which_in(std::string_view exe, const Range& search_paths) -> fs::u8path;

/********************
* Implementaiton *
********************/

namespace detail
{
[[nodiscard]] auto
which_in_impl(const fs::u8path& exe, const fs::u8path& dir, const fs::u8path& extension)
-> fs::u8path;
}


template <typename Iter>
auto which_in(std::string_view exe, Iter search_path_first, Iter search_path_last) -> fs::u8path
{
const auto extension = []() -> fs::u8path
{
if (util::on_win)
{
return ".exe";
}
return "";
}();

for (; search_path_first != search_path_last; ++search_path_first)
{
if (auto p = detail::which_in_impl(exe, *search_path_first, extension); !p.empty())
{
return p;
}
}
return "";
}

template <typename Range>
auto which_in(std::string_view exe, const Range& search_paths) -> fs::u8path
{
return which_in(exe, search_paths.cbegin(), search_paths.cend());
}
}
#endif
2 changes: 1 addition & 1 deletion libmamba/src/api/install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace mamba
)
{
const auto get_python_path = [&]
{ return env::which("python", get_path_dirs(target_prefix)).string(); };
{ return env::which_in("python", get_path_dirs(target_prefix)).string(); };

const std::unordered_map<std::string, command_args> other_pkg_mgr_install_instructions{
{ "pip",
Expand Down
44 changes: 19 additions & 25 deletions libmamba/src/core/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// The full license is in the file LICENSE, distributed with this software.

#include <cstdlib>
#include <optional>

#ifdef _WIN32
#include <mutex>
Expand Down Expand Up @@ -33,26 +34,27 @@ extern "C"

namespace mamba::env
{
fs::u8path which(const std::string& exe, const std::string& override_path)
auto which(std::string_view exe, std::string_view override_path) -> fs::u8path
{
// TODO maybe add a cache?
auto env_path = override_path == "" ? util::get_env("PATH") : override_path;
if (env_path)
auto env_path = std::string(
override_path == "" ? util::get_env("PATH").value_or("") : override_path
);
if (!env_path.empty())
{
std::string path = env_path.value();
const auto parts = util::split(path, util::pathsep());
const auto parts = util::split(env_path, util::pathsep());
const std::vector<fs::u8path> search_paths(parts.begin(), parts.end());
return which(exe, search_paths);
return which_in(exe, search_paths);
}


#ifndef _WIN32
if (override_path == "")
{
char* pathbuf;
size_t n = confstr(_CS_PATH, NULL, static_cast<size_t>(0));
size_t n = confstr(_CS_PATH, nullptr, static_cast<size_t>(0));
pathbuf = static_cast<char*>(malloc(n));
if (pathbuf != NULL)
if (pathbuf != nullptr)
{
confstr(_CS_PATH, pathbuf, n);
return which(exe, pathbuf);
Expand All @@ -63,34 +65,26 @@ namespace mamba::env
return ""; // empty path
}

fs::u8path which(const std::string& exe, const std::vector<fs::u8path>& search_paths)
namespace detail
{
for (auto& p : search_paths)
auto which_in_impl(const fs::u8path& exe, const fs::u8path& dir, const fs::u8path& extension)
-> fs::u8path
{
std::error_code _ec; // ignore
if (!fs::exists(p, _ec) || !fs::is_directory(p, _ec))
if (!fs::exists(dir, _ec) || !fs::is_directory(dir, _ec))
{
continue;
return ""; // Not found
}

#ifdef _WIN32
const auto exe_with_extension = exe + ".exe";
#endif
for (const auto& entry : fs::directory_iterator(p, _ec))
for (const auto& entry : fs::directory_iterator(dir, _ec))
{
const auto filename = entry.path().filename();
if (filename == exe

#ifdef _WIN32
|| filename == exe_with_extension
#endif
)
auto p = entry.path();
if ((p.stem() == exe.stem()) && (p.extension().empty() || p.extension() == extension))
{
return entry.path();
}
}
return ""; // Not found
}

return ""; // empty path
}
}

0 comments on commit fa110f0

Please sign in to comment.