Skip to content

Commit

Permalink
Refactor os utilities (#3248)
Browse files Browse the repository at this point in the history
* Refactor make_virtual_package

* Refactor macos_version

* Add new windows_version

* Add __win virtual package version

* Use new util::windows_version

* Add virtual packages version test

* Add Plaform os detection

* Refactor linux_version

* Fix linux_version on mac with unix_name_version
  • Loading branch information
AntoinePrv authored Mar 28, 2024
1 parent 3a31b83 commit 3275347
Show file tree
Hide file tree
Showing 24 changed files with 638 additions and 206 deletions.
7 changes: 7 additions & 0 deletions libmamba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ set(
${LIBMAMBA_SOURCE_DIR}/util/cryptography.cpp
${LIBMAMBA_SOURCE_DIR}/util/encoding.cpp
${LIBMAMBA_SOURCE_DIR}/util/environment.cpp
${LIBMAMBA_SOURCE_DIR}/util/os_linux.cpp
${LIBMAMBA_SOURCE_DIR}/util/os_osx.cpp
${LIBMAMBA_SOURCE_DIR}/util/os_unix.cpp
${LIBMAMBA_SOURCE_DIR}/util/os_win.cpp
${LIBMAMBA_SOURCE_DIR}/util/parsers.cpp
${LIBMAMBA_SOURCE_DIR}/util/path_manip.cpp
Expand Down Expand Up @@ -288,6 +291,10 @@ set(
${LIBMAMBA_INCLUDE_DIR}/mamba/util/iterator.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/json.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/loop_control.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_linux.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_osx.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_unix.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_win.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/parsers.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/path_manip.hpp
Expand Down
3 changes: 0 additions & 3 deletions libmamba/include/mamba/core/util_os.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ namespace mamba

void run_as_admin(const std::string& args);
bool enable_long_paths_support(bool force, Palette palette = Palette::no_color());
std::string windows_version();
std::string macos_version();
std::string linux_version();

void init_console();
void reset_console();
Expand Down
12 changes: 6 additions & 6 deletions libmamba/include/mamba/core/virtual_packages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ namespace mamba
std::string cuda_version();
std::string get_arch();

specs::PackageInfo make_virtual_package(
const std::string& name,
const std::string& subdir,
const std::string& version = "",
const std::string& build_string = ""
);
auto make_virtual_package(
std::string name,
std::string subdir,
std::string version = "",
std::string build_string = ""
) -> specs::PackageInfo;

std::vector<specs::PackageInfo> dist_packages(const Context& context);
}
Expand Down
25 changes: 18 additions & 7 deletions libmamba/include/mamba/specs/platform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,41 @@ namespace mamba::specs

using DynamicPlatform = std::string;

constexpr auto known_platforms_count() -> std::size_t
[[nodiscard]] constexpr auto known_platforms_count() -> std::size_t
{
return static_cast<std::size_t>(KnownPlatform::count_);
}

constexpr auto known_platforms() -> std::array<KnownPlatform, known_platforms_count()>;
[[nodiscard]] constexpr auto known_platforms()
-> std::array<KnownPlatform, known_platforms_count()>;

constexpr auto known_platform_names() -> std::array<std::string_view, known_platforms_count()>;
[[nodiscard]] constexpr auto known_platform_names()
-> std::array<std::string_view, known_platforms_count()>;

/**
* Convert the enumeration to its conda string.
*/
constexpr auto platform_name(KnownPlatform p) -> std::string_view;
[[nodiscard]] constexpr auto platform_name(KnownPlatform p) -> std::string_view;

/**
* Return the enum matching the platform name.
*/
auto platform_parse(std::string_view str) -> std::optional<KnownPlatform>;
[[nodiscard]] auto platform_parse(std::string_view str) -> std::optional<KnownPlatform>;

[[nodiscard]] auto platform_is_linux(KnownPlatform plat) -> bool;
[[nodiscard]] auto platform_is_linux(DynamicPlatform plat) -> bool;

[[nodiscard]] auto platform_is_osx(KnownPlatform plat) -> bool;
[[nodiscard]] auto platform_is_osx(DynamicPlatform plat) -> bool;

[[nodiscard]] auto platform_is_win(KnownPlatform plat) -> bool;
[[nodiscard]] auto platform_is_win(DynamicPlatform plat) -> bool;

/**
* Detect the platform on which mamba was built.
*/
auto build_platform() -> KnownPlatform;
auto build_platform_name() -> std::string_view;
[[nodiscard]] auto build_platform() -> KnownPlatform;
[[nodiscard]] auto build_platform_name() -> std::string_view;

/**
* Serialize to JSON string.
Expand Down
19 changes: 19 additions & 0 deletions libmamba/include/mamba/util/os.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 2024, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifndef MAMBA_UTIL_OS_HPP
#define MAMBA_UTIL_OS_HPP

#include <string>

namespace mamba::util
{
struct OSError
{
std::string message = {};
};
}
#endif
20 changes: 20 additions & 0 deletions libmamba/include/mamba/util/os_linux.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) 2024, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifndef MAMBA_UTIL_OS_LINUX_HPP
#define MAMBA_UTIL_OS_LINUX_HPP

#include <string>

#include <tl/expected.hpp>

#include "mamba/util/os.hpp"

namespace mamba::util
{
[[nodiscard]] auto linux_version() -> tl::expected<std::string, OSError>;
}
#endif
20 changes: 20 additions & 0 deletions libmamba/include/mamba/util/os_osx.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) 2024, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifndef MAMBA_UTIL_OS_OSX_HPP
#define MAMBA_UTIL_OS_OSX_HPP

#include <string>

#include <tl/expected.hpp>

#include "mamba/util/os.hpp"

namespace mamba::util
{
[[nodiscard]] auto osx_version() -> tl::expected<std::string, OSError>;
}
#endif
22 changes: 22 additions & 0 deletions libmamba/include/mamba/util/os_unix.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2024, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifndef MAMBA_UTIL_OS_UNIX_HPP
#define MAMBA_UTIL_OS_UNIX_HPP

#include <string>
#include <utility>

#include <tl/expected.hpp>

#include "mamba/util/os.hpp"

namespace mamba::util
{
[[nodiscard]] auto unix_name_version()
-> tl::expected<std::pair<std::string, std::string>, OSError>;
}
#endif
6 changes: 6 additions & 0 deletions libmamba/include/mamba/util/os_win.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include <string>
#include <string_view>

#include <tl/expected.hpp>

#include "mamba/util/os.hpp"

namespace mamba::util
{
enum class WindowsKnowUserFolder
Expand All @@ -27,5 +31,7 @@ namespace mamba::util
[[nodiscard]] auto utf8_to_windows_encoding(const std::string_view utf8_text) -> std::wstring;

[[nodiscard]] auto windows_encoding_to_utf8(std::wstring_view) -> std::string;

[[nodiscard]] auto windows_version() -> tl::expected<std::string, OSError>;
}
#endif
158 changes: 17 additions & 141 deletions libmamba/src/core/util_os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "mamba/core/util_os.hpp"
#include "mamba/util/build.hpp"
#include "mamba/util/environment.hpp"
#include "mamba/util/os_win.hpp"
#include "mamba/util/string.hpp"

#ifdef _WIN32
Expand Down Expand Up @@ -138,8 +139,15 @@ namespace mamba
bool enable_long_paths_support(bool force, Palette palette)
{
// Needs to be set system-wide & can only be run as admin ...
std::string win_ver = windows_version();
auto splitted = util::split(win_ver, ".");

auto win_ver = util::windows_version();
if (!win_ver.has_value())
{
LOG_WARNING << "Not setting long path registry key; Windows version must be at least 10 "
"with the fall 2016 \"Anniversary update\" or newer.";
return false;
}
auto splitted = util::split(win_ver.value(), ".");
if (!(splitted.size() >= 3 && std::stoull(splitted[0]) >= 10
&& std::stoull(splitted[2]) >= 14352))
{
Expand Down Expand Up @@ -209,141 +217,7 @@ namespace mamba
LOG_WARNING << "Changing registry value did not succeed.";
return false;
}
#endif

std::string windows_version()
{
LOG_DEBUG << "Loading Windows virtual package";
auto override_version = util::get_env("CONDA_OVERRIDE_WIN");
if (override_version)
{
return override_version.value();
}

if (!util::on_win)
{
return "";
}

std::string out, err;
std::vector<std::string> args = { util::get_env("COMSPEC").value_or(""), "/c", "ver" };
auto [status, ec] = reproc::run(
args,
reproc::options{},
reproc::sink::string(out),
reproc::sink::string(err)
);

if (ec)
{
LOG_WARNING << "Could not find Windows version by calling 'ver'\n"
<< "Please file a bug report.\nError: " << ec.message();
return "";
}
std::string xout(util::strip(out));

// from python
std::regex ver_output_regex("(?:([\\w ]+) ([\\w.]+) .*\\[.* ([\\d.]+)\\])");

std::smatch rmatch;

std::string full_version, norm_version;
if (std::regex_match(xout, rmatch, ver_output_regex))
{
full_version = rmatch[3];
auto version_els = util::split(full_version, ".");
norm_version = util::concat(version_els[0], ".", version_els[1], ".", version_els[2]);
LOG_DEBUG << "Windows version found: " << norm_version;
}
else
{
LOG_DEBUG << "Windows version not found";
norm_version = "0.0.0";
}
return norm_version;
}

std::string macos_version()
{
LOG_DEBUG << "Loading macos virtual package";
auto override_version = util::get_env("CONDA_OVERRIDE_OSX");
if (override_version)
{
return override_version.value();
}

if (!util::on_mac)
{
return "";
}

std::string out, err;
// Note: we could also inspect /System/Library/CoreServices/SystemVersion.plist which is
// an XML file
// that contains the same information. However, then we'd either need an xml
// parser or some other crude method to read the data
std::vector<std::string> args = { "sw_vers", "-productVersion" };
auto [status, ec] = reproc::run(
args,
reproc::options{},
reproc::sink::string(out),
reproc::sink::string(err)
);

if (ec)
{
LOG_WARNING << "Could not find macOS version by calling 'sw_vers -productVersion'\nPlease file a bug report.\nError: "
<< ec.message();
return "";
}

auto version = std::string(util::strip(out));
LOG_DEBUG << "macos version found: " << version;
return version;
}

std::string linux_version()
{
LOG_DEBUG << "Loading linux virtual package";
auto override_version = util::get_env("CONDA_OVERRIDE_LINUX");
if (override_version)
{
return override_version.value();
}
if (!util::on_linux)
{
return "";
}

#ifndef _WIN32
struct utsname uname_result = {};
const auto ret = ::uname(&uname_result);
if (ret != 0)
{
LOG_DEBUG << "Error calling uname (skipping): "
<< std::system_error(errno, std::generic_category()).what();
}

static const std::regex re("([0-9]+\\.[0-9]+\\.[0-9]+)(?:-.*)?");
std::smatch m;
std::string const version = uname_result.release;
if (std::regex_search(version, m, re))
{
if (m.size() == 2)
{
std::ssub_match linux_version = m[1];
LOG_DEBUG << "linux version found: " << linux_version;
return linux_version.str();
}
}

LOG_DEBUG << "Could not parse linux version";
#endif

return "";
}

#ifdef _WIN32
DWORD getppid()
{
HANDLE hSnapshot;
Expand Down Expand Up @@ -538,12 +412,14 @@ namespace mamba
&& console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING;
features.true_colors = false;

std::string win_ver = windows_version();
auto splitted = util::split(win_ver, ".");
if (splitted.size() >= 3 && std::stoull(splitted[0]) >= 10
&& std::stoull(splitted[2]) >= 15063)
if (auto version = util::windows_version())
{
features.true_colors = true;
auto splitted = util::split(version.value(), '.');
if (splitted.size() >= 3 && std::stoull(splitted[0]) >= 10
&& std::stoull(splitted[2]) >= 15063)
{
features.true_colors = true;
}
}
#endif
return features;
Expand Down
Loading

0 comments on commit 3275347

Please sign in to comment.