mirror of https://github.com/mamba-org/mamba.git
feat: add option revision to install command (#3966)
Co-authored-by: Klaim (Joël Lamotte) <142265+Klaim@users.noreply.github.com>
This commit is contained in:
parent
2c3ddf1eef
commit
e3e5f54540
|
@ -99,7 +99,6 @@ It can significantly reduce your CI setup time by:
|
|||
|
||||
While `mamba` and `micromamba` are generally a drop-in replacement for `conda` there are some differences:
|
||||
|
||||
- `mamba` and `micromamba` do no support revisions (for discussions, see <https://github.com/mamba-org/mamba/issues/803>)
|
||||
- `mamba` and `micromamba` normalize `MatchSpec` strings to the simplest form, whereas `conda` use a more verbose form
|
||||
This can lead to slight differences in the output of `conda env export` and `mamba env export`.
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace mamba
|
|||
|
||||
void install(Configuration& config);
|
||||
|
||||
void install_revision(Configuration& config, std::size_t revision);
|
||||
|
||||
void install_specs(
|
||||
Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
|
@ -130,6 +132,8 @@ namespace mamba
|
|||
inline void to_json(nlohmann::json&, const other_pkg_mgr_spec&)
|
||||
{
|
||||
}
|
||||
|
||||
void install_revision(Context& ctx, ChannelContext& channel_context, std::size_t revision);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,8 +66,9 @@ namespace mamba
|
|||
*/
|
||||
struct PackageDiff
|
||||
{
|
||||
std::unordered_map<std::string, specs::PackageInfo> removed_pkg_diff;
|
||||
std::unordered_map<std::string, specs::PackageInfo> installed_pkg_diff;
|
||||
using package_diff_map = std::unordered_map<std::string, specs::PackageInfo>;
|
||||
package_diff_map removed_pkg_diff;
|
||||
package_diff_map installed_pkg_diff;
|
||||
|
||||
[[nodiscard]] static PackageDiff
|
||||
from_revision(const std::vector<History::UserRequest>& user_requests, std::size_t target_revision);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mamba/core/context.hpp"
|
||||
#include "mamba/core/env_lockfile.hpp"
|
||||
#include "mamba/core/environments_manager.hpp"
|
||||
#include "mamba/core/history.hpp"
|
||||
#include "mamba/core/output.hpp"
|
||||
#include "mamba/core/package_cache.hpp"
|
||||
#include "mamba/core/package_database_loader.hpp"
|
||||
|
@ -304,6 +305,24 @@ namespace mamba
|
|||
}
|
||||
}
|
||||
|
||||
void install_revision(Configuration& config, std::size_t revision)
|
||||
{
|
||||
config.at("use_target_prefix_fallback").set_value(true);
|
||||
config.at("use_default_prefix_fallback").set_value(true);
|
||||
config.at("use_root_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
|
||||
);
|
||||
config.load();
|
||||
|
||||
auto& context = config.context();
|
||||
auto channel_context = ChannelContext::make_conda_compatible(context);
|
||||
|
||||
detail::install_revision(context, channel_context, revision);
|
||||
}
|
||||
|
||||
void install(Configuration& config)
|
||||
{
|
||||
auto& ctx = config.context();
|
||||
|
@ -542,18 +561,18 @@ namespace mamba
|
|||
};
|
||||
add_spdlog_logger_to_database(db);
|
||||
|
||||
auto exp_load = load_channels(ctx, channel_context, db, package_caches);
|
||||
if (!exp_load)
|
||||
auto maybe_load = load_channels(ctx, channel_context, db, package_caches);
|
||||
if (!maybe_load)
|
||||
{
|
||||
throw std::runtime_error(exp_load.error().what());
|
||||
throw std::runtime_error(maybe_load.error().what());
|
||||
}
|
||||
|
||||
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||
if (!exp_prefix_data)
|
||||
auto maybe_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||
if (!maybe_prefix_data)
|
||||
{
|
||||
throw std::runtime_error(exp_prefix_data.error().what());
|
||||
throw std::runtime_error(maybe_prefix_data.error().what());
|
||||
}
|
||||
PrefixData& prefix_data = exp_prefix_data.value();
|
||||
PrefixData& prefix_data = maybe_prefix_data.value();
|
||||
|
||||
load_installed_packages_in_database(ctx, db, prefix_data);
|
||||
|
||||
|
@ -741,15 +760,15 @@ namespace mamba
|
|||
// context. We need to create channels from the specs to be able
|
||||
// to download packages.
|
||||
init_channels_from_package_urls(ctx, channel_context, specs);
|
||||
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||
if (!exp_prefix_data)
|
||||
auto maybe_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||
if (!maybe_prefix_data)
|
||||
{
|
||||
// TODO: propagate tl::expected mechanism
|
||||
throw std::runtime_error(
|
||||
fmt::format("could not load prefix data: {}", exp_prefix_data.error().what())
|
||||
fmt::format("could not load prefix data: {}", maybe_prefix_data.error().what())
|
||||
);
|
||||
}
|
||||
PrefixData& prefix_data = exp_prefix_data.value();
|
||||
PrefixData& prefix_data = maybe_prefix_data.value();
|
||||
|
||||
MultiPackageCache pkg_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||
|
||||
|
@ -1164,5 +1183,82 @@ namespace mamba
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
get_all_pkg_info(PackageDiff::package_diff_map::value_type& pkg, solver::libsolv::Database& db)
|
||||
{
|
||||
const auto ms = pkg.second.name + "==" + pkg.second.version + " ="
|
||||
+ pkg.second.build_string;
|
||||
db.for_each_package_matching(
|
||||
specs::MatchSpec::parse(ms).value(),
|
||||
[&](specs::PackageInfo&& pkg_info) { pkg.second = pkg_info; }
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
install_revision(Context& ctx, ChannelContext& channel_context, std::size_t target_revision)
|
||||
{
|
||||
auto maybe_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||
if (!maybe_prefix_data)
|
||||
{
|
||||
throw std::runtime_error(maybe_prefix_data.error().what());
|
||||
}
|
||||
PrefixData& prefix_data = maybe_prefix_data.value();
|
||||
const auto user_requests = prefix_data.history().get_user_requests();
|
||||
|
||||
PackageDiff pkg_diff = PackageDiff::from_revision(user_requests, target_revision);
|
||||
auto removed_pkg_diff = pkg_diff.removed_pkg_diff;
|
||||
auto installed_pkg_diff = pkg_diff.installed_pkg_diff;
|
||||
|
||||
MultiPackageCache package_caches{ ctx.pkgs_dirs, ctx.validation_params };
|
||||
|
||||
solver::libsolv::Database db{ channel_context.params() };
|
||||
add_spdlog_logger_to_database(db);
|
||||
|
||||
auto maybe_load = load_channels(ctx, channel_context, db, package_caches);
|
||||
if (!maybe_load)
|
||||
{
|
||||
throw std::runtime_error(maybe_load.error().what());
|
||||
}
|
||||
|
||||
load_installed_packages_in_database(ctx, db, prefix_data);
|
||||
|
||||
for (auto& pkg : removed_pkg_diff)
|
||||
{
|
||||
get_all_pkg_info(pkg, db);
|
||||
}
|
||||
for (auto& pkg : installed_pkg_diff)
|
||||
{
|
||||
get_all_pkg_info(pkg, db);
|
||||
}
|
||||
|
||||
auto execute_transaction = [&](MTransaction& transaction)
|
||||
{
|
||||
if (ctx.output_params.json)
|
||||
{
|
||||
transaction.log_json();
|
||||
}
|
||||
|
||||
auto prompt_entry = transaction.prompt(ctx, channel_context);
|
||||
if (prompt_entry)
|
||||
{
|
||||
transaction.execute(ctx, channel_context, prefix_data);
|
||||
}
|
||||
return prompt_entry;
|
||||
};
|
||||
|
||||
std::vector<specs::PackageInfo> pkgs_to_remove;
|
||||
std::vector<specs::PackageInfo> pkgs_to_install;
|
||||
for (const auto& [_, pkg] : installed_pkg_diff)
|
||||
{
|
||||
pkgs_to_remove.push_back(pkg);
|
||||
}
|
||||
for (const auto& [_, pkg] : removed_pkg_diff)
|
||||
{
|
||||
pkgs_to_install.push_back(pkg);
|
||||
}
|
||||
auto transaction = MTransaction(ctx, db, pkgs_to_remove, pkgs_to_install, package_caches);
|
||||
execute_transaction(transaction);
|
||||
}
|
||||
} // detail
|
||||
} // mamba
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <optional>
|
||||
|
||||
#include "mamba/api/configuration.hpp"
|
||||
#include "mamba/api/install.hpp"
|
||||
|
||||
|
@ -24,5 +26,16 @@ set_install_command(CLI::App* subcom, Configuration& config)
|
|||
force_reinstall.description()
|
||||
);
|
||||
|
||||
subcom->callback([&] { return mamba::install(config); });
|
||||
static std::optional<std::size_t> revision = std::nullopt;
|
||||
subcom->callback(
|
||||
[&]
|
||||
{
|
||||
if (revision.has_value())
|
||||
{
|
||||
return mamba::install_revision(config, revision.value());
|
||||
}
|
||||
return mamba::install(config);
|
||||
}
|
||||
);
|
||||
subcom->add_option("--revision", revision, "Revert to the specified revision.");
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ from pathlib import Path
|
|||
from packaging.version import Version
|
||||
|
||||
import pytest
|
||||
import re
|
||||
|
||||
# Need to import everything to get fixtures
|
||||
from .helpers import * # noqa: F403
|
||||
|
@ -843,3 +844,20 @@ def test_dry_run_pip_section(tmp_home, tmp_root_prefix, tmp_path):
|
|||
# Check that the packages are not installed using `pip`
|
||||
res = helpers.umamba_run("-p", env_prefix, "pip", "list")
|
||||
assert "numpy" not in res
|
||||
|
||||
|
||||
def test_install_revision(tmp_home, tmp_root_prefix):
|
||||
env_name = "myenv"
|
||||
helpers.create("-n", env_name, "python=3.8")
|
||||
helpers.install("-n", env_name, "xtl=0.7.2", "nlohmann_json=3.12.0")
|
||||
helpers.update("-n", env_name, "xtl")
|
||||
helpers.uninstall("-n", env_name, "nlohmann_json")
|
||||
helpers.install("-n", env_name, "--revision", "1")
|
||||
res = helpers.umamba_list(
|
||||
"-n",
|
||||
env_name,
|
||||
)
|
||||
|
||||
xtl_regex = re.compile(r"xtl\s+0.7.2")
|
||||
assert xtl_regex.search(res)
|
||||
assert "nlohmann_json" in res
|
||||
|
|
Loading…
Reference in New Issue