Skip to content

Commit 3275347

Browse files
authored
Refactor os utilities (#3248)
* 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
1 parent 3a31b83 commit 3275347

24 files changed

+638
-206
lines changed

libmamba/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ set(
154154
${LIBMAMBA_SOURCE_DIR}/util/cryptography.cpp
155155
${LIBMAMBA_SOURCE_DIR}/util/encoding.cpp
156156
${LIBMAMBA_SOURCE_DIR}/util/environment.cpp
157+
${LIBMAMBA_SOURCE_DIR}/util/os_linux.cpp
158+
${LIBMAMBA_SOURCE_DIR}/util/os_osx.cpp
159+
${LIBMAMBA_SOURCE_DIR}/util/os_unix.cpp
157160
${LIBMAMBA_SOURCE_DIR}/util/os_win.cpp
158161
${LIBMAMBA_SOURCE_DIR}/util/parsers.cpp
159162
${LIBMAMBA_SOURCE_DIR}/util/path_manip.cpp
@@ -288,6 +291,10 @@ set(
288291
${LIBMAMBA_INCLUDE_DIR}/mamba/util/iterator.hpp
289292
${LIBMAMBA_INCLUDE_DIR}/mamba/util/json.hpp
290293
${LIBMAMBA_INCLUDE_DIR}/mamba/util/loop_control.hpp
294+
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os.hpp
295+
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_linux.hpp
296+
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_osx.hpp
297+
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_unix.hpp
291298
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_win.hpp
292299
${LIBMAMBA_INCLUDE_DIR}/mamba/util/parsers.hpp
293300
${LIBMAMBA_INCLUDE_DIR}/mamba/util/path_manip.hpp

libmamba/include/mamba/core/util_os.hpp

-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ namespace mamba
3838

3939
void run_as_admin(const std::string& args);
4040
bool enable_long_paths_support(bool force, Palette palette = Palette::no_color());
41-
std::string windows_version();
42-
std::string macos_version();
43-
std::string linux_version();
4441

4542
void init_console();
4643
void reset_console();

libmamba/include/mamba/core/virtual_packages.hpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ namespace mamba
2323
std::string cuda_version();
2424
std::string get_arch();
2525

26-
specs::PackageInfo make_virtual_package(
27-
const std::string& name,
28-
const std::string& subdir,
29-
const std::string& version = "",
30-
const std::string& build_string = ""
31-
);
26+
auto make_virtual_package(
27+
std::string name,
28+
std::string subdir,
29+
std::string version = "",
30+
std::string build_string = ""
31+
) -> specs::PackageInfo;
3232

3333
std::vector<specs::PackageInfo> dist_packages(const Context& context);
3434
}

libmamba/include/mamba/specs/platform.hpp

+18-7
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,41 @@ namespace mamba::specs
4848

4949
using DynamicPlatform = std::string;
5050

51-
constexpr auto known_platforms_count() -> std::size_t
51+
[[nodiscard]] constexpr auto known_platforms_count() -> std::size_t
5252
{
5353
return static_cast<std::size_t>(KnownPlatform::count_);
5454
}
5555

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

58-
constexpr auto known_platform_names() -> std::array<std::string_view, known_platforms_count()>;
59+
[[nodiscard]] constexpr auto known_platform_names()
60+
-> std::array<std::string_view, known_platforms_count()>;
5961

6062
/**
6163
* Convert the enumeration to its conda string.
6264
*/
63-
constexpr auto platform_name(KnownPlatform p) -> std::string_view;
65+
[[nodiscard]] constexpr auto platform_name(KnownPlatform p) -> std::string_view;
6466

6567
/**
6668
* Return the enum matching the platform name.
6769
*/
68-
auto platform_parse(std::string_view str) -> std::optional<KnownPlatform>;
70+
[[nodiscard]] auto platform_parse(std::string_view str) -> std::optional<KnownPlatform>;
71+
72+
[[nodiscard]] auto platform_is_linux(KnownPlatform plat) -> bool;
73+
[[nodiscard]] auto platform_is_linux(DynamicPlatform plat) -> bool;
74+
75+
[[nodiscard]] auto platform_is_osx(KnownPlatform plat) -> bool;
76+
[[nodiscard]] auto platform_is_osx(DynamicPlatform plat) -> bool;
77+
78+
[[nodiscard]] auto platform_is_win(KnownPlatform plat) -> bool;
79+
[[nodiscard]] auto platform_is_win(DynamicPlatform plat) -> bool;
6980

7081
/**
7182
* Detect the platform on which mamba was built.
7283
*/
73-
auto build_platform() -> KnownPlatform;
74-
auto build_platform_name() -> std::string_view;
84+
[[nodiscard]] auto build_platform() -> KnownPlatform;
85+
[[nodiscard]] auto build_platform_name() -> std::string_view;
7586

7687
/**
7788
* Serialize to JSON string.

libmamba/include/mamba/util/os.hpp

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) 2024, QuantStack and Mamba Contributors
2+
//
3+
// Distributed under the terms of the BSD 3-Clause License.
4+
//
5+
// The full license is in the file LICENSE, distributed with this software.
6+
7+
#ifndef MAMBA_UTIL_OS_HPP
8+
#define MAMBA_UTIL_OS_HPP
9+
10+
#include <string>
11+
12+
namespace mamba::util
13+
{
14+
struct OSError
15+
{
16+
std::string message = {};
17+
};
18+
}
19+
#endif
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) 2024, QuantStack and Mamba Contributors
2+
//
3+
// Distributed under the terms of the BSD 3-Clause License.
4+
//
5+
// The full license is in the file LICENSE, distributed with this software.
6+
7+
#ifndef MAMBA_UTIL_OS_LINUX_HPP
8+
#define MAMBA_UTIL_OS_LINUX_HPP
9+
10+
#include <string>
11+
12+
#include <tl/expected.hpp>
13+
14+
#include "mamba/util/os.hpp"
15+
16+
namespace mamba::util
17+
{
18+
[[nodiscard]] auto linux_version() -> tl::expected<std::string, OSError>;
19+
}
20+
#endif
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) 2024, QuantStack and Mamba Contributors
2+
//
3+
// Distributed under the terms of the BSD 3-Clause License.
4+
//
5+
// The full license is in the file LICENSE, distributed with this software.
6+
7+
#ifndef MAMBA_UTIL_OS_OSX_HPP
8+
#define MAMBA_UTIL_OS_OSX_HPP
9+
10+
#include <string>
11+
12+
#include <tl/expected.hpp>
13+
14+
#include "mamba/util/os.hpp"
15+
16+
namespace mamba::util
17+
{
18+
[[nodiscard]] auto osx_version() -> tl::expected<std::string, OSError>;
19+
}
20+
#endif
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) 2024, QuantStack and Mamba Contributors
2+
//
3+
// Distributed under the terms of the BSD 3-Clause License.
4+
//
5+
// The full license is in the file LICENSE, distributed with this software.
6+
7+
#ifndef MAMBA_UTIL_OS_UNIX_HPP
8+
#define MAMBA_UTIL_OS_UNIX_HPP
9+
10+
#include <string>
11+
#include <utility>
12+
13+
#include <tl/expected.hpp>
14+
15+
#include "mamba/util/os.hpp"
16+
17+
namespace mamba::util
18+
{
19+
[[nodiscard]] auto unix_name_version()
20+
-> tl::expected<std::pair<std::string, std::string>, OSError>;
21+
}
22+
#endif

libmamba/include/mamba/util/os_win.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include <string>
1111
#include <string_view>
1212

13+
#include <tl/expected.hpp>
14+
15+
#include "mamba/util/os.hpp"
16+
1317
namespace mamba::util
1418
{
1519
enum class WindowsKnowUserFolder
@@ -27,5 +31,7 @@ namespace mamba::util
2731
[[nodiscard]] auto utf8_to_windows_encoding(const std::string_view utf8_text) -> std::wstring;
2832

2933
[[nodiscard]] auto windows_encoding_to_utf8(std::wstring_view) -> std::string;
34+
35+
[[nodiscard]] auto windows_version() -> tl::expected<std::string, OSError>;
3036
}
3137
#endif

libmamba/src/core/util_os.cpp

+17-141
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "mamba/core/util_os.hpp"
3737
#include "mamba/util/build.hpp"
3838
#include "mamba/util/environment.hpp"
39+
#include "mamba/util/os_win.hpp"
3940
#include "mamba/util/string.hpp"
4041

4142
#ifdef _WIN32
@@ -138,8 +139,15 @@ namespace mamba
138139
bool enable_long_paths_support(bool force, Palette palette)
139140
{
140141
// Needs to be set system-wide & can only be run as admin ...
141-
std::string win_ver = windows_version();
142-
auto splitted = util::split(win_ver, ".");
142+
143+
auto win_ver = util::windows_version();
144+
if (!win_ver.has_value())
145+
{
146+
LOG_WARNING << "Not setting long path registry key; Windows version must be at least 10 "
147+
"with the fall 2016 \"Anniversary update\" or newer.";
148+
return false;
149+
}
150+
auto splitted = util::split(win_ver.value(), ".");
143151
if (!(splitted.size() >= 3 && std::stoull(splitted[0]) >= 10
144152
&& std::stoull(splitted[2]) >= 14352))
145153
{
@@ -209,141 +217,7 @@ namespace mamba
209217
LOG_WARNING << "Changing registry value did not succeed.";
210218
return false;
211219
}
212-
#endif
213-
214-
std::string windows_version()
215-
{
216-
LOG_DEBUG << "Loading Windows virtual package";
217-
auto override_version = util::get_env("CONDA_OVERRIDE_WIN");
218-
if (override_version)
219-
{
220-
return override_version.value();
221-
}
222-
223-
if (!util::on_win)
224-
{
225-
return "";
226-
}
227-
228-
std::string out, err;
229-
std::vector<std::string> args = { util::get_env("COMSPEC").value_or(""), "/c", "ver" };
230-
auto [status, ec] = reproc::run(
231-
args,
232-
reproc::options{},
233-
reproc::sink::string(out),
234-
reproc::sink::string(err)
235-
);
236-
237-
if (ec)
238-
{
239-
LOG_WARNING << "Could not find Windows version by calling 'ver'\n"
240-
<< "Please file a bug report.\nError: " << ec.message();
241-
return "";
242-
}
243-
std::string xout(util::strip(out));
244-
245-
// from python
246-
std::regex ver_output_regex("(?:([\\w ]+) ([\\w.]+) .*\\[.* ([\\d.]+)\\])");
247-
248-
std::smatch rmatch;
249-
250-
std::string full_version, norm_version;
251-
if (std::regex_match(xout, rmatch, ver_output_regex))
252-
{
253-
full_version = rmatch[3];
254-
auto version_els = util::split(full_version, ".");
255-
norm_version = util::concat(version_els[0], ".", version_els[1], ".", version_els[2]);
256-
LOG_DEBUG << "Windows version found: " << norm_version;
257-
}
258-
else
259-
{
260-
LOG_DEBUG << "Windows version not found";
261-
norm_version = "0.0.0";
262-
}
263-
return norm_version;
264-
}
265-
266-
std::string macos_version()
267-
{
268-
LOG_DEBUG << "Loading macos virtual package";
269-
auto override_version = util::get_env("CONDA_OVERRIDE_OSX");
270-
if (override_version)
271-
{
272-
return override_version.value();
273-
}
274220

275-
if (!util::on_mac)
276-
{
277-
return "";
278-
}
279-
280-
std::string out, err;
281-
// Note: we could also inspect /System/Library/CoreServices/SystemVersion.plist which is
282-
// an XML file
283-
// that contains the same information. However, then we'd either need an xml
284-
// parser or some other crude method to read the data
285-
std::vector<std::string> args = { "sw_vers", "-productVersion" };
286-
auto [status, ec] = reproc::run(
287-
args,
288-
reproc::options{},
289-
reproc::sink::string(out),
290-
reproc::sink::string(err)
291-
);
292-
293-
if (ec)
294-
{
295-
LOG_WARNING << "Could not find macOS version by calling 'sw_vers -productVersion'\nPlease file a bug report.\nError: "
296-
<< ec.message();
297-
return "";
298-
}
299-
300-
auto version = std::string(util::strip(out));
301-
LOG_DEBUG << "macos version found: " << version;
302-
return version;
303-
}
304-
305-
std::string linux_version()
306-
{
307-
LOG_DEBUG << "Loading linux virtual package";
308-
auto override_version = util::get_env("CONDA_OVERRIDE_LINUX");
309-
if (override_version)
310-
{
311-
return override_version.value();
312-
}
313-
if (!util::on_linux)
314-
{
315-
return "";
316-
}
317-
318-
#ifndef _WIN32
319-
struct utsname uname_result = {};
320-
const auto ret = ::uname(&uname_result);
321-
if (ret != 0)
322-
{
323-
LOG_DEBUG << "Error calling uname (skipping): "
324-
<< std::system_error(errno, std::generic_category()).what();
325-
}
326-
327-
static const std::regex re("([0-9]+\\.[0-9]+\\.[0-9]+)(?:-.*)?");
328-
std::smatch m;
329-
std::string const version = uname_result.release;
330-
if (std::regex_search(version, m, re))
331-
{
332-
if (m.size() == 2)
333-
{
334-
std::ssub_match linux_version = m[1];
335-
LOG_DEBUG << "linux version found: " << linux_version;
336-
return linux_version.str();
337-
}
338-
}
339-
340-
LOG_DEBUG << "Could not parse linux version";
341-
#endif
342-
343-
return "";
344-
}
345-
346-
#ifdef _WIN32
347221
DWORD getppid()
348222
{
349223
HANDLE hSnapshot;
@@ -538,12 +412,14 @@ namespace mamba
538412
&& console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING;
539413
features.true_colors = false;
540414

541-
std::string win_ver = windows_version();
542-
auto splitted = util::split(win_ver, ".");
543-
if (splitted.size() >= 3 && std::stoull(splitted[0]) >= 10
544-
&& std::stoull(splitted[2]) >= 15063)
415+
if (auto version = util::windows_version())
545416
{
546-
features.true_colors = true;
417+
auto splitted = util::split(version.value(), '.');
418+
if (splitted.size() >= 3 && std::stoull(splitted[0]) >= 10
419+
&& std::stoull(splitted[2]) >= 15063)
420+
{
421+
features.true_colors = true;
422+
}
547423
}
548424
#endif
549425
return features;

0 commit comments

Comments
 (0)