Fine tune clang-format proposal (#2290)

* Fine-tune .clang-format

* Fix missing header and right const

* Fix header order on Windows

* Apply pre-commit
This commit is contained in:
Antoine Prouvost 2023-02-20 16:01:43 +01:00 committed by GitHub
parent 0002794f3c
commit 365342cc04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
155 changed files with 6698 additions and 4273 deletions

View File

@ -1,15 +1,20 @@
BasedOnStyle: Mozilla
Language: Cpp
Standard: c++17
AccessModifierOffset: '-4'
AlignAfterOpenBracket: Align
AlignAfterOpenBracket: BlockIndent
AlignEscapedNewlinesLeft: 'false'
AllowAllParametersOfDeclarationOnNextLine: 'true'
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: 'false'
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakTemplateDeclarations: 'true'
SpaceAfterTemplateKeyword: 'true'
BinPackArguments: false
BinPackParameters: false
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: 'true'
@ -22,22 +27,49 @@ ContinuationIndentWidth: '4'
Cpp11BracedListStyle: 'false'
DerivePointerAlignment: 'false'
DisableFormat: 'false'
EmptyLineAfterAccessModifier: Always
EmptyLineBeforeAccessModifier: Always
ExperimentalAutoDetectBinPacking: 'true'
IncludeBlocks: Regroup
IncludeCategories:
- Regex: <[^.]+>
Priority: 1
- Regex: <mamba/.+>
Priority: 3
- Regex: <.+>
Priority: 2
- Regex: '"mamba/.+"'
Priority: 4
- Regex: '".+/.+"'
Priority: 5
- Regex: '".+"'
Priority: 6
IndentCaseLabels: 'true'
IndentWidth: '4'
IndentWrappedFunctionNames: 'false'
JavaScriptQuotes: Single
InsertBraces: true # Experimental
KeepEmptyLinesAtTheStartOfBlocks: 'false'
Language: Cpp
MaxEmptyLinesToKeep: '2'
NamespaceIndentation: All
ObjCBlockIndentWidth: '4'
ObjCSpaceAfterProperty: 'false'
ObjCSpaceBeforeProtocolList: 'false'
PackConstructorInitializers: Never
PenaltyBreakAssignment: 100000
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyBreakComment: 10
PenaltyBreakOpenParenthesis: 0
PenaltyBreakTemplateDeclaration: 0
PenaltyExcessCharacter: 10
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 10
PointerAlignment: Left
QualifierAlignment: Custom # Experimental
QualifierOrder: [inline, static, constexpr, const, volatile, type]
ReflowComments: 'true'
SortIncludes: 'false'
SortIncludes: CaseInsensitive
SpaceAfterCStyleCast: 'true'
SpaceAfterTemplateKeyword: 'true'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
@ -47,6 +79,5 @@ SpacesInCStyleCastParentheses: 'false'
SpacesInContainerLiterals: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
Standard: c++17
TabWidth: '4'
UseTab: Never

View File

@ -5,7 +5,6 @@ namespace mamba
class MPool;
class MultiPackageCache;
expected_t<void, mamba_aggregated_error> load_channels(MPool& pool,
MultiPackageCache& package_caches,
int is_retry);
expected_t<void, mamba_aggregated_error>
load_channels(MPool& pool, MultiPackageCache& package_caches, int is_retry);
}

View File

@ -7,16 +7,16 @@
#ifndef MAMBA_API_CONFIGURATION_HPP
#define MAMBA_API_CONFIGURATION_HPP
#include <functional>
#include <yaml-cpp/yaml.h>
#include "mamba/api/configuration_impl.hpp"
#include "mamba/api/constants.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/environment.hpp"
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/output.hpp"
#include "mamba/api/constants.hpp"
#include "mamba/api/configuration_impl.hpp"
#include <yaml-cpp/yaml.h>
#include <functional>
#define CONTEXT_DEBUGGING \
@ -25,13 +25,12 @@
Context::instance().debug_print(); \
exit(0); \
}
#define CONFIG_DEBUGGING \
if (Configuration::instance().at("print_config_only").value<bool>()) \
{ \
int dump_opts \
= MAMBA_SHOW_CONFIG_VALUES | MAMBA_SHOW_CONFIG_SRCS | MAMBA_SHOW_ALL_CONFIGS; \
std::cout << Configuration::instance().dump(dump_opts) << std::endl; \
exit(0); \
#define CONFIG_DEBUGGING \
if (Configuration::instance().at("print_config_only").value<bool>()) \
{ \
int dump_opts = MAMBA_SHOW_CONFIG_VALUES | MAMBA_SHOW_CONFIG_SRCS | MAMBA_SHOW_ALL_CONFIGS; \
std::cout << Configuration::instance().dump(dump_opts) << std::endl; \
exit(0); \
}
namespace mamba
@ -81,20 +80,32 @@ namespace YAML
static bool decode(const Node& node, mamba::RCConfigLevel& rhs)
{
if (!node.IsScalar())
{
return false;
}
auto str = node.as<std::string>();
if (str == "HomeDir")
{
rhs = mamba::RCConfigLevel::kHomeDir;
}
else if (str == "RootPrefix")
{
rhs = mamba::RCConfigLevel::kRootPrefix;
}
else if (str == "SystemDir")
{
rhs = mamba::RCConfigLevel::kSystemDir;
}
else if (str == "TargetPrefix")
{
rhs = mamba::RCConfigLevel::kTargetPrefix;
}
else
{
return false;
}
return true;
}
@ -120,9 +131,10 @@ namespace mamba
virtual void set_default_value() = 0;
virtual void set_rc_yaml_value(const YAML::Node& value, const std::string& source) = 0;
virtual void set_rc_yaml_values(const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources)
= 0;
virtual void set_rc_yaml_values(
const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources
) = 0;
virtual void set_cli_yaml_value(const YAML::Node& value) = 0;
virtual void set_cli_yaml_value(const std::string& value) = 0;
virtual void set_yaml_value(const YAML::Node& value) = 0;
@ -175,8 +187,10 @@ namespace mamba
void set_default_value() override;
void set_rc_yaml_value(const YAML::Node& value, const std::string& source) override;
void set_rc_yaml_values(const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources) override;
void set_rc_yaml_values(
const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources
) override;
void set_cli_yaml_value(const YAML::Node& value) override;
void set_cli_yaml_value(const std::string& value) override;
void set_yaml_value(const YAML::Node& value) override;
@ -191,8 +205,10 @@ namespace mamba
void dump_json(nlohmann::json& node, const std::string& name) const override;
void set_rc_value(const T& value, const std::string& source);
void set_rc_values(const std::map<std::string, T>& mapped_values,
const std::vector<std::string>& sources);
void set_rc_values(
const std::map<std::string, T>& mapped_values,
const std::vector<std::string>& sources
);
void set_value(const T& value);
using cli_config_type = detail::cli_config<T>;
@ -221,6 +237,7 @@ namespace mamba
class Configurable
{
public:
template <class T>
Configurable(const std::string& name, T* context);
@ -284,8 +301,10 @@ namespace mamba
Configurable&& set_rc_value(const T& value, const std::string& source);
template <class T>
Configurable&& set_rc_values(const std::map<std::string, T>& mapped_values,
const std::vector<std::string>& sources);
Configurable&& set_rc_values(
const std::map<std::string, T>& mapped_values,
const std::vector<std::string>& sources
);
template <class T>
Configurable&& set_value(const T& value);
@ -327,15 +346,17 @@ namespace mamba
cli_storage_type<T>& get_cli_config();
Configurable&& set_rc_yaml_value(const YAML::Node& value, const std::string& source);
Configurable&& set_rc_yaml_values(const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources);
Configurable&& set_rc_yaml_values(
const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources
);
Configurable&& set_cli_yaml_value(const YAML::Node& value);
Configurable&& set_cli_yaml_value(const std::string& value);
Configurable&& set_yaml_value(const YAML::Node& value);
Configurable&& set_yaml_value(const std::string& value);
Configurable&& compute(int options = 0,
const ConfigurationLevel& level = ConfigurationLevel::kDefault);
Configurable&&
compute(int options = 0, const ConfigurationLevel& level = ConfigurationLevel::kDefault);
bool is_valid_serialization(const std::string& value) const;
bool is_sequence() const;
@ -344,6 +365,7 @@ namespace mamba
void dump_json(nlohmann::json& node, const std::string& name) const;
private:
template <class T>
detail::ConfigurableImpl<T>& get_wrapped();
@ -353,13 +375,13 @@ namespace mamba
std::unique_ptr<detail::ConfigurableImplBase> p_impl;
};
int const MAMBA_SHOW_CONFIG_VALUES = 1 << 0;
int const MAMBA_SHOW_CONFIG_SRCS = 1 << 1;
int const MAMBA_SHOW_CONFIG_DESCS = 1 << 2;
int const MAMBA_SHOW_CONFIG_LONG_DESCS = 1 << 3;
int const MAMBA_SHOW_CONFIG_GROUPS = 1 << 4;
int const MAMBA_SHOW_ALL_CONFIGS = 1 << 5;
int const MAMBA_SHOW_ALL_RC_CONFIGS = 1 << 6;
const int MAMBA_SHOW_CONFIG_VALUES = 1 << 0;
const int MAMBA_SHOW_CONFIG_SRCS = 1 << 1;
const int MAMBA_SHOW_CONFIG_DESCS = 1 << 2;
const int MAMBA_SHOW_CONFIG_LONG_DESCS = 1 << 3;
const int MAMBA_SHOW_CONFIG_GROUPS = 1 << 4;
const int MAMBA_SHOW_ALL_CONFIGS = 1 << 5;
const int MAMBA_SHOW_ALL_RC_CONFIGS = 1 << 6;
/*****************
* Configuration *
@ -368,6 +390,7 @@ namespace mamba
class Configuration
{
public:
static Configuration& instance();
std::map<std::string, Configurable>& config();
@ -406,10 +429,12 @@ namespace mamba
void reset_configurables();
protected:
Configuration();
~Configuration();
protected:
Configuration(const Configuration&) = delete;
Configuration& operator=(const Configuration&) = delete;
Configuration(Configuration&&) = delete;
@ -423,16 +448,15 @@ namespace mamba
void clear_rc_sources();
void add_to_loading_sequence(std::vector<std::string>& seq,
const std::string& name,
std::vector<std::string>&);
void
add_to_loading_sequence(std::vector<std::string>& seq, const std::string& name, std::vector<std::string>&);
static YAML::Node load_rc_file(const fs::u8path& file);
static std::vector<fs::u8path> compute_default_rc_sources(const RCConfigLevel& level);
std::vector<fs::u8path> get_existing_rc_sources(
const std::vector<fs::u8path>& possible_rc_paths);
std::vector<fs::u8path>
get_existing_rc_sources(const std::vector<fs::u8path>& possible_rc_paths);
std::vector<fs::u8path> m_sources;
std::vector<fs::u8path> m_valid_sources;
@ -477,8 +501,8 @@ namespace mamba
}
template <class T>
void ConfigurableImpl<T>::set_rc_yaml_value(const YAML::Node& value,
const std::string& source)
void
ConfigurableImpl<T>::set_rc_yaml_value(const YAML::Node& value, const std::string& source)
{
try
{
@ -494,7 +518,8 @@ namespace mamba
template <class T>
void ConfigurableImpl<T>::set_rc_yaml_values(
const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources)
const std::vector<std::string>& sources
)
{
std::map<std::string, T> converted_values;
for (auto& y : values)
@ -570,21 +595,25 @@ namespace mamba
}
template <>
inline void ConfigurableImpl<fs::u8path>::dump_json(nlohmann::json& node,
const std::string& name) const
inline void
ConfigurableImpl<fs::u8path>::dump_json(nlohmann::json& node, const std::string& name) const
{
node[name] = m_value.string();
}
template <>
inline void ConfigurableImpl<std::vector<fs::u8path>>::dump_json(
nlohmann::json& node, const std::string& name) const
nlohmann::json& node,
const std::string& name
) const
{
std::vector<std::string> values(m_value.size());
std::transform(m_value.begin(),
m_value.end(),
values.begin(),
[](const auto& value) { return value.string(); });
std::transform(
m_value.begin(),
m_value.end(),
values.begin(),
[](const auto& value) { return value.string(); }
);
node[name] = values;
}
@ -597,8 +626,10 @@ namespace mamba
}
template <class T>
void ConfigurableImpl<T>::set_rc_values(const std::map<std::string, T>& mapped_values,
const std::vector<std::string>& sources)
void ConfigurableImpl<T>::set_rc_values(
const std::map<std::string, T>& mapped_values,
const std::vector<std::string>& sources
)
{
assert(mapped_values.size() == sources.size());
this->m_rc_sources.insert(this->m_rc_sources.end(), sources.begin(), sources.end());
@ -620,14 +651,20 @@ namespace mamba
bool force_compute = options & MAMBA_CONF_FORCE_COMPUTE;
if (force_compute)
{
LOG_TRACE << "Update configurable '" << this->m_name << "'";
}
else
{
LOG_TRACE << "Compute configurable '" << this->m_name << "'";
}
if (!force_compute
&& (Configuration::instance().is_loading() && (m_compute_counter > 0)))
throw std::runtime_error("Multiple computation of '" + m_name
+ "' detected during loading sequence.");
if (!force_compute && (Configuration::instance().is_loading() && (m_compute_counter > 0)))
{
throw std::runtime_error(
"Multiple computation of '" + m_name + "' detected during loading sequence."
);
}
auto& ctx = Context::instance();
m_sources.clear();
@ -655,7 +692,8 @@ namespace mamba
try
{
m_values.insert(
{ env_var, detail::Source<T>::deserialize(env_var_value.value()) });
{ env_var, detail::Source<T>::deserialize(env_var_value.value()) }
);
m_sources.push_back(env_var);
}
catch (const YAML::Exception& e)
@ -689,7 +727,9 @@ namespace mamba
}
if (!m_sources.empty())
{
detail::Source<T>::merge(m_values, m_sources, m_value, m_source);
}
else
{
m_value = m_default_value;
@ -697,7 +737,9 @@ namespace mamba
}
if (!hook_disabled && (p_post_merge_hook != NULL))
{
p_post_merge_hook(m_value);
}
++m_compute_counter;
if (p_context != nullptr)
@ -706,7 +748,9 @@ namespace mamba
}
if (p_post_ctx_hook != nullptr)
{
p_post_ctx_hook();
}
}
}
@ -747,7 +791,9 @@ namespace mamba
T& Configurable::value()
{
if (Configuration::instance().is_loading() && p_impl->m_compute_counter == 0)
{
throw std::runtime_error("Using '" + name() + "' value without previous computation.");
}
return get_wrapped<T>().m_value;
}
@ -755,7 +801,9 @@ namespace mamba
const T& Configurable::cli_value() const
{
if (!cli_configured())
{
throw std::runtime_error("Trying to get unset CLI value of '" + name() + "'");
}
return get_wrapped<T>().m_cli_config.value();
}
@ -774,8 +822,10 @@ namespace mamba
}
template <class T>
Configurable&& Configurable::set_rc_values(const std::map<std::string, T>& mapped_values,
const std::vector<std::string>& sources)
Configurable&& Configurable::set_rc_values(
const std::map<std::string, T>& mapped_values,
const std::vector<std::string>& sources
)
{
get_wrapped<T>().set_rc_values(mapped_values, sources);
return std::move(*this);
@ -886,8 +936,7 @@ namespace mamba
{
if (!allow_redefinition)
{
throw std::runtime_error("Redefinition of configurable '" + name
+ "' not allowed.");
throw std::runtime_error("Redefinition of configurable '" + name + "' not allowed.");
}
}

View File

@ -61,10 +61,12 @@ namespace mamba
return std::vector<std::string>({ "default" });
};
static void merge(const std::map<std::string, T>& values,
const std::vector<std::string>& sources,
T& value,
std::vector<std::string>& source);
static void merge(
const std::map<std::string, T>& values,
const std::vector<std::string>& sources,
T& value,
std::vector<std::string>& source
);
static T deserialize(const std::string& value);
@ -79,10 +81,12 @@ namespace mamba
return std::vector<std::string>(init.size(), "default");
};
static void merge(const std::map<std::string, std::vector<T>>& values,
const std::vector<std::string>& sources,
std::vector<T>& value,
std::vector<std::string>& source);
static void merge(
const std::map<std::string, std::vector<T>>& values,
const std::vector<std::string>& sources,
std::vector<T>& value,
std::vector<std::string>& source
);
static std::vector<T> deserialize(const std::string& value);
@ -94,10 +98,12 @@ namespace mamba
*************************/
template <class T>
void Source<T>::merge(const std::map<std::string, T>& values,
const std::vector<std::string>& sources,
T& value,
std::vector<std::string>& source)
void Source<T>::merge(
const std::map<std::string, T>& values,
const std::vector<std::string>& sources,
T& value,
std::vector<std::string>& source
)
{
source = sources;
value = values.at(sources.front());
@ -123,10 +129,12 @@ namespace mamba
}
template <class T>
void Source<std::vector<T>>::merge(const std::map<std::string, std::vector<T>>& values,
const std::vector<std::string>& sources,
std::vector<T>& value,
std::vector<std::string>& source)
void Source<std::vector<T>>::merge(
const std::map<std::string, std::vector<T>>& values,
const std::vector<std::string>& sources,
std::vector<T>& value,
std::vector<std::string>& source
)
{
value.clear();
source.clear();
@ -234,7 +242,8 @@ namespace YAML
else
{
throw std::runtime_error(
"Invalid 'VerificationLevel', should be in {'enabled', 'warn', 'disabled'}");
"Invalid 'VerificationLevel', should be in {'enabled', 'warn', 'disabled'}"
);
}
return true;
@ -318,10 +327,13 @@ namespace YAML
struct convert<mamba::log_level>
{
private:
static inline const std::array<std::string, 7> log_level_names
= { "trace", "debug", "info", "warning", "error", "critical", "off" };
inline static const std::array<std::string, 7> log_level_names = {
"trace", "debug", "info", "warning", "error", "critical", "off"
};
public:
static Node encode(const mamba::log_level& rhs)
{
return Node(log_level_names[static_cast<size_t>(rhs)]);
@ -337,9 +349,8 @@ namespace YAML
return true;
}
LOG_ERROR
<< "Invalid log level, should be in {'critical', 'error', 'warning', 'info', 'debug', 'trace', 'off'} but is '"
<< name << "'";
LOG_ERROR << "Invalid log level, should be in {'critical', 'error', 'warning', 'info', 'debug', 'trace', 'off'} but is '"
<< name << "'";
return false;
}
};

View File

@ -3,24 +3,24 @@
namespace mamba
{
int const MAMBA_NO_PREFIX_CHECK = 1 << 0;
int const MAMBA_ALLOW_EXISTING_PREFIX = 1 << 1;
int const MAMBA_ALLOW_MISSING_PREFIX = 1 << 2;
int const MAMBA_ALLOW_NOT_ENV_PREFIX = 1 << 3;
int const MAMBA_EXPECT_EXISTING_PREFIX = 1 << 4;
const int MAMBA_NO_PREFIX_CHECK = 1 << 0;
const int MAMBA_ALLOW_EXISTING_PREFIX = 1 << 1;
const int MAMBA_ALLOW_MISSING_PREFIX = 1 << 2;
const int MAMBA_ALLOW_NOT_ENV_PREFIX = 1 << 3;
const int MAMBA_EXPECT_EXISTING_PREFIX = 1 << 4;
int const MAMBA_NOT_ALLOW_EXISTING_PREFIX = 0;
int const MAMBA_NOT_ALLOW_MISSING_PREFIX = 0;
int const MAMBA_NOT_ALLOW_NOT_ENV_PREFIX = 0;
int const MAMBA_NOT_EXPECT_EXISTING_PREFIX = 0;
const int MAMBA_NOT_ALLOW_EXISTING_PREFIX = 0;
const int MAMBA_NOT_ALLOW_MISSING_PREFIX = 0;
const int MAMBA_NOT_ALLOW_NOT_ENV_PREFIX = 0;
const int MAMBA_NOT_EXPECT_EXISTING_PREFIX = 0;
int const MAMBA_CONF_FORCE_COMPUTE = 1 << 0;
int const MAMBA_CONF_DISABLE_HOOK = 1 << 1;
const int MAMBA_CONF_FORCE_COMPUTE = 1 << 0;
const int MAMBA_CONF_DISABLE_HOOK = 1 << 1;
int const MAMBA_FORCE = 1 << 0;
int const MAMBA_REMOVE_FORCE = MAMBA_FORCE;
int const MAMBA_REMOVE_PRUNE = 1 << 1;
int const MAMBA_REMOVE_ALL = 1 << 2;
const int MAMBA_FORCE = 1 << 0;
const int MAMBA_REMOVE_FORCE = MAMBA_FORCE;
const int MAMBA_REMOVE_PRUNE = 1 << 1;
const int MAMBA_REMOVE_ALL = 1 << 2;
}
#endif

View File

@ -7,6 +7,9 @@
#ifndef MAMBA_API_CREATE_HPP
#define MAMBA_API_CREATE_HPP
#include <string>
#include "mamba/core/mamba_fs.hpp"
namespace mamba
{

View File

@ -7,12 +7,12 @@
#ifndef MAMBA_API_INFO_HPP
#define MAMBA_API_INFO_HPP
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/util.hpp"
#include <string>
#include <vector>
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/util.hpp"
namespace mamba
{
@ -21,14 +21,16 @@ namespace mamba
std::string version();
std::string banner();
const std::string mamba_banner = std::string(strip(R"MAMBARAW(
const std::string mamba_banner = std::string(strip(
R"MAMBARAW(
__
_____ ___ ____ _____ ___ / /_ ____ _
/ __ `__ \/ __ `/ __ `__ \/ __ \/ __ `/
/ / / / / / /_/ / / / / / / /_/ / /_/ /
/_/ /_/ /_/\__,_/_/ /_/ /_/_.___/\__,_/
)MAMBARAW",
"\n"));
"\n"
));
namespace detail
{

View File

@ -7,6 +7,12 @@
#ifndef MAMBA_API_INSTALL_HPP
#define MAMBA_API_INSTALL_HPP
#include <string>
#include <vector>
#include <nlohmann/json.hpp>
#include <yaml-cpp/yaml.h>
#include "mamba/core/context.hpp"
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/package_cache.hpp"
@ -15,27 +21,24 @@
#include "mamba/core/repo.hpp"
#include "mamba/core/solver.hpp"
#include <yaml-cpp/yaml.h>
#include <nlohmann/json.hpp>
#include <string>
#include <vector>
namespace mamba
{
void install();
void install_specs(const std::vector<std::string>& specs,
bool create_env = false,
int solver_flag = SOLVER_INSTALL,
int is_retry = 0);
void install_specs(
const std::vector<std::string>& specs,
bool create_env = false,
int solver_flag = SOLVER_INSTALL,
int is_retry = 0
);
void install_explicit_specs(const std::vector<std::string>& specs, bool create_env = false);
void install_lockfile_specs(const std::string& lockfile_specs,
const std::vector<std::string>& categories,
bool create_env = false);
void install_lockfile_specs(
const std::string& lockfile_specs,
const std::vector<std::string>& categories,
bool create_env = false
);
namespace detail
{
@ -69,8 +72,8 @@ namespace mamba
yaml_file_contents read_yaml_file(fs::u8path yaml_file);
std::tuple<std::vector<PackageInfo>, std::vector<MatchSpec>> parse_urls_to_package_info(
const std::vector<std::string>& urls);
std::tuple<std::vector<PackageInfo>, std::vector<MatchSpec>>
parse_urls_to_package_info(const std::vector<std::string>& urls);
inline void to_json(nlohmann::json&, const other_pkg_mgr_spec&)
{

View File

@ -8,8 +8,6 @@
namespace mamba
{
void repoquery(QueryType type,
QueryResultFormat format,
bool use_local,
const std::string& query);
void
repoquery(QueryType type, QueryResultFormat format, bool use_local, const std::string& query);
}

View File

@ -7,20 +7,22 @@
#ifndef MAMBA_API_SHELL_HPP
#define MAMBA_API_SHELL_HPP
#include "mamba/core/mamba_fs.hpp"
#include <string>
#include <vector>
#include "mamba/core/mamba_fs.hpp"
namespace mamba
{
void detect_shell(std::string& shell_type);
void shell(const std::string& action,
std::string& shell_type,
const std::string& prefix = "",
bool stack = false);
void shell(
const std::string& action,
std::string& shell_type,
const std::string& prefix = "",
bool stack = false
);
}
#endif

View File

@ -7,12 +7,12 @@
#ifndef MAMBA_API_UPDATE_HPP
#define MAMBA_API_UPDATE_HPP
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/query.hpp"
#include <string>
#include <vector>
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/query.hpp"
namespace mamba
{

View File

@ -38,6 +38,7 @@ namespace mamba
class Activator
{
public:
virtual ~Activator() = default;
Activator(const Activator&) = delete;
@ -46,9 +47,8 @@ namespace mamba
Activator& operator=(Activator&&) = delete;
virtual std::string script(const EnvironmentTransform& env) = 0;
virtual std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier)
= 0;
virtual std::pair<std::string, std::string>
update_prompt(const std::string& conda_prompt_modifier) = 0;
virtual std::string shell_extension() = 0;
virtual std::string shell() = 0;
@ -56,23 +56,26 @@ namespace mamba
std::vector<fs::u8path> get_deactivate_scripts(const fs::u8path& prefix);
std::string get_default_env(const fs::u8path& prefix);
std::vector<std::pair<std::string, std::string>> get_environment_vars(
const fs::u8path& prefix);
std::vector<std::pair<std::string, std::string>>
get_environment_vars(const fs::u8path& prefix);
std::string get_prompt_modifier(const fs::u8path& prefix,
const std::string& conda_default_env,
int old_conda_shlvl);
std::string get_prompt_modifier(
const fs::u8path& prefix,
const std::string& conda_default_env,
int old_conda_shlvl
);
std::vector<fs::u8path> get_clean_dirs();
std::string add_prefix_to_path(const fs::u8path& prefix, int old_conda_shlvl);
std::string replace_prefix_in_path(const fs::u8path& old_prefix,
const fs::u8path& new_prefix);
std::string
replace_prefix_in_path(const fs::u8path& old_prefix, const fs::u8path& new_prefix);
std::string remove_prefix_from_path(const fs::u8path& prefix);
void get_export_unset_vars(
EnvironmentTransform& envt,
const std::vector<std::pair<std::string, std::string>>& to_export);
const std::vector<std::pair<std::string, std::string>>& to_export
);
EnvironmentTransform build_reactivate();
EnvironmentTransform build_deactivate();
@ -89,6 +92,7 @@ namespace mamba
std::string hook(const std::string& shell_type);
protected:
Activator();
bool m_stack = false;
@ -100,12 +104,13 @@ namespace mamba
class PosixActivator : public Activator
{
public:
PosixActivator() = default;
virtual ~PosixActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string>
update_prompt(const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string shell() override;
@ -117,12 +122,13 @@ namespace mamba
class CshActivator : public Activator
{
public:
CshActivator() = default;
virtual ~CshActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string>
update_prompt(const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string shell() override;
@ -134,12 +140,13 @@ namespace mamba
class CmdExeActivator : public Activator
{
public:
CmdExeActivator() = default;
virtual ~CmdExeActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string>
update_prompt(const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string shell() override;
@ -151,12 +158,13 @@ namespace mamba
class PowerShellActivator : public Activator
{
public:
PowerShellActivator() = default;
virtual ~PowerShellActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string>
update_prompt(const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string shell() override;
@ -168,12 +176,13 @@ namespace mamba
class XonshActivator : public Activator
{
public:
XonshActivator() = default;
virtual ~XonshActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string>
update_prompt(const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string shell() override;
@ -185,12 +194,13 @@ namespace mamba
class FishActivator : public Activator
{
public:
FishActivator() = default;
virtual ~FishActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string>
update_prompt(const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string shell() override;

View File

@ -7,20 +7,21 @@
#ifndef MAMBA_CORE_CHANNEL_HPP
#define MAMBA_CORE_CHANNEL_HPP
#include "mamba/core/package_cache.hpp"
#include "mamba/core/validate.hpp"
#include <map>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "mamba/core/package_cache.hpp"
#include "mamba/core/validate.hpp"
namespace mamba
{
class Channel
{
public:
const std::string& scheme() const;
const std::string& location() const;
const std::string& name() const;
@ -34,18 +35,21 @@ namespace mamba
std::string base_url() const;
std::string platform_url(std::string platform, bool with_credential = true) const;
// The pairs consist of (platform,url)
std::vector<std::pair<std::string, std::string>> platform_urls(bool with_credential
= true) const;
std::vector<std::pair<std::string, std::string>>
platform_urls(bool with_credential = true) const;
std::vector<std::string> urls(bool with_credential = true) const;
private:
Channel(const std::string& scheme,
const std::string& location,
const std::string& name,
const std::optional<std::string>& auth = {},
const std::optional<std::string>& token = {},
const std::optional<std::string>& package_filename = {},
const std::optional<std::string>& canonical_name = {});
Channel(
const std::string& scheme,
const std::string& location,
const std::string& name,
const std::optional<std::string>& auth = {},
const std::optional<std::string>& token = {},
const std::optional<std::string>& package_filename = {},
const std::optional<std::string>& canonical_name = {}
);
std::string m_scheme;
std::string m_location;

View File

@ -16,25 +16,31 @@ namespace mamba
class ChannelBuilder
{
public:
static Channel make_simple_channel(const Channel& channel_alias,
const std::string& channel_url,
const std::string& channel_name = "",
const std::string& multi_name = "");
static Channel make_simple_channel(
const Channel& channel_alias,
const std::string& channel_url,
const std::string& channel_name = "",
const std::string& multi_name = ""
);
static const Channel& make_cached_channel(const std::string& value);
static void clear_cache();
private:
static ChannelCache& get_cache();
static Channel from_url(const std::string& url);
static Channel from_name(const std::string& name);
static Channel from_value(const std::string& value);
static Channel from_alias(const std::string& scheme,
const std::string& location,
const std::optional<std::string>& auth = {},
const std::optional<std::string>& token = {});
static Channel from_alias(
const std::string& scheme,
const std::string& location,
const std::optional<std::string>& auth = {},
const std::optional<std::string>& token = {}
);
friend class ChannelContext;
};
@ -42,6 +48,7 @@ namespace mamba
class ChannelContext
{
public:
using channel_list = std::vector<std::string>;
using channel_map = std::map<std::string, Channel>;
using multichannel_map = std::map<std::string, std::vector<std::string>>;
@ -62,10 +69,12 @@ namespace mamba
const channel_list& get_whitelist_channels() const;
protected:
ChannelContext();
~ChannelContext();
private:
Channel build_channel_alias();
void init_custom_channels();

View File

@ -8,15 +8,15 @@
#define MAMBA_CORE_CONTEXT_HPP
#include <map>
#include <string>
#include <vector>
#include <optional>
#include <regex>
#include <string>
#include <vector>
#include "mamba/core/common_types.hpp"
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/tasksync.hpp"
#include "mamba/core/palette.hpp"
#include "mamba/core/tasksync.hpp"
#include "mamba/version.hpp"
#define ROOT_ENV_NAME "base"
@ -113,6 +113,7 @@ namespace mamba
class Context
{
public:
std::string caller_version = "";
std::string conda_version = "3.8.0";
std::string current_command = "mamba";
@ -226,7 +227,8 @@ namespace mamba
"https://repo.anaconda.com/pkgs/r",
"https://repo.anaconda.com/pkgs/msys2"
#else
"https://repo.anaconda.com/pkgs/main", "https://repo.anaconda.com/pkgs/r"
"https://repo.anaconda.com/pkgs/main",
"https://repo.anaconda.com/pkgs/r"
#endif
};
@ -261,11 +263,13 @@ namespace mamba
void dump_backtrace_no_guards();
protected:
Context();
~Context();
private:
void load_authentication_info();
std::map<std::string, AuthenticationInfo> m_authentication_info;
bool m_authentication_infos_loaded = false;

View File

@ -8,16 +8,16 @@
#ifndef MAMBA_CORE_ENVIRONMENT_LOCKFILE_HPP
#define MAMBA_CORE_ENVIRONMENT_LOCKFILE_HPP
#include <optional>
#include <string>
#include <typeindex>
#include <optional>
#include <unordered_map>
#include <tl/expected.hpp>
#include "error_handling.hpp"
#include "fsutil.hpp"
#include "package_info.hpp"
#include "error_handling.hpp"
namespace mamba
{
@ -43,9 +43,11 @@ namespace mamba
}
template <typename StringT>
static mamba_error make_error(file_parsing_error_code error_code,
StringT&& msg,
std::optional<std::type_index> yaml_error_type = std::nullopt)
static mamba_error make_error(
file_parsing_error_code error_code,
StringT&& msg,
std::optional<std::type_index> yaml_error_type = std::nullopt
)
{
return mamba_error{ std::forward<StringT>(msg),
mamba_error_code::env_lockfile_parsing_failed,
@ -56,6 +58,7 @@ namespace mamba
class EnvironmentLockFile
{
public:
struct Channel
{
std::string url;
@ -85,9 +88,9 @@ namespace mamba
{
}
std::vector<PackageInfo> get_packages_for(std::string_view category,
std::string_view platform,
std::string_view manager) const;
std::vector<PackageInfo>
get_packages_for(std::string_view category, std::string_view platform, std::string_view manager)
const;
const std::vector<Package>& get_all_packages() const
{
@ -99,14 +102,15 @@ namespace mamba
}
private:
Meta metadata;
std::vector<Package> packages;
};
/// Read an environment lock YAML file and returns it's structured content or an error if
/// failed.
tl::expected<EnvironmentLockFile, mamba_error> read_environment_lockfile(
const fs::u8path& lockfile_location);
tl::expected<EnvironmentLockFile, mamba_error>
read_environment_lockfile(const fs::u8path& lockfile_location);
/// Returns `true` if the filename matches names of files which should be interpreted as conda

View File

@ -7,11 +7,11 @@
#ifndef MAMBA_CORE_ENVIRONMENT_HPP
#define MAMBA_CORE_ENVIRONMENT_HPP
#include <map>
#include <cstdlib>
#include <cassert>
#include <string_view>
#include <cstdlib>
#include <map>
#include <optional>
#include <string_view>
#include "mamba_fs.hpp"
@ -20,11 +20,11 @@
#endif
#ifndef _WIN32
#include <sys/utsname.h>
#include <wordexp.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <wordexp.h>
extern "C"
{
@ -36,7 +36,7 @@ namespace mamba
{
namespace env
{
constexpr inline const char* pathsep()
inline constexpr const char* pathsep()
{
#ifdef _WIN32
return ";";

View File

@ -7,8 +7,8 @@
#ifndef MAMBA_CORE_ENVIRONMENT_MANAGER
#define MAMBA_CORE_ENVIRONMENT_MANAGER
#include <string>
#include <set>
#include <string>
#include "fsutil.hpp"
@ -21,13 +21,15 @@ namespace mamba
class EnvironmentsManager
{
public:
void register_env(const fs::u8path& location);
void unregister_env(const fs::u8path& location);
std::set<fs::u8path> list_all_known_prefixes();
private:
std::set<std::string> clean_environments_txt(const fs::u8path& env_txt_file,
const fs::u8path& location);
std::set<std::string>
clean_environments_txt(const fs::u8path& env_txt_file, const fs::u8path& location);
std::string remove_trailing_slash(std::string p);
fs::u8path get_environments_txt_file(const fs::u8path& home) const;
};

View File

@ -36,6 +36,7 @@ namespace mamba
class mamba_error : public std::runtime_error
{
public:
using base_type = std::runtime_error;
mamba_error(const std::string& msg, mamba_error_code ec);
@ -47,6 +48,7 @@ namespace mamba
const std::any& data() const noexcept;
private:
mamba_error_code m_error_code;
std::any m_data;
};
@ -54,6 +56,7 @@ namespace mamba
class mamba_aggregated_error : public mamba_error
{
public:
using base_type = mamba_error;
using error_list_t = std::vector<mamba_error>;
@ -62,9 +65,10 @@ namespace mamba
const char* what() const noexcept override;
private:
error_list_t m_error_list;
mutable std::string m_aggregated_message;
constexpr static const char* m_base_message = "Multiple errors occured:\n";
static constexpr const char* m_base_message = "Multiple errors occured:\n";
};
/********************************
@ -75,6 +79,7 @@ namespace mamba
class expected_ref_wrapper : private tl::expected<std::reference_wrapper<T>, E>
{
public:
using value_type = T;
using self_type = expected_ref_wrapper<T, E>;
using reference = std::reference_wrapper<T>;
@ -246,8 +251,8 @@ namespace mamba
}
template <class T1, class E1, class T2, class E2>
constexpr bool operator==(const expected_ref_wrapper<T1, E1>& x,
const expected_ref_wrapper<T2, E2>& y)
constexpr bool
operator==(const expected_ref_wrapper<T1, E1>& x, const expected_ref_wrapper<T2, E2>& y)
{
using base_type1 = typename expected_ref_wrapper<T1, E1>::base_type;
using base_type2 = typename expected_ref_wrapper<T2, E2>::base_type;

View File

@ -7,11 +7,11 @@
#ifndef MAMBA_CORE_EXECUTION_HPP
#define MAMBA_CORE_EXECUTION_HPP
#include <vector>
#include <future>
#include <thread>
#include <atomic>
#include <future>
#include <mutex>
#include <thread>
#include <vector>
namespace mamba
@ -33,6 +33,7 @@ namespace mamba
class MainExecutor
{
public:
// Set itself as the main executor.
// Throws `MainExecutorError` if another instance already exists.
MainExecutor();
@ -65,7 +66,9 @@ namespace mamba
void schedule(Task&& task, Args&&... args)
{
if (!is_open)
{
return;
}
std::scoped_lock lock{ threads_mutex };
if (is_open) // Double check necessary for correctness
@ -84,7 +87,9 @@ namespace mamba
void take_ownership(std::thread thread)
{
if (!thread.joinable() || !is_open)
{
return;
}
std::scoped_lock lock{ threads_mutex };
if (is_open) // Double check necessary for correctness
@ -105,13 +110,17 @@ namespace mamba
{
bool expected = true;
if (!is_open.compare_exchange_strong(expected, false))
{
return;
}
invoke_close_handlers();
std::scoped_lock lock{ threads_mutex };
for (auto&& t : threads)
{
t.join();
}
threads.clear();
}
@ -120,7 +129,9 @@ namespace mamba
void on_close(on_close_handler handler)
{
if (!is_open)
{
return;
}
std::scoped_lock lock{ handlers_mutex };
if (is_open) // Double check needed to avoid adding new handles while closing.
@ -130,6 +141,7 @@ namespace mamba
}
private:
std::atomic<bool> is_open{ true };
std::vector<std::thread> threads;
std::recursive_mutex threads_mutex; // TODO: replace by synchronized_value once available

View File

@ -15,8 +15,9 @@ extern "C"
#include <string>
#include <vector>
#include <zstd.h>
#include <bzlib.h>
#include <zstd.h>
#include "progress_bar.hpp"
#include "validate.hpp"
@ -27,7 +28,7 @@ namespace mamba
struct ZstdStream
{
constexpr static size_t BUFFER_SIZE = 256000;
static constexpr size_t BUFFER_SIZE = 256000;
ZstdStream(curl_write_callback write_callback, void* write_callback_data)
: stream(ZSTD_createDCtx())
, m_write_callback(write_callback)
@ -58,7 +59,7 @@ namespace mamba
struct Bzip2Stream
{
constexpr static size_t BUFFER_SIZE = 256000;
static constexpr size_t BUFFER_SIZE = 256000;
Bzip2Stream(curl_write_callback write_callback, void* write_callback_data)
: m_write_callback(write_callback)
@ -100,10 +101,9 @@ namespace mamba
class DownloadTarget
{
public:
DownloadTarget() = default;
DownloadTarget(const std::string& name,
const std::string& url,
const std::string& filename);
DownloadTarget(const std::string& name, const std::string& url, const std::string& filename);
~DownloadTarget();
DownloadTarget(const DownloadTarget&) = delete;
@ -116,7 +116,12 @@ namespace mamba
static size_t header_callback(char* buffer, size_t size, size_t nitems, void* self);
static int progress_callback(
void*, curl_off_t total_to_download, curl_off_t now_downloaded, curl_off_t, curl_off_t);
void*,
curl_off_t total_to_download,
curl_off_t now_downloaded,
curl_off_t,
curl_off_t
);
void set_mod_etag_headers(const std::string& mod, const std::string& etag);
void set_progress_bar(ProgressProxy progress_proxy);
void set_expected_size(std::size_t size);
@ -174,6 +179,7 @@ namespace mamba
std::string etag, mod, cache_control;
private:
std::unique_ptr<ZstdStream> m_zstd_stream;
std::unique_ptr<Bzip2Stream> m_bzip2_stream;
std::function<bool(const DownloadTarget&)> m_finalize_callback;
@ -209,6 +215,7 @@ namespace mamba
class MultiDownloadTarget
{
public:
MultiDownloadTarget();
~MultiDownloadTarget();
@ -217,6 +224,7 @@ namespace mamba
bool download(int options);
private:
std::vector<DownloadTarget*> m_targets;
std::vector<DownloadTarget*> m_retry_targets;
CURLM* m_handle;

View File

@ -12,9 +12,9 @@
#include "mamba/core/environment.hpp"
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/util_scope.hpp"
#include "mamba/core/output.hpp"
namespace mamba
{
@ -31,7 +31,9 @@ namespace mamba
inline void create_directories_sudo_safe(const fs::u8path& path)
{
if (fs::is_directory(path))
{
return;
}
fs::u8path base_dir = path.parent_path();
if (!fs::is_directory(base_dir))
@ -42,9 +44,11 @@ namespace mamba
#ifndef _WIN32
// set permissions to 0o2775
fs::permissions(path,
fs::perms::set_gid | fs::perms::owner_all | fs::perms::group_all
| fs::perms::others_read | fs::perms::others_exec);
fs::permissions(
path,
fs::perms::set_gid | fs::perms::owner_all | fs::perms::group_all
| fs::perms::others_read | fs::perms::others_exec
);
#endif
}
@ -75,11 +79,17 @@ namespace mamba
std::ofstream outfile{ path.std_path(), std::ios::out };
if (!outfile.good())
{
LOG_INFO << "Could not touch file at " << path;
}
if (outfile.fail())
throw fs::filesystem_error("File creation failed",
std::make_error_code(std::errc::permission_denied));
{
throw fs::filesystem_error(
"File creation failed",
std::make_error_code(std::errc::permission_denied)
);
}
return false;
}
@ -95,28 +105,34 @@ namespace mamba
{
const auto& path_to_write_in = fs::exists(path) ? path : path.parent_path();
static constexpr auto writable_flags
= fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write;
static constexpr auto writable_flags = fs::perms::owner_write | fs::perms::group_write
| fs::perms::others_write;
std::error_code ec;
const auto status = fs::status(path_to_write_in, ec);
const bool should_be_writable
= !ec && status.type() != fs::file_type::not_found
&& (status.permissions() & writable_flags) != fs::perms::none;
const bool should_be_writable = !ec && status.type() != fs::file_type::not_found
&& (status.permissions() & writable_flags)
!= fs::perms::none;
// If it should not be writable, stop there.
if (!should_be_writable)
{
return false;
}
// If it should be, check that it's true by creating or editing a file.
const bool is_directory
= fs::exists(path)
&& fs::is_directory(path, ec); // fs::is_directory fails if path does not exist
const bool is_directory = fs::exists(path)
&& fs::is_directory(path, ec); // fs::is_directory
// fails if
// path does
// not exist
if (ec)
{
return false;
}
const auto& test_file_path
= is_directory ? path / ".mamba-is-writable-check-delete-me" : path;
const auto& test_file_path = is_directory ? path / ".mamba-is-writable-check-delete-me"
: path;
const auto _ = on_scope_exit(
[&]
{
@ -125,7 +141,8 @@ namespace mamba
std::error_code ec;
fs::remove(test_file_path, ec);
}
});
}
);
std::ofstream test_file{ test_file_path.std_path(),
std::ios_base::out | std::ios_base::app };
return test_file.is_open();
@ -140,9 +157,7 @@ namespace mamba
// if both rename and move fail, the error code is set to the error code of the
// copy_file operation and the `to` file is removed. You will have to handle removal
// of the `from` file yourself.
inline void rename_or_move(const fs::u8path& from,
const fs::u8path& to,
std::error_code& ec)
inline void rename_or_move(const fs::u8path& from, const fs::u8path& to, std::error_code& ec)
{
fs::rename(from, to, ec);
if (ec)

View File

@ -20,6 +20,7 @@ namespace mamba
class History
{
public:
History(const fs::u8path& prefix);
struct ParseResult

View File

@ -10,9 +10,7 @@ namespace mamba
template <typename Func, typename... Args>
auto safe_invoke(Func&& func, Args&&... args)
-> tl::expected<decltype(std::invoke(std::forward<Func>(func),
std::forward<Args>(args)...)),
mamba_error>
-> tl::expected<decltype(std::invoke(std::forward<Func>(func), std::forward<Args>(args)...)), mamba_error>
{
try
{
@ -34,13 +32,17 @@ namespace mamba
}
catch (const std::runtime_error& err)
{
return make_unexpected(std::string("callback invocation failed : ") + err.what(),
mamba_error_code::unknown);
return make_unexpected(
std::string("callback invocation failed : ") + err.what(),
mamba_error_code::unknown
);
}
catch (...)
{
return make_unexpected("callback invocation failed : unknown error",
mamba_error_code::unknown);
return make_unexpected(
"callback invocation failed : unknown error",
mamba_error_code::unknown
);
}
}

View File

@ -25,12 +25,15 @@ namespace mamba
std::string replace_long_shebang(const std::string& shebang);
std::string python_shebang(const std::string& python_exe);
static const std::regex shebang_regex(
"^(#!" // pretty much the whole match string
"(?:[ ]*)" // allow spaces between #! and beginning of the executable path
"(/(?:\\\\ |[^ \n\r\t])*)" // the executable is the next text block without an escaped
// space or non-space whitespace character
"(.*))$"); // the rest of the line can contain option flags and end whole_shebang group
static const std::regex shebang_regex("^(#!" // pretty much the whole match string
"(?:[ ]*)" // allow spaces between #! and beginning of
// the executable path
"(/(?:\\\\ |[^ \n\r\t])*)" // the executable is the next
// text block without an
// escaped space or non-space
// whitespace character
"(.*))$"); // the rest of the line can contain option
// flags and end whole_shebang group
constexpr size_t MAX_SHEBANG_LENGTH = on_linux ? 127 : 512;
@ -42,14 +45,14 @@ namespace mamba
class UnlinkPackage
{
public:
UnlinkPackage(const PackageInfo& pkg_info,
const fs::u8path& cache_path,
TransactionContext* context);
UnlinkPackage(const PackageInfo& pkg_info, const fs::u8path& cache_path, TransactionContext* context);
bool execute();
bool undo();
private:
bool unlink_path(const nlohmann::json& path_data);
PackageInfo m_pkg_info;
@ -61,22 +64,23 @@ namespace mamba
class LinkPackage
{
public:
LinkPackage(const PackageInfo& pkg_info,
const fs::u8path& cache_path,
TransactionContext* context);
LinkPackage(const PackageInfo& pkg_info, const fs::u8path& cache_path, TransactionContext* context);
bool execute();
bool undo();
private:
std::tuple<std::string, std::string> link_path(const PathData& path_data,
bool noarch_python);
std::tuple<std::string, std::string> link_path(const PathData& path_data, bool noarch_python);
std::vector<fs::u8path> compile_pyc_files(const std::vector<fs::u8path>& py_files);
auto create_python_entry_point(const fs::u8path& path,
const python_entry_point_parsed& entry_point);
void create_application_entry_point(const fs::u8path& source_full_path,
const fs::u8path& target_full_path,
const fs::u8path& python_full_path);
auto
create_python_entry_point(const fs::u8path& path, const python_entry_point_parsed& entry_point);
void create_application_entry_point(
const fs::u8path& source_full_path,
const fs::u8path& target_full_path,
const fs::u8path& python_full_path
);
PackageInfo m_pkg_info;
fs::u8path m_cache_path;

View File

@ -4,13 +4,14 @@
#include <filesystem>
#include <fstream>
#include <string>
#include <fmt/format.h>
#include "mamba/core/util_string.hpp"
#if !defined(_WIN32)
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/stat.h>
// We can use the presence of UTIME_OMIT to detect platforms that provide
// utimensat.
@ -125,6 +126,7 @@ namespace fs
class u8path
{
public:
u8path() = default;
// Copy is allowed.
@ -633,12 +635,14 @@ namespace fs
}
private:
std::filesystem::path m_path;
};
class directory_entry : private std::filesystem::directory_entry
{
public:
using std::filesystem::directory_entry::exists;
using std::filesystem::directory_entry::file_size;
using std::filesystem::directory_entry::hard_link_count;
@ -720,6 +724,7 @@ namespace fs
class directory_iterator : private std::filesystem::directory_iterator
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = directory_entry;
using difference_type = std::ptrdiff_t;
@ -772,11 +777,11 @@ namespace fs
}
private:
mutable directory_entry current_entry;
};
static_assert(std::is_same_v<std::decay_t<decltype(*std::declval<directory_iterator>())>,
directory_entry>);
static_assert(std::is_same_v<std::decay_t<decltype(*std::declval<directory_iterator>())>, directory_entry>);
inline directory_iterator begin(directory_iterator iter) noexcept
{
@ -790,6 +795,7 @@ namespace fs
class recursive_directory_iterator : private std::filesystem::recursive_directory_iterator
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = directory_entry;
using difference_type = std::ptrdiff_t;
@ -810,8 +816,10 @@ namespace fs
template <typename... OtherArgs>
explicit recursive_directory_iterator(const u8path& path, OtherArgs&&... args)
: std::filesystem::recursive_directory_iterator(path.std_path(),
std::forward<OtherArgs>(args)...)
: std::filesystem::recursive_directory_iterator(
path.std_path(),
std::forward<OtherArgs>(args)...
)
{
}
@ -840,22 +848,20 @@ namespace fs
bool operator==(const recursive_directory_iterator& other) const noexcept
{
return static_cast<const std::filesystem::recursive_directory_iterator&>(*this)
== other;
return static_cast<const std::filesystem::recursive_directory_iterator&>(*this) == other;
}
bool operator!=(const recursive_directory_iterator& other) const noexcept
{
return static_cast<const std::filesystem::recursive_directory_iterator&>(*this)
!= other;
return static_cast<const std::filesystem::recursive_directory_iterator&>(*this) != other;
}
private:
mutable directory_entry current_entry;
};
static_assert(std::is_same_v<std::decay_t<decltype(*std::declval<directory_iterator>())>,
directory_entry>);
static_assert(std::is_same_v<std::decay_t<decltype(*std::declval<directory_iterator>())>, directory_entry>);
inline recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept
{
@ -923,12 +929,9 @@ namespace fs
// const path& new_symlink,
// error_code& ec) noexcept;
template <typename... OtherArgs>
void copy_symlink(const u8path& existing_symlink,
const u8path& new_symlink,
OtherArgs&&... args)
void copy_symlink(const u8path& existing_symlink, const u8path& new_symlink, OtherArgs&&... args)
{
std::filesystem::copy_symlink(
existing_symlink, new_symlink, std::forward<OtherArgs>(args)...);
std::filesystem::copy_symlink(existing_symlink, new_symlink, std::forward<OtherArgs>(args)...);
}
// bool create_directories(const path& p);
@ -952,8 +955,7 @@ namespace fs
template <typename... OtherArgs>
bool create_directory(const u8path& path, const u8path& attributes, OtherArgs&&... args)
{
return std::filesystem::create_directory(
path, attributes, std::forward<OtherArgs>(args)...);
return std::filesystem::create_directory(path, attributes, std::forward<OtherArgs>(args)...);
}
@ -963,8 +965,7 @@ namespace fs
template <typename... OtherArgs>
void create_directory_symlink(const u8path& to, const u8path& new_symlink, OtherArgs&&... args)
{
std::filesystem::create_directory_symlink(
to, new_symlink, std::forward<OtherArgs>(args)...);
std::filesystem::create_directory_symlink(to, new_symlink, std::forward<OtherArgs>(args)...);
}
// void create_hard_link(const path& to, const path& new_hard_link);
@ -1279,13 +1280,17 @@ namespace fs
{
#if defined(WIN32) && _MSC_VER < 1930 // Workaround https://github.com/microsoft/STL/issues/1511
if (!fs::exists(path))
{
return 0;
}
uintmax_t counter = 0;
for (const auto& entry : fs::recursive_directory_iterator(path, args...))
{
if (fs::is_directory(entry.path())) // Skip directories, we'll delete them later.
if (fs::is_directory(entry.path()))
{ // Skip directories, we'll delete them later.
continue;
}
if (fs::remove(entry.path(), args...))
{
@ -1375,9 +1380,9 @@ struct std::hash<::fs::u8path>
{
std::size_t operator()(const ::fs::u8path& path) const noexcept
{
return std::filesystem::hash_value(
path.std_path()); // TODO: once we stop using gcc < 12 we can properly use
// std::hash<std::filesystem::path>{}(path.std_path());
return std::filesystem::hash_value(path.std_path()
); // TODO: once we stop using gcc < 12 we can properly use
// std::hash<std::filesystem::path>{}(path.std_path());
}
};
@ -1388,7 +1393,9 @@ struct fmt::formatter<::fs::u8path>
{
// make sure that range is empty
if (ctx.begin() != ctx.end() && *ctx.begin() != '}')
{
throw format_error("invalid format");
}
return ctx.begin();
}

View File

@ -16,6 +16,7 @@ namespace mamba
class MatchSpec
{
public:
MatchSpec() = default;
MatchSpec(const std::string& i_spec);

View File

@ -13,8 +13,8 @@
#include <string_view>
#include <vector>
#include <nlohmann/json.hpp>
#include <fmt/color.h>
#include <nlohmann/json.hpp>
#include "mamba/core/common_types.hpp"
#include "mamba/core/progress_bar.hpp"
@ -57,17 +57,19 @@ namespace mamba
class Table
{
public:
Table(const std::vector<FormattedString>& header);
void set_alignment(const std::vector<alignment>& a);
void set_padding(const std::vector<int>& p);
void add_row(const std::vector<FormattedString>& r);
void add_rows(const std::string& header,
const std::vector<std::vector<FormattedString>>& rs);
void
add_rows(const std::string& header, const std::vector<std::vector<FormattedString>>& rs);
std::ostream& print(std::ostream& out);
private:
std::vector<FormattedString> m_header;
std::vector<alignment> m_align;
std::vector<int> m_padding;
@ -82,6 +84,7 @@ namespace mamba
class ConsoleStream : public std::stringstream
{
public:
ConsoleStream() = default;
~ConsoleStream();
};
@ -92,6 +95,7 @@ namespace mamba
class Console
{
public:
Console(const Console&) = delete;
Console& operator=(const Console&) = delete;
@ -101,14 +105,12 @@ namespace mamba
static Console& instance();
static ConsoleStream stream();
static bool prompt(const std::string_view& message, char fallback = '_');
static bool prompt(const std::string_view& message,
char fallback,
std::istream& input_stream);
static bool
prompt(const std::string_view& message, char fallback, std::istream& input_stream);
ProgressProxy add_progress_bar(const std::string& name, size_t expected_total = 0);
void clear_progress_bars();
ProgressBarManager& init_progress_bar_manager(ProgressBarMode mode
= ProgressBarMode::multi);
ProgressBarManager& init_progress_bar_manager(ProgressBarMode mode = ProgressBarMode::multi);
void terminate_progress_bar_manager();
ProgressBarManager& progress_bar_manager();
@ -126,10 +128,12 @@ namespace mamba
void cancel_json_print();
protected:
Console();
~Console();
private:
void json_print();
void deactivate_progress_bar(std::size_t idx, const std::string_view& msg = "");
@ -141,6 +145,7 @@ namespace mamba
class MessageLogger
{
public:
MessageLogger(const char* file, int line, log_level level);
~MessageLogger();
@ -151,6 +156,7 @@ namespace mamba
static void print_buffer(std::ostream& ostream);
private:
std::string m_file;
int m_line;
log_level m_level;

View File

@ -30,6 +30,7 @@ namespace mamba
class PackageCacheData
{
public:
PackageCacheData(const fs::u8path& path);
bool create_directory();
@ -42,6 +43,7 @@ namespace mamba
bool has_valid_extracted_dir(const PackageInfo& s);
private:
void check_writable();
std::map<std::string, bool> m_valid_tarballs;
@ -53,6 +55,7 @@ namespace mamba
class MultiPackageCache
{
public:
MultiPackageCache(const std::vector<fs::u8path>& pkgs_dirs);
std::vector<fs::u8path> paths() const;
@ -67,6 +70,7 @@ namespace mamba
void clear_query_cache(const PackageInfo& s);
private:
std::vector<PackageCacheData> m_caches;
std::map<std::string, fs::u8path> m_cached_tarballs;
std::map<std::string, fs::u8path> m_cached_extracted_dirs;

View File

@ -23,28 +23,36 @@ namespace mamba
zstd
};
void create_archive(const fs::u8path& directory,
const fs::u8path& destination,
compression_algorithm,
int compression_level,
int compression_threads,
bool (*filter)(const fs::u8path&));
void create_package(const fs::u8path& directory,
const fs::u8path& out_file,
int compression_threads,
int compression_level);
void create_archive(
const fs::u8path& directory,
const fs::u8path& destination,
compression_algorithm,
int compression_level,
int compression_threads,
bool (*filter)(const fs::u8path&)
);
void create_package(
const fs::u8path& directory,
const fs::u8path& out_file,
int compression_threads,
int compression_level
);
void extract_archive(const fs::u8path& file, const fs::u8path& destination);
void extract_conda(const fs::u8path& file,
const fs::u8path& dest_dir,
const std::vector<std::string>& parts = { "info", "pkg" });
void extract_conda(
const fs::u8path& file,
const fs::u8path& dest_dir,
const std::vector<std::string>& parts = { "info", "pkg" }
);
void extract(const fs::u8path& file, const fs::u8path& destination);
fs::u8path extract(const fs::u8path& file);
void extract_subproc(const fs::u8path& file, const fs::u8path& dest);
bool transmute(const fs::u8path& pkg_file,
const fs::u8path& target,
int compression_level,
int compression_threads);
bool transmute(
const fs::u8path& pkg_file,
const fs::u8path& target,
int compression_level,
int compression_threads
);
bool validate(const fs::u8path& pkg_folder);
} // namespace mamba

View File

@ -15,9 +15,9 @@ extern "C"
#include <solv/solvable.h>
}
#include <set>
#include <string>
#include <vector>
#include <set>
#include "nlohmann/json.hpp"
@ -26,6 +26,7 @@ namespace mamba
class PackageInfo
{
public:
using field_getter = std::function<std::string(const PackageInfo&)>;
using compare_fun = std::function<bool(const PackageInfo&, const PackageInfo&)>;
@ -37,17 +38,19 @@ namespace mamba
PackageInfo(nlohmann::json&& j);
PackageInfo(const std::string& name);
PackageInfo(std::string&& name);
PackageInfo(const std::string& name,
const std::string& version,
const std::string build_string,
std::size_t build_number);
PackageInfo(
const std::string& name,
const std::string& version,
const std::string build_string,
std::size_t build_number
);
PackageInfo(PackageInfo const&) = default;
PackageInfo(const PackageInfo&) = default;
PackageInfo(PackageInfo&&) noexcept = default;
PackageInfo& operator=(PackageInfo const&) = default;
PackageInfo& operator=(const PackageInfo&) = default;
PackageInfo& operator=(PackageInfo&&) noexcept = default;
bool operator==(PackageInfo const& other) const;
bool operator==(const PackageInfo& other) const;
nlohmann::json json_record() const;
nlohmann::json json_signable() const;

View File

@ -7,10 +7,10 @@
#ifndef MAMBA_CORE_PINNING_HPP
#define MAMBA_CORE_PINNING_HPP
#include "prefix_data.hpp"
#include <vector>
#include <string>
#include <vector>
#include "prefix_data.hpp"
namespace mamba

View File

@ -7,13 +7,13 @@
#ifndef MAMBA_CORE_POOL_HPP
#define MAMBA_CORE_POOL_HPP
#include <optional>
#include <memory>
#include <optional>
#include <solv/pooltypes.h>
#include "mamba/core/repo.hpp"
#include "mamba/core/package_info.hpp"
#include "mamba/core/repo.hpp"
namespace mamba
{
@ -28,6 +28,7 @@ namespace mamba
class MPool
{
public:
MPool();
~MPool();
@ -40,16 +41,17 @@ namespace mamba
std::optional<PackageInfo> id2pkginfo(Id id);
operator Pool*();
operator Pool const*() const;
operator const Pool*() const;
MRepo& add_repo(MRepo&& repo);
void remove_repo(Id repo_id);
private:
struct MPoolData;
Pool* pool();
Pool const* pool() const;
const Pool* pool() const;
/**
* Make MPool behave like a shared_ptr (with move and copy).

View File

@ -7,8 +7,8 @@
#ifndef MAMBA_CORE_PREFIX_DATA_HPP
#define MAMBA_CORE_PREFIX_DATA_HPP
#include <string>
#include <map>
#include <string>
#include "error_handling.hpp"
#include "history.hpp"
@ -19,6 +19,7 @@ namespace mamba
class PrefixData
{
public:
using package_map = std::map<std::string, PackageInfo>;
static expected_t<PrefixData> create(const fs::u8path& prefix_path);
@ -32,6 +33,7 @@ namespace mamba
std::vector<PackageInfo> sorted_records() const;
private:
PrefixData(const fs::u8path& prefix_path);
void load();

View File

@ -7,8 +7,8 @@
#ifndef MAMBA_CORE_PROGRESS_BAR_HPP
#define MAMBA_CORE_PROGRESS_BAR_HPP
#include <cstddef>
#include <chrono>
#include <cstddef>
#include <functional>
#include <string>
@ -28,6 +28,7 @@ namespace mamba
class ProgressProxy
{
public:
ProgressProxy() = default;
ProgressProxy(ProgressBar* ptr);
~ProgressProxy() = default;
@ -57,8 +58,8 @@ namespace mamba
std::size_t in_progress() const;
std::size_t total() const;
std::size_t speed() const;
std::size_t avg_speed(const std::chrono::milliseconds& ref_duration
= std::chrono::milliseconds::max());
std::size_t
avg_speed(const std::chrono::milliseconds& ref_duration = std::chrono::milliseconds::max());
double progress() const;
bool completed() const;
@ -66,8 +67,8 @@ namespace mamba
ProgressProxy& set_postfix(const std::string& text);
ProgressProxy& set_repr_hook(std::function<void(ProgressBarRepr&)> f);
ProgressProxy& set_progress_hook(std::function<void(ProgressProxy&)> f);
ProgressProxy& mark_as_completed(const std::chrono::milliseconds& delay
= std::chrono::milliseconds::zero());
ProgressProxy&
mark_as_completed(const std::chrono::milliseconds& delay = std::chrono::milliseconds::zero());
std::string elapsed_time_to_str() const;
std::string prefix() const;
@ -87,6 +88,7 @@ namespace mamba
int width() const;
private:
ProgressBar* p_bar = nullptr;
friend class ProgressBarManager;

View File

@ -11,9 +11,9 @@
#include <string>
#include <vector>
#include "mamba/core/util_graph.hpp"
#include "mamba/core/package_info.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/util_graph.hpp"
extern "C"
{
@ -26,19 +26,22 @@ extern "C"
namespace mamba
{
void print_dep_graph(std::ostream& out,
Solvable* s,
const std::string& solv_str,
int level,
int max_level,
bool last,
const std::string& prefix);
void print_dep_graph(
std::ostream& out,
Solvable* s,
const std::string& solv_str,
int level,
int max_level,
bool last,
const std::string& prefix
);
class query_result;
class Query
{
public:
Query(MPool& pool);
query_result find(const std::string& query) const;
@ -46,6 +49,7 @@ namespace mamba
query_result depends(const std::string& query, bool tree) const;
private:
std::reference_wrapper<MPool> m_pool;
};
@ -68,6 +72,7 @@ namespace mamba
class query_result
{
public:
using dependency_graph = DiGraph<PackageInfo>;
using package_list = dependency_graph::node_list;
using package_view_list = std::vector<package_list::const_iterator>;
@ -96,6 +101,7 @@ namespace mamba
std::ostream& pretty(std::ostream&) const;
private:
void reset_pkg_view_list();
std::string get_package_repr(const PackageInfo& pkg) const;

View File

@ -19,13 +19,16 @@ namespace mamba
class MQueue
{
public:
MQueue()
: p_queue(new Queue)
{
queue_init(p_queue);
if (!p_queue)
{
throw std::runtime_error("libsolv error: could not initialize Queue");
}
}
~MQueue()
@ -95,6 +98,7 @@ namespace mamba
}
private:
Queue* p_queue;
};
} // namespace mamba

View File

@ -52,6 +52,7 @@ namespace mamba
class MRepo
{
public:
~MRepo();
MRepo(const MRepo&) = delete;
@ -85,10 +86,8 @@ namespace mamba
* @param filename Name of the index file
* @param url Subdirectory URL
*/
static MRepo& create(MPool& pool,
const std::string& name,
const std::string& filename,
const std::string& url);
static MRepo&
create(MPool& pool, const std::string& name, const std::string& filename, const std::string& url);
/**
* Static constructor.
@ -98,11 +97,13 @@ namespace mamba
* @param meta Metadata of the repo
* @param channel Channel of the repo
*/
static MRepo& create(MPool& pool,
const std::string& name,
const fs::u8path& filename,
const RepoMetadata& meta,
const Channel& channel);
static MRepo& create(
MPool& pool,
const std::string& name,
const fs::u8path& filename,
const RepoMetadata& meta,
const Channel& channel
);
/**
* Static constructor.
@ -117,21 +118,20 @@ namespace mamba
* @param name Name
* @param uris Matchspecs pointing to unique resources (URL or files)
*/
static MRepo& create(MPool& pool,
const std::string& name,
const std::vector<PackageInfo>& uris);
static MRepo&
create(MPool& pool, const std::string& name, const std::vector<PackageInfo>& uris);
private:
MRepo(MPool& pool,
const std::string& name,
const std::string& filename,
const std::string& url);
MRepo(MPool& pool,
const std::string& name,
const fs::u8path& filename,
const RepoMetadata& meta,
const Channel& channel);
MRepo(MPool& pool, const std::string& name, const std::string& filename, const std::string& url);
MRepo(
MPool& pool,
const std::string& name,
const fs::u8path& filename,
const RepoMetadata& meta,
const Channel& channel
);
MRepo(MPool& pool, const PrefixData& prefix_data);

View File

@ -1,5 +1,6 @@
#include <string>
#include <string_view>
#include <nlohmann/json.hpp>
#include "mamba/core/mamba_fs.hpp"
@ -18,9 +19,12 @@ namespace mamba
const fs::u8path location;
public:
ScopedProcFile(const std::string& name,
const std::vector<std::string>& command,
LockFile proc_dir_lock = lock_proc_dir());
ScopedProcFile(
const std::string& name,
const std::vector<std::string>& command,
LockFile proc_dir_lock = lock_proc_dir()
);
~ScopedProcFile();
};
@ -32,16 +36,19 @@ namespace mamba
SINKIN = 1 << 2,
};
int run_in_environment(std::vector<std::string> command,
const std::string& cwd,
int stream_options,
bool clean_env,
bool detach,
const std::vector<std::string>& env_vars,
const std::string& specific_process_name);
int run_in_environment(
std::vector<std::string> command,
const std::string& cwd,
int stream_options,
bool clean_env,
bool detach,
const std::vector<std::string>& env_vars,
const std::string& specific_process_name
);
nlohmann::json get_all_running_processes_info(
const std::function<bool(const nlohmann::json&)>& filter
= std::function<bool(const nlohmann::json&)>());
const std::function<bool(const nlohmann::json&)>& filter = std::function<
bool(const nlohmann::json&)>()
);
bool is_process_name_running(const std::string& name);
}

View File

@ -8,21 +8,21 @@
#define MAMBA_PROBLEMS_GRAPH_HPP
#include <array>
#include <string>
#include <functional>
#include <optional>
#include <ostream>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <variant>
#include <unordered_map>
#include <optional>
#include <vector>
#include <functional>
#include <solv/solver.h>
#include <fmt/color.h>
#include <solv/solver.h>
#include "mamba/core/util_graph.hpp"
#include "mamba/core/package_info.hpp"
#include "mamba/core/util_graph.hpp"
namespace mamba
{
@ -36,11 +36,12 @@ namespace mamba
class DependencyInfo
{
public:
DependencyInfo(const std::string& dependency);
DependencyInfo(DependencyInfo const&) = default;
DependencyInfo(const DependencyInfo&) = default;
DependencyInfo(DependencyInfo&&) noexcept = default;
DependencyInfo& operator=(DependencyInfo const&) = default;
DependencyInfo& operator=(const DependencyInfo&) = default;
DependencyInfo& operator=(DependencyInfo&&) noexcept = default;
const std::string& name() const;
@ -48,9 +49,10 @@ namespace mamba
const std::string& build_string() const;
std::string str() const;
bool operator==(DependencyInfo const& other) const;
bool operator==(const DependencyInfo& other) const;
private:
std::string m_name;
std::string m_version_range;
std::string m_build_range;
@ -60,6 +62,7 @@ namespace mamba
class conflict_map : private std::unordered_map<T, vector_set<T>>
{
public:
using Base = std::unordered_map<T, vector_set<T>>;
using typename Base::const_iterator;
using typename Base::key_type;
@ -69,9 +72,9 @@ namespace mamba
using Base::empty;
using Base::size;
bool has_conflict(key_type const& a) const;
auto conflicts(key_type const& a) const -> vector_set<T> const&;
bool in_conflict(key_type const& a, key_type const& b) const;
bool has_conflict(const key_type& a) const;
auto conflicts(const key_type& a) const -> const vector_set<T>&;
bool in_conflict(const key_type& a, const key_type& b) const;
using Base::cbegin;
using Base::cend;
@ -79,7 +82,7 @@ namespace mamba
const_iterator end() const noexcept;
using Base::clear;
void add(key_type const& a, key_type const& b);
void add(const key_type& a, const key_type& b);
};
/**
@ -88,6 +91,7 @@ namespace mamba
class ProblemsGraph
{
public:
struct RootNode
{
};
@ -95,31 +99,30 @@ namespace mamba
{
std::optional<SolverRuleinfo> problem_type;
PackageNode(PackageNode const&) = default;
PackageNode(const PackageNode&) = default;
PackageNode(PackageNode&&) noexcept = default;
PackageNode& operator=(PackageNode const&) = default;
PackageNode& operator=(const PackageNode&) = default;
PackageNode& operator=(PackageNode&&) noexcept = default;
};
struct UnresolvedDependencyNode : DependencyInfo
{
SolverRuleinfo problem_type;
UnresolvedDependencyNode(UnresolvedDependencyNode const&) = default;
UnresolvedDependencyNode(const UnresolvedDependencyNode&) = default;
UnresolvedDependencyNode(UnresolvedDependencyNode&&) noexcept = default;
UnresolvedDependencyNode& operator=(UnresolvedDependencyNode const&) = default;
UnresolvedDependencyNode& operator=(const UnresolvedDependencyNode&) = default;
UnresolvedDependencyNode& operator=(UnresolvedDependencyNode&&) noexcept = default;
};
struct ConstraintNode : DependencyInfo
{
static SolverRuleinfo constexpr problem_type = SOLVER_RULE_PKG_CONSTRAINS;
static constexpr SolverRuleinfo problem_type = SOLVER_RULE_PKG_CONSTRAINS;
ConstraintNode(ConstraintNode const&) = default;
ConstraintNode(const ConstraintNode&) = default;
ConstraintNode(ConstraintNode&&) noexcept = default;
ConstraintNode& operator=(ConstraintNode const&) = default;
ConstraintNode& operator=(const ConstraintNode&) = default;
ConstraintNode& operator=(ConstraintNode&&) noexcept = default;
};
using node_t
= std::variant<RootNode, PackageNode, UnresolvedDependencyNode, ConstraintNode>;
using node_t = std::variant<RootNode, PackageNode, UnresolvedDependencyNode, ConstraintNode>;
using edge_t = DependencyInfo;
@ -127,15 +130,16 @@ namespace mamba
using node_id = graph_t::node_id;
using conflicts_t = conflict_map<node_id>;
static ProblemsGraph from_solver(MSolver const& solver, MPool const& pool);
static ProblemsGraph from_solver(const MSolver& solver, const MPool& pool);
ProblemsGraph(graph_t graph, conflicts_t conflicts, node_id root_node);
graph_t const& graph() const noexcept;
conflicts_t const& conflicts() const noexcept;
const graph_t& graph() const noexcept;
const conflicts_t& conflicts() const noexcept;
node_id root_node() const noexcept;
private:
graph_t m_graph;
conflicts_t m_conflicts;
node_id m_root_node;
@ -144,6 +148,7 @@ namespace mamba
class CompressedProblemsGraph
{
public:
using RootNode = ProblemsGraph::RootNode;
/**
@ -159,7 +164,7 @@ namespace mamba
template <typename T>
struct RoughCompare
{
bool operator()(T const& a, T const& b);
bool operator()(const T& a, const T& b);
};
/**
@ -172,6 +177,7 @@ namespace mamba
class NamedList : private vector_set<T, RoughCompare<T>, Allocator>
{
public:
using Base = vector_set<T, RoughCompare<T>, Allocator>;
using typename Base::allocator_type;
using typename Base::const_iterator;
@ -184,8 +190,8 @@ namespace mamba
using Base::empty;
using Base::size;
value_type const& front() const noexcept;
value_type const& back() const noexcept;
const value_type& front() const noexcept;
const value_type& back() const noexcept;
using Base::cbegin;
using Base::cend;
using Base::crbegin;
@ -195,30 +201,35 @@ namespace mamba
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
std::string const& name() const;
std::pair<std::string, std::size_t> versions_trunc(std::string_view sep = "|",
std::string_view etc = "...",
std::size_t threshold = 5,
bool remove_duplicates = true) const;
std::pair<std::string, std::size_t> build_strings_trunc(std::string_view sep = "|",
std::string_view etc = "...",
std::size_t threshold = 5,
bool remove_duplicates
= true) const;
const std::string& name() const;
std::pair<std::string, std::size_t> versions_trunc(
std::string_view sep = "|",
std::string_view etc = "...",
std::size_t threshold = 5,
bool remove_duplicates = true
) const;
std::pair<std::string, std::size_t> build_strings_trunc(
std::string_view sep = "|",
std::string_view etc = "...",
std::size_t threshold = 5,
bool remove_duplicates = true
) const;
std::pair<std::string, std::size_t> versions_and_build_strings_trunc(
std::string_view sep = "|",
std::string_view etc = "...",
std::size_t threshold = 5,
bool remove_duplicates = true) const;
bool remove_duplicates = true
) const;
using Base::clear;
using Base::reserve;
void insert(value_type const& e);
void insert(const value_type& e);
void insert(value_type&& e);
template <typename InputIterator>
void insert(InputIterator first, InputIterator last);
private:
template <typename T_>
void insert_impl(T_&& e);
};
@ -226,10 +237,11 @@ namespace mamba
using PackageListNode = NamedList<ProblemsGraph::PackageNode>;
using UnresolvedDependencyListNode = NamedList<ProblemsGraph::UnresolvedDependencyNode>;
using ConstraintListNode = NamedList<ProblemsGraph::ConstraintNode>;
using node_t = std::variant<RootNode, //
PackageListNode,
UnresolvedDependencyListNode,
ConstraintListNode>;
using node_t = std::variant<
RootNode, //
PackageListNode,
UnresolvedDependencyListNode,
ConstraintListNode>;
using edge_t = NamedList<DependencyInfo>;
@ -237,20 +249,21 @@ namespace mamba
using node_id = graph_t::node_id;
using conflicts_t = conflict_map<node_id>;
using merge_criteria_t = std::function<bool(
ProblemsGraph const&, ProblemsGraph::node_id, ProblemsGraph::node_id)>;
using merge_criteria_t = std::function<
bool(const ProblemsGraph&, ProblemsGraph::node_id, ProblemsGraph::node_id)>;
static auto from_problems_graph(ProblemsGraph const& pbs,
merge_criteria_t const& merge_criteria = {})
static auto
from_problems_graph(const ProblemsGraph& pbs, const merge_criteria_t& merge_criteria = {})
-> CompressedProblemsGraph;
CompressedProblemsGraph(graph_t graph, conflicts_t conflicts, node_id root_node);
graph_t const& graph() const noexcept;
conflicts_t const& conflicts() const noexcept;
const graph_t& graph() const noexcept;
const conflicts_t& conflicts() const noexcept;
node_id root_node() const noexcept;
private:
graph_t m_graph;
conflicts_t m_conflicts;
node_id m_root_node;
@ -266,33 +279,35 @@ namespace mamba
std::array<std::string_view, 4> indents = { "", " ", "├─ ", "└─ " };
};
std::ostream& print_problem_summary_msg(std::ostream& out, CompressedProblemsGraph const& pbs);
std::string problem_summary_msg(CompressedProblemsGraph const& pbs);
std::ostream& print_problem_summary_msg(std::ostream& out, const CompressedProblemsGraph& pbs);
std::string problem_summary_msg(const CompressedProblemsGraph& pbs);
std::ostream& print_problem_tree_msg(std::ostream& out,
CompressedProblemsGraph const& pbs,
ProblemsMessageFormat const& format = {});
std::string problem_tree_msg(CompressedProblemsGraph const& pbs,
ProblemsMessageFormat const& format = {});
std::ostream& print_problem_tree_msg(
std::ostream& out,
const CompressedProblemsGraph& pbs,
const ProblemsMessageFormat& format = {}
);
std::string
problem_tree_msg(const CompressedProblemsGraph& pbs, const ProblemsMessageFormat& format = {});
/************************************
* Implementation of conflict_map *
************************************/
template <typename T>
bool conflict_map<T>::has_conflict(key_type const& a) const
bool conflict_map<T>::has_conflict(const key_type& a) const
{
return Base::find(a) != end();
}
template <typename T>
auto conflict_map<T>::conflicts(key_type const& a) const -> vector_set<T> const&
auto conflict_map<T>::conflicts(const key_type& a) const -> const vector_set<T>&
{
return Base::at(a);
}
template <typename T>
bool conflict_map<T>::in_conflict(key_type const& a, key_type const& b) const
bool conflict_map<T>::in_conflict(const key_type& a, const key_type& b) const
{
return has_conflict(a) && Base::at(a).contains(b);
}
@ -310,7 +325,7 @@ namespace mamba
}
template <typename T>
void conflict_map<T>::add(key_type const& a, key_type const& b)
void conflict_map<T>::add(const key_type& a, const key_type& b)
{
Base::operator[](a).insert(b);
Base::operator[](b).insert(a);

View File

@ -37,22 +37,21 @@ namespace mamba
// this function calls cygpath to convert win path to unix
std::string native_path_to_unix(const std::string& path, bool is_a_path_env = false);
std::string rcfile_content(const fs::u8path& env_prefix,
const std::string& shell,
const fs::u8path& mamba_exe);
std::string
rcfile_content(const fs::u8path& env_prefix, const std::string& shell, const fs::u8path& mamba_exe);
std::string xonsh_content(const fs::u8path& env_prefix,
const std::string& shell,
const fs::u8path& mamba_exe);
std::string
xonsh_content(const fs::u8path& env_prefix, const std::string& shell, const fs::u8path& mamba_exe);
void modify_rc_file(const fs::u8path& file_path,
const fs::u8path& conda_prefix,
const std::string& shell,
const fs::u8path& mamba_exe);
void modify_rc_file(
const fs::u8path& file_path,
const fs::u8path& conda_prefix,
const std::string& shell,
const fs::u8path& mamba_exe
);
void reset_rc_file(const fs::u8path& file_path,
const std::string& shell,
const fs::u8path& mamba_exe);
void
reset_rc_file(const fs::u8path& file_path, const std::string& shell, const fs::u8path& mamba_exe);
// we need this function during linking...
void init_root_prefix_cmdexe(const fs::u8path& root_prefix);

View File

@ -7,18 +7,18 @@
#ifndef MAMBA_CORE_SOLVER_HPP
#define MAMBA_CORE_SOLVER_HPP
#include <string>
#include <iosfwd>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <optional>
#include <memory>
#include <solv/queue.h>
#include <solv/solver.h>
#include "mamba/core/pool.hpp"
#include "mamba/core/package_info.hpp"
#include "mamba/core/pool.hpp"
#include "match_spec.hpp"
@ -29,7 +29,7 @@
namespace mamba
{
char const* solver_ruleinfo_name(SolverRuleinfo rule);
const char* solver_ruleinfo_name(SolverRuleinfo rule);
struct MSolverProblem
{
@ -46,6 +46,7 @@ namespace mamba
class MSolver
{
public:
MSolver(MPool pool, std::vector<std::pair<int, int>> flags = {});
~MSolver() = default;
@ -72,7 +73,7 @@ namespace mamba
std::ostream& explain_problems(std::ostream& out) const;
[[nodiscard]] std::string explain_problems() const;
[[nodiscard]] MPool const& pool() const&;
[[nodiscard]] const MPool& pool() const&;
[[nodiscard]] MPool& pool() &;
[[nodiscard]] MPool&& pool() &&;
@ -89,6 +90,7 @@ namespace mamba
bool force_reinstall = false;
private:
void add_channel_specific_job(const MatchSpec& ms, int job_flag);
void add_reinstall_job(MatchSpec& ms, int job_flag);

View File

@ -20,6 +20,7 @@
#include "mamba/core/pool.hpp"
#include "mamba/core/repo.hpp"
#include "mamba/core/util.hpp"
#include "package_handling.hpp"
namespace decompress
@ -77,11 +78,14 @@ namespace mamba
class MSubdirData
{
public:
static expected_t<MSubdirData> create(const Channel& channel,
const std::string& platform,
const std::string& url,
MultiPackageCache& caches,
const std::string& repodata_fn = "repodata.json");
static expected_t<MSubdirData> create(
const Channel& channel,
const std::string& platform,
const std::string& url,
MultiPackageCache& caches,
const std::string& repodata_fn = "repodata.json"
);
~MSubdirData() = default;
@ -92,8 +96,8 @@ namespace mamba
MSubdirData& operator=(MSubdirData&&);
// TODO return seconds as double
fs::file_time_type::duration check_cache(
const fs::u8path& cache_file, const fs::file_time_type::clock::time_point& ref) const;
fs::file_time_type::duration
check_cache(const fs::u8path& cache_file, const fs::file_time_type::clock::time_point& ref) const;
bool loaded() const;
bool forbid_cache();
@ -111,11 +115,14 @@ namespace mamba
expected_t<MRepo&> create_repo(MPool& pool);
private:
MSubdirData(const Channel& channel,
const std::string& platform,
const std::string& url,
MultiPackageCache& caches,
const std::string& repodata_fn = "repodata.json");
MSubdirData(
const Channel& channel,
const std::string& platform,
const std::string& url,
MultiPackageCache& caches,
const std::string& repodata_fn = "repodata.json"
);
bool load(MultiPackageCache& caches);
void check_repodata_existence();

View File

@ -6,12 +6,12 @@
#pragma once
#include <cassert>
#include <atomic>
#include <mutex>
#include <memory>
#include <functional>
#include <cassert>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include "mamba/core/util_scope.hpp"
@ -75,6 +75,7 @@ namespace mamba
}
public:
TaskSynchronizer() = default;
/** Destructor, joining tasks synchronized with this object.
@ -114,10 +115,9 @@ namespace mamba
{
// If status is alive then we know the TaskSynchronizer is alive too.
auto status = remote_status.lock();
if (status
&& !status
->join_requested) // Don't add running tasks while join was requested.
{ // We can use 'this' safely in this scope.
if (status && !status->join_requested) // Don't add running tasks while join was
// requested.
{ // We can use 'this' safely in this scope.
notify_begin_execution();
on_scope_exit _{ [&, this]
{
@ -175,6 +175,7 @@ namespace mamba
}
private:
struct Status
{
std::atomic<bool> join_requested{ false };
@ -204,7 +205,9 @@ namespace mamba
void wait_all_running_tasks()
{
if (!m_status)
{
return;
}
std::unique_lock exit_lock{ m_mutex };
@ -213,7 +216,9 @@ namespace mamba
m_status.reset();
m_task_end_condition.wait(
exit_lock, [&] { return m_running_tasks == 0 && remote_status.expired(); });
exit_lock,
[&] { return m_running_tasks == 0 && remote_status.expired(); }
);
}
};

View File

@ -40,6 +40,7 @@ namespace mamba
class thread_interrupted : public std::exception
{
public:
thread_interrupted() = default;
const char* what() const throw()
{
@ -71,6 +72,7 @@ namespace mamba
class thread
{
public:
thread() = default;
~thread() = default;
@ -96,6 +98,7 @@ namespace mamba
}
private:
std::thread m_thread;
};
@ -116,7 +119,8 @@ namespace mamba
errno = EINTR;
}
decrease_thread_count();
});
}
);
}
/**********************
@ -126,6 +130,7 @@ namespace mamba
class interruption_guard
{
public:
template <class Function, class... Args>
interruption_guard(Function&& func, Args&&... args);
~interruption_guard();
@ -137,6 +142,7 @@ namespace mamba
interruption_guard& operator=(interruption_guard&&) = delete;
private:
static std::function<void()> m_cleanup_function;
};
@ -149,6 +155,7 @@ namespace mamba
class counting_semaphore
{
public:
inline counting_semaphore(std::ptrdiff_t max = 0);
inline void lock();
inline void unlock();
@ -156,6 +163,7 @@ namespace mamba
inline void set_max(std::ptrdiff_t value);
private:
std::ptrdiff_t m_value, m_max;
std::mutex m_access_mutex;
std::condition_variable m_cv;
@ -199,11 +207,17 @@ namespace mamba
{
std::ptrdiff_t new_max;
if (value == 0)
{
new_max = std::thread::hardware_concurrency();
}
else if (value < 0)
{
new_max = std::thread::hardware_concurrency() + value;
}
else
{
new_max = value;
}
m_value += new_max - m_max;
m_max = new_max;

View File

@ -14,8 +14,11 @@
#include <tuple>
#include <vector>
#include "mamba/api/install.hpp"
#include "nlohmann/json.hpp"
#include "env_lockfile.hpp"
#include "fetch.hpp"
#include "mamba_fs.hpp"
#include "match_spec.hpp"
@ -26,8 +29,6 @@
#include "repo.hpp"
#include "thread_utils.hpp"
#include "transaction_context.hpp"
#include "env_lockfile.hpp"
#include "mamba/api/install.hpp"
extern "C"
{
@ -45,6 +46,7 @@ namespace mamba
class PackageDownloadExtractTarget
{
public:
PackageDownloadExtractTarget(Solvable* solvable);
PackageDownloadExtractTarget(const PackageInfo& pkg_info);
@ -76,6 +78,7 @@ namespace mamba
std::exception m_decompress_exception;
private:
bool m_finished;
PackageInfo m_package_info;
@ -100,10 +103,12 @@ namespace mamba
class DownloadExtractSemaphore
{
public:
static std::ptrdiff_t get_max();
static void set_max(int value);
private:
static counting_semaphore semaphore;
friend class PackageDownloadExtractTarget;
@ -112,6 +117,7 @@ namespace mamba
class MTransaction
{
public:
enum class FilterType
{
none,
@ -119,16 +125,16 @@ namespace mamba
ignore
};
MTransaction(MPool& pool,
const std::vector<MatchSpec>& specs_to_remove,
const std::vector<MatchSpec>& specs_to_install,
MultiPackageCache& caches);
MTransaction(
MPool& pool,
const std::vector<MatchSpec>& specs_to_remove,
const std::vector<MatchSpec>& specs_to_install,
MultiPackageCache& caches
);
MTransaction(MSolver& solver, MultiPackageCache& caches);
// Only use if the packages have been solved previously already.
MTransaction(MPool& pool,
const std::vector<PackageInfo>& packages,
MultiPackageCache& caches);
MTransaction(MPool& pool, const std::vector<PackageInfo>& packages, MultiPackageCache& caches);
~MTransaction();
@ -155,6 +161,7 @@ namespace mamba
std::pair<std::string, std::string> find_python_version();
private:
FilterType m_filter_type = FilterType::none;
std::set<Id> m_filter_name_ids;
@ -175,14 +182,16 @@ namespace mamba
MPool& pool,
const std::vector<std::string>& urls,
MultiPackageCache& package_caches,
std::vector<detail::other_pkg_mgr_spec>& other_specs);
std::vector<detail::other_pkg_mgr_spec>& other_specs
);
MTransaction create_explicit_transaction_from_lockfile(
MPool& pool,
const fs::u8path& env_lockfile_path,
const std::vector<std::string>& categories,
MultiPackageCache& package_caches,
std::vector<detail::other_pkg_mgr_spec>& other_specs);
std::vector<detail::other_pkg_mgr_spec>& other_specs
);
} // namespace mamba
#endif // MAMBA_TRANSACTION_HPP

View File

@ -23,17 +23,22 @@ namespace mamba
fs::u8path get_python_short_path(const std::string& python_version);
fs::u8path get_python_site_packages_short_path(const std::string& python_version);
fs::u8path get_bin_directory_short_path();
fs::u8path get_python_noarch_target_path(const std::string& source_short_path,
const fs::u8path& target_site_packages_short_path);
fs::u8path get_python_noarch_target_path(
const std::string& source_short_path,
const fs::u8path& target_site_packages_short_path
);
class TransactionContext
{
public:
TransactionContext();
TransactionContext& operator=(const TransactionContext&);
TransactionContext(const fs::u8path& target_prefix,
const std::pair<std::string, std::string>& py_versions,
const std::vector<MatchSpec>& requested_specs);
TransactionContext(
const fs::u8path& target_prefix,
const std::pair<std::string, std::string>& py_versions,
const std::vector<MatchSpec>& requested_specs
);
~TransactionContext();
bool try_pyc_compilation(const std::vector<fs::u8path>& py_files);
void wait_for_pyc_compilation();
@ -54,6 +59,7 @@ namespace mamba
std::vector<MatchSpec> requested_specs;
private:
bool start_pyc_compilation_process();
std::unique_ptr<reproc::process> m_pyc_process = nullptr;

View File

@ -45,11 +45,13 @@ namespace mamba
void split_anaconda_token(const std::string& url, std::string& cleaned_url, std::string& token);
void split_scheme_auth_token(const std::string& url,
std::string& remaining_url,
std::string& scheme,
std::string& auth,
std::string& token);
void split_scheme_auth_token(
const std::string& url,
std::string& remaining_url,
std::string& scheme,
std::string& auth,
std::string& token
);
bool compare_cleaned_url(const std::string& url1, const std::string& url2);
@ -69,6 +71,7 @@ namespace mamba
class URLHandler
{
public:
URLHandler(const std::string& url = "");
~URLHandler();
@ -108,6 +111,7 @@ namespace mamba
URLHandler& set_zoneid(const std::string& zoneid);
private:
std::string get_part(CURLUPart part);
void set_part(CURLUPart part, const std::string& s);

View File

@ -7,23 +7,24 @@
#ifndef MAMBA_CORE_UTIL_HPP
#define MAMBA_CORE_UTIL_HPP
#include "mamba/core/mamba_fs.hpp"
#include <array>
#include <chrono>
#include <limits>
#include <optional>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#include <time.h>
#include "mamba/core/error_handling.hpp"
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/util_string.hpp"
#include "nlohmann/json.hpp"
#include "tl/expected.hpp"
#include <array>
#include <limits>
#include <sstream>
#include <string>
#include <string_view>
#include <time.h>
#include <vector>
#include <chrono>
#include <optional>
#if defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64)
#include <iomanip>
#endif
@ -63,20 +64,22 @@ namespace mamba
std::vector<fs::u8path> filter_dir(const fs::u8path& dir, const std::string& suffix);
bool paths_equal(const fs::u8path& lhs, const fs::u8path& rhs);
std::string read_contents(const fs::u8path& path,
std::ios::openmode mode = std::ios::in | std::ios::binary);
std::string
read_contents(const fs::u8path& path, std::ios::openmode mode = std::ios::in | std::ios::binary);
std::vector<std::string> read_lines(const fs::u8path& path);
inline void make_executable(const fs::u8path& p)
{
fs::permissions(p,
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_read
| fs::perms::others_exec);
fs::permissions(
p,
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_read | fs::perms::others_exec
);
}
class TemporaryDirectory
{
public:
TemporaryDirectory();
~TemporaryDirectory();
@ -88,15 +91,19 @@ namespace mamba
operator fs::u8path();
private:
fs::u8path m_path;
};
class TemporaryFile
{
public:
TemporaryFile(const std::string& prefix = "mambaf",
const std::string& suffix = "",
const std::optional<fs::u8path>& dir = std::nullopt);
TemporaryFile(
const std::string& prefix = "mambaf",
const std::string& suffix = "",
const std::optional<fs::u8path>& dir = std::nullopt
);
~TemporaryFile();
TemporaryFile(const TemporaryFile&) = delete;
@ -107,6 +114,7 @@ namespace mamba
operator fs::u8path();
private:
fs::u8path m_path;
};
@ -160,6 +168,7 @@ namespace mamba
class LockFile
{
public:
// Non-throwing constructors, attempting lock on the provided path, file or directory.
// In case of a directory, a lock-file will be created, located at `this->lockfile_path()`
// and `this->is_locked()` (and `if(*this))` will always return true (unless this instance
@ -232,19 +241,22 @@ namespace mamba
std::optional<mamba_error> error() const
{
if (impl.has_value())
{
return {};
}
else
{
return impl.error();
}
}
private:
tl::expected<std::shared_ptr<LockFileOwner>, mamba_error> impl;
};
void split_package_extension(const std::string& file,
std::string& name,
std::string& extension);
void split_package_extension(const std::string& file, std::string& name, std::string& extension);
fs::u8path strip_package_extension(const std::string& file);
template <class T>
@ -264,13 +276,17 @@ namespace mamba
void assign_or(const nlohmann::json& j, const char* key, T& target, T default_value)
{
if (j.contains(key))
{
target = j[key];
}
else
{
target = default_value;
}
}
std::string quote_for_shell(const std::vector<std::string>& arguments,
const std::string& shell = "");
std::string
quote_for_shell(const std::vector<std::string>& arguments, const std::string& shell = "");
std::size_t clean_trash_files(const fs::u8path& prefix, bool deep_clean);
std::size_t remove_or_rename(const fs::u8path& path);
@ -292,21 +308,23 @@ namespace mamba
std::time_t parse_utc_timestamp(const std::string& timestamp);
std::ofstream open_ofstream(const fs::u8path& path,
std::ios::openmode mode = std::ios::out | std::ios::binary);
std::ofstream
open_ofstream(const fs::u8path& path, std::ios::openmode mode = std::ios::out | std::ios::binary);
std::ifstream open_ifstream(const fs::u8path& path,
std::ios::openmode mode = std::ios::in | std::ios::binary);
std::ifstream
open_ifstream(const fs::u8path& path, std::ios::openmode mode = std::ios::in | std::ios::binary);
bool ensure_comspec_set();
std::unique_ptr<TemporaryFile> wrap_call(const fs::u8path& root_prefix,
const fs::u8path& prefix,
bool dev_mode,
bool debug_wrapper_scripts,
const std::vector<std::string>& arguments);
std::unique_ptr<TemporaryFile> wrap_call(
const fs::u8path& root_prefix,
const fs::u8path& prefix,
bool dev_mode,
bool debug_wrapper_scripts,
const std::vector<std::string>& arguments
);
std::tuple<std::vector<std::string>, std::unique_ptr<TemporaryFile>> prepare_wrapped_call(
const fs::u8path& prefix, const std::vector<std::string>& cmd);
std::tuple<std::vector<std::string>, std::unique_ptr<TemporaryFile>>
prepare_wrapped_call(const fs::u8path& prefix, const std::vector<std::string>& cmd);
/// Returns `true` if the filename matches names of files which should be interpreted as YAML.
/// NOTE: this does not check if the file exists.
@ -320,11 +338,13 @@ namespace mamba
class non_copyable_base
{
public:
non_copyable_base()
{
}
private:
non_copyable_base(const non_copyable_base&);
non_copyable_base& operator=(const non_copyable_base&);
};

View File

@ -8,11 +8,11 @@
#define MAMBA_CORE_GRAPH_UTIL_HPP
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <functional>
#include <iterator>
#include <map>
#include <utility>
#include <vector>
namespace mamba
{
@ -20,12 +20,11 @@ namespace mamba
/**
* A sorted vector behaving like a set.
*/
template <typename Key,
typename Compare = std::less<Key>,
typename Allocator = std::allocator<Key>>
template <typename Key, typename Compare = std::less<Key>, typename Allocator = std::allocator<Key>>
class vector_set : private std::vector<Key, Allocator>
{
public:
using Base = std::vector<Key, Allocator>;
using typename Base::allocator_type;
using typename Base::const_iterator;
@ -45,27 +44,29 @@ namespace mamba
using Base::size;
vector_set() = default;
vector_set(std::initializer_list<value_type> il,
key_compare compare = key_compare(),
allocator_type const& alloc = allocator_type());
vector_set(
std::initializer_list<value_type> il,
key_compare compare = key_compare(),
const allocator_type& alloc = allocator_type()
);
template <typename InputIterator>
vector_set(InputIterator first,
InputIterator last,
key_compare compare = key_compare(),
allocator_type const& alloc = Allocator());
vector_set(vector_set const&) = default;
vector_set(
InputIterator first,
InputIterator last,
key_compare compare = key_compare(),
const allocator_type& alloc = Allocator()
);
vector_set(const vector_set&) = default;
vector_set(vector_set&&) = default;
explicit vector_set(std::vector<Key, Allocator>&& other,
key_compare compare = key_compare());
explicit vector_set(std::vector<Key, Allocator> const& other,
key_compare compare = key_compare());
explicit vector_set(std::vector<Key, Allocator>&& other, key_compare compare = key_compare());
explicit vector_set(const std::vector<Key, Allocator>& other, key_compare compare = key_compare());
vector_set& operator=(vector_set const&) = default;
vector_set& operator=(const vector_set&) = default;
vector_set& operator=(vector_set&&) = default;
bool contains(value_type const&) const;
value_type const& front() const noexcept;
value_type const& back() const noexcept;
bool contains(const value_type&) const;
const value_type& front() const noexcept;
const value_type& back() const noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
@ -77,11 +78,12 @@ namespace mamba
* Like std::vector and unlike std::set, inserting an element invalidates iterators.
*/
std::pair<const_iterator, bool> insert(value_type&& value);
std::pair<const_iterator, bool> insert(value_type const& value);
std::pair<const_iterator, bool> insert(const value_type& value);
template <typename InputIterator>
void insert(InputIterator first, InputIterator last);
private:
key_compare m_compare;
template <typename U>
@ -89,16 +91,17 @@ namespace mamba
void sort_and_remove_duplicates();
template <typename K, typename C, typename A>
friend bool operator==(vector_set<K, C, A> const& lhs, vector_set<K, C, A> const& rhs);
friend bool operator==(const vector_set<K, C, A>& lhs, const vector_set<K, C, A>& rhs);
};
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>>
vector_set(std::initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
-> vector_set<Key, Compare, Allocator>;
template <class InputIt,
class Comp = std::less<typename std::iterator_traits<InputIt>::value_type>,
class Alloc = std::allocator<typename std::iterator_traits<InputIt>::value_type>>
template <
class InputIt,
class Comp = std::less<typename std::iterator_traits<InputIt>::value_type>,
class Alloc = std::allocator<typename std::iterator_traits<InputIt>::value_type>>
vector_set(InputIt, InputIt, Comp = Comp(), Alloc = Alloc())
-> vector_set<typename std::iterator_traits<InputIt>::value_type, Comp, Alloc>;
@ -107,18 +110,21 @@ namespace mamba
-> vector_set<Key, Compare, Allocator>;
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>>
vector_set(std::vector<Key, Allocator> const&, Compare compare = Compare())
vector_set(const std::vector<Key, Allocator>&, Compare compare = Compare())
-> vector_set<Key, Compare, Allocator>;
template <typename Key, typename Compare, typename Allocator>
bool operator==(vector_set<Key, Compare, Allocator> const& lhs,
vector_set<Key, Compare, Allocator> const& rhs);
bool operator==(
const vector_set<Key, Compare, Allocator>& lhs,
const vector_set<Key, Compare, Allocator>& rhs
);
// Simplified implementation of a directed graph
template <typename Node, typename Derived>
class DiGraphBase
{
public:
using node_t = Node;
using node_id = std::size_t;
using node_list = std::vector<node_t>;
@ -135,7 +141,7 @@ namespace mamba
std::size_t in_degree(node_id id) const noexcept;
std::size_t out_degree(node_id id) const noexcept;
const node_list& nodes() const;
node_t const& node(node_id id) const;
const node_t& node(node_id id) const;
node_t& node(node_id id);
const node_id_list& successors(node_id id) const;
const adjacency_list& successors() const;
@ -163,10 +169,11 @@ namespace mamba
void depth_first_search(V& visitor, node_id start = node_id(0), bool reverse = false) const;
protected:
DiGraphBase() = default;
DiGraphBase(DiGraphBase const&) = default;
DiGraphBase(const DiGraphBase&) = default;
DiGraphBase(DiGraphBase&&) = default;
DiGraphBase& operator=(DiGraphBase const&) = default;
DiGraphBase& operator=(const DiGraphBase&) = default;
DiGraphBase& operator=(DiGraphBase&&) = default;
~DiGraphBase() = default;
@ -174,12 +181,13 @@ namespace mamba
{
return static_cast<Derived&>(*this);
}
Derived const& derived_cast() const
const Derived& derived_cast() const
{
return static_cast<Derived const&>(*this);
return static_cast<const Derived&>(*this);
}
private:
enum class visited
{
no,
@ -193,10 +201,12 @@ namespace mamba
node_id add_node_impl(V&& value);
template <class V>
void depth_first_search_impl(V& visitor,
node_id node,
visited_list& status,
adjacency_list const& successors) const;
void depth_first_search_impl(
V& visitor,
node_id node,
visited_list& status,
const adjacency_list& successors
) const;
node_list m_node_list;
adjacency_list m_predecessors;
@ -205,14 +215,17 @@ namespace mamba
};
template <typename Node, typename Derived>
auto is_reachable(DiGraphBase<Node, Derived> const& graph,
typename DiGraphBase<Node, Derived>::node_id source,
typename DiGraphBase<Node, Derived>::node_id target) -> bool;
auto is_reachable(
const DiGraphBase<Node, Derived>& graph,
typename DiGraphBase<Node, Derived>::node_id source,
typename DiGraphBase<Node, Derived>::node_id target
) -> bool;
template <class G>
class default_visitor
{
public:
using graph_t = G;
using node_id = typename graph_t::node_id;
@ -244,22 +257,24 @@ namespace mamba
class DiGraph : public DiGraphBase<Node, DiGraph<Node, Edge>>
{
public:
using Base = DiGraphBase<Node, DiGraph<Node, Edge>>;
using edge_t = Edge;
using typename Base::node_id;
using edge_id = std::pair<node_id, node_id>;
using edge_map = std::map<edge_id, edge_t>;
void add_edge(node_id from, node_id to, edge_t const& data);
void add_edge(node_id from, node_id to, const edge_t& data);
void add_edge(node_id from, node_id to, edge_t&& data);
const edge_map& edges() const;
edge_t const& edge(node_id from, node_id to) const;
edge_t const& edge(edge_id edge) const;
const edge_t& edge(node_id from, node_id to) const;
const edge_t& edge(edge_id edge) const;
edge_t& edge(node_id from, node_id to);
edge_t& edge(edge_id edge);
private:
template <typename T>
void add_edge_impl(node_id from, node_id to, T&& data);
@ -276,9 +291,11 @@ namespace mamba
*******************************/
template <typename K, typename C, typename A>
vector_set<K, C, A>::vector_set(std::initializer_list<value_type> il,
key_compare compare,
allocator_type const& alloc)
vector_set<K, C, A>::vector_set(
std::initializer_list<value_type> il,
key_compare compare,
const allocator_type& alloc
)
: Base(std::move(il), alloc)
, m_compare(std::move(compare))
{
@ -287,10 +304,12 @@ namespace mamba
template <typename K, typename C, typename A>
template <typename InputIterator>
vector_set<K, C, A>::vector_set(InputIterator first,
InputIterator last,
key_compare compare,
allocator_type const& alloc)
vector_set<K, C, A>::vector_set(
InputIterator first,
InputIterator last,
key_compare compare,
const allocator_type& alloc
)
: Base(first, last, alloc)
, m_compare(std::move(compare))
{
@ -306,7 +325,7 @@ namespace mamba
}
template <typename K, typename C, typename A>
vector_set<K, C, A>::vector_set(std::vector<K, A> const& other, C compare)
vector_set<K, C, A>::vector_set(const std::vector<K, A>& other, C compare)
: Base(std::move(other))
, m_compare(std::move(compare))
{
@ -314,19 +333,19 @@ namespace mamba
}
template <typename K, typename C, typename A>
auto vector_set<K, C, A>::contains(value_type const& value) const -> bool
auto vector_set<K, C, A>::contains(const value_type& value) const -> bool
{
return std::binary_search(begin(), end(), value);
}
template <typename K, typename C, typename A>
auto vector_set<K, C, A>::front() const noexcept -> value_type const&
auto vector_set<K, C, A>::front() const noexcept -> const value_type&
{
return Base::front();
}
template <typename K, typename C, typename A>
auto vector_set<K, C, A>::back() const noexcept -> value_type const&
auto vector_set<K, C, A>::back() const noexcept -> const value_type&
{
return Base::back();
}
@ -356,7 +375,7 @@ namespace mamba
}
template <typename K, typename C, typename A>
auto vector_set<K, C, A>::insert(value_type const& value) -> std::pair<const_iterator, bool>
auto vector_set<K, C, A>::insert(const value_type& value) -> std::pair<const_iterator, bool>
{
return insert_impl(value);
}
@ -395,10 +414,10 @@ namespace mamba
}
template <typename K, typename C, typename A>
bool operator==(vector_set<K, C, A> const& lhs, vector_set<K, C, A> const& rhs)
bool operator==(const vector_set<K, C, A>& lhs, const vector_set<K, C, A>& rhs)
{
return static_cast<std::vector<K, A> const&>(lhs)
== static_cast<std::vector<K, A> const&>(rhs);
return static_cast<const std::vector<K, A>&>(lhs)
== static_cast<const std::vector<K, A>&>(rhs);
}
/********************************
@ -442,7 +461,7 @@ namespace mamba
}
template <typename N, typename G>
auto DiGraphBase<N, G>::node(node_id id) const -> node_t const&
auto DiGraphBase<N, G>::node(node_id id) const -> const node_t&
{
return m_node_list[id];
}
@ -513,7 +532,7 @@ namespace mamba
template <typename BinaryFunc>
BinaryFunc DiGraphBase<N, G>::for_each_edge(BinaryFunc func) const
{
auto const n_nodes = number_of_nodes();
const auto n_nodes = number_of_nodes();
for (node_id i = 0; i < n_nodes; ++i)
{
for (node_id j : successors(i))
@ -528,7 +547,7 @@ namespace mamba
template <typename UnaryFunc>
UnaryFunc DiGraphBase<N, G>::for_each_leaf(UnaryFunc func) const
{
auto const n_nodes = number_of_nodes();
const auto n_nodes = number_of_nodes();
for (node_id i = 0; i < n_nodes; ++i)
{
if (out_degree(i) == 0)
@ -543,7 +562,7 @@ namespace mamba
template <typename UnaryFunc>
UnaryFunc DiGraphBase<N, G>::for_each_root(UnaryFunc func) const
{
auto const n_nodes = number_of_nodes();
const auto n_nodes = number_of_nodes();
for (node_id i = 0; i < n_nodes; ++i)
{
if (in_degree(i) == 0)
@ -568,7 +587,7 @@ namespace mamba
{
}
void start_node(node_id n, graph_t const& g)
void start_node(node_id n, const graph_t& g)
{
if (g.out_degree(n) == 0)
{
@ -595,7 +614,7 @@ namespace mamba
{
}
void start_node(node_id n, graph_t const& g)
void start_node(node_id n, const graph_t& g)
{
if (g.in_degree(n) == 0)
{
@ -631,10 +650,12 @@ namespace mamba
template <typename N, typename G>
template <class V>
void DiGraphBase<N, G>::depth_first_search_impl(V& visitor,
node_id node,
visited_list& status,
adjacency_list const& successors) const
void DiGraphBase<N, G>::depth_first_search_impl(
V& visitor,
node_id node,
visited_list& status,
const adjacency_list& successors
) const
{
status[node] = visited::ongoing;
visitor.start_node(node, derived_cast());
@ -665,9 +686,11 @@ namespace mamba
*******************************/
template <typename Node, typename Derived>
auto is_reachable(DiGraphBase<Node, Derived> const& graph,
typename DiGraphBase<Node, Derived>::node_id source,
typename DiGraphBase<Node, Derived>::node_id target) -> bool
auto is_reachable(
const DiGraphBase<Node, Derived>& graph,
typename DiGraphBase<Node, Derived>::node_id source,
typename DiGraphBase<Node, Derived>::node_id target
) -> bool
{
using graph_t = DiGraphBase<Node, Derived>;
using node_id = typename graph_t::node_id;
@ -692,7 +715,7 @@ namespace mamba
*********************************/
template <typename N, typename E>
void DiGraph<N, E>::add_edge(node_id from, node_id to, edge_t const& data)
void DiGraph<N, E>::add_edge(node_id from, node_id to, const edge_t& data)
{
add_edge_impl(from, to, data);
}
@ -719,13 +742,13 @@ namespace mamba
}
template <typename N, typename E>
auto DiGraph<N, E>::edge(edge_id edge) const -> edge_t const&
auto DiGraph<N, E>::edge(edge_id edge) const -> const edge_t&
{
return m_edges.at(edge);
}
template <typename N, typename E>
auto DiGraph<N, E>::edge(node_id from, node_id to) const -> edge_t const&
auto DiGraph<N, E>::edge(node_id from, node_id to) const -> const edge_t&
{
return edge({ from, to });
}

View File

@ -7,8 +7,8 @@
#ifndef MAMBA_CORE_UTIL_OS_HPP
#define MAMBA_CORE_UTIL_OS_HPP
#include <string>
#include <iosfwd>
#include <string>
#include "mamba/core/fsutil.hpp"
@ -42,7 +42,7 @@ namespace mamba
#ifdef _WIN32
std::string to_utf8(const wchar_t* w, size_t s);
std::string to_utf8(const wchar_t* w);
std::string to_utf8(std::wstring const& s);
std::string to_utf8(const std::wstring& s);
#endif
/* Test whether a given `std::ostream` object refers to a terminal. */

View File

@ -8,10 +8,10 @@
#define MAMBA_CORE_UTIL_RANDOM_HPP
#include <algorithm>
#include <cstring>
#include <limits>
#include <random>
#include <string>
#include <cstring>
namespace mamba
{
@ -20,9 +20,8 @@ namespace mamba
{
using std::begin;
using std::end;
auto constexpr seed_bits = sizeof(typename T::result_type) * T::state_size;
auto constexpr seed_len
= seed_bits / std::numeric_limits<std::seed_seq::result_type>::digits;
constexpr auto seed_bits = sizeof(typename T::result_type) * T::state_size;
constexpr auto seed_len = seed_bits / std::numeric_limits<std::seed_seq::result_type>::digits;
auto seed = std::array<std::seed_seq::result_type, seed_len>{};
auto dev = std::random_device{};
std::generate_n(begin(seed), seed_len, std::ref(dev));

View File

@ -3,9 +3,11 @@
#define MAMBA_CORE_UTIL_SCOPE_HPP
#include <stdexcept>
#include "spdlog/spdlog.h"
#include "mamba/core/output.hpp"
#include "spdlog/spdlog.h"
namespace mamba
{

View File

@ -7,15 +7,15 @@
#ifndef MAMBA_CORE_UTIL_STRING_HPP
#define MAMBA_CORE_UTIL_STRING_HPP
#include <vector>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <ostream>
#include <sstream>
#include <string>
#include <string_view>
#include <ostream>
#include <cstring>
#include <sstream>
#include <algorithm>
#include <iomanip>
#include <type_traits>
#include <vector>
#include "mamba/core/util_compare.hpp"
@ -36,8 +36,8 @@ namespace mamba
// TODO: add concepts here, or at least some contraints
template <typename T, typename AssociativeContainer>
auto contains(const AssociativeContainer& values, const T& value_to_find)
-> decltype(values.find(value_to_find)
!= values.end()) // this should make invalid usage SFINAE
-> decltype(values.find(value_to_find) != values.end()) // this should make invalid usage
// SFINAE
{
return values.find(value_to_find) != values.end();
}
@ -47,8 +47,8 @@ namespace mamba
bool starts_with_any(const std::string_view& str, const std::vector<std::string_view>& prefix);
template <class CharType>
std::basic_string_view<CharType> strip(const std::basic_string_view<CharType>& input,
const std::basic_string_view<CharType>& chars)
std::basic_string_view<CharType>
strip(const std::basic_string_view<CharType>& input, const std::basic_string_view<CharType>& chars)
{
size_t start = input.find_first_not_of(chars);
if (start == std::basic_string<CharType>::npos)
@ -71,9 +71,11 @@ namespace mamba
// FIXME: doesnt support const char* mixed with other string types as input.
template <class CharType>
std::vector<std::basic_string<CharType>> split(const std::basic_string_view<CharType> input,
const std::basic_string_view<CharType> sep,
std::size_t max_split = SIZE_MAX)
std::vector<std::basic_string<CharType>> split(
const std::basic_string_view<CharType> input,
const std::basic_string_view<CharType> sep,
std::size_t max_split = SIZE_MAX
)
{
std::vector<std::basic_string<CharType>> result;
std::size_t i = 0, j = 0, len = input.size(), n = sep.size();
@ -83,7 +85,9 @@ namespace mamba
if (input[i] == sep[0] && input.substr(i, n) == sep)
{
if (max_split-- <= 0)
{
break;
}
result.emplace_back(input.substr(j, i - j));
i = j = i + n;
}
@ -100,16 +104,14 @@ namespace mamba
// works, so this is a workaround that fixes it
// FIXME: this overload should not be necessary, but the generic version doesn't
// work with const char* and mixed with other types for some reason.
inline std::vector<std::string> split(const std::string_view& input,
const std::string_view& sep,
std::size_t max_split = SIZE_MAX)
inline std::vector<std::string>
split(const std::string_view& input, const std::string_view& sep, std::size_t max_split = SIZE_MAX)
{
return split<char>(input, sep, max_split);
}
std::vector<std::string> rsplit(const std::string_view& input,
const std::string_view& sep,
std::size_t max_split = SIZE_MAX);
std::vector<std::string>
rsplit(const std::string_view& input, const std::string_view& sep, std::size_t max_split = SIZE_MAX);
namespace details
{
@ -138,7 +140,7 @@ namespace mamba
std::size_t size(const wchar_t* s);
std::size_t size(const char c);
template <class T>
std::size_t size(T const& s)
std::size_t size(const T& s)
{
using std::size;
return size(s);
@ -154,7 +156,7 @@ namespace mamba
*/
// TODO(C++20) Take an input range and return a range
template <typename InputIt, typename UnaryFunction, typename Value>
UnaryFunction join_for_each(InputIt first, InputIt last, UnaryFunction func, Value const& sep)
UnaryFunction join_for_each(InputIt first, InputIt last, UnaryFunction func, const Value& sep)
{
if (first < last)
{
@ -178,7 +180,7 @@ namespace mamba
* @see join_for_each
*/
template <class Range, class Value, class Joiner = details::PlusEqual>
auto join(Value const& sep, const Range& container, Joiner joiner = details::PlusEqual{}) ->
auto join(const Value& sep, const Range& container, Joiner joiner = details::PlusEqual{}) ->
typename Range::value_type
{
using Result = typename Range::value_type;
@ -186,7 +188,7 @@ namespace mamba
if constexpr (details::has_reserve_v<Result>)
{
std::size_t final_size = 0;
auto inc_size = [&final_size](auto const& val) { final_size += details::size(val); };
auto inc_size = [&final_size](const auto& val) { final_size += details::size(val); };
join_for_each(container.begin(), container.end(), inc_size, sep);
out.reserve(final_size);
}
@ -217,13 +219,15 @@ namespace mamba
*/
// TODO(C++20) Take an input range and return a range
template <typename InputIt, typename UnaryFunction, typename Value>
UnaryFunction join_trunc_for_each(InputIt first,
InputIt last,
UnaryFunction func,
Value const& sep,
Value const& etc,
std::size_t threshold = 5,
std::pair<std::size_t, std::size_t> show = { 2, 1 })
UnaryFunction join_trunc_for_each(
InputIt first,
InputIt last,
UnaryFunction func,
const Value& sep,
const Value& etc,
std::size_t threshold = 5,
std::pair<std::size_t, std::size_t> show = { 2, 1 }
)
{
if (util::cmp_less_equal(last - first, threshold))
{
@ -243,7 +247,7 @@ namespace mamba
}
};
auto const [show_head, show_tail] = show;
const auto [show_head, show_tail] = show;
if (show_head > 0)
{
join_for_each_func(first, first + show_head, sep);
@ -271,19 +275,21 @@ namespace mamba
* @see join
*/
template <typename Range, typename Joiner = details::PlusEqual>
auto join_trunc(Range const& range,
std::string_view sep = ", ",
std::string_view etc = "...",
std::size_t threshold = 5,
std::pair<std::size_t, std::size_t> show = { 2, 1 },
Joiner joiner = details::PlusEqual{}) -> typename Range::value_type
auto join_trunc(
const Range& range,
std::string_view sep = ", ",
std::string_view etc = "...",
std::size_t threshold = 5,
std::pair<std::size_t, std::size_t> show = { 2, 1 },
Joiner joiner = details::PlusEqual{}
) -> typename Range::value_type
{
using Result = typename Range::value_type;
Result out{};
if constexpr (details::has_reserve_v<Result>)
{
std::size_t final_size = 0;
auto inc_size = [&final_size](auto const& val) { final_size += details::size(val); };
auto inc_size = [&final_size](const auto& val) { final_size += details::size(val); };
join_trunc_for_each(range.begin(), range.end(), inc_size, sep, etc, threshold, show);
out.reserve(final_size);
}

View File

@ -7,10 +7,10 @@
#ifndef MAMBA_CORE_VALIDATE_HPP
#define MAMBA_CORE_VALIDATE_HPP
#include <string>
#include <vector>
#include <set>
#include <stdexcept>
#include <string>
#include <vector>
#include <nlohmann/json.hpp>
@ -37,34 +37,35 @@ namespace validate
const std::size_t MAMBA_ED25519_SIGSIZE_BYTES = 64;
int generate_ed25519_keypair(unsigned char* pk, unsigned char* sk);
std::pair<std::array<unsigned char, MAMBA_ED25519_KEYSIZE_BYTES>,
std::array<unsigned char, MAMBA_ED25519_KEYSIZE_BYTES>>
std::pair<
std::array<unsigned char, MAMBA_ED25519_KEYSIZE_BYTES>,
std::array<unsigned char, MAMBA_ED25519_KEYSIZE_BYTES>>
generate_ed25519_keypair();
std::pair<std::string, std::string> generate_ed25519_keypair_hex();
int sign(const std::string& data, const unsigned char* sk, unsigned char* signature);
int sign(const std::string& data, const std::string& sk, std::string& signature);
std::array<unsigned char, MAMBA_ED25519_SIGSIZE_BYTES> ed25519_sig_hex_to_bytes(
const std::string& sig_hex) noexcept;
std::array<unsigned char, MAMBA_ED25519_SIGSIZE_BYTES>
ed25519_sig_hex_to_bytes(const std::string& sig_hex) noexcept;
std::array<unsigned char, MAMBA_ED25519_SIGSIZE_BYTES> ed25519_sig_hex_to_bytes(
const std::string& sig_hex, int& error_code) noexcept;
std::array<unsigned char, MAMBA_ED25519_SIGSIZE_BYTES>
ed25519_sig_hex_to_bytes(const std::string& sig_hex, int& error_code) noexcept;
std::array<unsigned char, MAMBA_ED25519_KEYSIZE_BYTES> ed25519_key_hex_to_bytes(
const std::string& key_hex) noexcept;
std::array<unsigned char, MAMBA_ED25519_KEYSIZE_BYTES>
ed25519_key_hex_to_bytes(const std::string& key_hex) noexcept;
std::array<unsigned char, MAMBA_ED25519_KEYSIZE_BYTES> ed25519_key_hex_to_bytes(
const std::string& key_hex, int& error_code) noexcept;
std::array<unsigned char, MAMBA_ED25519_KEYSIZE_BYTES>
ed25519_key_hex_to_bytes(const std::string& key_hex, int& error_code) noexcept;
int verify(const unsigned char* data,
std::size_t data_len,
const unsigned char* pk,
const unsigned char* signature);
int verify(
const unsigned char* data,
std::size_t data_len,
const unsigned char* pk,
const unsigned char* signature
);
int verify(const std::string& data, const unsigned char* pk, const unsigned char* signature);
int verify(const std::string& data,
const std::string& pk_hex,
const std::string& signature_hex);
int verify(const std::string& data, const std::string& pk_hex, const std::string& signature_hex);
/**
* Verify a GPG/PGP signature against the hash of the binary data and
@ -72,15 +73,15 @@ namespace validate
* See RFC4880, section 5.2.4 https://datatracker.ietf.org/doc/html/rfc4880#section-5.2.4
* This method assumes hash function to be SHA-256
*/
int verify_gpg_hashed_msg(const unsigned char* data,
const unsigned char* pk,
const unsigned char* signature);
int verify_gpg_hashed_msg(const std::string& data,
const unsigned char* pk,
const unsigned char* signature);
int verify_gpg_hashed_msg(const std::string& data,
const std::string& pk,
const std::string& signature);
int verify_gpg_hashed_msg(
const unsigned char* data,
const unsigned char* pk,
const unsigned char* signature
);
int
verify_gpg_hashed_msg(const std::string& data, const unsigned char* pk, const unsigned char* signature);
int
verify_gpg_hashed_msg(const std::string& data, const std::string& pk, const std::string& signature);
/**
* Verify a GPG/PGP signature against the binary data and
@ -88,10 +89,12 @@ namespace validate
* See RFC4880, section 5.2.4 https://datatracker.ietf.org/doc/html/rfc4880#section-5.2.4
* This method assumes hash function to be SHA-256
*/
int verify_gpg(const std::string& data,
const std::string& gpg_v4_trailer,
const std::string& pk,
const std::string& signature);
int verify_gpg(
const std::string& data,
const std::string& gpg_v4_trailer,
const std::string& pk,
const std::string& signature
);
/**
* Base class for artifact/package verification error.
@ -99,11 +102,13 @@ namespace validate
class trust_error : public std::exception
{
public:
trust_error(const std::string& message) noexcept;
virtual ~trust_error() = default;
virtual const char* what() const noexcept override;
private:
std::string m_message;
};
@ -116,6 +121,7 @@ namespace validate
class threshold_error : public trust_error
{
public:
threshold_error() noexcept;
virtual ~threshold_error() = default;
};
@ -127,6 +133,7 @@ namespace validate
class role_metadata_error : public trust_error
{
public:
role_metadata_error() noexcept;
virtual ~role_metadata_error() = default;
};
@ -139,6 +146,7 @@ namespace validate
class role_file_error : public trust_error
{
public:
role_file_error() noexcept;
virtual ~role_file_error() = default;
};
@ -151,6 +159,7 @@ namespace validate
class rollback_error : public trust_error
{
public:
rollback_error() noexcept;
virtual ~rollback_error() = default;
};
@ -163,6 +172,7 @@ namespace validate
class freeze_error : public trust_error
{
public:
freeze_error() noexcept;
virtual ~freeze_error() = default;
};
@ -175,6 +185,7 @@ namespace validate
class spec_version_error : public trust_error
{
public:
spec_version_error() noexcept;
virtual ~spec_version_error() = default;
};
@ -187,6 +198,7 @@ namespace validate
class fetching_error : public trust_error
{
public:
fetching_error() noexcept;
virtual ~fetching_error() = default;
};
@ -199,6 +211,7 @@ namespace validate
class package_error : public trust_error
{
public:
package_error() noexcept;
virtual ~package_error() = default;
};
@ -210,6 +223,7 @@ namespace validate
class role_error : public trust_error
{
public:
role_error() noexcept;
virtual ~role_error() = default;
};
@ -221,6 +235,7 @@ namespace validate
class index_error : public trust_error
{
public:
index_error() noexcept;
virtual ~index_error() = default;
};
@ -324,6 +339,7 @@ namespace validate
class TimeRef
{
public:
static TimeRef& instance();
void set(const std::time_t& time);
@ -331,10 +347,12 @@ namespace validate
std::string timestamp();
protected:
TimeRef();
~TimeRef();
private:
std::time_t m_time_ref;
};
@ -345,6 +363,7 @@ namespace validate
class SpecBase
{
public:
virtual ~SpecBase() = default;
std::string version_str() const;
@ -369,12 +388,14 @@ namespace validate
virtual std::set<RoleSignature> signatures(const json& j) const = 0;
protected:
SpecBase(const std::string& spec_version);
SpecBase() = delete;
std::string get_json_value(const json& j) const;
private:
std::string m_spec_version;
};
@ -388,6 +409,7 @@ namespace validate
class RoleBase
{
public:
RoleBase(const std::string& type, std::shared_ptr<SpecBase> sv);
virtual ~RoleBase() = 0;
@ -410,6 +432,7 @@ namespace validate
friend void from_json(const json& j, RoleBase* r);
protected:
json read_json_file(const fs::u8path& p, bool update = false) const;
/**
@ -424,9 +447,11 @@ namespace validate
* Check that a threshold of valid signatures is met
* for the signed metadata, using a set of keys.
*/
void check_signatures(const std::string& signed_data,
const std::set<RoleSignature>& signatures,
const RoleFullKeys& keyring) const;
void check_signatures(
const std::string& signed_data,
const std::set<RoleSignature>& signatures,
const RoleFullKeys& keyring
) const;
void set_spec_version(std::shared_ptr<SpecBase> sv);
void set_expiration(const std::string& expires);
@ -448,6 +473,7 @@ namespace validate
std::map<std::string, RoleFullKeys> m_defined_roles;
private:
std::string m_internal_type;
std::string m_type;
std::shared_ptr<SpecBase> p_spec;
@ -465,6 +491,7 @@ namespace validate
class RootRole : public RoleBase
{
public:
virtual ~RootRole() = default;
std::unique_ptr<RootRole> update(fs::u8path path);
@ -472,14 +499,15 @@ namespace validate
std::vector<fs::u8path> possible_update_files();
virtual std::unique_ptr<RepoIndexChecker> build_index_checker(
const std::string& url, const fs::u8path& cache_path) const
= 0;
virtual std::unique_ptr<RepoIndexChecker>
build_index_checker(const std::string& url, const fs::u8path& cache_path) const = 0;
protected:
RootRole(std::shared_ptr<SpecBase> spec);
private:
virtual std::unique_ptr<RootRole> create_update(const json& j) = 0;
};
@ -491,12 +519,14 @@ namespace validate
class RepoIndexChecker
{
public:
virtual ~RepoIndexChecker() = default;
virtual void verify_index(const json& j) const = 0;
virtual void verify_index(const fs::u8path& p) const = 0;
virtual void verify_package(const json& signed_data, const json& signatures) const = 0;
protected:
RepoIndexChecker() = default;
};
@ -509,15 +539,18 @@ namespace validate
class RepoChecker
{
public:
/**
* Constructor.
* @param base_url Repository base URL
* @param ref_path Path to the reference directory, hosting trusted root metadata
* @param cache_path Path to the cache directory
*/
RepoChecker(const std::string& base_url,
const fs::u8path& ref_path,
const fs::u8path& cache_path = "");
RepoChecker(
const std::string& base_url,
const fs::u8path& ref_path,
const fs::u8path& cache_path = ""
);
// Forwarding to a ``RepoIndexChecker`` implementation
void verify_index(const json& j) const;
@ -531,6 +564,7 @@ namespace validate
std::size_t root_version();
private:
std::string m_base_url;
std::size_t m_root_version = 0;
fs::u8path m_ref_path;
@ -556,6 +590,7 @@ namespace validate
class SpecImpl final : public SpecBase
{
public:
SpecImpl(const std::string& sv = "1.0.17");
std::string json_key() const override;
@ -573,18 +608,20 @@ namespace validate
class RootImpl final : public RootRole
{
public:
RootImpl(const fs::u8path& p);
RootImpl(const json& j);
RoleFullKeys self_keys() const override;
std::unique_ptr<RepoIndexChecker> build_index_checker(
const std::string& url, const fs::u8path& cache_path) const override;
std::unique_ptr<RepoIndexChecker>
build_index_checker(const std::string& url, const fs::u8path& cache_path) const override;
friend void to_json(json& j, const RootImpl& r);
friend void from_json(const json& j, RootImpl& r);
private:
RootImpl() = delete;
void load_from_json(const json& j);
@ -594,8 +631,8 @@ namespace validate
std::set<std::string> mandatory_defined_roles() const override;
std::set<std::string> optionally_defined_roles() const override;
void set_defined_roles(std::map<std::string, Key> keys,
std::map<std::string, RoleKeys> roles);
void
set_defined_roles(std::map<std::string, Key> keys, std::map<std::string, RoleKeys> roles);
};
}
@ -608,6 +645,7 @@ namespace validate
class SpecImpl final : public SpecBase
{
public:
SpecImpl(const std::string& sv = "0.6.0");
std::string json_key() const override;
@ -622,11 +660,13 @@ namespace validate
class V06RoleBaseExtension
{
public:
void set_timestamp(const std::string& ts);
std::string timestamp() const;
protected:
std::string m_timestamp;
void check_timestamp_format() const;
@ -644,6 +684,7 @@ namespace validate
, public V06RoleBaseExtension
{
public:
RootImpl(const fs::u8path& p);
RootImpl(const json& j);
RootImpl(const std::string& json_str);
@ -652,15 +693,14 @@ namespace validate
* Return a ``RepoIndexChecker`` implementation (derived class)
* from repository base URL.
*/
std::unique_ptr<RepoIndexChecker> build_index_checker(
const std::string& url, const fs::u8path& cache_path) const override;
std::unique_ptr<RepoIndexChecker>
build_index_checker(const std::string& url, const fs::u8path& cache_path) const override;
RoleFullKeys self_keys() const override;
json upgraded_signable() const;
RoleSignature upgraded_signature(const json& j,
const std::string& pk,
const unsigned char* sk) const;
RoleSignature
upgraded_signature(const json& j, const std::string& pk, const unsigned char* sk) const;
KeyMgrRole create_key_mgr(const fs::u8path& p) const;
KeyMgrRole create_key_mgr(const json& j) const;
@ -669,6 +709,7 @@ namespace validate
friend void from_json(const json& j, RootImpl& r);
private:
RootImpl() = delete;
void load_from_json(const json& j);
@ -693,15 +734,14 @@ namespace validate
, public V06RoleBaseExtension
{
public:
KeyMgrRole(const fs::u8path& p,
const RoleFullKeys& keys,
const std::shared_ptr<SpecBase> spec);
KeyMgrRole(const json& j,
const RoleFullKeys& keys,
const std::shared_ptr<SpecBase> spec);
KeyMgrRole(const std::string& json_str,
const RoleFullKeys& keys,
const std::shared_ptr<SpecBase> spec);
KeyMgrRole(const fs::u8path& p, const RoleFullKeys& keys, const std::shared_ptr<SpecBase> spec);
KeyMgrRole(const json& j, const RoleFullKeys& keys, const std::shared_ptr<SpecBase> spec);
KeyMgrRole(
const std::string& json_str,
const RoleFullKeys& keys,
const std::shared_ptr<SpecBase> spec
);
// std::set<std::string> roles() const override;
RoleFullKeys self_keys() const override;
@ -713,13 +753,14 @@ namespace validate
* Return a ``RepoIndexChecker`` implementation (derived class)
* from repository base URL.
*/
std::unique_ptr<RepoIndexChecker> build_index_checker(
const std::string& url, const fs::u8path& cache_path) const;
std::unique_ptr<RepoIndexChecker>
build_index_checker(const std::string& url, const fs::u8path& cache_path) const;
friend void to_json(json& j, const KeyMgrRole& r);
friend void from_json(const json& j, KeyMgrRole& r);
private:
KeyMgrRole() = delete;
void load_from_json(const json& j);
@ -746,16 +787,15 @@ namespace validate
, public RepoIndexChecker
{
public:
PkgMgrRole(const RoleFullKeys& keys, const std::shared_ptr<SpecBase> spec);
PkgMgrRole(const fs::u8path& p,
const RoleFullKeys& keys,
const std::shared_ptr<SpecBase> spec);
PkgMgrRole(const json& j,
const RoleFullKeys& keys,
const std::shared_ptr<SpecBase> spec);
PkgMgrRole(const std::string& json_str,
const RoleFullKeys& keys,
const std::shared_ptr<SpecBase> spec);
PkgMgrRole(const fs::u8path& p, const RoleFullKeys& keys, const std::shared_ptr<SpecBase> spec);
PkgMgrRole(const json& j, const RoleFullKeys& keys, const std::shared_ptr<SpecBase> spec);
PkgMgrRole(
const std::string& json_str,
const RoleFullKeys& keys,
const std::shared_ptr<SpecBase> spec
);
void verify_index(const fs::u8path& p) const override;
void verify_index(const json& j) const override;
@ -765,6 +805,7 @@ namespace validate
friend void from_json(const json& j, PkgMgrRole& r);
private:
PkgMgrRole() = delete;
void load_from_json(const json& j);

View File

@ -7,10 +7,10 @@
#ifndef MAMBA_CORE_VIRTUAL_PACKAGES_HPP
#define MAMBA_CORE_VIRTUAL_PACKAGES_HPP
#include "mamba/core/package_info.hpp"
#include <vector>
#include <string>
#include <vector>
#include "mamba/core/package_info.hpp"
namespace mamba
{
@ -21,9 +21,11 @@ namespace mamba
std::string cuda_version();
std::string get_arch();
PackageInfo make_virtual_package(const std::string& name,
const std::string& version = "",
const std::string& build_string = "");
PackageInfo make_virtual_package(
const std::string& name,
const std::string& version = "",
const std::string& build_string = ""
);
std::vector<PackageInfo> dist_packages();
}

View File

@ -26,8 +26,7 @@
(LIBMAMBA_VERSION_MAJOR * 10000 + LIBMAMBA_VERSION_MINOR * 100 + LIBMAMBA_VERSION_PATCH)
#define LIBMAMBA_VERSION_STRING \
__LIBMAMBA_STRINGIZE(LIBMAMBA_VERSION_MAJOR) \
"." __LIBMAMBA_STRINGIZE(LIBMAMBA_VERSION_MINOR) "." __LIBMAMBA_STRINGIZE( \
LIBMAMBA_VERSION_PATCH)
"." __LIBMAMBA_STRINGIZE(LIBMAMBA_VERSION_MINOR) "." __LIBMAMBA_STRINGIZE(LIBMAMBA_VERSION_PATCH)
namespace mamba
{

View File

@ -5,6 +5,9 @@
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/c_api.h"
#include <string>
#include "mamba/api/config.hpp"
#include "mamba/api/configuration.hpp"
#include "mamba/api/create.hpp"
@ -14,8 +17,6 @@
#include "mamba/api/remove.hpp"
#include "mamba/api/update.hpp"
#include <string>
using namespace mamba;

View File

@ -37,9 +37,8 @@ namespace mamba
}
}
expected_t<void, mamba_aggregated_error> load_channels(MPool& pool,
MultiPackageCache& package_caches,
int is_retry)
expected_t<void, mamba_aggregated_error>
load_channels(MPool& pool, MultiPackageCache& package_caches, int is_retry)
{
int RETRY_SUBDIR_FETCH = 1 << 0;
@ -62,8 +61,7 @@ namespace mamba
{
for (auto& [platform, url] : channel->platform_urls(true))
{
auto sdires
= MSubdirData::create(*channel, platform, url, package_caches, "repodata.json");
auto sdires = MSubdirData::create(*channel, platform, url, package_caches, "repodata.json");
if (!sdires.has_value())
{
error_list.push_back(std::move(sdires).error());
@ -99,8 +97,8 @@ namespace mamba
multi_dl.download(MAMBA_NO_CLEAR_PROGRESS_BARS);
if (is_sig_interrupted())
{
error_list.push_back(
mamba_error("Interrupted by user", mamba_error_code::user_interrupted));
error_list.push_back(mamba_error("Interrupted by user", mamba_error_code::user_interrupted)
);
return tl::unexpected(mamba_aggregated_error(std::move(error_list)));
}
@ -131,7 +129,9 @@ namespace mamba
{
LOG_INFO << "Creating repo from pkgs_dir for offline";
for (const auto& c : ctx.pkgs_dirs)
{
detail::create_repo_from_pkgs_dir(pool, c);
}
}
std::string prev_channel;
bool loading_failed = false;
@ -142,8 +142,10 @@ namespace mamba
{
if (!ctx.offline && mamba::ends_with(subdir.name(), "/noarch"))
{
error_list.push_back(mamba_error("Subdir " + subdir.name() + " not loaded!",
mamba_error_code::subdirdata_not_loaded));
error_list.push_back(mamba_error(
"Subdir " + subdir.name() + " not loaded!",
mamba_error_code::subdirdata_not_loaded
));
}
continue;
}
@ -161,8 +163,7 @@ namespace mamba
std::stringstream ss;
ss << "Could not load repodata.json for " << subdir.name() << " after retry."
<< "Please check repodata source. Exiting." << std::endl;
error_list.push_back(
mamba_error(ss.str(), mamba_error_code::repodata_not_loaded));
error_list.push_back(mamba_error(ss.str(), mamba_error_code::repodata_not_loaded));
}
else
{
@ -181,8 +182,10 @@ namespace mamba
LOG_WARNING << "Encountered malformed repodata.json cache. Redownloading.";
return load_channels(pool, package_caches, is_retry | RETRY_SUBDIR_FETCH);
}
error_list.push_back(mamba_error("Could not load repodata. Cache corrupted?",
mamba_error_code::repodata_not_loaded));
error_list.push_back(mamba_error(
"Could not load repodata. Cache corrupted?",
mamba_error_code::repodata_not_loaded
));
}
using return_type = expected_t<void, mamba_aggregated_error>;
return error_list.empty() ? return_type()

View File

@ -4,11 +4,11 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/clean.hpp"
#include <iostream>
#include "mamba/api/clean.hpp"
#include "mamba/api/configuration.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/package_cache.hpp"
@ -50,6 +50,7 @@ namespace mamba
Console::stream() << "Cleaning index cache..";
for (auto* pkg_cache : caches.writable_caches())
{
if (fs::exists(pkg_cache->path() / "cache"))
{
try
@ -61,6 +62,7 @@ namespace mamba
LOG_WARNING << "Could not clean " << pkg_cache->path() / "cache";
}
}
}
}
if (!ctx.dry_run && (clean_locks || clean_all))
@ -70,6 +72,7 @@ namespace mamba
for (auto* pkg_cache : caches.writable_caches())
{
if (fs::exists(pkg_cache->path()))
{
for (auto& p : fs::directory_iterator(pkg_cache->path()))
{
if (p.exists() && ends_with(p.path().string(), ".lock")
@ -89,8 +92,10 @@ namespace mamba
}
}
}
}
if (fs::exists(pkg_cache->path() / "cache"))
{
for (auto& p : fs::recursive_directory_iterator(pkg_cache->path() / "cache"))
{
if (p.exists() && ends_with(p.path().string(), ".lock"))
@ -107,6 +112,7 @@ namespace mamba
}
}
}
}
}
}
@ -165,8 +171,7 @@ namespace mamba
for (auto* pkg_cache : caches.writable_caches())
{
std::string header_line
= concat("Package cache folder: ", pkg_cache->path().string());
std::string header_line = concat("Package cache folder: ", pkg_cache->path().string());
std::vector<std::vector<printers::FormattedString>> rows;
for (auto& p : fs::directory_iterator(pkg_cache->path()))
{
@ -176,14 +181,15 @@ namespace mamba
|| ends_with(p.path().string(), ".conda")))
{
res.push_back(p.path());
rows.push_back(
{ p.path().filename().string(), get_file_size(p.file_size()) });
rows.push_back({ p.path().filename().string(), get_file_size(p.file_size()) });
total_size += p.file_size();
}
}
std::sort(rows.begin(),
rows.end(),
[](const auto& a, const auto& b) { return a[0].s < b[0].s; });
std::sort(
rows.begin(),
rows.end(),
[](const auto& a, const auto& b) { return a[0].s < b[0].s; }
);
t.add_rows(pkg_cache->path().string(), rows);
}
if (total_size)
@ -239,29 +245,28 @@ namespace mamba
for (auto* pkg_cache : caches.writable_caches())
{
std::string header_line
= concat("Package cache folder: ", pkg_cache->path().string());
std::string header_line = concat("Package cache folder: ", pkg_cache->path().string());
std::vector<std::vector<printers::FormattedString>> rows;
for (auto& p : fs::directory_iterator(pkg_cache->path()))
{
if (p.is_directory() && fs::exists(p.path() / "info" / "index.json"))
{
if (installed_pkgs.find(p.path().filename().string())
!= installed_pkgs.end())
if (installed_pkgs.find(p.path().filename().string()) != installed_pkgs.end())
{
// do not remove installed packages
continue;
}
res.push_back(p.path());
std::size_t folder_size = get_folder_size(p);
rows.push_back(
{ p.path().filename().string(), get_file_size(folder_size) });
rows.push_back({ p.path().filename().string(), get_file_size(folder_size) });
total_size += folder_size;
}
}
std::sort(rows.begin(),
rows.end(),
[](const auto& a, const auto& b) { return a[0].s < b[0].s; });
std::sort(
rows.begin(),
rows.end(),
[](const auto& a, const auto& b) { return a[0].s < b[0].s; }
);
t.add_rows(pkg_cache->path().string(), rows);
}
if (total_size)

View File

@ -18,12 +18,14 @@ namespace mamba
config.at("use_target_prefix_fallback").set_value(true);
config.at("show_banner").set_value(false);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_ALLOW_NOT_ENV_PREFIX | MAMBA_NOT_EXPECT_EXISTING_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_ALLOW_NOT_ENV_PREFIX | MAMBA_NOT_EXPECT_EXISTING_PREFIX
);
config.load();
auto show_group
= config.at("show_config_groups").value<bool>() ? MAMBA_SHOW_CONFIG_GROUPS : 0;
auto show_group = config.at("show_config_groups").value<bool>() ? MAMBA_SHOW_CONFIG_GROUPS
: 0;
auto show_long_desc = config.at("show_config_long_descriptions").value<bool>()
? MAMBA_SHOW_CONFIG_LONG_DESCS
: 0;
@ -42,19 +44,21 @@ namespace mamba
config.at("use_target_prefix_fallback").set_value(true);
config.at("show_banner").set_value(false);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_ALLOW_NOT_ENV_PREFIX | MAMBA_NOT_EXPECT_EXISTING_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_ALLOW_NOT_ENV_PREFIX | MAMBA_NOT_EXPECT_EXISTING_PREFIX
);
config.load();
auto show_sources
= config.at("show_config_sources").value<bool>() ? MAMBA_SHOW_CONFIG_SRCS : 0;
auto show_sources = config.at("show_config_sources").value<bool>() ? MAMBA_SHOW_CONFIG_SRCS
: 0;
auto show_all = config.at("show_all_configs").value<bool>() ? MAMBA_SHOW_ALL_CONFIGS : 0;
auto show_all_rcs
= config.at("show_all_rc_configs").value<bool>() ? MAMBA_SHOW_ALL_RC_CONFIGS : 0;
auto show_group
= config.at("show_config_groups").value<bool>() ? MAMBA_SHOW_CONFIG_GROUPS : 0;
auto show_desc
= config.at("show_config_descriptions").value<bool>() ? MAMBA_SHOW_CONFIG_DESCS : 0;
auto show_all_rcs = config.at("show_all_rc_configs").value<bool>() ? MAMBA_SHOW_ALL_RC_CONFIGS
: 0;
auto show_group = config.at("show_config_groups").value<bool>() ? MAMBA_SHOW_CONFIG_GROUPS
: 0;
auto show_desc = config.at("show_config_descriptions").value<bool>() ? MAMBA_SHOW_CONFIG_DESCS
: 0;
auto show_long_desc = config.at("show_config_long_descriptions").value<bool>()
? MAMBA_SHOW_CONFIG_LONG_DESCS
: 0;
@ -74,8 +78,10 @@ namespace mamba
config.at("use_target_prefix_fallback").set_value(true);
config.at("show_banner").set_value(false);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_ALLOW_NOT_ENV_PREFIX | MAMBA_NOT_EXPECT_EXISTING_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_ALLOW_NOT_ENV_PREFIX | MAMBA_NOT_EXPECT_EXISTING_PREFIX
);
config.load();
auto& no_rc = config.at("no_rc").value<bool>();

View File

@ -4,27 +4,26 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/configuration.hpp"
#include <algorithm>
#include <regex>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <nlohmann/json.hpp>
#include <reproc++/run.hpp>
#include <nlohmann/json.hpp>
#include "spdlog/spdlog.h"
#include "mamba/api/configuration.hpp"
#include "mamba/api/info.hpp"
#include "mamba/api/install.hpp"
#include "mamba/core/environment.hpp"
#include "mamba/core/fsutil.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/transaction.hpp"
#include "mamba/core/url.hpp"
#include "spdlog/spdlog.h"
namespace mamba
{
/************************
@ -36,11 +35,17 @@ namespace mamba
bool ConfigurableImplBase::env_var_configured() const
{
if (Context::instance().no_env)
{
return false;
}
for (const auto& env_var : m_env_var_names)
{
if (env::get(env_var))
{
return true;
}
}
return false;
}
@ -146,9 +151,13 @@ namespace mamba
p_impl->m_rc_configurable_policy = level;
if (level == RCConfigLevel::kTargetPrefix)
{
p_impl->m_needed_configs.insert("target_prefix");
}
else
{
p_impl->m_needed_configs.insert("root_prefix");
}
return std::move(*this);
}
@ -186,12 +195,18 @@ namespace mamba
Configurable&& Configurable::set_env_var_names(const std::vector<std::string>& names)
{
if (names.empty())
{
p_impl->m_env_var_names = { "MAMBA_" + to_upper(p_impl->m_name) };
}
else
{
p_impl->m_env_var_names = names;
}
if (name() != "no_env")
{
p_impl->m_needed_configs.insert("no_env");
}
return std::move(*this);
}
@ -236,8 +251,12 @@ namespace mamba
Configurable&& Configurable::clear_env_values()
{
if (env_var_configured())
{
for (const auto& ev : p_impl->m_env_var_names)
{
env::unset(ev);
}
}
return std::move(*this);
}
@ -269,15 +288,16 @@ namespace mamba
return std::move(*this);
}
Configurable&& Configurable::set_rc_yaml_value(const YAML::Node& value,
const std::string& source)
Configurable&& Configurable::set_rc_yaml_value(const YAML::Node& value, const std::string& source)
{
p_impl->set_rc_yaml_value(value, source);
return std::move(*this);
}
Configurable&& Configurable::set_rc_yaml_values(const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources)
Configurable&& Configurable::set_rc_yaml_values(
const std::map<std::string, YAML::Node>& values,
const std::vector<std::string>& sources
)
{
p_impl->set_rc_yaml_values(values, sources);
return std::move(*this);
@ -413,8 +433,8 @@ namespace mamba
if (name.find_first_of("/\\") != std::string::npos)
{
throw std::runtime_error(
"An unexpected file-system separator was found in environment name: '" + name
+ "'");
"An unexpected file-system separator was found in environment name: '" + name + "'"
);
}
}
@ -458,11 +478,15 @@ namespace mamba
if (!config.at("target_prefix").cli_configured()
&& config.at("env_name").cli_configured())
{
config.at("target_prefix").set_cli_value<fs::u8path>(prefix);
}
if (!config.at("target_prefix").api_configured()
&& config.at("env_name").api_configured())
{
config.at("target_prefix").set_value(prefix);
}
}
}
@ -492,7 +516,9 @@ namespace mamba
{
bool use_fallback = config.at("use_target_prefix_fallback").value<bool>();
if (use_fallback)
{
prefix = std::getenv("CONDA_PREFIX") ? std::getenv("CONDA_PREFIX") : "";
}
}
#ifdef _WIN32
@ -501,10 +527,11 @@ namespace mamba
std::string sep = "/";
#endif
if (!prefix.empty())
{
prefix = rstrip(fs::weakly_canonical(env::expand_user(prefix)).string(), sep);
}
if ((prefix == root_prefix)
&& Configuration::instance().at("create_base").value<bool>())
if ((prefix == root_prefix) && Configuration::instance().at("create_base").value<bool>())
{
path::touch(root_prefix / "conda-meta" / "history", true);
}
@ -538,19 +565,23 @@ namespace mamba
if (fs::is_directory(prefix))
{
if (!fs::is_empty(prefix)
&& (!(fs::exists(prefix / "pkgs") || fs::exists(prefix / "conda-meta")
|| fs::exists(prefix / "envs"))))
&& (!(
fs::exists(prefix / "pkgs") || fs::exists(prefix / "conda-meta")
|| fs::exists(prefix / "envs")
)))
{
throw std::runtime_error(fmt::format(
"Could not use default 'root_prefix': {}: Directory exists, is not empty and not a conda prefix.",
prefix.string()));
prefix.string()
));
}
}
else
{
throw std::runtime_error(fmt::format(
"Could not use default 'root_prefix': {}: File is not a directory.",
prefix.string()));
prefix.string()
));
}
}
@ -601,7 +632,9 @@ namespace mamba
auto& ctx = Context::instance();
if (ctx.json)
{
return mamba::log_level::off;
}
else if (Configuration::instance().at("verbose").configured())
{
switch (ctx.verbosity)
@ -617,7 +650,9 @@ namespace mamba
}
}
else
{
return mamba::log_level::warn;
}
}
void verbose_hook(int& lvl)
@ -638,7 +673,9 @@ namespace mamba
bool expect_existing = options & MAMBA_EXPECT_EXISTING_PREFIX;
if (no_checks)
{
return;
}
if (prefix.empty())
{
@ -670,8 +707,7 @@ namespace mamba
else if (expect_existing)
{
LOG_ERROR << "No prefix found at: " << prefix.string();
LOG_ERROR
<< "Environment must first be created with \"micromamba create -n {env_name} ...\"";
LOG_ERROR << "Environment must first be created with \"micromamba create -n {env_name} ...\"";
throw std::runtime_error("Aborting.");
}
}
@ -711,7 +747,9 @@ namespace mamba
void debug_hook(bool& value)
{
if (value)
{
LOG_WARNING << "Debug mode enabled";
}
}
void print_config_only_hook(bool& value)
@ -790,8 +828,12 @@ namespace mamba
void download_threads_hook(std::size_t& value)
{
if (!value)
{
throw std::runtime_error(fmt::format(
"Number of download threads as to be positive (currently set to {})", value));
"Number of download threads as to be positive (currently set to {})",
value
));
}
}
void extract_threads_hook()
@ -805,7 +847,11 @@ namespace mamba
std::vector<std::string> args = { "conda", "config", "--show", "root_prefix", "--json" };
std::string out, err;
auto [status, ec] = reproc::run(
args, reproc::options{}, reproc::sink::string(out), reproc::sink::string(err));
args,
reproc::options{},
reproc::sink::string(out),
reproc::sink::string(err)
);
if (ec)
{
@ -849,10 +895,8 @@ namespace mamba
void print_node(YAML::Emitter& out, YAML::Node value, YAML::Node source, bool show_source);
void print_scalar_node(YAML::Emitter& out,
YAML::Node value,
YAML::Node source,
bool show_source)
void
print_scalar_node(YAML::Emitter& out, YAML::Node value, YAML::Node source, bool show_source)
{
out << value;
@ -875,10 +919,7 @@ namespace mamba
}
}
void print_seq_node(YAML::Emitter& out,
YAML::Node value,
YAML::Node source,
bool show_source)
void print_seq_node(YAML::Emitter& out, YAML::Node value, YAML::Node source, bool show_source)
{
if (value.size() > 0)
{
@ -893,14 +934,13 @@ namespace mamba
{
out << YAML::_Null();
if (show_source)
{
out << YAML::Comment("'default'");
}
}
}
void print_map_node(YAML::Emitter& out,
YAML::Node value,
YAML::Node source,
bool show_source)
void print_map_node(YAML::Emitter& out, YAML::Node value, YAML::Node source, bool show_source)
{
out << YAML::BeginMap;
for (auto n : value)
@ -945,9 +985,9 @@ namespace mamba
int append_blk = blk_size - prepend_blk;
out << YAML::Comment(std::string(54, '#')) << YAML::Newline;
out << YAML::Comment("#" + std::string(prepend_blk, ' ') + group_title
+ std::string(append_blk, ' ') + "#")
<< YAML::Newline;
out << YAML::Comment(
"#" + std::string(prepend_blk, ' ') + group_title + std::string(append_blk, ' ') + "#"
) << YAML::Newline;
out << YAML::Comment(std::string(54, '#'));
}
@ -1117,13 +1157,13 @@ namespace mamba
.description("Custom channels")
.long_description("A dictionary with name: url to use for custom channels."));
insert(
Configurable("custom_multichannels", &ctx.custom_multichannels)
.group("Channels")
.set_rc_configurable()
.description("Custom multichannels")
.long_description(
"A dictionary with name: list of names/urls to use for custom multichannels."));
insert(Configurable("custom_multichannels", &ctx.custom_multichannels)
.group("Channels")
.set_rc_configurable()
.description("Custom multichannels")
.long_description(
"A dictionary with name: list of names/urls to use for custom multichannels."
));
insert(Configurable("override_channels_enabled", &ctx.override_channels_enabled)
.group("Channels")
@ -1260,19 +1300,18 @@ namespace mamba
.group("Solver")
.description("Freeze already installed dependencies"));
insert(Configurable("force_reinstall", false)
insert(
Configurable("force_reinstall", false).group("Solver").description("Force reinstall of package")
);
insert(Configurable("no_deps", false)
.group("Solver")
.description("Force reinstall of package"));
.description("Do not install dependencies. This WILL lead to broken environments "
"and inconsistent behavior. Use at your own risk"));
insert(
Configurable("no_deps", false)
.group("Solver")
.description("Do not install dependencies. This WILL lead to broken environments "
"and inconsistent behavior. Use at your own risk"));
insert(Configurable("only_deps", false)
.group("Solver")
.description("Only install dependencies"));
Configurable("only_deps", false).group("Solver").description("Only install dependencies")
);
insert(Configurable("categories", std::vector<std::string>({ "main" }))
.group("Solver")
@ -1287,8 +1326,8 @@ namespace mamba
.group("Solver")
.set_rc_configurable()
.set_env_var_names()
.description(
"Allow uninstall when installing or updating packages. Default is true."));
.description("Allow uninstall when installing or updating packages. Default is true."
));
insert(Configurable("allow_downgrade", &ctx.allow_downgrade)
.group("Solver")
@ -1352,13 +1391,13 @@ namespace mamba
!WARNING: Using this option can result in corruption of long-lived
environments due to broken links (deleted cache).)")));
insert(
Configurable("shortcuts", &ctx.shortcuts)
.group("Extract, Link & Install")
.set_rc_configurable()
.set_env_var_names()
.description(
"Install start-menu shortcuts on Windows (not implemented on Linux / macOS)"));
insert(Configurable("shortcuts", &ctx.shortcuts)
.group("Extract, Link & Install")
.set_rc_configurable()
.set_env_var_names()
.description(
"Install start-menu shortcuts on Windows (not implemented on Linux / macOS)"
));
insert(Configurable("safety_checks", &ctx.safety_checks)
.group("Extract, Link & Install")
@ -1400,8 +1439,7 @@ namespace mamba
.group("Extract, Link & Install")
.set_rc_configurable()
.set_env_var_names()
.description(
"Enable or disable the usage of filesystem lockfiles for shared resources")
.description("Enable or disable the usage of filesystem lockfiles for shared resources")
.long_description(unindent(R"(
By default, mamba uses lockfiles on the filesystem to synchronize access to
shared resources for multiple mamba processes (such as the package cache).
@ -1438,8 +1476,8 @@ namespace mamba
insert(Configurable("download_only", &ctx.download_only)
.group("Output, Prompt and Flow Control")
.set_env_var_names()
.description(
"Only download and extract packages, do not link them into environment."));
.description("Only download and extract packages, do not link them into environment."
));
insert(Configurable("log_level", &ctx.logging_level)
.group("Output, Prompt and Flow Control")
@ -1482,21 +1520,21 @@ namespace mamba
.set_env_var_names()
.description("Report all output as json"));
insert(
Configurable("changeps1", &ctx.change_ps1)
.group("Output, Prompt and Flow Control")
.set_rc_configurable()
.set_env_var_names()
.description(
"When using activate, change the command prompt ($PS1) to include the activated environment."));
insert(Configurable("changeps1", &ctx.change_ps1)
.group("Output, Prompt and Flow Control")
.set_rc_configurable()
.set_env_var_names()
.description(
"When using activate, change the command prompt ($PS1) to include the activated environment."
));
insert(
Configurable("shell_completion", &ctx.shell_completion)
.group("Output, Prompt and Flow Control")
.set_rc_configurable()
.set_env_var_names()
.description(
"Enable or disable shell autocompletion (currently works for bash and zsh)."));
insert(Configurable("shell_completion", &ctx.shell_completion)
.group("Output, Prompt and Flow Control")
.set_rc_configurable()
.set_env_var_names()
.description(
"Enable or disable shell autocompletion (currently works for bash and zsh)."
));
insert(Configurable("env_prompt", &ctx.env_prompt)
.group("Output, Prompt and Flow Control")
@ -1510,19 +1548,17 @@ namespace mamba
active environment is a named environment ('-n' flag), or otherwise holds the value
of '{prefix}'.)")));
insert(
Configurable("print_config_only", false)
.group("Output, Prompt and Flow Control")
.needs({ "debug" })
.set_post_merge_hook(detail::print_config_only_hook)
.description("Print the context after loading the config. Allow ultra-dry runs"));
insert(Configurable("print_config_only", false)
.group("Output, Prompt and Flow Control")
.needs({ "debug" })
.set_post_merge_hook(detail::print_config_only_hook)
.description("Print the context after loading the config. Allow ultra-dry runs"));
insert(
Configurable("print_context_only", false)
.group("Output, Prompt and Flow Control")
.needs({ "debug" })
.set_post_merge_hook(detail::print_context_only_hook)
.description("Print the context after loading the config. Allow ultra-dry runs"));
insert(Configurable("print_context_only", false)
.group("Output, Prompt and Flow Control")
.needs({ "debug" })
.set_post_merge_hook(detail::print_context_only_hook)
.description("Print the context after loading the config. Allow ultra-dry runs"));
insert(Configurable("show_banner", true)
.group("Output, Prompt and Flow Control")
@ -1675,13 +1711,21 @@ namespace mamba
std::vector<fs::u8path> sources;
if (level >= RCConfigLevel::kSystemDir)
{
sources.insert(sources.end(), system.begin(), system.end());
}
if ((level >= RCConfigLevel::kRootPrefix) && !ctx.root_prefix.empty())
{
sources.insert(sources.end(), root.begin(), root.end());
}
if (level >= RCConfigLevel::kHomeDir)
{
sources.insert(sources.end(), home.begin(), home.end());
}
if ((level >= RCConfigLevel::kTargetPrefix) && !ctx.target_prefix.empty())
{
sources.insert(sources.end(), prefix.begin(), prefix.end());
}
// Sort by precedence
std::reverse(sources.begin(), sources.end());
@ -1718,7 +1762,9 @@ namespace mamba
CONFIG_DEBUGGING;
if (at("show_banner").value<bool>())
{
Console::instance().print(banner());
}
auto& ctx = Context::instance();
ctx.set_log_level(ctx.logging_level);
@ -1728,9 +1774,13 @@ namespace mamba
Context::instance().dump_backtrace_no_guards();
if (ctx.log_backtrace > 0)
{
spdlog::enable_backtrace(ctx.log_backtrace);
}
else
{
spdlog::disable_backtrace();
}
}
bool Configuration::is_loading()
@ -1744,12 +1794,16 @@ namespace mamba
std::vector<std::string> locks;
for (auto& c : m_config_order)
{
add_to_loading_sequence(m_loading_sequence, c, locks);
}
}
void Configuration::add_to_loading_sequence(std::vector<std::string>& seq,
const std::string& name,
std::vector<std::string>& locks)
void Configuration::add_to_loading_sequence(
std::vector<std::string>& seq,
const std::string& name,
std::vector<std::string>& locks
)
{
auto found = std::find(seq.begin(), seq.end(), name);
@ -1763,8 +1817,7 @@ namespace mamba
if (at(n).locked())
{
LOG_ERROR << "Circular import: " << join("->", locks) << "->" << n;
throw std::runtime_error(
"Circular import detected in configuration. Aborting.");
throw std::runtime_error("Circular import detected in configuration. Aborting.");
}
add_to_loading_sequence(seq, n, locks);
}
@ -1780,20 +1833,26 @@ namespace mamba
locks.pop_back();
for (auto& n : at(name).implied())
{
add_to_loading_sequence(seq, n, locks);
}
}
}
void Configuration::reset_compute_counters()
{
for (auto& c : m_config)
{
c.second.reset_compute_counter();
}
}
void Configuration::clear_rc_values()
{
for (auto& c : m_config)
{
c.second.clear_rc_values();
}
}
void Configuration::clear_rc_sources()
@ -1806,22 +1865,32 @@ namespace mamba
void Configuration::clear_cli_values()
{
for (auto& c : m_config)
{
c.second.clear_cli_value();
}
}
void Configuration::clear_values()
{
for (auto& c : m_config)
{
c.second.clear_values();
}
}
void Configuration::operation_teardown()
{
for (auto& c : m_config)
{
if (c.second.has_single_op_lifetime())
{
c.second.clear_values();
}
else
{
c.second.clear_cli_value();
}
}
}
std::vector<fs::u8path> Configuration::sources()
@ -1871,13 +1940,15 @@ namespace mamba
return config;
}
void Configuration::set_rc_values(std::vector<fs::u8path> possible_rc_paths,
const RCConfigLevel& level)
void
Configuration::set_rc_values(std::vector<fs::u8path> possible_rc_paths, const RCConfigLevel& level)
{
LOG_TRACE << "Get RC files configuration from locations up to "
<< YAML::Node(level).as<std::string>();
if (possible_rc_paths.empty())
{
possible_rc_paths = compute_default_rc_sources(level);
}
m_sources = get_existing_rc_sources(possible_rc_paths);
m_valid_sources.clear();
@ -1888,7 +1959,9 @@ namespace mamba
{
auto node = load_rc_file(s);
if (node.IsNull())
{
continue;
}
m_rc_yaml_nodes_cache.insert({ s, node });
}
@ -1902,15 +1975,18 @@ namespace mamba
auto& key = it.first;
auto& c = it.second;
if (!c.rc_configurable() || (c.rc_configurable_level() > level)
|| c.rc_configured())
if (!c.rc_configurable() || (c.rc_configurable_level() > level) || c.rc_configured())
{
continue;
}
for (const auto& source : m_valid_sources)
{
auto yaml = m_rc_yaml_nodes_cache[source];
if (!yaml[key] || yaml[key].IsNull())
{
continue;
}
c.set_rc_yaml_value(yaml[key], env::shrink_user(source).string());
}
@ -1918,8 +1994,8 @@ namespace mamba
}
}
std::vector<fs::u8path> Configuration::get_existing_rc_sources(
const std::vector<fs::u8path>& possible_rc_paths)
std::vector<fs::u8path>
Configuration::get_existing_rc_sources(const std::vector<fs::u8path>& possible_rc_paths)
{
std::vector<fs::u8path> sources;
@ -1948,7 +2024,9 @@ namespace mamba
else
{
if (!l.empty())
{
LOG_TRACE << "Configuration not found at '" << l.string() << "'";
}
}
}
@ -1966,9 +2044,11 @@ namespace mamba
void dump_configurable(nl::json& node, const Configurable& c, const std::string& name);
}
std::string dump_json(int opts,
const std::vector<std::string>& names,
const std::vector<Configuration::grouped_config_type>& grouped_config)
std::string dump_json(
int opts,
const std::vector<std::string>& names,
const std::vector<Configuration::grouped_config_type>& grouped_config
)
{
// bool show_values = opts & MAMBA_SHOW_CONFIG_VALUES;
bool show_sources = opts & MAMBA_SHOW_CONFIG_SRCS;
@ -2042,9 +2122,11 @@ namespace mamba
return root.dump(4);
}
std::string dump_yaml(int opts,
const std::vector<std::string>& names,
const std::vector<Configuration::grouped_config_type>& grouped_config)
std::string dump_yaml(
int opts,
const std::vector<std::string>& names,
const std::vector<Configuration::grouped_config_type>& grouped_config
)
{
bool show_values = opts & MAMBA_SHOW_CONFIG_VALUES;
bool show_sources = opts & MAMBA_SHOW_CONFIG_SRCS;
@ -2080,12 +2162,16 @@ namespace mamba
if (show_groups && first_group_config)
{
if (!first_config)
{
out << YAML::Newline << YAML::Newline;
}
detail::print_group_title(out, group_name);
}
if (!first_config || (first_config && show_groups))
{
out << YAML::Newline << YAML::Newline;
}
out << YAML::Comment(c->name()) << YAML::Newline;
if (show_long_descs)
@ -2101,7 +2187,9 @@ namespace mamba
if (show_values)
{
if (first_config)
{
out << YAML::BeginMap;
}
out << YAML::Key << c->name();
out << YAML::Value;
detail::print_configurable(out, *c, show_sources);
@ -2113,7 +2201,9 @@ namespace mamba
}
}
if (show_values && !first_config)
{
out << YAML::EndMap;
}
return out.c_str();
}

View File

@ -4,10 +4,10 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/configuration.hpp"
#include "mamba/api/create.hpp"
#include "mamba/api/install.hpp"
#include "mamba/api/configuration.hpp"
#include "mamba/api/install.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/util.hpp"
@ -21,8 +21,10 @@ namespace mamba
config.at("use_target_prefix_fallback").set_value(false);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_NOT_ENV_PREFIX
| MAMBA_NOT_ALLOW_MISSING_PREFIX | MAMBA_NOT_EXPECT_EXISTING_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_NOT_ENV_PREFIX
| MAMBA_NOT_ALLOW_MISSING_PREFIX | MAMBA_NOT_EXPECT_EXISTING_PREFIX
);
config.load();
auto& create_specs = config.at("specs").value<std::vector<std::string>>();
@ -39,12 +41,17 @@ namespace mamba
}
else if (fs::exists(ctx.target_prefix / "conda-meta"))
{
if (Console::prompt("Found conda-prefix at '" + ctx.target_prefix.string()
+ "'. Overwrite?",
'n'))
if (Console::prompt(
"Found conda-prefix at '" + ctx.target_prefix.string() + "'. Overwrite?",
'n'
))
{
fs::remove_all(ctx.target_prefix);
}
else
{
throw std::runtime_error("Aborting.");
}
}
else
{
@ -53,10 +60,14 @@ namespace mamba
}
}
if (create_specs.empty())
{
detail::create_empty_target(ctx.target_prefix);
}
if (config.at("platform").configured() && !config.at("platform").rc_configured())
{
detail::store_platform_config(ctx.target_prefix, ctx.platform);
}
}
if (Context::instance().env_lockfile)
@ -65,14 +76,19 @@ namespace mamba
install_lockfile_specs(
lockfile_path,
Configuration::instance().at("categories").value<std::vector<std::string>>(),
true);
true
);
}
else if (!create_specs.empty())
{
if (use_explicit)
{
install_explicit_specs(create_specs, true);
}
else
{
install_specs(create_specs, true);
}
}
config.operation_teardown();
@ -83,7 +99,9 @@ namespace mamba
void store_platform_config(const fs::u8path& prefix, const std::string& platform)
{
if (!fs::exists(prefix))
{
fs::create_directories(prefix);
}
auto out = open_ofstream(prefix / ".mambarc");
out << "platform: " << platform;

View File

@ -4,9 +4,9 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/configuration.hpp"
#include "mamba/api/info.hpp"
#include "mamba/api/configuration.hpp"
#include "mamba/core/channel.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/environment.hpp"
@ -28,8 +28,9 @@ namespace mamba
config.at("use_target_prefix_fallback").set_value(true);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_ALLOW_NOT_ENV_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX | MAMBA_ALLOW_NOT_ENV_PREFIX
);
config.load();
detail::print_info();
@ -48,7 +49,9 @@ namespace mamba
void info_pretty_print(std::vector<std::tuple<std::string, nlohmann::json>> items)
{
if (Context::instance().json)
{
return;
}
int key_max_length = 0;
for (auto& item : items)
@ -82,7 +85,9 @@ namespace mamba
{
std::map<std::string, nlohmann::json> items_map;
for (auto& [key, val] : items)
{
items_map.insert({ key, val });
}
Console::instance().json_write(items_map);
}
@ -125,8 +130,8 @@ namespace mamba
items.push_back({ "env location", location });
// items.insert( { "shell level", { 1 } });
items.push_back(
{ "user config files", { (env::home_directory() / ".mambarc").string() } });
items.push_back({ "user config files",
{ (env::home_directory() / ".mambarc").string() } });
Configuration& config = Configuration::instance();
std::vector<std::string> sources;
@ -139,7 +144,9 @@ namespace mamba
items.push_back({ "libmamba version", version() });
if (ctx.is_micromamba && !ctx.caller_version.empty())
{
items.push_back({ "micromamba version", ctx.caller_version });
}
items.push_back({ "curl version", curl_version() });
items.push_back({ "libarchive version", archive_version_details() });

View File

@ -4,18 +4,21 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/install.hpp"
#include <stdexcept>
#include <fmt/color.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <fmt/color.h>
#include <reproc/reproc.h>
#include <reproc++/run.hpp>
#include <reproc/reproc.h>
#include "mamba/api/configuration.hpp"
#include "mamba/api/install.hpp"
#include "mamba/api/channel_loader.hpp"
#include "mamba/api/configuration.hpp"
#include "mamba/core/activation.hpp"
#include "mamba/core/env_lockfile.hpp"
#include "mamba/core/environments_manager.hpp"
#include "mamba/core/mamba_fs.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/package_cache.hpp"
@ -23,9 +26,6 @@
#include "mamba/core/transaction.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/virtual_packages.hpp"
#include "mamba/core/env_lockfile.hpp"
#include "mamba/core/activation.hpp"
#include "mamba/core/environments_manager.hpp"
namespace mamba
{
@ -34,31 +34,32 @@ namespace mamba
using command_args = std::vector<std::string>;
tl::expected<command_args, std::runtime_error> get_other_pkg_mgr_install_instructions(
const std::string& name, const std::string& target_prefix, const fs::u8path& spec_file)
const std::string& name,
const std::string& target_prefix,
const fs::u8path& spec_file
)
{
const auto get_python_path
= [&] { return env::which("python", get_path_dirs(target_prefix)).string(); };
const auto get_python_path = [&]
{ return env::which("python", get_path_dirs(target_prefix)).string(); };
const std::unordered_map<std::string, command_args> other_pkg_mgr_install_instructions{
{ "pip",
{ get_python_path(), "-m", "pip", "install", "-r", spec_file, "--no-input" } },
{ "pip --no-deps",
{ get_python_path(),
"-m",
"pip",
"install",
"--no-deps",
"-r",
spec_file,
"--no-input" } }
{ get_python_path(), "-m", "pip", "install", "--no-deps", "-r", spec_file, "--no-input" } }
};
auto found_it = other_pkg_mgr_install_instructions.find(name);
if (found_it != other_pkg_mgr_install_instructions.end())
{
return found_it->second;
}
else
{
return tl::unexpected(std::runtime_error(
fmt::format("no install instruction found for package manager '{}'", name)));
fmt::format("no install instruction found for package manager '{}'", name)
));
}
}
}
@ -87,11 +88,17 @@ namespace mamba
|| (!terminated_not_an_err && reproc_terminated(status)))
{
if (ec)
{
LOG_ERROR << "Subprocess call failed: " << ec.message();
}
else if (reproc_killed(status))
{
LOG_ERROR << "Subprocess call failed (killed)";
}
else
{
LOG_ERROR << "Subprocess call failed (terminated)";
}
throw std::runtime_error("Subprocess call failed. Aborting.");
}
}
@ -108,30 +115,40 @@ namespace mamba
{
std::ofstream specs_f = open_ofstream(specs.path());
for (auto& d : deps)
{
specs_f << d.c_str() << '\n';
}
}
command_args install_instructions = [&]
{
const auto maybe_instructions = get_other_pkg_mgr_install_instructions(
pkg_mgr, ctx.target_prefix.string(), specs.path());
pkg_mgr,
ctx.target_prefix.string(),
specs.path()
);
if (maybe_instructions)
{
return maybe_instructions.value();
}
else
{
throw maybe_instructions.error();
}
}();
auto [wrapped_command, tmpfile]
= prepare_wrapped_call(ctx.target_prefix, install_instructions);
auto [wrapped_command, tmpfile] = prepare_wrapped_call(ctx.target_prefix, install_instructions);
reproc::options options;
options.redirect.parent = true;
options.working_directory = cwd.c_str();
Console::stream() << fmt::format(Context::instance().palette.external,
"\nInstalling {} packages: {}",
pkg_mgr,
fmt::join(deps, ", "));
Console::stream() << fmt::format(
Context::instance().palette.external,
"\nInstalling {} packages: {}",
pkg_mgr,
fmt::join(deps, ", ")
);
fmt::print(LOG_INFO, "Calling: {}", fmt::join(install_instructions, " "));
auto [status, ec] = reproc::run(wrapped_command, options);
@ -178,7 +195,8 @@ namespace mamba
if (!(starts_with(selector, "sel(") && selector[selector.size() - 1] == ')'))
{
throw std::runtime_error(
"Couldn't parse selector. Needs to start with sel( and end with )");
"Couldn't parse selector. Needs to start with sel( and end with )"
);
}
std::string expr = selector.substr(4, selector.size() - 5);
@ -214,7 +232,9 @@ namespace mamba
YAML::Node deps;
if (f["dependencies"] && f["dependencies"].IsSequence() && f["dependencies"].size() > 0)
{
deps = f["dependencies"];
}
else
{
LOG_ERROR << "No 'dependencies' specified in YAML spec file '" << file.string()
@ -249,14 +269,15 @@ namespace mamba
else
{
throw std::runtime_error(
"Complicated selection merge not implemented yet.");
"Complicated selection merge not implemented yet."
);
}
}
}
else if (key == "pip")
{
const auto yaml_parent_path
= fs::absolute(yaml_file).parent_path().string();
const auto yaml_parent_path = fs::absolute(yaml_file).parent_path().string(
);
result.others_pkg_mgrs_specs.push_back({
"pip",
map_el.second.as<std::vector<std::string>>(),
@ -275,13 +296,14 @@ namespace mamba
}
catch (const YAML::Exception& e)
{
LOG_ERROR << "Bad conversion of 'dependencies' to a vector of string: "
<< final_deps;
LOG_ERROR << "Bad conversion of 'dependencies' to a vector of string: " << final_deps;
throw e;
}
if (has_pip_deps && !std::count(dependencies.begin(), dependencies.end(), "pip"))
{
dependencies.push_back("pip");
}
result.dependencies = dependencies;
@ -313,15 +335,17 @@ namespace mamba
return result;
}
std::tuple<std::vector<PackageInfo>, std::vector<MatchSpec>> parse_urls_to_package_info(
const std::vector<std::string>& urls)
std::tuple<std::vector<PackageInfo>, std::vector<MatchSpec>>
parse_urls_to_package_info(const std::vector<std::string>& urls)
{
std::vector<PackageInfo> pi_result;
std::vector<MatchSpec> ms_result;
for (auto& u : urls)
{
if (strip(u).size() == 0)
{
continue;
}
std::size_t hash = u.find_first_of('#');
MatchSpec ms(u.substr(0, hash));
PackageInfo p(ms.name);
@ -355,8 +379,10 @@ namespace mamba
config.at("create_base").set_value(true);
config.at("use_target_prefix_fallback").set_value(true);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_NOT_ALLOW_MISSING_PREFIX
| MAMBA_NOT_ALLOW_NOT_ENV_PREFIX | MAMBA_EXPECT_EXISTING_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_NOT_ALLOW_MISSING_PREFIX
| MAMBA_NOT_ALLOW_NOT_ENV_PREFIX | MAMBA_EXPECT_EXISTING_PREFIX
);
config.load();
auto& install_specs = config.at("specs").value<std::vector<std::string>>();
@ -369,7 +395,8 @@ namespace mamba
install_lockfile_specs(
lockfile_path,
Configuration::instance().at("categories").value<std::vector<std::string>>(),
false);
false
);
}
else if (!install_specs.empty())
{
@ -393,10 +420,8 @@ namespace mamba
int RETRY_SUBDIR_FETCH = 1 << 0;
int RETRY_SOLVE_ERROR = 1 << 1;
void install_specs(const std::vector<std::string>& specs,
bool create_env,
int solver_flag,
int is_retry)
void
install_specs(const std::vector<std::string>& specs, bool create_env, int solver_flag, int is_retry)
{
auto& ctx = Context::instance();
auto& config = Configuration::instance();
@ -416,7 +441,8 @@ namespace mamba
if (!fs::exists(ctx.target_prefix) && create_env == false)
{
throw std::runtime_error(
fmt::format("Prefix does not exist at: {}", ctx.target_prefix.string()));
fmt::format("Prefix does not exist at: {}", ctx.target_prefix.string())
);
}
MultiPackageCache package_caches(ctx.pkgs_dirs);
@ -458,17 +484,20 @@ namespace mamba
std::vector<std::string> prefix_pkgs;
for (auto& it : prefix_data.records())
{
prefix_pkgs.push_back(it.first);
}
prefix_data.add_packages(get_virtual_packages());
MRepo::create(pool, prefix_data);
MSolver solver(std::move(pool),
{ { SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall },
{ SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY,
ctx.channel_priority == ChannelPriority::kStrict } });
MSolver solver(
std::move(pool),
{ { SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall },
{ SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY, ctx.channel_priority == ChannelPriority::kStrict } }
);
solver.set_postsolve_flags({ { MAMBA_NO_DEPS, no_deps },
{ MAMBA_ONLY_DEPS, only_deps },
@ -500,7 +529,9 @@ namespace mamba
{
std::vector<std::string> pinned_str;
for (auto& ms : solver.pinned_specs())
{
pinned_str.push_back(" - " + ms.conda_build_form() + "\n");
}
Console::instance().print("\nPinned packages:\n" + join("", pinned_str));
}
@ -514,15 +545,19 @@ namespace mamba
return install_specs(specs, create_env, solver_flag, is_retry | RETRY_SOLVE_ERROR);
}
if (freeze_installed)
{
Console::instance().print("Possible hints:\n - 'freeze_installed' is turned on\n");
}
if (ctx.json)
{
Console::instance().json_write(
{ { "success", false }, { "solver_problems", solver.all_problems() } });
Console::instance().json_write({ { "success", false },
{ "solver_problems", solver.all_problems() } });
}
throw mamba_error("Could not solve for environment specs",
mamba_error_code::satisfiablitity_error);
throw mamba_error(
"Could not solve for environment specs",
mamba_error_code::satisfiablitity_error
);
}
MTransaction trans(solver, package_caches);
@ -537,12 +572,14 @@ namespace mamba
if (trans.prompt())
{
if (create_env && !Context::instance().dry_run)
{
detail::create_target_directory(ctx.target_prefix);
}
trans.execute(prefix_data);
for (auto other_spec : config.at("others_pkg_mgrs_specs")
.value<std::vector<detail::other_pkg_mgr_spec>>())
for (auto other_spec :
config.at("others_pkg_mgrs_specs").value<std::vector<detail::other_pkg_mgr_spec>>())
{
install_for_other_pkgmgr(other_spec);
}
@ -567,8 +604,8 @@ namespace mamba
MultiPackageCache pkg_caches(ctx.pkgs_dirs);
prefix_data.add_packages(get_virtual_packages());
MRepo::create(
pool, prefix_data); // Potentially re-alloc (moves in memory) Solvables in the pool
MRepo::create(pool, prefix_data); // Potentially re-alloc (moves in memory) Solvables
// in the pool
std::vector<detail::other_pkg_mgr_spec> others;
// Note that the Transaction will gather the Solvables,
@ -576,12 +613,16 @@ namespace mamba
auto transaction = create_transaction(pool, pkg_caches, others);
if (ctx.json)
{
transaction.log_json();
}
if (transaction.prompt())
{
if (create_env && !Context::instance().dry_run)
{
detail::create_target_directory(ctx.target_prefix);
}
transaction.execute(prefix_data);
@ -598,12 +639,15 @@ namespace mamba
detail::install_explicit_with_transaction(
[&](auto& pool, auto& pkg_caches, auto& others)
{ return create_explicit_transaction_from_urls(pool, specs, pkg_caches, others); },
create_env);
create_env
);
}
void install_lockfile_specs(const std::string& lockfile,
const std::vector<std::string>& categories,
bool create_env)
void install_lockfile_specs(
const std::string& lockfile,
const std::vector<std::string>& categories,
bool create_env
)
{
std::unique_ptr<TemporaryFile> tmp_lock_file;
fs::u8path file;
@ -617,7 +661,8 @@ namespace mamba
if (!success || dt.http_status != 200)
{
throw std::runtime_error(
fmt::format("Could not download environment lockfile from {}", lockfile));
fmt::format("Could not download environment lockfile from {}", lockfile)
);
}
file = tmp_lock_file->path();
@ -629,10 +674,10 @@ namespace mamba
detail::install_explicit_with_transaction(
[&](auto& pool, auto& pkg_caches, auto& others) {
return create_explicit_transaction_from_lockfile(
pool, file, categories, pkg_caches, others);
return create_explicit_transaction_from_lockfile(pool, file, categories, pkg_caches, others);
},
create_env);
create_env
);
}
namespace detail
@ -641,10 +686,10 @@ namespace mamba
{
detail::create_target_directory(prefix);
Console::instance().print(
join("",
std::vector<std::string>(
{ "Empty environment created at prefix: ", prefix.string() })));
Console::instance().print(join(
"",
std::vector<std::string>({ "Empty environment created at prefix: ", prefix.string() })
));
Console::instance().json_write({ { "success", true } });
}
@ -666,7 +711,9 @@ namespace mamba
auto& channels = config.at("channels");
if (file_specs.size() == 0)
{
return;
}
for (const auto& file : file_specs)
{
@ -766,7 +813,9 @@ namespace mamba
{
std::string_view spec = strip((*f));
if (!spec.empty() && spec[0] != '#')
{
explicit_specs.push_back(*f);
}
}
specs.clear_values();

View File

@ -4,12 +4,12 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <regex>
#include <iostream>
#include "mamba/api/list.hpp"
#include "mamba/api/configuration.hpp"
#include <iostream>
#include <regex>
#include "mamba/api/configuration.hpp"
#include "mamba/core/channel.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/prefix_data.hpp"
@ -23,8 +23,10 @@ namespace mamba
config.at("show_banner").set_value(false);
config.at("use_target_prefix_fallback").set_value(true);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_NOT_ALLOW_NOT_ENV_PREFIX | MAMBA_EXPECT_EXISTING_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX
| MAMBA_NOT_ALLOW_NOT_ENV_PREFIX | MAMBA_EXPECT_EXISTING_PREFIX
);
config.load();
detail::list_packages(regex);

View File

@ -28,8 +28,10 @@ namespace mamba
config.at("use_target_prefix_fallback").set_value(true);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_NOT_ALLOW_MISSING_PREFIX
| MAMBA_NOT_ALLOW_NOT_ENV_PREFIX | MAMBA_EXPECT_EXISTING_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_NOT_ALLOW_MISSING_PREFIX
| MAMBA_NOT_ALLOW_NOT_ENV_PREFIX | MAMBA_EXPECT_EXISTING_PREFIX
);
config.load();
auto remove_specs = config.at("specs").value<std::vector<std::string>>();
@ -90,10 +92,14 @@ namespace mamba
auto execute_transaction = [&](MTransaction& transaction)
{
if (ctx.json)
{
transaction.log_json();
}
if (transaction.prompt())
{
transaction.execute(prefix_data);
}
};
if (force)
@ -104,24 +110,30 @@ namespace mamba
}
else
{
MSolver solver(std::move(pool),
{ { SOLVER_FLAG_ALLOW_DOWNGRADE, 1 },
{ SOLVER_FLAG_ALLOW_UNINSTALL, 1 },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY,
ctx.channel_priority == ChannelPriority::kStrict } });
MSolver solver(
std::move(pool),
{ { SOLVER_FLAG_ALLOW_DOWNGRADE, 1 },
{ SOLVER_FLAG_ALLOW_UNINSTALL, 1 },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY,
ctx.channel_priority == ChannelPriority::kStrict } }
);
History history(ctx.target_prefix);
auto hist_map = history.get_requested_specs_map();
std::vector<std::string> keep_specs;
for (auto& it : hist_map)
{
keep_specs.push_back(it.second.conda_build_form());
}
solver.add_jobs(keep_specs, SOLVER_USERINSTALLED);
int solver_flag = SOLVER_ERASE;
if (prune)
{
solver_flag |= SOLVER_CLEANDEPS;
}
solver.add_jobs(specs, solver_flag);
solver.must_solve();

View File

@ -4,19 +4,16 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/repoquery.hpp"
#include <iostream>
#include "mamba/api/configuration.hpp"
#include "mamba/api/channel_loader.hpp"
#include "mamba/api/repoquery.hpp"
#include "mamba/api/configuration.hpp"
namespace mamba
{
void repoquery(QueryType type,
QueryResultFormat format,
bool use_local,
const std::string& query)
void repoquery(QueryType type, QueryResultFormat format, bool use_local, const std::string& query)
{
auto& ctx = Context::instance();
auto& config = Configuration::instance();
@ -76,9 +73,10 @@ namespace mamba
}
else if (type == QueryType::kDEPENDS)
{
auto res = q.depends(query,
format == QueryResultFormat::kTREE
|| format == QueryResultFormat::kRECURSIVETABLE);
auto res = q.depends(
query,
format == QueryResultFormat::kTREE || format == QueryResultFormat::kRECURSIVETABLE
);
switch (format)
{
case QueryResultFormat::kTREE:
@ -95,9 +93,10 @@ namespace mamba
}
else if (type == QueryType::kWHONEEDS)
{
auto res = q.whoneeds(query,
format == QueryResultFormat::kTREE
|| format == QueryResultFormat::kRECURSIVETABLE);
auto res = q.whoneeds(
query,
format == QueryResultFormat::kTREE || format == QueryResultFormat::kRECURSIVETABLE
);
switch (format)
{
case QueryResultFormat::kTREE:
@ -111,7 +110,8 @@ namespace mamba
case QueryResultFormat::kRECURSIVETABLE:
res.sort("name").table(
std::cout,
{ "Name", "Version", "Build", concat("Depends:", query), "Channel" });
{ "Name", "Version", "Build", concat("Depends:", query), "Channel" }
);
}
}

View File

@ -4,11 +4,11 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/shell.hpp"
#include <iostream>
#include "mamba/api/configuration.hpp"
#include "mamba/api/shell.hpp"
#include "mamba/core/activation.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/environment.hpp"
@ -43,10 +43,8 @@ namespace mamba
}
}
void shell(const std::string& action,
std::string& shell_type,
const std::string& prefix,
bool stack)
void
shell(const std::string& action, std::string& shell_type, const std::string& prefix, bool stack)
{
auto& ctx = Context::instance();
auto& config = Configuration::instance();
@ -95,18 +93,26 @@ namespace mamba
if (action == "init")
{
if (prefix.empty() || prefix == "base")
{
shell_prefix = ctx.root_prefix.string();
}
else
{
shell_prefix = fs::weakly_canonical(env::expand_user(prefix)).string();
}
init_shell(shell_type, shell_prefix);
}
else if (action == "deinit")
{
if (prefix.empty() || prefix == "base")
{
shell_prefix = ctx.root_prefix.string();
}
else
{
shell_prefix = fs::weakly_canonical(env::expand_user(prefix)).string();
}
deinit_shell(shell_type, shell_prefix);
}
@ -127,7 +133,8 @@ namespace mamba
{ { "success", true },
{ "operation", "shell_hook" },
{ "context", { { "shell_type", shell_type } } },
{ "actions", { { "print", { activator->hook(shell_type) } } } } });
{ "actions", { { "print", { activator->hook(shell_type) } } } } }
);
}
else
{
@ -137,15 +144,22 @@ namespace mamba
else if (action == "activate")
{
if (prefix.empty() || prefix == "base")
{
shell_prefix = ctx.root_prefix.string();
}
else if (prefix.find_first_of("/\\") == std::string::npos)
{
shell_prefix = (ctx.root_prefix / "envs" / prefix).string();
}
else
{
shell_prefix = fs::weakly_canonical(env::expand_user(prefix)).string();
}
if (!fs::exists(shell_prefix))
throw std::runtime_error("Cannot activate, prefix does not exist at: "
+ shell_prefix);
{
throw std::runtime_error("Cannot activate, prefix does not exist at: " + shell_prefix);
}
std::cout << activator->activate(shell_prefix, stack);
}
@ -168,8 +182,7 @@ namespace mamba
#endif
else
{
throw std::runtime_error(
"Need an action {init, hook, activate, deactivate, reactivate}");
throw std::runtime_error("Need an action {init, hook, activate, deactivate, reactivate}");
}
config.operation_teardown();

View File

@ -4,13 +4,13 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/api/configuration.hpp"
#include "mamba/api/update.hpp"
#include "mamba/api/channel_loader.hpp"
#include "mamba/api/channel_loader.hpp"
#include "mamba/api/configuration.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/pinning.hpp"
#include "mamba/core/transaction.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/virtual_packages.hpp"
@ -23,8 +23,10 @@ namespace mamba
config.at("use_target_prefix_fallback").set_value(true);
config.at("target_prefix_checks")
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_NOT_ALLOW_MISSING_PREFIX
| MAMBA_NOT_ALLOW_NOT_ENV_PREFIX | MAMBA_EXPECT_EXISTING_PREFIX);
.set_value(
MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_NOT_ALLOW_MISSING_PREFIX
| MAMBA_NOT_ALLOW_NOT_ENV_PREFIX | MAMBA_EXPECT_EXISTING_PREFIX
);
config.load();
auto update_specs = config.at("specs").value<std::vector<std::string>>();
@ -59,17 +61,20 @@ namespace mamba
std::vector<std::string> prefix_pkgs;
for (auto& it : prefix_data.records())
{
prefix_pkgs.push_back(it.first);
}
prefix_data.add_packages(get_virtual_packages());
MRepo::create(pool, prefix_data);
MSolver solver(std::move(pool),
{ { SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade },
{ SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY,
ctx.channel_priority == ChannelPriority::kStrict } });
MSolver solver(
std::move(pool),
{ { SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade },
{ SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY, ctx.channel_priority == ChannelPriority::kStrict } }
);
if (update_all)
{
@ -113,7 +118,9 @@ namespace mamba
{
std::vector<std::string> pinned_str;
for (auto& ms : solver.pinned_specs())
{
pinned_str.push_back(" - " + ms.conda_build_form() + "\n");
}
Console::instance().print("\nPinned packages:\n" + join("", pinned_str));
}
@ -124,11 +131,15 @@ namespace mamba
auto execute_transaction = [&](MTransaction& transaction)
{
if (ctx.json)
{
transaction.log_json();
}
bool yes = transaction.prompt();
if (yes)
{
transaction.execute(prefix_data);
}
};
execute_transaction(transaction);

View File

@ -5,6 +5,7 @@
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/activation.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/environment.hpp"
#include "mamba/core/output.hpp"
@ -63,8 +64,8 @@ namespace mamba
}
}
std::vector<std::pair<std::string, std::string>> Activator::get_environment_vars(
const fs::u8path& prefix)
std::vector<std::pair<std::string, std::string>>
Activator::get_environment_vars(const fs::u8path& prefix)
{
fs::u8path env_vars_file = prefix / PREFIX_STATE_FILE;
fs::u8path pkg_env_var_dir = prefix / PACKAGE_ENV_VARS_DIR;
@ -125,9 +126,11 @@ namespace mamba
return res;
}
std::string Activator::get_prompt_modifier(const fs::u8path& prefix,
const std::string& conda_default_env,
int old_conda_shlvl)
std::string Activator::get_prompt_modifier(
const fs::u8path& prefix,
const std::string& conda_default_env,
int old_conda_shlvl
)
{
if (Context::instance().change_ps1)
{
@ -136,10 +139,12 @@ namespace mamba
std::string env_i;
for (int i = 1; i < old_conda_shlvl + 1; ++i)
{
const std::string env_prefix
= (i == old_conda_shlvl) ? "CONDA_PREFIX" : "CONDA_PREFIX_" + std::to_string(i);
const std::string default_prefix
= (m_env.find(env_prefix) != m_env.end()) ? m_env[env_prefix] : "";
const std::string env_prefix = (i == old_conda_shlvl)
? "CONDA_PREFIX"
: "CONDA_PREFIX_" + std::to_string(i);
const std::string default_prefix = (m_env.find(env_prefix) != m_env.end())
? m_env[env_prefix]
: "";
env_i = get_default_env(default_prefix);
bool stacked_i = m_env.find("CONDA_STACKED_" + std::to_string(i)) != m_env.end();
@ -156,11 +161,15 @@ namespace mamba
if (m_action == ActivationType::DEACTIVATE)
{
if (prompt_stack.size())
{
prompt_stack.pop_back();
}
if (env_stack.size())
{
env_stack.pop_back();
bool stacked
= m_env.find("CONDA_STACKED_" + std::to_string(old_conda_shlvl)) != m_env.end();
}
bool stacked = m_env.find("CONDA_STACKED_" + std::to_string(old_conda_shlvl))
!= m_env.end();
if (!stacked && env_stack.size())
{
prompt_stack.push_back(env_stack.back());
@ -268,10 +277,11 @@ namespace mamba
// never trigger.
if (old_conda_shlvl == 0)
{
bool no_condabin = std::none_of(path_list.begin(),
path_list.end(),
[](const fs::u8path& s)
{ return ends_with(s.string(), "condabin"); });
bool no_condabin = std::none_of(
path_list.begin(),
path_list.end(),
[](const fs::u8path& s) { return ends_with(s.string(), "condabin"); }
);
if (no_condabin)
{
auto condabin_dir = Context::instance().root_prefix / "condabin";
@ -289,8 +299,8 @@ namespace mamba
return result;
}
std::string Activator::replace_prefix_in_path(const fs::u8path& old_prefix,
const fs::u8path& new_prefix)
std::string
Activator::replace_prefix_in_path(const fs::u8path& old_prefix, const fs::u8path& new_prefix)
{
// TODO not done yet.
std::vector<fs::u8path> current_path = get_clean_dirs();
@ -333,8 +343,10 @@ namespace mamba
}
else
{
current_path.erase(std::unique(current_path.begin(), current_path.end()),
current_path.end());
current_path.erase(
std::unique(current_path.begin(), current_path.end()),
current_path.end()
);
std::string result = join(env::pathsep(), current_path).string();
return result;
}
@ -347,7 +359,8 @@ namespace mamba
void Activator::get_export_unset_vars(
EnvironmentTransform& envt,
const std::vector<std::pair<std::string, std::string>>& to_export)
const std::vector<std::pair<std::string, std::string>>& to_export
)
{
// conda_exe_vars_export = OrderedDict()
// for k, v in context.conda_exe_vars_dict.items():
@ -395,8 +408,11 @@ namespace mamba
auto new_path = replace_prefix_in_path(conda_prefix, conda_prefix);
std::string conda_prompt_modifier
= get_prompt_modifier(conda_prefix, conda_default_env, conda_shlvl);
std::string conda_prompt_modifier = get_prompt_modifier(
conda_prefix,
conda_default_env,
conda_shlvl
);
if (Context::instance().change_ps1)
{
auto res = update_prompt(conda_prompt_modifier);
@ -406,10 +422,11 @@ namespace mamba
}
}
std::vector<std::pair<std::string, std::string>> env_vars_to_export
= { { "path", new_path },
{ "conda_shlvl", std::to_string(conda_shlvl) },
{ "conda_prompt_modifier", conda_prompt_modifier } };
std::vector<std::pair<std::string, std::string>> env_vars_to_export = {
{ "path", new_path },
{ "conda_shlvl", std::to_string(conda_shlvl) },
{ "conda_prompt_modifier", conda_prompt_modifier }
};
get_export_unset_vars(envt, env_vars_to_export);
// TODO figure out if this is all really necessary?
@ -456,11 +473,12 @@ namespace mamba
// and anything at all in my env still references it (apart from the shell
// script, we need something I suppose!)
envt.export_path = new_path;
std::vector<std::pair<std::string, std::string>> env_vars_to_export
= { { "conda_prefix", "" },
{ "conda_shlvl", std::to_string(new_conda_shlvl) },
{ "conda_default_env", "" },
{ "conda_prompt_modifier", "" } };
std::vector<std::pair<std::string, std::string>> env_vars_to_export = {
{ "conda_prefix", "" },
{ "conda_shlvl", std::to_string(new_conda_shlvl) },
{ "conda_default_env", "" },
{ "conda_prompt_modifier", "" }
};
get_export_unset_vars(envt, env_vars_to_export);
}
else
@ -468,8 +486,7 @@ namespace mamba
assert(old_conda_shlvl > 1);
std::string new_prefix = m_env.at("CONDA_PREFIX_" + std::to_string(new_conda_shlvl));
std::string conda_default_env = get_default_env(new_prefix);
conda_prompt_modifier
= get_prompt_modifier(new_prefix, conda_default_env, old_conda_shlvl);
conda_prompt_modifier = get_prompt_modifier(new_prefix, conda_default_env, old_conda_shlvl);
auto new_conda_environment_env_vars = get_environment_vars(new_prefix);
bool old_prefix_stacked
@ -487,11 +504,12 @@ namespace mamba
new_path = replace_prefix_in_path(old_conda_prefix, new_prefix);
}
std::vector<std::pair<std::string, std::string>> env_vars_to_export
= { { "conda_prefix", new_prefix },
{ "conda_shlvl", std::to_string(new_conda_shlvl) },
{ "conda_default_env", conda_default_env },
{ "conda_prompt_modifier", conda_prompt_modifier } };
std::vector<std::pair<std::string, std::string>> env_vars_to_export = {
{ "conda_prefix", new_prefix },
{ "conda_shlvl", std::to_string(new_conda_shlvl) },
{ "conda_default_env", conda_default_env },
{ "conda_prompt_modifier", conda_prompt_modifier }
};
get_export_unset_vars(envt, env_vars_to_export);
@ -516,8 +534,7 @@ namespace mamba
for (auto& env_var : old_conda_environment_env_vars)
{
envt.unset_vars.push_back(env_var.first);
std::string save_var
= fmt::format("__CONDA_SHLVL_{}_{}", new_conda_shlvl, env_var.first);
std::string save_var = fmt::format("__CONDA_SHLVL_{}_{}", new_conda_shlvl, env_var.first);
if (m_env.find(save_var) != m_env.end())
{
envt.export_vars.push_back({ env_var.first, m_env[save_var] });
@ -576,27 +593,35 @@ namespace mamba
envt.activate_scripts = get_activate_scripts(prefix);
std::string conda_default_env = get_default_env(prefix);
std::string conda_prompt_modifier
= get_prompt_modifier(prefix, conda_default_env, old_conda_shlvl);
std::string conda_prompt_modifier = get_prompt_modifier(
prefix,
conda_default_env,
old_conda_shlvl
);
auto conda_environment_env_vars = get_environment_vars(prefix);
// TODO check with conda if that's really what's supposed to happen ...
std::remove_if(conda_environment_env_vars.begin(),
conda_environment_env_vars.end(),
[](auto& el) { return el.second == CONDA_ENV_VARS_UNSET_VAR; });
std::remove_if(
conda_environment_env_vars.begin(),
conda_environment_env_vars.end(),
[](auto& el) { return el.second == CONDA_ENV_VARS_UNSET_VAR; }
);
std::vector<std::string> clobbering_env_vars;
for (auto& env_var : conda_environment_env_vars)
{
if (m_env.find(env_var.first) != m_env.end())
{
clobbering_env_vars.push_back(env_var.first);
}
}
for (const auto& v : clobbering_env_vars)
{
conda_environment_env_vars.push_back(
{ fmt::format("__CONDA_SHLVL_{}_{}", old_conda_shlvl, v), m_env[v] });
{ fmt::format("__CONDA_SHLVL_{}_{}", old_conda_shlvl, v), m_env[v] }
);
}
if (clobbering_env_vars.size())
@ -627,10 +652,9 @@ namespace mamba
else if (m_stack)
{
get_export_unset_vars(envt, env_vars_to_export);
envt.export_vars.push_back(
{ fmt::format("CONDA_PREFIX_{}", old_conda_shlvl), old_conda_prefix });
envt.export_vars.push_back(
{ fmt::format("CONDA_STACKED_{}", new_conda_shlvl), "true" });
envt.export_vars.push_back({ fmt::format("CONDA_PREFIX_{}", old_conda_shlvl),
old_conda_prefix });
envt.export_vars.push_back({ fmt::format("CONDA_STACKED_{}", new_conda_shlvl), "true" });
}
else
{
@ -647,15 +671,17 @@ namespace mamba
+ env_var.first; // % (new_conda_shlvl, env_var)
if (m_env.find(save_var) != m_env.end())
{
envt.export_vars.insert(envt.export_vars.begin(),
{ env_var.first, m_env[save_var] });
envt.export_vars.insert(
envt.export_vars.begin(),
{ env_var.first, m_env[save_var] }
);
}
}
env_vars_to_export[0] = { "PATH", new_path };
get_export_unset_vars(envt, env_vars_to_export);
envt.export_vars.push_back(
{ fmt::format("CONDA_PREFIX_{}", old_conda_shlvl), old_conda_prefix });
envt.export_vars.push_back({ fmt::format("CONDA_PREFIX_{}", old_conda_shlvl),
old_conda_prefix });
}
if (Context::instance().change_ps1)
@ -788,8 +814,8 @@ namespace mamba
return out.str();
}
std::pair<std::string, std::string> PosixActivator::update_prompt(
const std::string& conda_prompt_modifier)
std::pair<std::string, std::string>
PosixActivator::update_prompt(const std::string& conda_prompt_modifier)
{
std::string ps1 = (m_env.find("PS1") != m_env.end()) ? m_env["PS1"] : "";
if (ps1.find("POWERLINE_COMMAND") != ps1.npos)
@ -907,8 +933,8 @@ namespace mamba
return out.str();
}
std::pair<std::string, std::string> CshActivator::update_prompt(
const std::string& conda_prompt_modifier)
std::pair<std::string, std::string>
CshActivator::update_prompt(const std::string& conda_prompt_modifier)
{
std::string prompt = (m_env.find("prompt") != m_env.end()) ? m_env["prompt"] : "";
auto current_prompt_modifier = env::get("CONDA_PROMPT_MODIFIER");
@ -975,8 +1001,8 @@ namespace mamba
return "";
}
std::pair<std::string, std::string> CmdExeActivator::update_prompt(
const std::string& /* conda_prompt_modifier */)
std::pair<std::string, std::string>
CmdExeActivator::update_prompt(const std::string& /* conda_prompt_modifier */)
{
return { "", "" };
}
@ -1035,8 +1061,10 @@ namespace mamba
std::string PowerShellActivator::hook_preamble()
{
return fmt::format("$MambaModuleArgs = @{{ChangePs1 = ${}}}",
Context::instance().change_ps1 ? "True" : "False");
return fmt::format(
"$MambaModuleArgs = @{{ChangePs1 = ${}}}",
Context::instance().change_ps1 ? "True" : "False"
);
}
std::string PowerShellActivator::hook_postamble()
@ -1049,8 +1077,8 @@ namespace mamba
return Context::instance().root_prefix / "condabin" / "mamba_hook.ps1";
}
std::pair<std::string, std::string> PowerShellActivator::update_prompt(
const std::string& /*conda_prompt_modifier*/)
std::pair<std::string, std::string>
PowerShellActivator::update_prompt(const std::string& /*conda_prompt_modifier*/)
{
return { "", "" };
}
@ -1117,8 +1145,8 @@ namespace mamba
return Context::instance().root_prefix / "etc" / "profile.d" / "mamba.xsh";
}
std::pair<std::string, std::string> XonshActivator::update_prompt(
const std::string& /*conda_prompt_modifier*/)
std::pair<std::string, std::string>
XonshActivator::update_prompt(const std::string& /*conda_prompt_modifier*/)
{
return { "", "" };
}
@ -1185,8 +1213,8 @@ namespace mamba
return Context::instance().root_prefix / "etc" / "fish" / "conf.d" / "mamba.fish";
}
std::pair<std::string, std::string> FishActivator::update_prompt(
const std::string& /*conda_prompt_modifier*/)
std::pair<std::string, std::string>
FishActivator::update_prompt(const std::string& /*conda_prompt_modifier*/)
{
return { "", "" };
}

View File

@ -22,7 +22,6 @@
#include "mamba/core/url.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/validate.hpp"
#include "mamba/core/environment.hpp"
namespace mamba
@ -30,22 +29,27 @@ namespace mamba
// Constants used by Channel and ChannelContext
namespace
{
const std::map<std::string, std::string> DEFAULT_CUSTOM_CHANNELS
= { { "pkgs/pro", "https://repo.anaconda.com" } };
const std::map<std::string, std::string> DEFAULT_CUSTOM_CHANNELS = {
{ "pkgs/pro", "https://repo.anaconda.com" }
};
const char UNKNOWN_CHANNEL[] = "<unknown>";
const std::set<std::string> INVALID_CHANNELS
= { "<unknown>", "None:///<unknown>", "None", "", ":///<unknown>" };
const std::set<std::string> INVALID_CHANNELS = { "<unknown>",
"None:///<unknown>",
"None",
"",
":///<unknown>" };
const char LOCAL_CHANNELS_NAME[] = "local";
const char DEFAULT_CHANNELS_NAME[] = "defaults";
// ATTENTION names with substrings need to go longer -> smalle
// otherwise linux-ppc64 matches for linux-ppc64le etc!
const std::vector<std::string> KNOWN_PLATFORMS
= { "noarch", "linux-32", "linux-64", "linux-aarch64", "linux-armv6l",
"linux-armv7l", "linux-ppc64le", "linux-ppc64", "osx-64", "osx-arm64",
"win-32", "win-64", "zos-z" };
const std::vector<std::string> KNOWN_PLATFORMS = {
"noarch", "linux-32", "linux-64", "linux-aarch64", "linux-armv6l",
"linux-armv7l", "linux-ppc64le", "linux-ppc64", "osx-64", "osx-arm64",
"win-32", "win-64", "zos-z"
};
} // namespace
/**************************
@ -86,13 +90,15 @@ namespace mamba
}
}
Channel::Channel(const std::string& scheme,
const std::string& location,
const std::string& name,
const std::optional<std::string>& auth,
const std::optional<std::string>& token,
const std::optional<std::string>& package_filename,
const std::optional<std::string>& canonical_name)
Channel::Channel(
const std::string& scheme,
const std::string& location,
const std::string& name,
const std::optional<std::string>& auth,
const std::optional<std::string>& token,
const std::optional<std::string>& package_filename,
const std::optional<std::string>& canonical_name
)
: m_scheme(scheme)
, m_location(location)
, m_name(name)
@ -147,7 +153,8 @@ namespace mamba
rsplit(base_url(), "/", 1).front(),
Context::instance().root_prefix / "etc" / "trusted-repos"
/ cache_name_from_url(base_url()),
caches.first_writable_path() / "cache" / cache_name_from_url(base_url()));
caches.first_writable_path() / "cache" / cache_name_from_url(base_url())
);
fs::create_directories(p_repo_checker->cache_path());
p_repo_checker->generate_index_checker();
@ -204,8 +211,9 @@ namespace mamba
}
std::string platform = m_platforms[0];
return { { build_url(
*this, join_url(base, name(), platform, *package_filename()), with_credential) } };
return {
{ build_url(*this, join_url(base, name(), platform, *package_filename()), with_credential) }
};
}
else
{
@ -218,8 +226,7 @@ namespace mamba
}
}
std::vector<std::pair<std::string, std::string>> Channel::platform_urls(
bool with_credential) const
std::vector<std::pair<std::string, std::string>> Channel::platform_urls(bool with_credential) const
{
std::string base = location();
if (with_credential && token())
@ -230,8 +237,10 @@ namespace mamba
std::vector<std::pair<std::string, std::string>> ret;
for (const auto& platform : platforms())
{
ret.emplace_back(platform,
build_url(*this, join_url(base, name(), platform), with_credential));
ret.emplace_back(
platform,
build_url(*this, join_url(base, name(), platform), with_credential)
);
}
return ret;
}
@ -309,24 +318,30 @@ namespace mamba
if (whitelist.size())
{
std::vector<std::string> accepted_urls(whitelist.size());
std::transform(whitelist.begin(),
whitelist.end(),
accepted_urls.begin(),
[](const std::string& url) { return make_channel(url).base_url(); });
std::for_each(urls.begin(),
urls.end(),
[&accepted_urls](const std::string& s)
{
auto it = std::find(accepted_urls.begin(),
accepted_urls.end(),
make_channel(s).base_url());
if (it == accepted_urls.end())
{
std::ostringstream str;
str << "Channel " << s << " not allowed";
throw std::runtime_error(str.str().c_str());
}
});
std::transform(
whitelist.begin(),
whitelist.end(),
accepted_urls.begin(),
[](const std::string& url) { return make_channel(url).base_url(); }
);
std::for_each(
urls.begin(),
urls.end(),
[&accepted_urls](const std::string& s)
{
auto it = std::find(
accepted_urls.begin(),
accepted_urls.end(),
make_channel(s).base_url()
);
if (it == accepted_urls.end())
{
std::ostringstream str;
str << "Channel " << s << " not allowed";
throw std::runtime_error(str.str().c_str());
}
}
);
}
}
@ -334,10 +349,12 @@ namespace mamba
* ChannelBuilder implementation *
*********************************/
Channel ChannelBuilder::make_simple_channel(const Channel& channel_alias,
const std::string& channel_url,
const std::string& channel_name,
const std::string& multi_name)
Channel ChannelBuilder::make_simple_channel(
const Channel& channel_alias,
const std::string& channel_url,
const std::string& channel_name,
const std::string& multi_name
)
{
std::string name(channel_name);
std::string location, scheme, auth, token;
@ -362,18 +379,22 @@ namespace mamba
std::string full_url = concat_scheme_url(scheme, location);
URLHandler parser(full_url);
location = rstrip(
URLHandler().set_host(parser.host()).set_port(parser.port()).url(), "/");
URLHandler().set_host(parser.host()).set_port(parser.port()).url(),
"/"
);
name = lstrip(parser.path(), "/");
}
}
name = name != "" ? strip(name, "/") : strip(channel_url, "/");
return Channel(scheme,
location,
name,
nonempty_str(std::move(auth)),
nonempty_str(std::move(token)),
{},
nonempty_str(std::string(multi_name)));
return Channel(
scheme,
location,
name,
nonempty_str(std::move(auth)),
nonempty_str(std::move(token)),
{},
nonempty_str(std::string(multi_name))
);
}
const Channel& ChannelBuilder::make_cached_channel(const std::string& value)
@ -386,10 +407,12 @@ namespace mamba
auto chan = ChannelBuilder::from_value(value);
if (!chan.token())
{
auto const& with_channel
= join_url(chan.location(), chan.name() == UNKNOWN_CHANNEL ? "" : chan.name());
auto const& without_channel = chan.location();
for (auto const& auth : { with_channel, without_channel })
const auto& with_channel = join_url(
chan.location(),
chan.name() == UNKNOWN_CHANNEL ? "" : chan.name()
);
const auto& without_channel = chan.location();
for (const auto& auth : { with_channel, without_channel })
{
auto it = ctx.authentication_info().find(auth);
if (it != ctx.authentication_info().end()
@ -398,8 +421,7 @@ namespace mamba
chan.m_token = it->second.value;
break;
}
else if (it != ctx.authentication_info().end()
&& it->second.type == AuthenticationType::kBasicHTTPAuthentication)
else if (it != ctx.authentication_info().end() && it->second.type == AuthenticationType::kBasicHTTPAuthentication)
{
chan.m_auth = it->second.value;
break;
@ -418,14 +440,16 @@ namespace mamba
namespace
{
void split_conda_url(const std::string& url,
std::string& scheme,
std::string& host,
std::string& port,
std::string& path,
std::string& auth,
std::string& token,
std::string& package_name)
void split_conda_url(
const std::string& url,
std::string& scheme,
std::string& host,
std::string& port,
std::string& path,
std::string& auth,
std::string& token,
std::string& package_name
)
{
std::string cleaned_url, extension;
split_anaconda_token(url, cleaned_url, token);
@ -452,11 +476,13 @@ namespace mamba
struct channel_configuration
{
channel_configuration(const std::string& location,
const std::string& name,
const std::string& scheme,
const std::string& auth,
const std::string& token)
channel_configuration(
const std::string& location,
const std::string& name,
const std::string& scheme,
const std::string& auth,
const std::string& token
)
: m_location(location)
, m_name(name)
, m_scheme(scheme)
@ -472,23 +498,27 @@ namespace mamba
std::string m_token;
};
channel_configuration read_channel_configuration(const std::string& scheme,
const std::string& host,
const std::string& port,
const std::string& path)
channel_configuration read_channel_configuration(
const std::string& scheme,
const std::string& host,
const std::string& port,
const std::string& path
)
{
std::string spath = std::string(rstrip(path, "/"));
std::string url
= URLHandler().set_scheme(scheme).set_host(host).set_port(port).set_path(spath).url(
true);
std::string url = URLHandler()
.set_scheme(scheme)
.set_host(host)
.set_port(port)
.set_path(spath)
.url(true);
// Case 1: No path given, channel name is ""
if (spath == "")
{
URLHandler handler;
handler.set_host(host).set_port(port);
return channel_configuration(
std::string(rstrip(handler.url(), "/")), "", scheme, "", "");
return channel_configuration(std::string(rstrip(handler.url(), "/")), "", scheme, "", "");
}
// Case 2: migrated_custom_channels not implemented yet
@ -504,11 +534,13 @@ namespace mamba
{
auto subname = std::string(strip(url.replace(0u, test_url.size(), ""), "/"));
return channel_configuration(channel.location(),
join_url(channel.name(), subname),
scheme,
channel.auth().value_or(""),
channel.token().value_or(""));
return channel_configuration(
channel.location(),
join_url(channel.name(), subname),
scheme,
channel.auth().value_or(""),
channel.token().value_or("")
);
}
}
@ -518,7 +550,12 @@ namespace mamba
{
auto name = std::string(strip(url.replace(0u, ca.location().size(), ""), "/"));
return channel_configuration(
ca.location(), name, scheme, ca.auth().value_or(""), ca.token().value_or(""));
ca.location(),
name,
scheme,
ca.auth().value_or(""),
ca.token().value_or("")
);
}
// Case 6: not-otherwise-specified file://-type urls
@ -548,7 +585,8 @@ namespace mamba
config.m_name,
auth.size() ? std::make_optional(auth) : nonempty_str(std::move(config.m_auth)),
token.size() ? std::make_optional(token) : nonempty_str(std::move(config.m_token)),
nonempty_str(std::move(package_name)));
nonempty_str(std::move(package_name))
);
}
Channel ChannelBuilder::from_name(const std::string& name)
@ -585,13 +623,15 @@ namespace mamba
combined_name += name.substr(name.find('/') + 1, std::string::npos);
}
return Channel(it->second.scheme(),
it->second.location(),
combined_name,
it->second.auth(),
it->second.token(),
it->second.package_filename(),
name);
return Channel(
it->second.scheme(),
it->second.location(),
combined_name,
it->second.auth(),
it->second.token(),
it->second.package_filename(),
name
);
}
else
{
@ -619,21 +659,29 @@ namespace mamba
#endif
}
void split_platform(const std::vector<std::string>& known_platforms,
const std::string& url,
std::string& cleaned_url,
std::string& platform)
void split_platform(
const std::vector<std::string>& known_platforms,
const std::string& url,
std::string& cleaned_url,
std::string& platform
)
{
platform = "";
auto check_platform_position = [&url](std::size_t pos, const std::string& platform) -> bool
{
if (pos == std::string::npos)
{
return false;
}
if (pos > 0 && url[pos - 1] != '/')
{
return false;
}
if ((pos + platform.size()) < url.size() && url[pos + platform.size()] != '/')
{
return false;
}
return true;
};
@ -684,7 +732,9 @@ namespace mamba
platforms.emplace_back(value.substr(ind, end - ind));
ind = end;
while (value[ind] == ',' || value[ind] == ' ')
{
ind++;
}
}
value.resize(end_value);
@ -732,10 +782,12 @@ namespace mamba
return chan;
}
Channel ChannelBuilder::from_alias(const std::string& scheme,
const std::string& location,
const std::optional<std::string>& auth,
const std::optional<std::string>& token)
Channel ChannelBuilder::from_alias(
const std::string& scheme,
const std::string& location,
const std::optional<std::string>& auth,
const std::optional<std::string>& token
)
{
return Channel(scheme, location, "<alias>", auth, token);
}
@ -792,7 +844,11 @@ namespace mamba
std::string location, scheme, auth, token;
split_scheme_auth_token(alias, location, scheme, auth, token);
return ChannelBuilder::from_alias(
scheme, location, nonempty_str(std::move(auth)), nonempty_str(std::move(token)));
scheme,
location,
nonempty_str(std::move(auth)),
nonempty_str(std::move(token))
);
}
void ChannelContext::init_custom_channels()
@ -808,7 +864,11 @@ namespace mamba
for (auto& url : default_channels)
{
auto channel = ChannelBuilder::make_simple_channel(
m_channel_alias, url, "", DEFAULT_CHANNELS_NAME);
m_channel_alias,
url,
"",
DEFAULT_CHANNELS_NAME
);
std::string name = channel.name();
auto res = m_custom_channels.emplace(std::move(name), std::move(channel));
*default_name_iter++ = res.first->first;
@ -816,10 +876,11 @@ namespace mamba
m_custom_multichannels.emplace(DEFAULT_CHANNELS_NAME, std::move(default_names));
// Local channels
std::vector<std::string> local_channels
= { Context::instance().target_prefix.string() + "/conda-bld",
Context::instance().root_prefix.string() + "/conda-bld",
"~/conda-bld" };
std::vector<std::string> local_channels = {
Context::instance().target_prefix.string() + "/conda-bld",
Context::instance().root_prefix.string() + "/conda-bld",
"~/conda-bld"
};
std::vector<std::string> local_names;
local_names.reserve(local_channels.size());
@ -829,7 +890,11 @@ namespace mamba
{
std::string url = path_to_url(p);
auto channel = ChannelBuilder::make_simple_channel(
m_channel_alias, url, "", LOCAL_CHANNELS_NAME);
m_channel_alias,
url,
"",
LOCAL_CHANNELS_NAME
);
std::string name = channel.name();
auto res = m_custom_channels.emplace(std::move(name), std::move(channel));
local_names.push_back(res.first->first);
@ -842,7 +907,9 @@ namespace mamba
{
std::string url = p;
if (!starts_with(url, "http"))
{
url = path_to_url(url);
}
auto channel = ChannelBuilder::make_simple_channel(m_channel_alias, url, n, "");
m_custom_channels.emplace(n, std::move(channel));
@ -856,7 +923,11 @@ namespace mamba
for (auto& url : urllist)
{
auto channel = ChannelBuilder::make_simple_channel(
m_channel_alias, url, "", multichannelname);
m_channel_alias,
url,
"",
multichannelname
);
std::string name = channel.name();
m_custom_channels.emplace(std::move(name), std::move(channel));
*name_iter++ = url;
@ -873,7 +944,8 @@ namespace mamba
{
m_custom_channels.emplace(
ch.first,
ChannelBuilder::make_simple_channel(m_channel_alias, ch.second, ch.first));
ChannelBuilder::make_simple_channel(m_channel_alias, ch.second, ch.first)
);
}
}
} // namespace mamba

View File

@ -4,25 +4,28 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/context.hpp"
#include <iostream>
#include <spdlog/spdlog.h>
#include <spdlog/pattern_formatter.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include "mamba/core/context.hpp"
#include "mamba/core/environment.hpp"
#include "mamba/core/execution.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/thread_utils.hpp"
#include "mamba/core/url.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/util_os.hpp"
#include "mamba/core/url.hpp"
#include "mamba/core/execution.hpp"
namespace mamba
{
class Logger : public spdlog::logger
{
public:
Logger(const std::string& name, const std::string& pattern, const std::string& eol);
void dump_backtrace_no_guards();
@ -32,7 +35,10 @@ namespace mamba
: spdlog::logger(name, std::make_shared<spdlog::sinks::stderr_color_sink_mt>())
{
auto f = std::make_unique<spdlog::pattern_formatter>(
pattern, spdlog::pattern_time_type::local, eol);
pattern,
spdlog::pattern_time_type::local,
eol
);
set_formatter(std::move(f));
}
@ -45,8 +51,11 @@ namespace mamba
[this](const log_msg& msg)
{
if (this->should_log(msg.level))
{
this->sink_it_(msg);
});
}
}
);
}
}
@ -76,7 +85,7 @@ namespace mamba
keep_temp_directories = env::get("MAMBA_KEEP_TEMP_DIRS") ? true : false;
{
bool const cout_is_atty = is_atty(std::cout);
const bool cout_is_atty = is_atty(std::cout);
no_progress_bars = (on_ci || !cout_is_atty);
palette = cout_is_atty ? Palette::terminal() : Palette::no_color();
}
@ -90,10 +99,16 @@ namespace mamba
set_default_signal_handler();
std::shared_ptr<spdlog::logger> l = std::make_shared<Logger>("libmamba", log_pattern, "\n");
std::shared_ptr<spdlog::logger> libcurl_logger
= std::make_shared<Logger>("libcurl", log_pattern, "");
std::shared_ptr<spdlog::logger> libsolv_logger
= std::make_shared<Logger>("libsolv", log_pattern, "");
std::shared_ptr<spdlog::logger> libcurl_logger = std::make_shared<Logger>(
"libcurl",
log_pattern,
""
);
std::shared_ptr<spdlog::logger> libsolv_logger = std::make_shared<Logger>(
"libsolv",
log_pattern,
""
);
spdlog::register_logger(libcurl_logger);
spdlog::register_logger(libsolv_logger);
@ -152,7 +167,9 @@ namespace mamba
std::map<std::string, AuthenticationInfo>& Context::authentication_info()
{
if (!m_authentication_infos_loaded)
{
load_authentication_info();
}
return m_authentication_info;
}
@ -196,8 +213,7 @@ namespace mamba
}
std::map<std::string, AuthenticationInfo> res;
fs::u8path auth_loc(mamba::env::home_directory() / ".mamba" / "auth"
/ "authentication.json");
fs::u8path auth_loc(mamba::env::home_directory() / ".mamba" / "auth" / "authentication.json");
try
{
if (fs::exists(auth_loc))
@ -220,7 +236,7 @@ namespace mamba
else if (type == "BasicHTTPAuthentication")
{
info.type = AuthenticationType::kBasicHTTPAuthentication;
auto const& user = el.value("user", "");
const auto& user = el.value("user", "");
auto pass = decode_base64(el["password"].get<std::string>());
if (pass)
{

View File

@ -6,12 +6,11 @@
#include "mamba/core/env_lockfile.hpp"
#include <yaml-cpp/yaml.h>
#include <spdlog/spdlog.h>
#include "mamba/core/output.hpp"
#include <yaml-cpp/yaml.h>
#include "mamba/core/match_spec.hpp"
#include "mamba/core/output.hpp"
namespace mamba
{
@ -27,7 +26,9 @@ namespace mamba
[&]
{
if (const auto& optional_node = package_node["optional"])
{
return optional_node.as<bool>();
}
return false;
}(),
/* .category = */
@ -39,13 +40,20 @@ namespace mamba
package.info.version = package_node["version"].as<std::string>();
const auto& hash_node = package_node["hash"];
if (const auto& md5_node = hash_node["md5"])
{
package.info.md5 = md5_node.as<std::string>();
}
if (const auto& sha256_node = hash_node["sha256"])
{
package.info.sha256 = sha256_node.as<std::string>();
}
if (package.info.sha256.empty() && package.info.md5.empty())
{
return tl::unexpected(EnvLockFileError::make_error(
file_parsing_error_code::invalid_data,
"either package 'package.info.hash.md5' or 'package.info.hash.sha256' must be specified, found none"));
"either package 'package.info.hash.md5' or 'package.info.hash.sha256' must be specified, found none"
));
}
package.info.url = package_node["url"].as<std::string>();
const MatchSpec spec{ package.info.url };
@ -59,7 +67,8 @@ namespace mamba
const auto dependency_name = dependency.first.as<std::string>();
const auto dependency_constraint = dependency.second.as<std::string>();
package.info.depends.push_back(
fmt::format("{} {}", dependency_name, dependency_constraint));
fmt::format("{} {}", dependency_name, dependency_constraint)
);
}
if (const auto& constraints_nodes = package_node["constrains"])
@ -69,15 +78,16 @@ namespace mamba
const auto constraint_dep_name = dependency.first.as<std::string>();
const auto constraint_expr = dependency.second.as<std::string>();
package.info.constrains.push_back(
fmt::format("{} {}", constraint_dep_name, constraint_expr));
fmt::format("{} {}", constraint_dep_name, constraint_expr)
);
}
}
return package;
}
tl::expected<EnvironmentLockFile::Meta, mamba_error> read_metadata(
const YAML::Node& metadata_node)
tl::expected<EnvironmentLockFile::Meta, mamba_error>
read_metadata(const YAML::Node& metadata_node)
{
EnvironmentLockFile::Meta metadata;
@ -86,25 +96,30 @@ namespace mamba
metadata.platforms.push_back(platform_node.as<std::string>());
}
if (metadata.platforms.empty())
{
return tl::unexpected(EnvLockFileError::make_error(
file_parsing_error_code::invalid_data,
"at least one 'metadata.platform.*' must be specified, found none"));
"at least one 'metadata.platform.*' must be specified, found none"
));
}
for (const auto& source_node : metadata_node["sources"])
{
metadata.sources.push_back(source_node.as<std::string>());
}
if (metadata.sources.empty())
{
return tl::unexpected(EnvLockFileError::make_error(
file_parsing_error_code::invalid_data,
"at least one 'metadata.source.*' must be specified, found none"));
"at least one 'metadata.source.*' must be specified, found none"
));
}
for (const auto& channel_node : metadata_node["channels"])
{
EnvironmentLockFile::Channel channel;
channel.url = channel_node["url"].as<std::string>();
channel.used_env_vars
= channel_node["used_env_vars"].as<std::vector<std::string>>();
channel.used_env_vars = channel_node["used_env_vars"].as<std::vector<std::string>>();
metadata.channels.push_back(std::move(channel));
}
@ -112,23 +127,30 @@ namespace mamba
{
const auto& platform_node = node_pair.first;
const auto& hash_node = node_pair.first;
metadata.content_hash.emplace(platform_node.as<std::string>(),
hash_node.as<std::string>());
metadata.content_hash.emplace(
platform_node.as<std::string>(),
hash_node.as<std::string>()
);
}
if (metadata.content_hash.empty())
{
return tl::unexpected(EnvLockFileError::make_error(
file_parsing_error_code::invalid_data,
"at least one 'metadata.content_hash.*' value must be specified, found none"));
"at least one 'metadata.content_hash.*' value must be specified, found none"
));
}
return metadata;
}
tl::expected<EnvironmentLockFile, mamba_error> read_environment_lockfile(
const YAML::Node& lockfile_yaml)
tl::expected<EnvironmentLockFile, mamba_error>
read_environment_lockfile(const YAML::Node& lockfile_yaml)
{
const auto& maybe_metadata = read_metadata(lockfile_yaml["metadata"]);
if (!maybe_metadata)
{
return tl::unexpected(maybe_metadata.error());
}
auto metadata = maybe_metadata.value();
@ -149,11 +171,11 @@ namespace mamba
}
}
tl::expected<EnvironmentLockFile, mamba_error> read_environment_lockfile(
const fs::u8path& lockfile_location)
tl::expected<EnvironmentLockFile, mamba_error>
read_environment_lockfile(const fs::u8path& lockfile_location)
{
const auto file_path = fs::absolute(
lockfile_location); // Having the complete path helps with logging and error reports.
const auto file_path = fs::absolute(lockfile_location); // Having the complete path helps
// with logging and error reports.
try
{
// TODO: add fields validation here (using some schema validation tool)
@ -171,7 +193,9 @@ namespace mamba
fmt::format(
"Failed to read environment lockfile at '{}' : unknown version '{}'",
file_path.string(),
lockfile_version)));
lockfile_version
)
));
}
}
}
@ -182,21 +206,28 @@ namespace mamba
fmt::format(
"YAML parsing error while reading environment lockfile located at '{}' : {}",
file_path.string(),
err.what()),
std::type_index{ typeid(err) }));
err.what()
),
std::type_index{ typeid(err) }
));
}
catch (...)
{
return tl::unexpected(EnvLockFileError::make_error(
file_parsing_error_code::parsing_failure,
fmt::format("unknown error while reading environment lockfile located at '{}'",
file_path.string())));
fmt::format(
"unknown error while reading environment lockfile located at '{}'",
file_path.string()
)
));
}
}
std::vector<PackageInfo> EnvironmentLockFile::get_packages_for(std::string_view category,
std::string_view platform,
std::string_view manager) const
std::vector<PackageInfo> EnvironmentLockFile::get_packages_for(
std::string_view category,
std::string_view platform,
std::string_view manager
) const
{
std::vector<PackageInfo> results;
@ -209,7 +240,9 @@ namespace mamba
for (const auto& package : packages)
{
if (package_predicate(package))
{
results.push_back(package.info);
}
}
return results;

View File

@ -1,4 +1,5 @@
#include "mamba/core/environment.hpp"
#include "mamba/core/util.hpp"
#ifdef _WIN32
@ -41,9 +42,13 @@ namespace mamba
#else
const char* value = std::getenv(key.c_str());
if (value)
{
return value;
}
else
{
return {};
}
#endif
}
@ -146,8 +151,8 @@ namespace mamba
{
std::string_view s(c);
auto pos = s.find("=");
m[std::string(s.substr(0, pos))]
= (pos != s.npos) ? std::string(s.substr(pos + 1)) : "";
m[std::string(s.substr(0, pos))] = (pos != s.npos) ? std::string(s.substr(pos + 1))
: "";
c = *(environ + i);
}
#else
@ -202,13 +207,16 @@ namespace mamba
std::string maybe_home = env::get("USERPROFILE").value_or("");
if (maybe_home.empty())
{
maybe_home
= concat(env::get("HOMEDRIVE").value_or(""), env::get("HOMEPATH").value_or(""));
maybe_home = concat(
env::get("HOMEDRIVE").value_or(""),
env::get("HOMEPATH").value_or("")
);
}
if (maybe_home.empty())
{
throw std::runtime_error(
"Cannot determine HOME (checked USERPROFILE, HOMEDRIVE and HOMEPATH env vars)");
"Cannot determine HOME (checked USERPROFILE, HOMEDRIVE and HOMEPATH env vars)"
);
}
#else
std::string maybe_home = env::get("HOME").value_or("");

View File

@ -3,12 +3,13 @@
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/environments_manager.hpp"
#include <set>
#include <string>
#include <vector>
#include "mamba/core/context.hpp"
#include "mamba/core/environments_manager.hpp"
#include "mamba/core/environment.hpp"
#include "mamba/core/fsutil.hpp"
#include "mamba/core/output.hpp"
@ -50,7 +51,9 @@ namespace mamba
for (auto& l : lines)
{
if (l == final_location_string)
{
return;
}
}
std::ofstream out = open_ofstream(env_txt_file, std::ios::app);
@ -65,7 +68,10 @@ namespace mamba
else
{
throw std::system_error(
errno, std::system_category(), "failed to open " + env_txt_file.string());
errno,
std::system_category(),
"failed to open " + env_txt_file.string()
);
}
}
}
@ -149,20 +155,24 @@ namespace mamba
return all_env_paths;
}
std::set<std::string> EnvironmentsManager::clean_environments_txt(
const fs::u8path& env_txt_file, const fs::u8path& location)
std::set<std::string>
EnvironmentsManager::clean_environments_txt(const fs::u8path& env_txt_file, const fs::u8path& location)
{
if (!fs::exists(env_txt_file))
{
return {};
}
std::error_code fsabs_error;
fs::u8path abs_loc = fs::absolute(
location, fsabs_error); // If it fails we just get the defaultly constructed path.
fs::u8path abs_loc = fs::absolute(location, fsabs_error); // If it fails we just get the
// defaultly constructed path.
if (fsabs_error && !location.empty()) // Ignore cases where we got an empty location.
{
LOG_WARNING << fmt::format("Failed to get absolute path for location '{}' : {}",
location.string(),
fsabs_error.message());
LOG_WARNING << fmt::format(
"Failed to get absolute path for location '{}' : {}",
location.string(),
fsabs_error.message()
);
}
std::vector<std::string> lines = read_lines(env_txt_file);

View File

@ -9,7 +9,9 @@ namespace mamba
void maybe_dump_backtrace(mamba_error_code ec)
{
if (ec == mamba_error_code::internal_failure)
{
spdlog::dump_backtrace();
}
}
}

View File

@ -14,8 +14,10 @@ namespace mamba
{
const auto result = safe_invoke(handler);
if (!result)
{
LOG_ERROR << "main executor close handler failed (ignored): "
<< result.error().what();
}
}
}
}

View File

@ -4,17 +4,18 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/fetch.hpp"
#include <string_view>
#include "spdlog/spdlog.h"
#include "mamba/version.hpp"
#include "mamba/core/fetch.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/thread_utils.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/url.hpp"
#include "mamba/core/util.hpp"
#include "mamba/version.hpp"
#include "spdlog/spdlog.h"
#include "progress_bar_impl.hpp"
@ -65,7 +66,11 @@ namespace mamba
}
size_t wcb_res = m_write_callback(
buffer, 1, BUFFER_SIZE - stream->avail_out, m_write_callback_data);
buffer,
1,
BUFFER_SIZE - stream->avail_out,
m_write_callback_data
);
if (wcb_res != BUFFER_SIZE - stream->avail_out)
{
return size + 1;
@ -163,9 +168,7 @@ namespace mamba
* DownloadTarget implementation *
*********************************/
DownloadTarget::DownloadTarget(const std::string& name,
const std::string& url,
const std::string& filename)
DownloadTarget::DownloadTarget(const std::string& name, const std::string& url, const std::string& filename)
: m_name(name)
, m_filename(filename)
, m_url(unc_url(url))
@ -279,8 +282,9 @@ namespace mamba
curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, Context::instance().connect_timeout_secs);
std::string ssl_no_revoke_env
= std::getenv("MAMBA_SSL_NO_REVOKE") ? std::getenv("MAMBA_SSL_NO_REVOKE") : "0";
std::string ssl_no_revoke_env = std::getenv("MAMBA_SSL_NO_REVOKE")
? std::getenv("MAMBA_SSL_NO_REVOKE")
: "0";
if (Context::instance().ssl_no_revoke || ssl_no_revoke_env != "0")
{
curl_easy_setopt(handle, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
@ -334,8 +338,8 @@ namespace mamba
}
}
int curl_debug_callback(
CURL* /* handle */, curl_infotype type, char* data, size_t size, void* userptr)
int
curl_debug_callback(CURL* /* handle */, curl_infotype type, char* data, size_t size, void* userptr)
{
auto* logger = (spdlog::logger*) (userptr);
auto log = Console::hide_secrets(std::string_view(data, size));
@ -399,8 +403,11 @@ namespace mamba
m_headers = curl_slist_append(m_headers, "Content-Type: application/json");
}
std::string user_agent
= fmt::format("User-Agent: {} {}", Context::instance().user_agent, curl_version());
std::string user_agent = fmt::format(
"User-Agent: {} {}",
Context::instance().user_agent,
curl_version()
);
m_headers = curl_slist_append(m_headers, user_agent.c_str());
curl_easy_setopt(m_handle, CURLOPT_HTTPHEADER, m_headers);
@ -458,8 +465,7 @@ namespace mamba
init_curl_target(m_url);
if (m_has_progress_bar)
{
curl_easy_setopt(
m_handle, CURLOPT_XFERINFOFUNCTION, &DownloadTarget::progress_callback);
curl_easy_setopt(m_handle, CURLOPT_XFERINFOFUNCTION, &DownloadTarget::progress_callback);
curl_easy_setopt(m_handle, CURLOPT_XFERINFODATA, this);
}
m_retry_wait_seconds = m_retry_wait_seconds * Context::instance().retry_backoff;
@ -544,19 +550,25 @@ namespace mamba
return [&](ProgressBarRepr& r) -> void
{
r.current.set_value(
fmt::format("{:>7}", to_human_readable_filesize(m_progress_bar.current(), 1)));
fmt::format("{:>7}", to_human_readable_filesize(m_progress_bar.current(), 1))
);
std::string total_str;
if (!m_progress_bar.total()
|| (m_progress_bar.total() == std::numeric_limits<std::size_t>::max()))
{
total_str = "??.?MB";
}
else
{
total_str = to_human_readable_filesize(m_progress_bar.total(), 1);
}
r.total.set_value(fmt::format("{:>7}", total_str));
auto speed = m_progress_bar.speed();
r.speed.set_value(
fmt::format("@ {:>7}/s", speed ? to_human_readable_filesize(speed, 1) : "??.?MB"));
fmt::format("@ {:>7}/s", speed ? to_human_readable_filesize(speed, 1) : "??.?MB")
);
r.separator.set_value("/");
};
@ -567,32 +579,48 @@ namespace mamba
return m_progress_throttle_time;
}
void DownloadTarget::set_progress_throttle_time(
const std::chrono::steady_clock::time_point& time)
void DownloadTarget::set_progress_throttle_time(const std::chrono::steady_clock::time_point& time)
{
m_progress_throttle_time = time;
}
int DownloadTarget::progress_callback(
void* f, curl_off_t total_to_download, curl_off_t now_downloaded, curl_off_t, curl_off_t)
void* f,
curl_off_t total_to_download,
curl_off_t now_downloaded,
curl_off_t,
curl_off_t
)
{
auto* target = static_cast<DownloadTarget*>(f);
auto now = std::chrono::steady_clock::now();
if (now - target->progress_throttle_time() < std::chrono::milliseconds(50))
{
return 0;
}
else
{
target->set_progress_throttle_time(now);
}
if (!total_to_download && !target->expected_size())
{
target->m_progress_bar.activate_spinner();
}
else
{
target->m_progress_bar.deactivate_spinner();
}
if (!total_to_download && target->expected_size())
{
target->m_progress_bar.update_current(now_downloaded);
}
else
{
target->m_progress_bar.update_progress(now_downloaded, total_to_download);
}
target->m_progress_bar.set_speed(target->get_speed());
@ -659,7 +687,9 @@ namespace mamba
curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(handle, CURLOPT_NOBODY, 1L);
if (curl_easy_perform(handle) == CURLE_OK)
{
return true;
}
long response_code;
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response_code);
@ -674,7 +704,9 @@ namespace mamba
return curl_easy_perform(handle) == CURLE_OK;
}
else
{
return false;
}
}
bool DownloadTarget::perform()
@ -698,9 +730,13 @@ namespace mamba
if (res != CURLE_OK)
{
if (m_has_progress_bar)
{
speed = m_progress_bar.avg_speed();
}
else
{
speed = 0;
}
}
return speed;
}
@ -722,8 +758,8 @@ namespace mamba
}
LOG_INFO << err.str();
m_next_retry
= std::chrono::steady_clock::now() + std::chrono::seconds(m_retry_wait_seconds);
m_next_retry = std::chrono::steady_clock::now()
+ std::chrono::seconds(m_retry_wait_seconds);
if (m_has_progress_bar)
{
@ -758,8 +794,8 @@ namespace mamba
m_retry_wait_seconds = get_default_retry_timeout();
}
m_next_retry
= std::chrono::steady_clock::now() + std::chrono::seconds(m_retry_wait_seconds);
m_next_retry = std::chrono::steady_clock::now()
+ std::chrono::seconds(m_retry_wait_seconds);
std::stringstream msg;
msg << "Failed (" << http_status << "), retry in " << m_retry_wait_seconds << "s";
if (m_has_progress_bar)
@ -789,9 +825,13 @@ namespace mamba
else
{
if (m_has_progress_bar)
{
m_progress_bar.mark_as_completed();
}
else
{
Console::instance().print(name() + " completed");
}
}
if (m_has_progress_bar)
@ -828,8 +868,7 @@ namespace mamba
MultiDownloadTarget::MultiDownloadTarget()
{
m_handle = curl_multi_init();
curl_multi_setopt(
m_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, Context::instance().download_threads);
curl_multi_setopt(m_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, Context::instance().download_threads);
}
MultiDownloadTarget::~MultiDownloadTarget()
@ -840,7 +879,9 @@ namespace mamba
void MultiDownloadTarget::add(DownloadTarget* target)
{
if (!target)
{
return;
}
CURLMcode code = curl_multi_add_handle(m_handle, target->handle());
if (code != CURLM_CALL_MULTI_PERFORM)
{
@ -902,8 +943,9 @@ namespace mamba
{
if (failfast && current_target->ignore_failure() == false)
{
throw std::runtime_error("Multi-download failed. Reason: "
+ current_target->get_transfer_msg());
throw std::runtime_error(
"Multi-download failed. Reason: " + current_target->get_transfer_msg()
);
}
}
}
@ -927,10 +969,14 @@ namespace mamba
}
if (sort)
std::sort(m_targets.begin(),
m_targets.end(),
[](DownloadTarget* a, DownloadTarget* b) -> bool
{ return a->expected_size() > b->expected_size(); });
{
std::sort(
m_targets.begin(),
m_targets.end(),
[](DownloadTarget* a, DownloadTarget* b) -> bool
{ return a->expected_size() > b->expected_size(); }
);
}
LOG_INFO << "Starting to download targets";
@ -983,11 +1029,15 @@ namespace mamba
throw std::runtime_error(curl_multi_strerror(code));
}
if (curl_timeout == 0) // No wait
if (curl_timeout == 0)
{ // No wait
continue;
}
if (curl_timeout < 0 || curl_timeout > max_wait_msecs) // Wait no more than 1s
if (curl_timeout < 0 || curl_timeout > max_wait_msecs)
{ // Wait no more than 1s
curl_timeout = max_wait_msecs;
}
int numfds;
code = curl_multi_wait(m_handle, NULL, 0, curl_timeout, &numfds);
@ -1020,7 +1070,9 @@ namespace mamba
{
pbar_manager.terminate();
if (!no_clear_progress_bars)
{
pbar_manager.clear_progress_bars();
}
}
return true;

View File

@ -4,11 +4,12 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/history.hpp"
#include <regex>
#include "mamba/core/context.hpp"
#include "mamba/core/fsutil.hpp"
#include "mamba/core/history.hpp"
#include "mamba/core/output.hpp"
namespace mamba
@ -51,7 +52,9 @@ namespace mamba
while (getline(in_file, line))
{
if (line.size() == 0)
{
continue;
}
std::smatch base_match;
if (std::regex_match(line, base_match, head_re))
{
@ -91,7 +94,9 @@ namespace mamba
{
std::size_t colon_idx = line.find_first_of(':');
if (colon_idx == std::string::npos)
{
return false;
}
std::string key(strip(line.substr(1, colon_idx - 1)));
std::string value(strip(line.substr(colon_idx + 1)));
@ -266,7 +271,9 @@ namespace mamba
const std::vector<std::string>& specs) -> std::string
{
if (specs.empty())
{
return "";
}
std::stringstream spec_ss;
spec_ss << "# " << action << " specs: [";
for (auto spec : specs)

View File

@ -4,24 +4,25 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/link.hpp"
#include <iostream>
#include <regex>
#include <string>
#include <tuple>
#include <vector>
#include <iostream>
#include <reproc++/run.hpp>
#include <reproc++/reproc.hpp>
#include <reproc++/run.hpp>
#include "mamba/core/environment.hpp"
#include "mamba/core/menuinst.hpp"
#include "mamba/core/link.hpp"
#include "mamba/core/match_spec.hpp"
#include "mamba/core/menuinst.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/transaction_context.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/validate.hpp"
#include "mamba/core/util_os.hpp"
#include "mamba/core/validate.hpp"
#if _WIN32
#include "../data/conda_exe.hpp"
@ -46,8 +47,7 @@ namespace mamba
out << " sys.exit(" << p.func << "())\n";
}
void application_entry_point_template(std::ostream& out,
const std::string_view& source_full_path)
void application_entry_point_template(std::ostream& out, const std::string_view& source_full_path)
{
out << "# -*- coding: utf-8 -*-\n";
out << "if __name__ == '__main__':\n";
@ -135,8 +135,10 @@ namespace mamba
}
// for noarch python packages that have entry points
auto LinkPackage::create_python_entry_point(const fs::u8path& path,
const python_entry_point_parsed& entry_point)
auto LinkPackage::create_python_entry_point(
const fs::u8path& path,
const python_entry_point_parsed& entry_point
)
{
#ifdef _WIN32
// We add -script.py to WIN32, and link the conda.exe launcher which will
@ -148,8 +150,7 @@ namespace mamba
#endif
if (fs::exists(script_path))
{
m_clobber_warnings.push_back(
fs::relative(script_path, m_context->target_prefix).string());
m_clobber_warnings.push_back(fs::relative(script_path, m_context->target_prefix).string());
fs::remove(script_path);
}
std::ofstream out_file = open_ofstream(script_path);
@ -177,8 +178,10 @@ namespace mamba
fs::remove(m_context->target_prefix / script_exe);
}
std::ofstream conda_exe_f
= open_ofstream(m_context->target_prefix / script_exe, std::ios::binary);
std::ofstream conda_exe_f = open_ofstream(
m_context->target_prefix / script_exe,
std::ios::binary
);
conda_exe_f.write(reinterpret_cast<char*>(conda_exe), conda_exe_len);
conda_exe_f.close();
make_executable(m_context->target_prefix / script_exe);
@ -226,9 +229,11 @@ namespace mamba
#endif
}
void LinkPackage::create_application_entry_point(const fs::u8path& source_full_path,
const fs::u8path& target_full_path,
const fs::u8path& python_full_path)
void LinkPackage::create_application_entry_point(
const fs::u8path& source_full_path,
const fs::u8path& target_full_path,
const fs::u8path& python_full_path
)
{
// source_full_path: where the entry point file points to
// target_full_path: the location of the new entry point file being created
@ -244,8 +249,7 @@ namespace mamba
std::ofstream out_file = open_ofstream(target_full_path);
out_file << "!#" << python_full_path.string() << "\n";
application_entry_point_template(out_file,
win_path_double_escape(source_full_path.string()));
application_entry_point_template(out_file, win_path_double_escape(source_full_path.string()));
out_file.close();
make_executable(target_full_path);
@ -283,9 +287,11 @@ namespace mamba
{
std::ifstream msgs = open_ifstream(messages_file);
std::stringstream res;
std::copy(std::istreambuf_iterator<char>(msgs),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(res));
std::copy(
std::istreambuf_iterator<char>(msgs),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(res)
);
return res.str();
}
catch (...)
@ -301,11 +307,13 @@ namespace mamba
call the post-link or pre-unlink script and return true / false on success /
failure
*/
bool run_script(const fs::u8path& prefix,
const PackageInfo& pkg_info,
const std::string& action = "post-link",
const std::string& env_prefix = "",
bool activate = false)
bool run_script(
const fs::u8path& prefix,
const PackageInfo& pkg_info,
const std::string& action = "post-link",
const std::string& env_prefix = "",
bool activate = false
)
{
fs::u8path path;
if (on_win)
@ -351,11 +359,13 @@ namespace mamba
if (activate)
{
script_file = wrap_call(Context::instance().root_prefix,
prefix,
Context::instance().dev,
false,
{ "@CALL", path.string() });
script_file = wrap_call(
Context::instance().root_prefix,
prefix,
Context::instance().dev,
false,
{ "@CALL", path.string() }
);
command_args = { comspec.value(), "/d", "/c", script_file->path().string() };
}
@ -377,11 +387,13 @@ namespace mamba
if (activate)
{
// std::string caller
script_file = wrap_call(Context::instance().root_prefix.string(),
prefix,
Context::instance().dev,
false,
{ ".", path.string() });
script_file = wrap_call(
Context::instance().root_prefix.string(),
prefix,
Context::instance().dev,
false,
{ ".", path.string() }
);
command_args.push_back(shell_path.string());
command_args.push_back(script_file->path().string());
}
@ -450,9 +462,11 @@ namespace mamba
return true;
}
UnlinkPackage::UnlinkPackage(const PackageInfo& pkg_info,
const fs::u8path& cache_path,
TransactionContext* context)
UnlinkPackage::UnlinkPackage(
const PackageInfo& pkg_info,
const fs::u8path& cache_path,
TransactionContext* context
)
: m_pkg_info(pkg_info)
, m_cache_path(cache_path)
, m_specifier(m_pkg_info.str())
@ -469,7 +483,9 @@ namespace mamba
std::error_code err;
if (remove_or_rename(dst) == 0)
{
LOG_DEBUG << "Error when removing file '" << dst.string() << "' will be ignored";
}
// TODO what do we do with empty directories?
// remove empty parent path
@ -478,12 +494,16 @@ namespace mamba
{
bool exists = fs::exists(parent_path, err);
if (err)
{
break;
}
if (exists)
{
bool is_empty = fs::is_empty(parent_path, err);
if (err)
{
break;
}
if (is_empty)
{
remove_or_rename(parent_path);
@ -537,9 +557,11 @@ namespace mamba
return lp.execute();
}
LinkPackage::LinkPackage(const PackageInfo& pkg_info,
const fs::u8path& cache_path,
TransactionContext* context)
LinkPackage::LinkPackage(
const PackageInfo& pkg_info,
const fs::u8path& cache_path,
TransactionContext* context
)
: m_pkg_info(pkg_info)
, m_cache_path(cache_path)
, m_source(cache_path / m_pkg_info.str())
@ -547,8 +569,8 @@ namespace mamba
{
}
std::tuple<std::string, std::string> LinkPackage::link_path(const PathData& path_data,
bool noarch_python)
std::tuple<std::string, std::string>
LinkPackage::link_path(const PathData& path_data, bool noarch_python)
{
std::string subtarget = path_data.path;
LOG_TRACE << "linking '" << subtarget << "'";
@ -627,8 +649,8 @@ namespace mamba
buffer = read_contents(src, std::ios::in | std::ios::binary);
#ifdef _WIN32
auto has_pyzzer_entrypoint
= [](const std::string& data) { return data.rfind("PK\x05\x06"); };
auto has_pyzzer_entrypoint = [](const std::string& data)
{ return data.rfind("PK\x05\x06"); };
// on win we only replace pyzzer entrypoints apparently
auto entry_point = has_pyzzer_entrypoint(buffer);
@ -642,10 +664,11 @@ namespace mamba
if (entry_point != std::string::npos)
{
std::string launcher, shebang;
pyzzer_entry
= *reinterpret_cast<const pyzzer_struct*>(buffer.c_str() + entry_point);
std::size_t arc_pos
= entry_point - pyzzer_entry.cdr_size - pyzzer_entry.cdr_offset;
pyzzer_entry = *reinterpret_cast<const pyzzer_struct*>(
buffer.c_str() + entry_point
);
std::size_t arc_pos = entry_point - pyzzer_entry.cdr_size
- pyzzer_entry.cdr_offset;
if (arc_pos > 0)
{
@ -670,10 +693,10 @@ namespace mamba
return std::make_tuple(validate::sha256sum(dst), rel_dst.string());
}
#else
std::size_t padding_size
= (path_data.prefix_placeholder.size() > new_prefix.size())
? path_data.prefix_placeholder.size() - new_prefix.size()
: 0;
std::size_t padding_size = (path_data.prefix_placeholder.size() > new_prefix.size())
? path_data.prefix_placeholder.size()
- new_prefix.size()
: 0;
std::string padding(padding_size, '\0');
std::size_t pos = buffer.find(path_data.prefix_placeholder);
@ -706,7 +729,9 @@ namespace mamba
std::error_code ec;
fs::permissions(dst, fs::status(src).permissions(), ec);
if (ec)
{
LOG_WARNING << "Could not set permissions on [" << dst << "]: " << ec.message();
}
#if defined(__APPLE__)
if (binary_changed && m_pkg_info.subdir == "osx-arm64")
@ -770,18 +795,23 @@ namespace mamba
}
else
{
throw std::runtime_error(std::string("Path type not implemented: ")
+ std::to_string(static_cast<int>(path_data.path_type)));
throw std::runtime_error(
std::string("Path type not implemented: ")
+ std::to_string(static_cast<int>(path_data.path_type))
);
}
return std::make_tuple(path_data.sha256.empty() ? validate::sha256sum(dst)
: path_data.sha256,
rel_dst.string());
return std::make_tuple(
path_data.sha256.empty() ? validate::sha256sum(dst) : path_data.sha256,
rel_dst.string()
);
}
std::vector<fs::u8path> LinkPackage::compile_pyc_files(const std::vector<fs::u8path>& py_files)
{
if (py_files.size() == 0)
{
return {};
}
std::vector<fs::u8path> pyc_files;
for (auto& f : py_files)
@ -850,12 +880,11 @@ namespace mamba
for (auto& path : paths_data)
{
auto [sha256_in_prefix, final_path]
= link_path(path, noarch_type == NoarchType::PYTHON);
auto [sha256_in_prefix, final_path] = link_path(path, noarch_type == NoarchType::PYTHON);
files_record.push_back(final_path);
nlohmann::json json_record
= { { "_path", final_path }, { "sha256_in_prefix", sha256_in_prefix } };
nlohmann::json json_record = { { "_path", final_path },
{ "sha256_in_prefix", sha256_in_prefix } };
if (!path.sha256.empty())
{
@ -908,8 +937,8 @@ namespace mamba
LOG_TRACE << "Found symlink and target " << files_record[i]
<< " -> " << files_record[pix];
// use already computed value
paths_json["paths"][i]["sha256_in_prefix"]
= paths_json["paths"][pix]["sha256_in_prefix"];
paths_json["paths"][i]["sha256_in_prefix"] = paths_json["paths"][pix]
["sha256_in_prefix"];
found = true;
break;
}
@ -928,8 +957,9 @@ namespace mamba
if (exists)
{
paths_json["paths"][i]["sha256_in_prefix"]
= validate::sha256sum(m_context->target_prefix / files_record[i]);
paths_json["paths"][i]["sha256_in_prefix"] = validate::sha256sum(
m_context->target_prefix / files_record[i]
);
}
else
{
@ -978,16 +1008,17 @@ namespace mamba
{
if (std::regex_match(sub_path_json.path, py_file_re))
{
for_compilation.push_back(get_python_noarch_target_path(
sub_path_json.path, m_context->site_packages_path));
for_compilation.push_back(
get_python_noarch_target_path(sub_path_json.path, m_context->site_packages_path)
);
}
}
std::vector<fs::u8path> pyc_files = compile_pyc_files(for_compilation);
for (const fs::u8path& pyc_path : pyc_files)
{
out_json["paths_data"]["paths"].push_back(
{ { "_path", pyc_path.string() }, { "path_type", "pyc_file" } });
out_json["paths_data"]["paths"].push_back({ { "_path", pyc_path.string() },
{ "path_type", "pyc_file" } });
out_json["files"].push_back(pyc_path.string());
}
@ -999,23 +1030,24 @@ namespace mamba
{
// install entry points
auto entry_point_parsed = parse_entry_point(ep.get<std::string>());
auto entry_point_path
= get_bin_directory_short_path() / entry_point_parsed.command;
auto entry_point_path = get_bin_directory_short_path()
/ entry_point_parsed.command;
LOG_TRACE << "entry point path: " << entry_point_path << std::endl;
auto files = create_python_entry_point(entry_point_path, entry_point_parsed);
#ifdef _WIN32
out_json["paths_data"]["paths"].push_back(
{ { "_path", files[0] },
{ "path_type", "windows_python_entry_point_script" } });
{ { "_path", files[0] }, { "path_type", "windows_python_entry_point_script" } }
);
out_json["paths_data"]["paths"].push_back(
{ { "_path", files[1] },
{ "path_type", "windows_python_entry_point_exe" } });
{ { "_path", files[1] }, { "path_type", "windows_python_entry_point_exe" } }
);
out_json["files"].push_back(files[0]);
out_json["files"].push_back(files[1]);
#else
out_json["paths_data"]["paths"].push_back(
{ { "_path", files }, { "path_type", "unix_python_entry_point" } });
{ { "_path", files }, { "path_type", "unix_python_entry_point" } }
);
out_json["files"].push_back(files);
#endif
}

View File

@ -4,14 +4,15 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/match_spec.hpp"
#include <regex>
#include "mamba/core/match_spec.hpp"
#include "mamba/core/channel.hpp"
#include "mamba/core/environment.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/url.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/channel.hpp"
#include "mamba/core/environment.hpp"
namespace mamba
{
@ -50,8 +51,7 @@ namespace mamba
{
std::size_t pm1 = pos - 1;
char d = s[pm1];
if (d == '=' || d == '!' || d == '|' || d == ',' || d == '<' || d == '>'
|| d == '~')
if (d == '=' || d == '!' || d == '|' || d == ',' || d == '<' || d == '>' || d == '~')
{
std::string tmp = s;
replace_all(tmp, " ", "");
@ -215,7 +215,8 @@ namespace mamba
if (version.find("[") != version.npos)
{
throw std::runtime_error(
"Invalid match spec: multiple bracket sections not allowed " + spec);
"Invalid match spec: multiple bracket sections not allowed " + spec
);
}
version = std::string(strip(version));
@ -344,8 +345,8 @@ namespace mamba
std::vector<std::string> formatted_brackets;
bool version_exact = false;
auto is_complex_relation
= [](const std::string& s) { return s.find_first_of("><$^|,") != s.npos; };
auto is_complex_relation = [](const std::string& s)
{ return s.find_first_of("><$^|,") != s.npos; };
if (!version.empty())
{
@ -415,9 +416,10 @@ namespace mamba
}
}
std::vector<std::string> check
= { "build_number", "track_features", "features", "url",
"md5", "license", "license_family", "fn" };
std::vector<std::string> check = {
"build_number", "track_features", "features", "url",
"md5", "license", "license_family", "fn"
};
if (!url.empty())
{

View File

@ -6,8 +6,8 @@
#include "mamba/core/util.hpp"
#ifdef _WIN32
#include <windows.h>
#include <shlobj.h>
#include <windows.h>
#endif
namespace mamba
@ -42,13 +42,15 @@ namespace mamba
* icon_path: path to an .ico file
* icon_index: index for icon
*/
void create_shortcut(const fs::u8path& path,
const std::string& description,
const fs::u8path& filename,
const std::string& arguments,
const fs::u8path& work_dir,
const fs::u8path& icon_path,
int icon_index)
void create_shortcut(
const fs::u8path& path,
const std::string& description,
const fs::u8path& filename,
const std::string& arguments,
const fs::u8path& work_dir,
const fs::u8path& icon_path,
int icon_index
)
{
IShellLink* pShellLink = nullptr;
IPersistFile* pPersistFile = nullptr;
@ -66,11 +68,13 @@ namespace mamba
{
throw std::runtime_error("Could not initialize COM");
}
hres = CoCreateInstance(CLSID_ShellLink,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IShellLink,
(void**) &pShellLink);
hres = CoCreateInstance(
CLSID_ShellLink,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IShellLink,
(void**) &pShellLink
);
if (FAILED(hres))
{
throw std::runtime_error("CoCreateInstance failed.");
@ -79,8 +83,9 @@ namespace mamba
hres = pShellLink->QueryInterface(IID_IPersistFile, (void**) &pPersistFile);
if (FAILED(hres))
{
throw std::runtime_error("QueryInterface(IPersistFile) error 0x"
+ std::to_string(hres));
throw std::runtime_error(
"QueryInterface(IPersistFile) error 0x" + std::to_string(hres)
);
}
hres = pShellLink->SetPath(path.string().c_str());
@ -92,8 +97,9 @@ namespace mamba
hres = pShellLink->SetDescription(description.c_str());
if (FAILED(hres))
{
throw std::runtime_error("SetDescription() failed, error 0x"
+ std::to_string(hres));
throw std::runtime_error(
"SetDescription() failed, error 0x" + std::to_string(hres)
);
}
if (!arguments.empty())
@ -110,8 +116,7 @@ namespace mamba
hres = pShellLink->SetIconLocation(icon_path.string().c_str(), icon_index);
if (FAILED(hres))
{
throw std::runtime_error("SetIconLocation() error 0x"
+ std::to_string(hres));
throw std::runtime_error("SetIconLocation() error 0x" + std::to_string(hres));
}
}
@ -120,16 +125,18 @@ namespace mamba
hres = pShellLink->SetWorkingDirectory(work_dir.string().c_str());
if (FAILED(hres))
{
throw std::runtime_error("SetWorkingDirectory() error 0x"
+ std::to_string(hres));
throw std::runtime_error(
"SetWorkingDirectory() error 0x" + std::to_string(hres)
);
}
}
hres = pPersistFile->Save(filename.wstring().c_str(), true);
if (FAILED(hres))
{
throw std::runtime_error(concat(
"Failed to create shortcut: ", filename.string(), std::to_string(hres)));
throw std::runtime_error(
concat("Failed to create shortcut: ", filename.string(), std::to_string(hres))
);
}
}
catch (const std::runtime_error& e)
@ -164,8 +171,7 @@ namespace mamba
wchar_t* localAppData;
HRESULT hres;
hres = SHGetKnownFolderPath(
knownfolders.at(id), KF_FLAG_DONT_VERIFY, nullptr, &localAppData);
hres = SHGetKnownFolderPath(knownfolders.at(id), KF_FLAG_DONT_VERIFY, nullptr, &localAppData);
if (FAILED(hres))
{
@ -261,9 +267,11 @@ namespace mamba
namespace detail
{
void create_remove_shortcut_impl(const fs::u8path& json_file,
TransactionContext* transaction_context,
bool remove)
void create_remove_shortcut_impl(
const fs::u8path& json_file,
TransactionContext* transaction_context,
bool remove
)
{
std::string json_content = mamba::read_contents(json_file);
replace_variables(json_content, transaction_context);
@ -305,9 +313,11 @@ namespace mamba
const fs::u8path env_pyw = target_prefix / "pythonw.exe";
const auto cwp_path = root_prefix / "cwp.py";
std::vector<std::string> cwp_py_args(
{ cwp_path.string(), target_prefix.string(), env_py.string() });
{ cwp_path.string(), target_prefix.string(), env_py.string() }
);
std::vector<std::string> cwp_pyw_args(
{ cwp_path.string(), target_prefix.string(), env_pyw.string() });
{ cwp_path.string(), target_prefix.string(), env_pyw.string() }
);
fs::u8path target_dir = win::get_folder("programs") / menu_name;
if (!fs::exists(target_dir))
@ -427,8 +437,7 @@ namespace mamba
workdir = "%HOMEPATH%";
}
mamba::win::create_shortcut(
script, full_name, dst, argstring, workdir, iconpath, 0);
mamba::win::create_shortcut(script, full_name, dst, argstring, workdir, iconpath, 0);
}
else
{

View File

@ -10,22 +10,22 @@
#include <map>
#include <string>
#include <fmt/format.h>
#include <fmt/color.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include "mamba/core/context.hpp"
#include "mamba/core/execution.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/tasksync.hpp"
#include "mamba/core/thread_utils.hpp"
#include "mamba/core/url.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/execution.hpp"
#include "mamba/core/tasksync.hpp"
#include "progress_bar_impl.hpp"
@ -74,34 +74,46 @@ namespace mamba
m_table.push_back(r);
}
void Table::add_rows(const std::string& header,
const std::vector<std::vector<FormattedString>>& rs)
void
Table::add_rows(const std::string& header, const std::vector<std::vector<FormattedString>>& rs)
{
m_table.push_back({ header });
for (auto& r : rs)
{
m_table.push_back(r);
}
}
std::ostream& Table::print(std::ostream& out)
{
if (m_table.size() == 0)
{
return out;
}
std::size_t n_col = m_header.size();
if (m_align.size() == 0)
{
m_align = std::vector<alignment>(n_col, alignment::left);
}
std::vector<std::size_t> cell_sizes(n_col);
for (size_t i = 0; i < n_col; ++i)
{
cell_sizes[i] = m_header[i].size();
}
for (size_t i = 0; i < m_table.size(); ++i)
{
if (m_table[i].size() == 1)
{
continue;
}
for (size_t j = 0; j < m_table[i].size(); ++j)
{
cell_sizes[j] = std::max(cell_sizes[j], m_table[i][j].size());
}
}
if (m_padding.empty())
@ -118,19 +130,23 @@ namespace mamba
{
if (this->m_align[j] == alignment::left)
{
fmt::print(out,
"{: ^{}}{: <{}}",
"",
this->m_padding[j],
fmt::styled(row[j].s, row[j].style),
cell_sizes[j]);
fmt::print(
out,
"{: ^{}}{: <{}}",
"",
this->m_padding[j],
fmt::styled(row[j].s, row[j].style),
cell_sizes[j]
);
}
else
{
fmt::print(out,
"{: >{}}",
fmt::styled(row[j].s, row[j].style),
cell_sizes[j] + m_padding[j]);
fmt::print(
out,
"{: >{}}",
fmt::styled(row[j].s, row[j].style),
cell_sizes[j] + m_padding[j]
);
}
}
};
@ -156,7 +172,9 @@ namespace mamba
{
// print header
if (i != 0)
{
out << "\n";
}
for (int x = 0; x < m_padding[0]; ++x)
{
@ -194,8 +212,12 @@ namespace mamba
std::ostringstream out;
for (const auto& d : data)
{
if (d.size() > data_max_width)
{
data_max_width = d.size();
}
}
max_width -= max_width % (data_max_width + padding);
int block_width = padding + data_max_width;
@ -237,6 +259,7 @@ namespace mamba
class ConsoleData
{
public:
std::mutex m_mutex;
std::unique_ptr<ProgressBarManager> p_progress_bar_manager;
@ -255,7 +278,8 @@ namespace mamba
{
init_progress_bar_manager(ProgressBarMode::multi);
MainExecutor::instance().on_close(
p_data->tasksync.synchronized([this] { terminate_progress_bar_manager(); }));
p_data->tasksync.synchronized([this] { terminate_progress_bar_manager(); })
);
#ifdef _WIN32
// initialize ANSI codes on Win terminals
auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
@ -265,9 +289,11 @@ namespace mamba
Console::~Console()
{
if (!p_data->is_json_print_cancelled
&& !p_data->json_log.is_null()) // Note: we cannot rely on Context::instance() to still
// be valid at this point.
if (!p_data->is_json_print_cancelled && !p_data->json_log.is_null()) // Note: we cannot
// rely on
// Context::instance()
// to still be valid
// at this point.
{
this->json_print();
}
@ -310,7 +336,9 @@ namespace mamba
{
auto& data = instance().p_data;
for (auto& message : data->m_buffer)
{
ostream << message << '\n';
}
const std::lock_guard<std::mutex> lock(data->m_mutex);
data->m_buffer.clear();
@ -372,9 +400,13 @@ namespace mamba
ProgressProxy Console::add_progress_bar(const std::string& name, size_t expected_total)
{
if (Context::instance().no_progress_bars)
{
return ProgressProxy();
}
else
{
return p_data->p_progress_bar_manager->add_progress_bar(name, expected_total);
}
}
void Console::clear_progress_bars()
@ -430,7 +462,9 @@ namespace mamba
{
nlohmann::json tmp = j.flatten();
for (auto it = tmp.begin(); it != tmp.end(); ++it)
{
p_data->json_log[p_data->json_hier + it.key()] = it.value();
}
}
}
@ -451,9 +485,10 @@ namespace mamba
{
nlohmann::json tmp = j.flatten();
for (auto it = tmp.begin(); it != tmp.end(); ++it)
p_data->json_log[p_data->json_hier + '/' + std::to_string(p_data->json_index)
+ it.key()]
= it.value();
{
p_data->json_log[p_data->json_hier + '/' + std::to_string(p_data->json_index) + it.key()] = it.value(
);
}
p_data->json_index += 1;
}
}
@ -472,7 +507,9 @@ namespace mamba
void Console::json_up()
{
if (Context::instance().json && !p_data->json_hier.empty())
{
p_data->json_hier.erase(p_data->json_hier.rfind('/'));
}
}
/*****************
@ -497,7 +534,9 @@ namespace mamba
MessageLogger::~MessageLogger()
{
if (!MessageLoggerData::use_buffer)
{
emit(m_stream.str(), m_level);
}
else
{
const std::lock_guard<std::mutex> lock(MessageLoggerData::m_mutex);
@ -513,7 +552,9 @@ namespace mamba
case log_level::critical:
SPDLOG_CRITICAL(prepend(str, "", std::string(4, ' ').c_str()));
if (Context::instance().logging_level != log_level::off)
{
spdlog::dump_backtrace();
}
break;
case log_level::err:
SPDLOG_ERROR(prepend(str, "", std::string(4, ' ').c_str()));
@ -553,7 +594,9 @@ namespace mamba
void MessageLogger::print_buffer(std::ostream& /*ostream*/)
{
for (auto& [msg, level] : MessageLoggerData::m_buffer)
{
emit(msg, level);
}
spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->flush(); });

View File

@ -4,13 +4,15 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "nlohmann/json.hpp"
#include "mamba/core/package_cache.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/package_cache.hpp"
#include "mamba/core/package_handling.hpp"
#include "mamba/core/validate.hpp"
#include "mamba/core/url.hpp"
#include "mamba/core/validate.hpp"
#include "nlohmann/json.hpp"
namespace mamba
{
@ -25,9 +27,11 @@ namespace mamba
{
LOG_DEBUG << "Attempt to create package cache directory '" << m_path.string() << "'";
bool sudo_safe = path::starts_with_home(m_path);
path::touch(m_path / PACKAGE_CACHE_MAGIC_FILE,
/*mkdir*/ true,
sudo_safe);
path::touch(
m_path / PACKAGE_CACHE_MAGIC_FILE,
/*mkdir*/ true,
sudo_safe
);
return true;
}
catch (...)
@ -45,7 +49,9 @@ namespace mamba
auto PackageCacheData::is_writable() -> Writable
{
if (m_writable == Writable::UNKNOWN)
{
check_writable();
}
return m_writable;
}
@ -87,7 +93,9 @@ namespace mamba
}
}
else
{
LOG_TRACE << "Cache path does not exists or is not writable";
}
try
{
@ -145,14 +153,19 @@ namespace mamba
throw std::runtime_error(
"Could not validate package '" + tarball_path.string()
+ "': md5 and sha256 sum unknown.\n"
"Set safety_checks to warn or disabled to override this error.");
"Set safety_checks to warn or disabled to override this error."
);
}
}
if (valid)
{
LOG_TRACE << "Package tarball '" << tarball_path.string() << "' is valid";
}
else
{
LOG_WARNING << "Package tarball '" << tarball_path.string() << "' is invalid";
}
m_valid_tarballs[pkg] = valid;
}
@ -206,7 +219,8 @@ namespace mamba
throw std::runtime_error(
"Could not validate package '" + repodata_record_path.string()
+ "': md5 and sha256 sum unknown.\n"
"Set safety_checks to warn or disabled to override this error.");
"Set safety_checks to warn or disabled to override this error."
);
}
}
@ -267,8 +281,7 @@ namespace mamba
{
if (!repodata_record["url"].get<std::string>().empty())
{
if (!compare_cleaned_url(repodata_record["url"].get<std::string>(),
s.url))
if (!compare_cleaned_url(repodata_record["url"].get<std::string>(), s.url))
{
LOG_WARNING << "Extracted package cache '" << extracted_dir.string()
<< "' has invalid url";
@ -372,8 +385,12 @@ namespace mamba
fs::u8path MultiPackageCache::first_writable_path()
{
for (auto& pc : m_caches)
{
if (pc.is_writable() == Writable::WRITABLE)
{
return pc.path();
}
}
return fs::u8path();
}
@ -388,14 +405,18 @@ namespace mamba
}
for (PackageCacheData& c : m_caches)
{
if (c.has_valid_tarball(s))
{
m_cached_tarballs[pkg] = c.path();
return c.path();
}
}
if (return_empty)
{
return fs::u8path();
}
else
{
LOG_ERROR << "Cannot find tarball cache for '" << s.fn << "'";
@ -414,14 +435,18 @@ namespace mamba
}
for (auto& c : m_caches)
{
if (c.has_valid_extracted_dir(s))
{
m_cached_extracted_dirs[pkg] = c.path();
return c.path();
}
}
if (return_empty)
{
return fs::u8path();
}
else
{
LOG_ERROR << "Cannot find a valid extracted directory cache for '" << s.fn << "'";
@ -433,7 +458,9 @@ namespace mamba
{
std::vector<fs::u8path> paths;
for (auto& c : m_caches)
{
paths.push_back(c.path());
}
return paths;
}
@ -441,6 +468,8 @@ namespace mamba
void MultiPackageCache::clear_query_cache(const PackageInfo& s)
{
for (auto& c : m_caches)
{
c.clear_query_cache(s);
}
}
} // namespace mamba

View File

@ -5,29 +5,31 @@
// The full license is in the file LICENSE, distributed with this software.
#include <archive.h>
#include <archive_entry.h>
#include <zstd.h>
#include "mamba/core/package_handling.hpp"
#include <sstream>
#include <archive.h>
#include <archive_entry.h>
#include <reproc++/run.hpp>
#include <zstd.h>
#include "nlohmann/json.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/package_handling.hpp"
#include "mamba/core/package_paths.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/package_paths.hpp"
#include "mamba/core/thread_utils.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/util_os.hpp"
#include "mamba/core/validate.hpp"
#include "nlohmann/json.hpp"
namespace mamba
{
class extraction_guard
{
public:
explicit extraction_guard(const fs::u8path& file)
: m_file(file)
{
@ -55,12 +57,14 @@ namespace mamba
extraction_guard& operator=(extraction_guard&&) = delete;
private:
const fs::u8path& m_file;
};
class scoped_archive_read : non_copyable_base
{
public:
scoped_archive_read()
: scoped_archive_read(archive_read_new()){};
static scoped_archive_read read_disk()
@ -79,6 +83,7 @@ namespace mamba
}
private:
explicit scoped_archive_read(archive* a)
: m_archive(a)
{
@ -94,6 +99,7 @@ namespace mamba
class scoped_archive_write : non_copyable_base
{
public:
scoped_archive_write()
: scoped_archive_write(archive_write_new())
{
@ -115,6 +121,7 @@ namespace mamba
}
private:
explicit scoped_archive_write(archive* a)
: m_archive(a)
{
@ -130,6 +137,7 @@ namespace mamba
class scoped_archive_entry : non_copyable_base
{
public:
scoped_archive_entry()
: m_entry(archive_entry_new())
{
@ -150,6 +158,7 @@ namespace mamba
}
private:
archive_entry* m_entry;
};
@ -184,10 +193,12 @@ namespace mamba
bool path_has_prefix(const fs::u8path& path, const fs::u8path& prefix)
{
auto pair = std::mismatch(path.std_path().begin(),
path.std_path().end(),
prefix.std_path().begin(),
prefix.std_path().end());
auto pair = std::mismatch(
path.std_path().begin(),
path.std_path().end(),
prefix.std_path().begin(),
prefix.std_path().end()
);
return pair.second == prefix.std_path().end();
}
@ -203,17 +214,21 @@ namespace mamba
int init_order = starts_with(path.filename().string(), "info-");
// sort metadata.json first in zip folder
if (path.filename().string() == "metadata.json")
{
init_order = -1;
}
return init_order;
}
// Bundle up all files in directory and create destination archive
void create_archive(const fs::u8path& directory,
const fs::u8path& destination,
compression_algorithm ca,
int compression_level,
int compression_threads,
bool (*filter)(const fs::u8path&))
void create_archive(
const fs::u8path& directory,
const fs::u8path& destination,
compression_algorithm ca,
int compression_level,
int compression_threads,
bool (*filter)(const fs::u8path&)
)
{
int r;
@ -228,9 +243,11 @@ namespace mamba
archive_write_add_filter_bzip2(a);
if (compression_level < 0 || compression_level > 9)
{
throw std::runtime_error("bzip2 compression level should be between 0 and 9");
std::string comp_level
= std::string("bzip2:compression-level=") + std::to_string(compression_level);
}
std::string comp_level = std::string("bzip2:compression-level=")
+ std::to_string(compression_level);
archive_write_set_options(a, comp_level.c_str());
}
if (ca == compression_algorithm::zip)
@ -238,9 +255,11 @@ namespace mamba
archive_write_set_format_zip(a);
if (compression_level < 0 || compression_level > 9)
{
throw std::runtime_error("zip compression level should be between 0 and 9");
std::string comp_level
= std::string("zip:compression-level=") + std::to_string(compression_level);
}
std::string comp_level = std::string("zip:compression-level=")
+ std::to_string(compression_level);
archive_write_set_options(a, comp_level.c_str());
}
if (ca == compression_algorithm::zstd)
@ -250,10 +269,12 @@ namespace mamba
archive_write_add_filter_zstd(a);
if (compression_level < 1 || compression_level > 22)
{
throw std::runtime_error("zstd compression level should be between 1 and 22");
}
std::string comp_level
= std::string("zstd:compression-level=") + std::to_string(compression_level);
std::string comp_level = std::string("zstd:compression-level=")
+ std::to_string(compression_level);
int res = archive_write_set_options(a, comp_level.c_str());
if (res != 0)
@ -263,8 +284,8 @@ namespace mamba
if (compression_threads > 2)
{
std::string comp_threads_level
= std::string("zstd:threads=") + std::to_string(compression_threads);
std::string comp_threads_level = std::string("zstd:threads=")
+ std::to_string(compression_threads);
res = archive_write_set_options(a, comp_threads_level.c_str());
if (res != 0)
{
@ -381,42 +402,50 @@ namespace mamba
}
// note the info folder must have already been created!
void create_package(const fs::u8path& directory,
const fs::u8path& out_file,
int compression_level,
int compression_threads)
void create_package(
const fs::u8path& directory,
const fs::u8path& out_file,
int compression_level,
int compression_threads
)
{
fs::u8path out_file_abs = fs::absolute(out_file);
if (ends_with(out_file.string(), ".tar.bz2"))
{
create_archive(directory,
out_file_abs,
bzip2,
compression_level,
compression_threads,
[](const fs::u8path&) { return false; });
create_archive(
directory,
out_file_abs,
bzip2,
compression_level,
compression_threads,
[](const fs::u8path&) { return false; }
);
}
else if (ends_with(out_file.string(), ".conda"))
{
TemporaryDirectory tdir;
create_archive(directory,
tdir.path() / concat("info-", out_file.stem().string(), ".tar.zst"),
zstd,
compression_level,
compression_threads,
[](const fs::u8path& p) -> bool {
return p.std_path().begin() != p.std_path().end()
&& *p.std_path().begin() != "info";
});
create_archive(directory,
tdir.path() / concat("pkg-", out_file.stem().string(), ".tar.zst"),
zstd,
compression_level,
compression_threads,
[](const fs::u8path& p) -> bool {
return p.std_path().begin() != p.std_path().end()
&& *p.std_path().begin() == "info";
});
create_archive(
directory,
tdir.path() / concat("info-", out_file.stem().string(), ".tar.zst"),
zstd,
compression_level,
compression_threads,
[](const fs::u8path& p) -> bool {
return p.std_path().begin() != p.std_path().end()
&& *p.std_path().begin() != "info";
}
);
create_archive(
directory,
tdir.path() / concat("pkg-", out_file.stem().string(), ".tar.zst"),
zstd,
compression_level,
compression_threads,
[](const fs::u8path& p) -> bool {
return p.std_path().begin() != p.std_path().end()
&& *p.std_path().begin() == "info";
}
);
nlohmann::json pkg_metadata;
pkg_metadata["conda_pkg_format_version"] = 2;
@ -425,12 +454,14 @@ namespace mamba
metadata_file << pkg_metadata;
metadata_file.close();
create_archive(tdir.path(),
out_file_abs,
zip,
0,
compression_threads,
[](const fs::u8path&) { return false; });
create_archive(
tdir.path(),
out_file_abs,
zip,
0,
compression_threads,
[](const fs::u8path&) { return false; }
);
}
}
@ -562,7 +593,8 @@ namespace mamba
if (read < 0)
{
throw std::runtime_error(
fmt::format("Error reading from archive: {}", archive_error_string(mine->source)));
fmt::format("Error reading from archive: {}", archive_error_string(mine->source))
);
}
return read;
}
@ -576,9 +608,8 @@ namespace mamba
}
void extract_conda(const fs::u8path& file,
const fs::u8path& dest_dir,
const std::vector<std::string>& parts)
void
extract_conda(const fs::u8path& file, const fs::u8path& dest_dir, const std::vector<std::string>& parts)
{
scoped_archive_read a;
archive_read_support_format_zip(a);
@ -595,7 +626,9 @@ namespace mamba
{
std::size_t pos = name.find_first_of('-');
if (pos == std::string::npos)
{
return false;
}
std::string part = name.substr(0, pos);
if (std::find(parts.begin(), parts.end(), part) != parts.end())
{
@ -681,9 +714,13 @@ namespace mamba
std::lock_guard<std::mutex> lock(extract_mutex);
if (ends_with(file.string(), ".tar.bz2"))
{
extract_archive(file, dest);
}
else if (ends_with(file.string(), ".conda"))
{
extract_conda(file, dest);
}
else
{
LOG_ERROR << "Unknown package format '" << file.string() << "'";
@ -703,9 +740,7 @@ namespace mamba
std::vector<std::string> args;
if (Context::instance().is_micromamba)
{
args = {
get_self_exe_path().string(), "package", "extract", file.string(), dest.string()
};
args = { get_self_exe_path().string(), "package", "extract", file.string(), dest.string() };
}
else
{
@ -715,7 +750,11 @@ namespace mamba
std::string out, err;
LOG_DEBUG << "Running subprocess extraction '" << join(" ", args) << "'";
auto [status, ec] = reproc::run(
args, reproc::options{}, reproc::sink::string(out), reproc::sink::string(err));
args,
reproc::options{},
reproc::sink::string(out),
reproc::sink::string(err)
);
if (ec)
{
@ -726,10 +765,8 @@ namespace mamba
}
}
bool transmute(const fs::u8path& pkg_file,
const fs::u8path& target,
int compression_level,
int compression_threads)
bool
transmute(const fs::u8path& pkg_file, const fs::u8path& target, int compression_level, int compression_threads)
{
TemporaryDirectory extract_dir;

View File

@ -4,11 +4,12 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/package_info.hpp"
#include <functional>
#include <map>
#include <tuple>
#include "mamba/core/package_info.hpp"
#include "mamba/core/channel.hpp"
#include "mamba/core/util.hpp"
@ -20,15 +21,14 @@ namespace mamba
std::string get_package_info_field(const PackageInfo&, T PackageInfo::*field);
template <>
std::string get_package_info_field<std::string>(const PackageInfo& pkg,
std::string PackageInfo::*field)
std::string
get_package_info_field<std::string>(const PackageInfo& pkg, std::string PackageInfo::*field)
{
return pkg.*field;
}
template <>
std::string get_package_info_field<size_t>(const PackageInfo& pkg,
size_t PackageInfo::*field)
std::string get_package_info_field<size_t>(const PackageInfo& pkg, size_t PackageInfo::*field)
{
return std::to_string(pkg.*field);
}
@ -102,7 +102,9 @@ namespace mamba
version = pool_id2str(pool, s->evr);
str = solvable_lookup_str(s, SOLVABLE_BUILDFLAVOR);
if (str)
{
build_string = str;
}
str = solvable_lookup_str(s, SOLVABLE_BUILDVERSION);
if (str)
{
@ -135,22 +137,32 @@ namespace mamba
fn = check_char(solvable_lookup_str(s, SOLVABLE_MEDIAFILE));
str = check_char(solvable_lookup_str(s, SOLVABLE_LICENSE));
if (str)
{
license = str;
}
size = solvable_lookup_num(s, SOLVABLE_DOWNLOADSIZE, 0);
timestamp = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0);
str = solvable_lookup_checksum(s, SOLVABLE_PKGID, &check_type);
if (str)
{
md5 = str;
}
str = solvable_lookup_checksum(s, SOLVABLE_CHECKSUM, &check_type);
if (str)
{
sha256 = str;
}
signatures = check_char(solvable_lookup_str(s, SIGNATURE_DATA));
if (signatures.empty())
{
signatures = "{}";
}
queue_init(&q);
if (!solvable_lookup_deparray(s, SOLVABLE_REQUIRES, &q, -1))
{
defaulted_keys.insert("depends");
}
depends.resize(q.count);
for (int i = 0; i < q.count; ++i)
{
@ -158,7 +170,9 @@ namespace mamba
}
queue_empty(&q);
if (!solvable_lookup_deparray(s, SOLVABLE_CONSTRAINS, &q, -1))
{
defaulted_keys.insert("constrains");
}
constrains.resize(q.count);
for (int i = 0; i < q.count; ++i)
{
@ -185,14 +199,18 @@ namespace mamba
solvable_lookup_idarray(s, extra_keys_id, &q);
std::vector<std::string> extra_keys;
for (int i = 0; i < q.count; ++i)
{
extra_keys.push_back(pool_dep2str(pool, q.elements[i]));
}
// Get extra signed values
queue_empty(&q);
solvable_lookup_idarray(s, extra_values_id, &q);
std::vector<std::string> extra_values;
for (int i = 0; i < q.count; ++i)
{
extra_values.push_back(pool_dep2str(pool, q.elements[i]));
}
// Build a JSON string for extra signed metadata
if (!extra_keys.empty() && (extra_keys.size() == extra_values.size()))
@ -206,7 +224,9 @@ namespace mamba
}
}
else
{
extra_metadata = "{}";
}
queue_free(&q);
}
@ -268,10 +288,7 @@ namespace mamba
{
}
PackageInfo::PackageInfo(const std::string& n,
const std::string& v,
const std::string b,
std::size_t bn)
PackageInfo::PackageInfo(const std::string& n, const std::string& v, const std::string b, std::size_t bn)
: name(n)
, version(v)
, build_string(b)
@ -279,30 +296,32 @@ namespace mamba
{
}
bool PackageInfo::operator==(PackageInfo const& other) const
bool PackageInfo::operator==(const PackageInfo& other) const
{
auto attrs = [](PackageInfo const& p)
auto attrs = [](const PackageInfo& p)
{
return std::tie(p.name,
p.version,
p.build_string,
p.noarch,
p.build_number,
p.channel,
p.url,
p.subdir,
p.fn,
p.license,
p.size,
p.timestamp,
p.md5,
p.sha256,
p.track_features,
p.depends,
p.constrains,
p.signatures,
p.extra_metadata,
p.defaulted_keys);
return std::tie(
p.name,
p.version,
p.build_string,
p.noarch,
p.build_number,
p.channel,
p.url,
p.subdir,
p.fn,
p.license,
p.size,
p.timestamp,
p.md5,
p.sha256,
p.track_features,
p.depends,
p.constrains,
p.signatures,
p.extra_metadata,
p.defaulted_keys
);
};
return attrs(*this) == attrs(other);
}
@ -371,7 +390,9 @@ namespace mamba
if (depends.empty())
{
if (defaulted_keys.find("depends") == defaulted_keys.end())
{
j["depends"] = nlohmann::json::array();
}
}
else
{
@ -380,7 +401,9 @@ namespace mamba
if (constrains.empty())
{
if (defaulted_keys.find("constrains") == defaulted_keys.end())
{
j["constrains"] = nlohmann::json::array();
}
}
else
{

View File

@ -4,11 +4,12 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/package_paths.hpp"
#include <map>
#include <set>
#include <string>
#include "mamba/core/package_paths.hpp"
#include "mamba/core/util.hpp"
namespace mamba

View File

@ -4,12 +4,13 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/output.hpp"
#include "mamba/core/pinning.hpp"
#include "mamba/core/util.hpp"
#include <fstream>
#include "mamba/core/output.hpp"
#include "mamba/core/util.hpp"
namespace mamba
{

View File

@ -4,16 +4,17 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/pool.hpp"
#include <list>
#include <solv/pool.h>
#include <solv/solver.h>
#include <solv/selection.h>
#include <solv/evr.h>
#include <solv/pool.h>
#include <solv/selection.h>
#include <solv/solver.h>
#include <spdlog/spdlog.h>
#include "mamba/core/context.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/queue.hpp"
@ -80,7 +81,7 @@ namespace mamba
return m_data->pool.get();
}
Pool const* MPool::pool() const
const Pool* MPool::pool() const
{
return m_data->pool.get();
}
@ -108,7 +109,7 @@ namespace mamba
return pool();
}
MPool::operator Pool const*() const
MPool::operator const Pool*() const
{
return pool();
}
@ -121,14 +122,16 @@ namespace mamba
if (sorted)
{
std::sort(solvables.begin(),
solvables.end(),
[this](Id a, Id b)
{
Solvable* sa = pool_id2solvable(pool(), a);
Solvable* sb = pool_id2solvable(pool(), b);
return (pool_evrcmp(this->pool(), sa->evr, sb->evr, EVRCMP_COMPARE) > 0);
});
std::sort(
solvables.begin(),
solvables.end(),
[this](Id a, Id b)
{
Solvable* sa = pool_id2solvable(pool(), a);
Solvable* sb = pool_id2solvable(pool(), b);
return (pool_evrcmp(this->pool(), sa->evr, sb->evr, EVRCMP_COMPARE) > 0);
}
);
}
return solvables.as<std::vector>();
}
@ -137,7 +140,9 @@ namespace mamba
{
Id id = pool_conda_matchspec(pool(), ms.c_str());
if (!id)
{
throw std::runtime_error("libsolv error: could not create matchspec from string");
}
return id;
}

View File

@ -9,10 +9,9 @@ extern "C"
#include <solv/transaction.h>
}
#include "mamba/core/prefix_data.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/prefix_data.hpp"
#include "mamba/core/queue.hpp"
#include "mamba/core/repo.hpp"
@ -26,14 +25,15 @@ namespace mamba
}
catch (std::exception& e)
{
return tl::make_unexpected(
mamba_error(e.what(), mamba_error_code::prefix_data_not_loaded));
return tl::make_unexpected(mamba_error(e.what(), mamba_error_code::prefix_data_not_loaded)
);
}
catch (...)
{
return tl::make_unexpected(
mamba_error("Unknown error when trying to load prefix data " + prefix_path.string(),
mamba_error_code::unknown));
return tl::make_unexpected(mamba_error(
"Unknown error when trying to load prefix data " + prefix_path.string(),
mamba_error_code::unknown
));
}
}
@ -119,7 +119,8 @@ namespace mamba
}
default:
throw std::runtime_error(
"Package not found in prefix records or other unexpected condition");
"Package not found in prefix records or other unexpected condition"
);
}
}
return result;

View File

@ -1,4 +1,5 @@
#include "mamba/core/progress_bar.hpp"
#include "progress_bar_impl.hpp"
namespace mamba

File diff suppressed because it is too large Load Diff

View File

@ -7,16 +7,16 @@
#ifndef MAMBA_CORE_PROGRESS_BAR_IMPL_HPP
#define MAMBA_CORE_PROGRESS_BAR_IMPL_HPP
#include <iosfwd>
#include <mutex>
#include <atomic>
#include <iosfwd>
#include <map>
#include <mutex>
#include <set>
#include <string_view>
#include <vector>
#include <map>
#include <spdlog/spdlog.h>
#include <fmt/color.h>
#include <spdlog/spdlog.h>
#include "mamba/core/progress_bar.hpp"
@ -44,9 +44,9 @@ namespace mamba
class Chrono
{
public:
using duration_t = std::chrono::milliseconds;
using time_point_t
= std::chrono::time_point<std::chrono::high_resolution_clock, duration_t>;
using time_point_t = std::chrono::time_point<std::chrono::high_resolution_clock, duration_t>;
Chrono() = default;
@ -75,6 +75,7 @@ namespace mamba
std::unique_lock<std::mutex> chrono_lock();
private:
time_point_t m_start;
duration_t m_elapsed_ns = duration_t::zero();
ChronoState m_state = ChronoState::unset;
@ -83,12 +84,14 @@ namespace mamba
void compute_elapsed();
protected:
static time_point_t now();
};
class FieldRepr
{
public:
bool active() const;
bool defined() const;
operator bool() const;
@ -109,6 +112,7 @@ namespace mamba
FieldRepr& resize(std::size_t size);
private:
std::string m_value = "";
std::size_t m_width = 0;
std::string m_format = "";
@ -123,6 +127,7 @@ namespace mamba
class ProgressBarRepr
{
public:
ProgressBarRepr();
ProgressBarRepr(ProgressBar* pbar);
@ -136,7 +141,7 @@ namespace mamba
ProgressBarRepr& set_width(std::size_t width);
std::size_t width() const;
fmt::text_style const& style() const;
const fmt::text_style& style() const;
void clear_style();
void reset_style();
@ -145,6 +150,7 @@ namespace mamba
const ProgressBar& progress_bar() const;
private:
fmt::text_style m_style_none;
fmt::text_style m_style_downloaded;
fmt::text_style m_style_extracted;
@ -170,6 +176,7 @@ namespace mamba
class ProgressBarManager : public Chrono
{
public:
virtual ~ProgressBarManager();
ProgressBarManager(const ProgressBarManager&) = delete;
@ -177,17 +184,17 @@ namespace mamba
ProgressBarManager(ProgressBarManager&&) = delete;
ProgressBarManager& operator=(ProgressBarManager&&) = delete;
virtual ProgressProxy add_progress_bar(const std::string& name, size_t expected_total = 0)
= 0;
virtual ProgressProxy add_progress_bar(const std::string& name, size_t expected_total = 0) = 0;
virtual void clear_progress_bars();
virtual void add_label(const std::string& label, const ProgressProxy& progress_bar);
void watch_print(const duration_t& period = std::chrono::milliseconds(100));
virtual std::size_t print(std::ostream& os,
std::size_t width = 0,
std::size_t max_lines = std::numeric_limits<std::size_t>::max(),
bool with_endl = true)
= 0;
virtual std::size_t print(
std::ostream& os,
std::size_t width = 0,
std::size_t max_lines = std::numeric_limits<std::size_t>::max(),
bool with_endl = true
) = 0;
void start();
void terminate();
@ -201,6 +208,7 @@ namespace mamba
void deactivate_sorting();
protected:
using progress_bar_ptr = std::unique_ptr<ProgressBar>;
ProgressBarManager() = default;
@ -240,27 +248,30 @@ namespace mamba
class MultiBarManager : public ProgressBarManager
{
public:
MultiBarManager();
MultiBarManager(std::size_t width);
virtual ~MultiBarManager() = default;
ProgressProxy add_progress_bar(const std::string& name, size_t expected_total) override;
std::size_t print(std::ostream& os,
std::size_t width = 0,
std::size_t max_lines = std::numeric_limits<std::size_t>::max(),
bool with_endl = true) override;
std::size_t print(
std::ostream& os,
std::size_t width = 0,
std::size_t max_lines = std::numeric_limits<std::size_t>::max(),
bool with_endl = true
) override;
};
class AggregatedBarManager : public ProgressBarManager
{
public:
AggregatedBarManager();
AggregatedBarManager(std::size_t width);
virtual ~AggregatedBarManager() = default;
ProgressProxy add_progress_bar(const std::string& name,
std::size_t expected_total) override;
ProgressProxy add_progress_bar(const std::string& name, std::size_t expected_total) override;
void update_download_bar(std::size_t current_diff);
void update_extract_bar();
@ -273,12 +284,15 @@ namespace mamba
ProgressBar* aggregated_bar(const std::string& label);
std::size_t print(std::ostream& os,
std::size_t width = 0,
std::size_t max_lines = std::numeric_limits<std::size_t>::max(),
bool with_endl = true) override;
std::size_t print(
std::ostream& os,
std::size_t width = 0,
std::size_t max_lines = std::numeric_limits<std::size_t>::max(),
bool with_endl = true
) override;
private:
std::map<std::string, progress_bar_ptr> m_aggregated_bars;
bool m_print_sub_bars = false;
@ -290,6 +304,7 @@ namespace mamba
class ProgressBar : public Chrono
{
public:
virtual ~ProgressBar();
ProgressBar(const ProgressBar&) = delete;
@ -315,15 +330,15 @@ namespace mamba
ProgressBar& activate_spinner();
ProgressBar& deactivate_spinner();
ProgressBar& mark_as_completed(const std::chrono::milliseconds& delay
= std::chrono::milliseconds::zero());
ProgressBar&
mark_as_completed(const std::chrono::milliseconds& delay = std::chrono::milliseconds::zero());
std::size_t current() const;
std::size_t in_progress() const;
std::size_t total() const;
std::size_t speed() const;
std::size_t avg_speed(const std::chrono::milliseconds& ref_duration
= std::chrono::milliseconds::max());
std::size_t
avg_speed(const std::chrono::milliseconds& ref_duration = std::chrono::milliseconds::max());
double progress() const;
bool completed() const;
bool is_spinner() const;
@ -347,6 +362,7 @@ namespace mamba
int width() const;
protected:
ProgressBar(const std::string& prefix, std::size_t total, int width = 0);
double m_progress = 0.;
@ -380,6 +396,7 @@ namespace mamba
class DefaultProgressBar : public ProgressBar
{
public:
DefaultProgressBar(const std::string& prefix, std::size_t total, int width = 0);
virtual ~DefaultProgressBar() = default;
@ -389,10 +406,13 @@ namespace mamba
class HiddenProgressBar : public ProgressBar
{
public:
HiddenProgressBar(const std::string& prefix,
AggregatedBarManager* manager,
std::size_t total,
int width = 0);
HiddenProgressBar(
const std::string& prefix,
AggregatedBarManager* manager,
std::size_t total,
int width = 0
);
virtual ~HiddenProgressBar() = default;
void print(std::ostream& stream, std::size_t width = 0, bool with_endl = true) override;

View File

@ -4,33 +4,36 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/query.hpp"
#include <iostream>
#include <stack>
#include <spdlog/spdlog.h>
#include <fmt/chrono.h>
#include <fmt/color.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <fmt/color.h>
#include <solv/evr.h>
#include <spdlog/spdlog.h>
#include "mamba/core/context.hpp"
#include "mamba/core/query.hpp"
#include "mamba/core/match_spec.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/package_info.hpp"
#include "mamba/core/queue.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/url.hpp"
#include "mamba/core/util.hpp"
namespace mamba
{
void walk_graph(query_result::dependency_graph& dep_graph,
query_result::dependency_graph::node_id parent,
Solvable* s,
std::map<Solvable*, size_t>& visited,
std::map<std::string, size_t>& not_found,
int depth = -1)
void walk_graph(
query_result::dependency_graph& dep_graph,
query_result::dependency_graph::node_id parent,
Solvable* s,
std::map<Solvable*, size_t>& visited,
std::map<std::string, size_t>& not_found,
int depth = -1
)
{
if (depth == 0)
{
@ -82,8 +85,9 @@ namespace mamba
auto it = not_found.find(name);
if (it == not_found.end())
{
auto dep_id
= dep_graph.add_node(PackageInfo(concat(name, " >>> NOT FOUND <<<")));
auto dep_id = dep_graph.add_node(
PackageInfo(concat(name, " >>> NOT FOUND <<<"))
);
dep_graph.add_edge(parent, dep_id);
not_found.insert(std::make_pair(name, dep_id));
}
@ -98,10 +102,12 @@ namespace mamba
}
}
void reverse_walk_graph(query_result::dependency_graph& dep_graph,
query_result::dependency_graph::node_id parent,
Solvable* s,
std::map<Solvable*, size_t>& visited)
void reverse_walk_graph(
query_result::dependency_graph& dep_graph,
query_result::dependency_graph::node_id parent,
Solvable* s,
std::map<Solvable*, size_t>& visited
)
{
if (s)
{
@ -214,16 +220,18 @@ namespace mamba
query_result::dependency_graph g;
Pool* pool = m_pool.get();
std::sort(solvables.begin(),
solvables.end(),
[pool](Id a, Id b)
{
Solvable* sa;
Solvable* sb;
sa = pool_id2solvable(pool, a);
sb = pool_id2solvable(pool, b);
return (pool_evrcmp(pool, sa->evr, sb->evr, EVRCMP_COMPARE) > 0);
});
std::sort(
solvables.begin(),
solvables.end(),
[pool](Id a, Id b)
{
Solvable* sa;
Solvable* sb;
sa = pool_id2solvable(pool, a);
sb = pool_id2solvable(pool, b);
return (pool_evrcmp(pool, sa->evr, sb->evr, EVRCMP_COMPARE) > 0);
}
);
for (auto& el : solvables)
{
@ -322,9 +330,7 @@ namespace mamba
* query_result implementation *
*******************************/
query_result::query_result(QueryType type,
const std::string& query,
dependency_graph&& dep_graph)
query_result::query_result(QueryType type, const std::string& query, dependency_graph&& dep_graph)
: m_type(type)
, m_query(query)
, m_dep_graph(std::move(dep_graph))
@ -347,22 +353,25 @@ namespace mamba
{
package_view_list tmp(rhs.m_pkg_view_list.size());
std::transform(
rhs.m_pkg_view_list.begin(), rhs.m_pkg_view_list.end(), tmp.begin(), offset_lbd);
std::transform(rhs.m_pkg_view_list.begin(), rhs.m_pkg_view_list.end(), tmp.begin(), offset_lbd);
swap(tmp, m_pkg_view_list);
}
if (!rhs.m_ordered_pkg_list.empty())
{
auto tmp(rhs.m_ordered_pkg_list);
std::for_each(tmp.begin(),
tmp.end(),
[offset_lbd](auto& entry) {
std::transform(entry.second.begin(),
entry.second.end(),
entry.second.begin(),
offset_lbd);
});
std::for_each(
tmp.begin(),
tmp.end(),
[offset_lbd](auto& entry) {
std::transform(
entry.second.begin(),
entry.second.end(),
entry.second.begin(),
offset_lbd
);
}
);
swap(m_ordered_pkg_list, tmp);
}
}
@ -396,16 +405,20 @@ namespace mamba
{
for (auto& entry : m_ordered_pkg_list)
{
std::sort(entry.second.begin(),
entry.second.end(),
[fun](const auto& lhs, const auto& rhs) { return fun(*lhs, *rhs); });
std::sort(
entry.second.begin(),
entry.second.end(),
[fun](const auto& lhs, const auto& rhs) { return fun(*lhs, *rhs); }
);
}
}
else
{
std::sort(m_pkg_view_list.begin(),
m_pkg_view_list.end(),
[fun](const auto& lhs, const auto& rhs) { return fun(*lhs, *rhs); });
std::sort(
m_pkg_view_list.begin(),
m_pkg_view_list.end(),
[fun](const auto& lhs, const auto& rhs) { return fun(*lhs, *rhs); }
);
}
return *this;
@ -539,6 +552,7 @@ namespace mamba
class graph_printer
{
public:
using graph_type = query_result::dependency_graph;
using node_id = graph_type::node_id;
@ -602,6 +616,7 @@ namespace mamba
}
private:
bool is_on_last_stack(node_id node) const
{
return !m_last_stack.empty() && m_last_stack.top() == node;
@ -671,8 +686,8 @@ namespace mamba
: (m_type == QueryType::kDEPENDS ? "depends" : "whoneeds");
j["query"] = { { "query", MatchSpec(m_query).conda_build_form() }, { "type", query_type } };
std::string msg
= m_pkg_view_list.empty() ? "No entries matching \"" + m_query + "\" found" : "";
std::string msg = m_pkg_view_list.empty() ? "No entries matching \"" + m_query + "\" found"
: "";
j["result"] = { { "msg", msg }, { "status", "OK" } };
j["result"]["pkgs"] = nlohmann::json::array();
@ -685,8 +700,9 @@ namespace mamba
{
bool has_root = !m_dep_graph.successors(0).empty();
j["result"]["graph_roots"] = nlohmann::json::array();
j["result"]["graph_roots"].push_back(has_root ? m_dep_graph.nodes()[0].json_record()
: nlohmann::json(m_query));
j["result"]["graph_roots"].push_back(
has_root ? m_dep_graph.nodes()[0].json_record() : nlohmann::json(m_query)
);
}
return j;
}

View File

@ -4,11 +4,12 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "mamba/core/context.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/repo.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/package_info.hpp"
#include "mamba/core/pool.hpp"
extern "C"
{
@ -30,11 +31,13 @@ namespace mamba
return MTV;
}
MRepo::MRepo(MPool& pool,
const std::string& /*name*/,
const fs::u8path& index,
const RepoMetadata& metadata,
const Channel& channel)
MRepo::MRepo(
MPool& pool,
const std::string& /*name*/,
const fs::u8path& index,
const RepoMetadata& metadata,
const Channel& channel
)
: m_metadata(metadata)
{
m_url = rsplit(metadata.url, "/", 1)[0];
@ -44,10 +47,7 @@ namespace mamba
p_channel = &channel;
}
MRepo::MRepo(MPool& pool,
const std::string& name,
const std::string& index,
const std::string& url)
MRepo::MRepo(MPool& pool, const std::string& name, const std::string& index, const std::string& url)
: m_url(url)
{
m_repo = repo_create(pool, name.c_str());
@ -55,9 +55,7 @@ namespace mamba
read_file(index);
}
MRepo::MRepo(MPool& pool,
const std::string& name,
const std::vector<PackageInfo>& package_infos)
MRepo::MRepo(MPool& pool, const std::string& name, const std::vector<PackageInfo>& package_infos)
{
m_repo = repo_create(pool, name.c_str());
m_repo->appdata = this;
@ -154,8 +152,7 @@ namespace mamba
Id handle = repo_add_solvable(m_repo);
Solvable* s = pool_id2solvable(pool, handle);
repodata_set_str(
data, handle, SOLVABLE_BUILDVERSION, std::to_string(info.build_number).c_str());
repodata_set_str(data, handle, SOLVABLE_BUILDVERSION, std::to_string(info.build_number).c_str());
repodata_add_poolstr_array(data, handle, SOLVABLE_BUILDFLAVOR, info.build_string.c_str());
s->name = pool_str2id(pool, info.name.c_str(), 1);
s->evr = pool_str2id(pool, info.version.c_str(), 1);
@ -165,12 +162,13 @@ namespace mamba
solvable_set_str(s, real_repo_key, info.url.c_str());
if (!info.noarch.empty())
{
solvable_set_str(s, noarch_repo_key, info.noarch.c_str());
}
repodata_set_location(data, handle, 0, info.subdir.c_str(), info.fn.c_str());
repodata_set_checksum(
data, handle, SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, info.sha256.c_str());
repodata_set_checksum(data, handle, SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, info.sha256.c_str());
if (!info.depends.empty())
{
@ -196,8 +194,12 @@ namespace mamba
}
}
s->provides
= repo_addid_dep(m_repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
s->provides = repo_addid_dep(
m_repo,
s->provides,
pool_rel2id(pool, s->name, s->evr, REL_EQ, 1),
0
);
}
Id MRepo::id() const
@ -261,25 +263,29 @@ namespace mamba
}
if (pkg_s->name == pip)
{
pkg_s->requires
= repo_addid_dep(m_repo, pkg_s->requires, python_dep, SOLVABLE_PREREQMARKER);
pkg_s->requires = repo_addid_dep(
m_repo,
pkg_s->requires,
python_dep,
SOLVABLE_PREREQMARKER
);
}
}
}
MRepo& MRepo::create(MPool& pool,
const std::string& name,
const std::string& filename,
const std::string& url)
MRepo&
MRepo::create(MPool& pool, const std::string& name, const std::string& filename, const std::string& url)
{
return pool.add_repo(MRepo(pool, name, filename, url));
}
MRepo& MRepo::create(MPool& pool,
const std::string& name,
const fs::u8path& filename,
const RepoMetadata& meta,
const Channel& channel)
MRepo& MRepo::create(
MPool& pool,
const std::string& name,
const fs::u8path& filename,
const RepoMetadata& meta,
const Channel& channel
)
{
return pool.add_repo(MRepo(pool, name, filename, meta, channel));
}
@ -352,16 +358,24 @@ namespace mamba
static constexpr auto failure = std::numeric_limits<unsigned long long>::max();
const char* url = repodata_lookup_str(repodata, SOLVID_META, url_id);
const auto pip_added
= repodata_lookup_num(repodata, SOLVID_META, pip_added_id, failure);
const auto pip_added = repodata_lookup_num(
repodata,
SOLVID_META,
pip_added_id,
failure
);
const char* etag = repodata_lookup_str(repodata, SOLVID_META, etag_id);
const char* mod = repodata_lookup_str(repodata, SOLVID_META, mod_id);
const char* tool_version
= repodata_lookup_str(repodata, SOLVID_META, REPOSITORY_TOOLVERSION);
const char* tool_version = repodata_lookup_str(
repodata,
SOLVID_META,
REPOSITORY_TOOLVERSION
);
LOG_INFO << "Metadata solv file: " << url << " " << pip_added << " " << etag
<< " " << mod << " " << tool_version;
bool metadata_valid
= !(!url || !etag || !mod || !tool_version || pip_added == failure);
bool metadata_valid = !(
!url || !etag || !mod || !tool_version || pip_added == failure
);
if (metadata_valid)
{
@ -370,8 +384,7 @@ namespace mamba
&& (std::strcmp(tool_version, mamba_tool_version()) == 0);
}
LOG_INFO << "Metadata from SOLV are "
<< (metadata_valid ? "valid" : "NOT valid");
LOG_INFO << "Metadata from SOLV are " << (metadata_valid ? "valid" : "NOT valid");
if (!metadata_valid)
{
@ -412,8 +425,10 @@ namespace mamba
if (ret != 0)
{
fclose(fp);
throw std::runtime_error("Could not read JSON repodata file (" + m_json_file.string()
+ ") " + std::string(pool_errstr(m_repo->pool)));
throw std::runtime_error(
"Could not read JSON repodata file (" + m_json_file.string() + ") "
+ std::string(pool_errstr(m_repo->pool))
);
}
// TODO move this to a more structured approach for repodata patching?

View File

@ -1,32 +1,32 @@
#include <iostream>
#include "mamba/core/run.hpp"
#include <csignal>
#include <exception>
#include <iostream>
#include <thread>
#include <spdlog/spdlog.h>
#include <fmt/color.h>
#include <fmt/ostream.h>
#include <reproc++/run.hpp>
#include <nlohmann/json.hpp>
#include <reproc++/run.hpp>
#include <spdlog/spdlog.h>
#include "mamba/api/configuration.hpp"
#include "mamba/api/install.hpp"
#include "mamba/core/error_handling.hpp"
#include "mamba/core/execution.hpp"
#include "mamba/core/util_os.hpp"
#include "mamba/core/util_random.hpp"
#include "mamba/core/execution.hpp"
#include "mamba/core/error_handling.hpp"
#include "mamba/core/run.hpp"
#ifndef _WIN32
extern "C"
{
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
}
#else
#include <process.h>
@ -62,10 +62,8 @@ namespace mamba
if (!prefixes_bag.empty())
{
// Pick a random prefix from our bag of prefixes.
const auto selected_prefix_idx
= random_int<std::size_t>(0, prefixes_bag.size() - 1);
const auto selected_prefix_it
= std::next(prefixes_bag.begin(), selected_prefix_idx);
const auto selected_prefix_idx = random_int<std::size_t>(0, prefixes_bag.size() - 1);
const auto selected_prefix_it = std::next(prefixes_bag.begin(), selected_prefix_idx);
selected_prefix = *selected_prefix_it;
prefixes_bag.erase(selected_prefix_it);
}
@ -90,7 +88,9 @@ namespace mamba
const auto new_process_name = fmt::format("{}_{}", selected_prefix, selected_name);
if (!is_process_name_running(new_process_name))
{
return new_process_name;
}
}
}
@ -112,23 +112,23 @@ namespace mamba
fmt::format(
"'mamba run' failed to lock ({}) or lockfile was not properly deleted - error: {}",
proc_dir_path.string(),
error->what()),
error->what()
),
mamba_error_code::lockfile_failure
};
}
else
{
LOG_DEBUG
<< "`mamba run` file locking attempt ignored because locking is disabled - path: "
<< proc_dir_path.string();
LOG_DEBUG << "`mamba run` file locking attempt ignored because locking is disabled - path: "
<< proc_dir_path.string();
}
}
return lockfile;
}
nlohmann::json get_all_running_processes_info(
const std::function<bool(const nlohmann::json&)>& filter)
nlohmann::json
get_all_running_processes_info(const std::function<bool(const nlohmann::json&)>& filter)
{
nlohmann::json all_processes_info;
@ -138,7 +138,9 @@ namespace mamba
{
const auto file_location = entry.path();
if (file_location.extension() != ".json")
{
continue;
}
std::ifstream pid_file{ file_location.std_path(), open_mode };
if (!pid_file.is_open())
@ -150,7 +152,9 @@ namespace mamba
auto running_processes_info = nlohmann::json::parse(pid_file);
running_processes_info["pid"] = file_location.filename().replace_extension().string();
if (!filter || filter(running_processes_info))
{
all_processes_info.push_back(running_processes_info);
}
}
return all_processes_info;
@ -159,25 +163,31 @@ namespace mamba
bool is_process_name_running(const std::string& name)
{
const auto other_processes_with_same_name = get_all_running_processes_info(
[&](const nlohmann::json& process_info) { return process_info["name"] == name; });
[&](const nlohmann::json& process_info) { return process_info["name"] == name; }
);
return !other_processes_with_same_name.empty();
}
ScopedProcFile::ScopedProcFile(const std::string& name,
const std::vector<std::string>& command,
LockFile proc_dir_lock)
ScopedProcFile::ScopedProcFile(
const std::string& name,
const std::vector<std::string>& command,
LockFile proc_dir_lock
)
: location{ proc_dir() / fmt::format("{}.json", getpid()) }
{
// Lock must be hold for the duraction of this constructor.
if (Context::instance().use_lockfiles)
{
assert(proc_dir_lock);
}
const auto open_mode = std::ios::binary | std::ios::trunc | std::ios::out;
std::ofstream pid_file(location.std_path(), open_mode);
if (!pid_file.is_open())
{
throw std::runtime_error(
fmt::format("'mamba run' failed to open/create file: {}", location.string()));
fmt::format("'mamba run' failed to open/create file: {}", location.string())
);
}
nlohmann::json file_json;
@ -196,7 +206,10 @@ namespace mamba
if (!is_removed)
{
LOG_WARNING << fmt::format(
"Failed to remove file '{}' : {}", location.string(), errcode.message());
"Failed to remove file '{}' : {}",
location.string(),
errcode.message()
);
}
}
@ -208,22 +221,30 @@ namespace mamba
// already a daemon
if (getppid() == 1)
{
return;
}
// fork parent process
pid = fork();
if (pid < 0)
{
exit(1);
}
// exit parent process
if (pid > 0)
{
exit(0);
}
// at this point we are executing as the child process
// create a new SID for the child process
sid = setsid();
if (sid < 0)
{
exit(1);
}
fd = open("/dev/null", O_RDWR, 0);
@ -244,18 +265,19 @@ namespace mamba
}
#endif
int run_in_environment(std::vector<std::string> command,
const std::string& cwd,
int stream_options,
bool clean_env,
bool detach,
const std::vector<std::string>& env_vars,
const std::string& specific_process_name)
int run_in_environment(
std::vector<std::string> command,
const std::string& cwd,
int stream_options,
bool clean_env,
bool detach,
const std::vector<std::string>& env_vars,
const std::string& specific_process_name
)
{
if (!fs::exists(Context::instance().target_prefix))
{
LOG_CRITICAL << "The given prefix does not exist: "
<< Context::instance().target_prefix;
LOG_CRITICAL << "The given prefix does not exist: " << Context::instance().target_prefix;
return 1;
}
std::vector<std::string> raw_command = command;
@ -264,8 +286,7 @@ namespace mamba
bool is_created = fs::create_directories(proc_dir(), ec);
if (!is_created && ec)
{
LOG_WARNING << "Could not create proc dir: " << proc_dir() << " (" << ec.message()
<< ")";
LOG_WARNING << "Could not create proc dir: " << proc_dir() << " (" << ec.message() << ")";
}
LOG_DEBUG << "Currently running processes: " << get_all_running_processes_info();
@ -274,11 +295,15 @@ namespace mamba
// replace the wrapping bash with new process entirely
#ifndef _WIN32
if (command.front() != "exec")
{
command.insert(command.begin(), "exec");
}
#endif
auto [wrapped_command, script_file]
= prepare_wrapped_call(Context::instance().target_prefix, command);
auto [wrapped_command, script_file] = prepare_wrapped_call(
Context::instance().target_prefix,
command
);
LOG_DEBUG << "Running wrapped script: " << join(" ", command);
@ -317,8 +342,7 @@ namespace mamba
}
else
{
LOG_WARNING << "Requested env var " << e
<< " does not exist in environment";
LOG_WARNING << "Requested env var " << e << " does not exist in environment";
}
}
}
@ -332,9 +356,11 @@ namespace mamba
#ifndef _WIN32
if (detach)
{
Console::stream() << fmt::format(Context::instance().palette.success,
"Running wrapped script {} in the background\n",
fmt::join(command, " "));
Console::stream() << fmt::format(
Context::instance().palette.success,
"Running wrapped script {} in the background\n",
fmt::join(command, " ")
);
daemonize();
}
#endif
@ -362,9 +388,10 @@ namespace mamba
{
if (is_process_name_running(specific_process_name))
{
throw std::runtime_error(
fmt::format("Another process with name '{}' is currently running.",
specific_process_name));
throw std::runtime_error(fmt::format(
"Another process with name '{}' is currently running.",
specific_process_name
));
}
command.insert(exe_name_it, { { "-a" }, specific_process_name });
return specific_process_name;
@ -377,7 +404,10 @@ namespace mamba
if (fs::is_directory(proc_dir()) && mamba::path::is_writable(proc_dir()))
{
scoped_proc_file = std::make_unique<ScopedProcFile>(
process_name, raw_command, std::move(proc_dir_lock));
process_name,
raw_command,
std::move(proc_dir_lock)
);
}
#endif
PID pid;
@ -398,24 +428,25 @@ namespace mamba
MainExecutor::instance().schedule(
[]()
{
signal(SIGTERM,
[](int signum)
{
LOG_INFO
<< "Received SIGTERM on micromamba run - terminating process";
reproc::stop_actions sa;
sa.first = reproc::stop_action{ reproc::stop::terminate,
std::chrono::milliseconds(3000) };
sa.second = reproc::stop_action{ reproc::stop::kill,
std::chrono::milliseconds(3000) };
proc.stop(sa);
});
});
signal(
SIGTERM,
[](int signum)
{
LOG_INFO << "Received SIGTERM on micromamba run - terminating process";
reproc::stop_actions sa;
sa.first = reproc::stop_action{ reproc::stop::terminate,
std::chrono::milliseconds(3000) };
sa.second = reproc::stop_action{ reproc::stop::kill,
std::chrono::milliseconds(3000) };
proc.stop(sa);
}
);
}
);
#endif
// check if we need this
if (!opt.redirect.discard && opt.redirect.file == nullptr
&& opt.redirect.path == nullptr)
if (!opt.redirect.discard && opt.redirect.file == nullptr && opt.redirect.path == nullptr)
{
opt.redirect.parent = true;
}

File diff suppressed because it is too large Load Diff

View File

@ -7,21 +7,21 @@
#include <regex>
#include <stdexcept>
#include <fmt/format.h>
#include <fmt/color.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <reproc++/run.hpp>
#ifdef _WIN32
#include <WinReg.hpp>
#endif
#include "mamba/core/shell_init.hpp"
#include "mamba/core/activation.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/environment.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/shell_init.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/util_os.hpp"
#include "mamba/core/activation.hpp"
#include "mamba/core/environment.hpp"
#include "progress_bar_impl.hpp"
@ -29,17 +29,15 @@ namespace mamba
{
namespace
{
static std::regex const MAMBA_INITIALIZE_RE_BLOCK(
"\n?# >>> mamba initialize >>>(?:\n|\r\n)?"
"([\\s\\S]*?)"
"# <<< mamba initialize <<<(?:\n|\r\n)?");
static std::regex const MAMBA_INITIALIZE_RE_BLOCK("\n?# >>> mamba initialize >>>(?:\n|\r\n)?"
"([\\s\\S]*?)"
"# <<< mamba initialize <<<(?:\n|\r\n)?");
static std::regex const MAMBA_INITIALIZE_PS_RE_BLOCK(
"\n?#region mamba initialize(?:\n|\r\n)?"
"([\\s\\S]*?)"
"#endregion(?:\n|\r\n)?");
static std::wregex const MAMBA_CMDEXE_HOOK_REGEX(L"(\"[^\"]*?mamba[-_]hook\\.bat\")",
std::regex_constants::icase);
static std::regex const MAMBA_INITIALIZE_PS_RE_BLOCK("\n?#region mamba initialize(?:\n|\r\n)?"
"([\\s\\S]*?)"
"#endregion(?:\n|\r\n)?");
static std::wregex const
MAMBA_CMDEXE_HOOK_REGEX(L"(\"[^\"]*?mamba[-_]hook\\.bat\")", std::regex_constants::icase);
}
@ -113,9 +111,11 @@ namespace mamba
void set_autorun_registry_key(const std::wstring& reg_path, const std::wstring& value)
{
auto out = Console::stream();
fmt::print(out,
"Setting cmd.exe AUTORUN to: {}",
fmt::styled(to_utf8(value), Context::instance().palette.success));
fmt::print(
out,
"Setting cmd.exe AUTORUN to: {}",
fmt::styled(to_utf8(value), Context::instance().palette.success)
);
winreg::RegKey key{ HKEY_CURRENT_USER, reg_path };
key.SetStringValue(L"AutoRun", value);
@ -135,10 +135,12 @@ namespace mamba
// modify registry key
std::wstring replace_str(L"__CONDA_REPLACE_ME_123__");
std::wstring replaced_value = std::regex_replace(prev_value,
MAMBA_CMDEXE_HOOK_REGEX,
replace_str,
std::regex_constants::format_first_only);
std::wstring replaced_value = std::regex_replace(
prev_value,
MAMBA_CMDEXE_HOOK_REGEX,
replace_str,
std::regex_constants::format_first_only
);
std::wstring new_value = replaced_value;
@ -169,7 +171,8 @@ namespace mamba
fmt::print(
out,
"{}",
fmt::styled("cmd.exe already initialized.", Context::instance().palette.success));
fmt::styled("cmd.exe already initialized.", Context::instance().palette.success)
);
}
}
@ -187,11 +190,14 @@ namespace mamba
autorun_list = split(std::wstring_view(prev_value), std::wstring_view(L"&"));
// remove the mamba hook from the autorun list
autorun_list.erase(std::remove_if(autorun_list.begin(),
autorun_list.end(),
[&hook_string](const std::wstring& s)
{ return strip(s) == hook_string; }),
autorun_list.end());
autorun_list.erase(
std::remove_if(
autorun_list.begin(),
autorun_list.end(),
[&hook_string](const std::wstring& s) { return strip(s) == hook_string; }
),
autorun_list.end()
);
// join the list back into a string
std::wstring new_value = join(L" & ", autorun_list);
@ -207,7 +213,8 @@ namespace mamba
fmt::print(
out,
"{}",
fmt::styled("cmd.exe not initialized yet.", Context::instance().palette.success));
fmt::styled("cmd.exe not initialized yet.", Context::instance().palette.success)
);
}
}
#endif // _WIN32
@ -224,23 +231,31 @@ namespace mamba
fs::u8path bash;
fs::u8path parent_process_name = get_process_name_by_pid(getppid());
if (contains(parent_process_name.filename().string(), "bash"))
{
bash = parent_process_name;
}
else
#ifdef _WIN32
bash = env::which("bash.exe");
#else
bash = env::which("bash");
#endif
const std::string command
= bash.empty() ? "cygpath" : (bash.parent_path() / "cygpath").string();
const std::string command = bash.empty() ? "cygpath"
: (bash.parent_path() / "cygpath").string();
std::string out, err;
try
{
std::vector<std::string> args{ command, path };
if (is_a_path_env)
{
args.push_back("--path");
}
auto [status, ec] = reproc::run(
args, reproc::options{}, reproc::sink::string(out), reproc::sink::string(err));
args,
reproc::options{},
reproc::sink::string(out),
reproc::sink::string(err)
);
if (ec)
{
throw std::runtime_error(ec.message());
@ -250,14 +265,14 @@ namespace mamba
catch (...)
{
throw std::runtime_error(
"Could not find bash, or use cygpath to convert Windows path to Unix.");
"Could not find bash, or use cygpath to convert Windows path to Unix."
);
}
}
std::string rcfile_content(const fs::u8path& env_prefix,
const std::string& shell,
const fs::u8path& mamba_exe)
std::string
rcfile_content(const fs::u8path& env_prefix, const std::string& shell, const fs::u8path& mamba_exe)
{
std::stringstream content;
@ -303,9 +318,8 @@ namespace mamba
#endif
}
std::string xonsh_content(const fs::u8path& env_prefix,
const std::string& /*shell*/,
const fs::u8path& mamba_exe)
std::string
xonsh_content(const fs::u8path& env_prefix, const std::string& /*shell*/, const fs::u8path& mamba_exe)
{
std::stringstream content;
std::string s_mamba_exe;
@ -326,22 +340,18 @@ namespace mamba
content << "import sys as _sys\n";
content << "from types import ModuleType as _ModuleType\n";
content << "_mod = _ModuleType(\"xontrib.mamba\",\n";
content
<< " \'Autogenerated from $($MAMBA_EXE shell hook -s xonsh -p $MAMBA_ROOT_PREFIX)\')\n";
content
<< "__xonsh__.execer.exec($($MAMBA_EXE shell hook -s xonsh -p $MAMBA_ROOT_PREFIX),\n";
content << " \'Autogenerated from $($MAMBA_EXE shell hook -s xonsh -p $MAMBA_ROOT_PREFIX)\')\n";
content << "__xonsh__.execer.exec($($MAMBA_EXE shell hook -s xonsh -p $MAMBA_ROOT_PREFIX),\n";
content << " glbs=_mod.__dict__,\n";
content
<< " filename=\'$($MAMBA_EXE shell hook -s xonsh -p $MAMBA_ROOT_PREFIX)\')\n";
content << " filename=\'$($MAMBA_EXE shell hook -s xonsh -p $MAMBA_ROOT_PREFIX)\')\n";
content << "_sys.modules[\"xontrib.mamba\"] = _mod\n";
content << "del _sys, _mod, _ModuleType\n";
content << "# <<< mamba initialize <<<\n";
return content.str();
}
std::string fish_content(const fs::u8path& env_prefix,
const std::string& /*shell*/,
const fs::u8path& mamba_exe)
std::string
fish_content(const fs::u8path& env_prefix, const std::string& /*shell*/, const fs::u8path& mamba_exe)
{
std::stringstream content;
std::string s_mamba_exe;
@ -364,9 +374,8 @@ namespace mamba
return content.str();
}
std::string csh_content(const fs::u8path& env_prefix,
const std::string& /*shell*/,
const fs::u8path& mamba_exe)
std::string
csh_content(const fs::u8path& env_prefix, const std::string& /*shell*/, const fs::u8path& mamba_exe)
{
std::stringstream content;
std::string s_mamba_exe;
@ -389,19 +398,23 @@ namespace mamba
return content.str();
}
void modify_rc_file(const fs::u8path& file_path,
const fs::u8path& conda_prefix,
const std::string& shell,
const fs::u8path& mamba_exe)
void modify_rc_file(
const fs::u8path& file_path,
const fs::u8path& conda_prefix,
const std::string& shell,
const fs::u8path& mamba_exe
)
{
auto out = Console::stream();
fmt::print(out,
"Modifying RC file {}\n"
"Generating config for root prefix {}\n"
"Setting mamba executable to: {}",
fmt::streamed(file_path),
fmt::styled(fmt::streamed(conda_prefix), fmt::emphasis::bold),
fmt::styled(fmt::streamed(mamba_exe), fmt::emphasis::bold));
fmt::print(
out,
"Modifying RC file {}\n"
"Generating config for root prefix {}\n"
"Setting mamba executable to: {}",
fmt::streamed(file_path),
fmt::styled(fmt::streamed(conda_prefix), fmt::emphasis::bold),
fmt::styled(fmt::streamed(mamba_exe), fmt::emphasis::bold)
);
// TODO do we need binary or not?
std::string conda_init_content, rc_content;
@ -432,18 +445,19 @@ namespace mamba
conda_init_content = rcfile_content(conda_prefix, shell, mamba_exe);
}
fmt::print(out,
"Adding (or replacing) the following in your {} file\n{}",
fmt::streamed(file_path),
fmt::styled(conda_init_content, Context::instance().palette.success));
fmt::print(
out,
"Adding (or replacing) the following in your {} file\n{}",
fmt::streamed(file_path),
fmt::styled(conda_init_content, Context::instance().palette.success)
);
if (Context::instance().dry_run)
{
return;
}
std::string result
= std::regex_replace(rc_content, MAMBA_INITIALIZE_RE_BLOCK, conda_init_content);
std::string result = std::regex_replace(rc_content, MAMBA_INITIALIZE_RE_BLOCK, conda_init_content);
if (result.find("# >>> mamba initialize >>>") == std::string::npos)
{
@ -457,12 +471,10 @@ namespace mamba
}
}
void reset_rc_file(const fs::u8path& file_path,
const std::string& shell,
const fs::u8path& mamba_exe)
void
reset_rc_file(const fs::u8path& file_path, const std::string& shell, const fs::u8path& mamba_exe)
{
Console::stream() << "Resetting RC file " << file_path
<< "\nDeleting config for root prefix "
Console::stream() << "Resetting RC file " << file_path << "\nDeleting config for root prefix "
<< "\nClearing mamba executable environment variable";
std::string conda_init_content, rc_content;
@ -478,11 +490,15 @@ namespace mamba
}
auto out = Console::stream();
fmt::print(out,
"Removing the following in your {} file\n{}",
fmt::streamed(file_path),
fmt::styled("# >>> mamba initialize >>>\n...\n# <<< mamba initialize <<<",
Context::instance().palette.success));
fmt::print(
out,
"Removing the following in your {} file\n{}",
fmt::streamed(file_path),
fmt::styled(
"# >>> mamba initialize >>>\n...\n# <<< mamba initialize <<<",
Context::instance().palette.success
)
);
if (rc_content.find("# >>> mamba initialize >>>") == std::string::npos)
{
@ -538,10 +554,10 @@ namespace mamba
{
init_root_prefix_cmdexe(Context::instance().root_prefix);
LOG_WARNING << "Hook installed, now 'manually' execute:";
LOG_WARNING
<< " CALL "
<< std::quoted(
(Context::instance().root_prefix / "condabin" / "mamba_hook.bat").string());
LOG_WARNING << " CALL "
<< std::quoted(
(Context::instance().root_prefix / "condabin" / "mamba_hook.bat").string()
);
}
else if (shell == "fish")
{
@ -568,40 +584,51 @@ namespace mamba
std::ofstream mamba_bat_f = open_ofstream(root_prefix / "condabin" / "micromamba.bat");
std::string mamba_bat_contents(data_micromamba_bat);
replace_all(mamba_bat_contents,
std::string("__MAMBA_INSERT_ROOT_PREFIX__"),
std::string("@SET \"MAMBA_ROOT_PREFIX=" + root_prefix.string() + "\""));
replace_all(mamba_bat_contents,
std::string("__MAMBA_INSERT_MAMBA_EXE__"),
std::string("@SET \"MAMBA_EXE=" + exe.string() + "\""));
replace_all(
mamba_bat_contents,
std::string("__MAMBA_INSERT_ROOT_PREFIX__"),
std::string("@SET \"MAMBA_ROOT_PREFIX=" + root_prefix.string() + "\"")
);
replace_all(
mamba_bat_contents,
std::string("__MAMBA_INSERT_MAMBA_EXE__"),
std::string("@SET \"MAMBA_EXE=" + exe.string() + "\"")
);
mamba_bat_f << mamba_bat_contents;
std::ofstream _mamba_activate_bat_f
= open_ofstream(root_prefix / "condabin" / "_mamba_activate.bat");
std::ofstream _mamba_activate_bat_f = open_ofstream(
root_prefix / "condabin" / "_mamba_activate.bat"
);
_mamba_activate_bat_f << data__mamba_activate_bat;
std::string activate_bat_contents(data_activate_bat);
replace_all(activate_bat_contents,
std::string("__MAMBA_INSERT_ROOT_PREFIX__"),
std::string("@SET \"MAMBA_ROOT_PREFIX=" + root_prefix.string() + "\""));
replace_all(activate_bat_contents,
std::string("__MAMBA_INSERT_MAMBA_EXE__"),
std::string("@SET \"MAMBA_EXE=" + exe.string() + "\""));
replace_all(
activate_bat_contents,
std::string("__MAMBA_INSERT_ROOT_PREFIX__"),
std::string("@SET \"MAMBA_ROOT_PREFIX=" + root_prefix.string() + "\"")
);
replace_all(
activate_bat_contents,
std::string("__MAMBA_INSERT_MAMBA_EXE__"),
std::string("@SET \"MAMBA_EXE=" + exe.string() + "\"")
);
std::ofstream condabin_activate_bat_f
= open_ofstream(root_prefix / "condabin" / "activate.bat");
std::ofstream condabin_activate_bat_f = open_ofstream(
root_prefix / "condabin" / "activate.bat"
);
condabin_activate_bat_f << activate_bat_contents;
std::ofstream scripts_activate_bat_f
= open_ofstream(root_prefix / "Scripts" / "activate.bat");
std::ofstream scripts_activate_bat_f = open_ofstream(root_prefix / "Scripts" / "activate.bat");
scripts_activate_bat_f << activate_bat_contents;
std::string hook_content = data_mamba_hook_bat;
replace_all(hook_content,
std::string("__MAMBA_INSERT_MAMBA_EXE__"),
std::string("@SET \"MAMBA_EXE=" + exe.string() + "\""));
replace_all(
hook_content,
std::string("__MAMBA_INSERT_MAMBA_EXE__"),
std::string("@SET \"MAMBA_EXE=" + exe.string() + "\"")
);
std::ofstream mamba_hook_bat_f = open_ofstream(root_prefix / "condabin" / "mamba_hook.bat");
mamba_hook_bat_f << hook_content;
@ -832,21 +859,26 @@ namespace mamba
std::string conda_init_content = powershell_contents(conda_prefix);
bool found_mamba_initialize
= profile_content.find("#region mamba initialize") != std::string::npos;
bool found_mamba_initialize = profile_content.find("#region mamba initialize")
!= std::string::npos;
// Find what content we need to add.
auto out = Console::stream();
fmt::print(out,
"Adding (or replacing) the following in your {} file\n{}",
fmt::streamed(profile_path),
fmt::styled(conda_init_content, Context::instance().palette.success));
fmt::print(
out,
"Adding (or replacing) the following in your {} file\n{}",
fmt::streamed(profile_path),
fmt::styled(conda_init_content, Context::instance().palette.success)
);
if (found_mamba_initialize)
{
LOG_DEBUG << "Found mamba initialize. Replacing mamba initialize block.";
profile_content = std::regex_replace(
profile_content, MAMBA_INITIALIZE_PS_RE_BLOCK, conda_init_content);
profile_content,
MAMBA_INITIALIZE_PS_RE_BLOCK,
conda_init_content
);
}
LOG_DEBUG << "Original profile content:\n" << profile_original_content;
@ -893,11 +925,12 @@ namespace mamba
LOG_DEBUG << "Original profile content:\n" << profile_content;
auto out = Console::stream();
fmt::print(out,
"Removing the following in your {} file\n{}",
fmt::streamed(profile_path),
fmt::styled("#region mamba initialize\n...\n#endregion\n",
Context::instance().palette.success));
fmt::print(
out,
"Removing the following in your {} file\n{}",
fmt::streamed(profile_path),
fmt::styled("#region mamba initialize\n...\n#endregion\n", Context::instance().palette.success)
);
profile_content = std::regex_replace(profile_content, MAMBA_INITIALIZE_PS_RE_BLOCK, "");
LOG_DEBUG << "Profile content:\n" << profile_content;
@ -946,7 +979,8 @@ namespace mamba
std::vector<std::string>{ exe, "-NoProfile", "-Command", profile_var },
reproc::options{},
reproc::sink::string(out),
reproc::sink::string(err));
reproc::sink::string(err)
);
if (ec)
{
throw std::runtime_error(ec.message());
@ -1014,13 +1048,14 @@ namespace mamba
if (!profile_path.empty())
{
if (pwsh_profiles.count(profile_path))
{
Console::stream()
<< exe << " profile already initialized at '" << profile_path << "'";
}
else
{
pwsh_profiles.insert(profile_path);
Console::stream()
<< "Init " << exe << " profile at '" << profile_path << "'";
Console::stream() << "Init " << exe << " profile at '" << profile_path << "'";
init_powershell(profile_path, conda_prefix);
}
}

View File

@ -1,7 +1,7 @@
#include <atomic>
#include <mutex>
#include <cassert>
#include <mutex>
#include <regex>
extern "C"
@ -9,14 +9,14 @@ extern "C"
#include <curl/urlapi.h>
}
#include "spdlog/spdlog.h"
#include "mamba/api/configuration.hpp"
#include "mamba/core/channel_builder.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/execution.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/validate.hpp"
#include "mamba/core/channel_builder.hpp"
#include "mamba/core/execution.hpp"
#include "spdlog/spdlog.h"
namespace mamba
@ -39,6 +39,7 @@ namespace mamba
class CURLSetup final
{
public:
CURLSetup()
{
#ifdef LIBMAMBA_STATIC_DEPS
@ -47,37 +48,38 @@ namespace mamba
if (on_linux)
{
sslset_res
= curl_global_sslset(CURLSSLBACKEND_OPENSSL, nullptr, &available_backends);
sslset_res = curl_global_sslset(CURLSSLBACKEND_OPENSSL, nullptr, &available_backends);
}
else if (on_mac)
{
sslset_res = curl_global_sslset(
CURLSSLBACKEND_SECURETRANSPORT, nullptr, &available_backends);
CURLSSLBACKEND_SECURETRANSPORT,
nullptr,
&available_backends
);
}
else if (on_win)
{
sslset_res
= curl_global_sslset(CURLSSLBACKEND_SCHANNEL, nullptr, &available_backends);
sslset_res = curl_global_sslset(CURLSSLBACKEND_SCHANNEL, nullptr, &available_backends);
}
if (sslset_res == CURLSSLSET_TOO_LATE)
{
LOG_ERROR << "cURL SSL init called too late, that is a bug.";
}
else if (sslset_res == CURLSSLSET_UNKNOWN_BACKEND
|| sslset_res == CURLSSLSET_NO_BACKENDS)
else if (sslset_res == CURLSSLSET_UNKNOWN_BACKEND || sslset_res == CURLSSLSET_NO_BACKENDS)
{
LOG_WARNING
<< "Could not use preferred SSL backend (Linux: OpenSSL, OS X: SecureTransport, Win: SChannel)"
<< std::endl;
LOG_WARNING << "Could not use preferred SSL backend (Linux: OpenSSL, OS X: SecureTransport, Win: SChannel)"
<< std::endl;
LOG_WARNING << "Please check the cURL library configuration that you are using."
<< std::endl;
}
#endif
if (curl_global_init(CURL_GLOBAL_ALL) != 0)
{
throw std::runtime_error("failed to initialize curl");
}
}
~CURLSetup()
@ -133,7 +135,9 @@ namespace mamba
{
MainExecutor* expected = nullptr;
if (!main_executor.compare_exchange_strong(expected, this))
{
throw MainExecutorError("attempted to create multiple main executors");
}
}
MainExecutor::~MainExecutor()
@ -162,9 +166,12 @@ namespace mamba
if (!ptr)
{
throw mamba::mamba_error(
fmt::format("attempt to use {} singleton instance after destruction",
typeid(T).name()),
mamba_error_code::internal_failure);
fmt::format(
"attempt to use {} singleton instance after destruction",
typeid(T).name()
),
mamba_error_code::internal_failure
);
}
return *ptr;

Some files were not shown because too many files have changed in this diff Show More