Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libmamba/include/mamba/core/package_fetcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ namespace mamba
void update_monitor(progress_callback_t* cb, PackageExtractEvent event) const;

specs::PackageInfo m_package_info;
MultiPackageCache* m_caches = nullptr;

fs::u8path m_tarball_path;
fs::u8path m_cache_path;
Expand Down
14 changes: 12 additions & 2 deletions libmamba/src/api/update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,20 @@ namespace mamba
request.jobs.emplace_back(Request::UpdateAll{ /* .clean_dependencies= */ false });
}

// Install everything else
// Specs passed with `update --all`:
// - Update jobs constrain already-installed packages without globally pinning them
// - Install jobs add packages that are not yet in the prefix
for (auto& ms : parsed_specs)
{
request.jobs.emplace_back(Request::Install{ std::move(ms) });
const auto& match_spec_name = ms.name().to_string();
if (prefix_data.records().contains(match_spec_name))
{
request.jobs.emplace_back(Request::Update{ std::move(ms) });
}
else
{
request.jobs.emplace_back(Request::Install{ std::move(ms) });
}
}
}
else
Expand Down
3 changes: 3 additions & 0 deletions libmamba/src/core/package_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,9 @@ namespace mamba

void MultiPackageCache::clear_query_cache(const specs::PackageInfo& s)
{
const std::string pkg = s.long_str();
m_cached_tarballs.erase(pkg);
m_cached_extracted_dirs.erase(pkg);
for (auto& c : m_caches)
{
c.clear_query_cache(s);
Expand Down
2 changes: 2 additions & 0 deletions libmamba/src/core/package_fetcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ namespace mamba

PackageFetcher::PackageFetcher(const specs::PackageInfo& pkg_info, MultiPackageCache& caches)
: m_package_info(pkg_info)
, m_caches(&caches)
{
const fs::u8path extracted_cache = caches.get_extracted_dir_path(m_package_info);
if (extracted_cache.empty())
Expand Down Expand Up @@ -360,6 +361,7 @@ namespace mamba
LOG_DEBUG << "Extracted to '" << extract_path.string() << "'";
write_repodata_record(extract_path);
update_urls_txt();
m_caches->clear_query_cache(m_package_info);
update_monitor(cb, PackageExtractEvent::extract_success);
}
catch (const std::logic_error&)
Expand Down
57 changes: 55 additions & 2 deletions libmamba/src/core/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "mamba/core/execution.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/package_fetcher.hpp"
#include "mamba/core/package_handling.hpp"
#include "mamba/core/repo_checker_store.hpp"
#include "mamba/core/thread_utils.hpp"
#include "mamba/core/transaction.hpp"
Expand Down Expand Up @@ -57,6 +58,58 @@ namespace mamba
&& caches.get_tarball_path(pkg_info).empty();
}

/**
* Resolve the extracted package cache directory for linking.
*
* Clears stale negative cache entries (e.g. from before fetch/extract in the same
* transaction) and, if needed, re-extracts from a cached tarball at link time.
*/
fs::u8path resolve_extracted_cache_path(
const specs::PackageInfo& pkg,
MultiPackageCache& caches,
const Context& ctx
)
{
auto lookup = [&]() { return caches.get_extracted_dir_path(pkg); };

if (auto path = lookup(); !path.empty())
{
return path;
}

caches.clear_query_cache(pkg);
if (auto path = lookup(); !path.empty())
{
return path;
}

PackageFetcher fetcher(pkg, caches);
if (fetcher.needs_download())
{
LOG_ERROR << "Cannot find a valid extracted directory cache for '" << pkg.filename
<< "'";
throw std::runtime_error("Package cache error.");
}

if (fetcher.needs_extract())
{
const auto extract_options = ExtractOptions::from_context(ctx);
if (!fetcher.extract(extract_options))
{
LOG_ERROR << "Failed to extract package '" << pkg.filename << "' for linking";
throw std::runtime_error("Package cache error.");
}
caches.clear_query_cache(pkg);
if (auto path = lookup(); !path.empty())
{
return path;
}
}

LOG_ERROR << "Cannot find a valid extracted directory cache for '" << pkg.filename << "'";
throw std::runtime_error("Package cache error.");
}

auto explicit_spec(const specs::PackageInfo& pkg) -> specs::MatchSpec
{
auto out = specs::MatchSpec();
Expand Down Expand Up @@ -241,7 +294,7 @@ namespace mamba
request,
[&](const auto& item) { m_history_entry.update.push_back(item.spec.to_string()); }
);
solver::for_each_of<Request::Remove, Request::Update>(
solver::for_each_of<Request::Remove>(
request,
[&](const auto& item) { m_history_entry.remove.push_back(item.spec.to_string()); }
);
Expand Down Expand Up @@ -764,7 +817,7 @@ namespace mamba
}

Console::stream() << "Linking " << pkg.str();
const fs::u8path cache_path(m_multi_cache.get_extracted_dir_path(pkg, false));
const fs::u8path cache_path(resolve_extracted_cache_path(pkg, m_multi_cache, ctx));
LinkPackage lp(pkg, cache_path, &transaction_context);
try
{
Expand Down
16 changes: 16 additions & 0 deletions libmamba/tests/src/core/test_package_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,21 @@ namespace mamba
MultiPackageCache cache({ long_pkgs_dir }, params);
REQUIRE(cache.get_extracted_dir_path(pkg_info) == long_pkgs_dir / rel_path);
}

SECTION("Stale negative cache is cleared and package is found")
{
MultiPackageCache cache({ pkgs_dir }, params);

// Negative lookup is cached before the extracted directory exists
REQUIRE(cache.get_extracted_dir_path(pkg_info).empty());

write_repodata_record(hierarchical_dir / "info" / "repodata_record.json", pkg_info);

// Without clearing the query cache, the negative result is reused
REQUIRE(cache.get_extracted_dir_path(pkg_info).empty());

cache.clear_query_cache(pkg_info);
REQUIRE(cache.get_extracted_dir_path(pkg_info) == pkgs_dir / rel_path);
}
}
} // namespace mamba
6 changes: 5 additions & 1 deletion micromamba/src/update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ set_update_command(CLI::App* subcom, Configuration& config)
subcom->add_flag("--prune-deps,!--no-prune-deps", prune_deps, "Prune dependencies (default)");

subcom->get_option("specs")->description("Specs to update in the environment");
subcom->add_flag("-a,--all", update_all, "Update all packages in the environment");
subcom->add_flag(
"-a,--all",
update_all,
"Update all packages in the environment (optionally constrained by specs)"
);

subcom->callback(
[&]
Expand Down
13 changes: 13 additions & 0 deletions micromamba/tests/test_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,19 @@ def test_update_all(self, env_created):
pkgs = helpers.umamba_list("-n", TestUpdate.env_name, "--json")
assert any(pkg["name"] == "numpy" for pkg in pkgs)

def test_update_all_with_constraint(self, env_created):
update_res = helpers.update("--all", "xtensor<=" + self.medium_old_version, "--json")
xtensor_link = [
to_link for to_link in update_res["actions"]["LINK"] if to_link["name"] == "xtensor"
][0]
assert xtensor_link["version"].startswith(self.medium_old_version)

if helpers.dry_run_tests == helpers.DryRun.OFF:
with open(Path(self.prefix) / "conda-meta" / "history") as h:
history = h.read()
assert "update specs" in history
assert "xtensor<=" + self.medium_old_version in history

@pytest.mark.parametrize(
"alias",
[
Expand Down
Loading