Skip to content

feat: Complete exclude_newer policy - #4344

Open
jjerphan wants to merge 41 commits into
mamba-org:mainfrom
jjerphan:feat/exclude-newer-policy
Open

feat: Complete exclude_newer policy#4344
jjerphan wants to merge 41 commits into
mamba-org:mainfrom
jjerphan:feat/exclude-newer-policy

Conversation

@jjerphan

@jjerphan jjerphan commented Jul 1, 2026

Copy link
Copy Markdown
Member

Description

Continues #4228 by completing the exclude_newer policy: wiring config/CLI through to the solver, adding per-package overrides, and hardening duration/date parsing.

  • exclude_newer / exclude_newer_package: global cutoff plus per-package overrides (false to exempt, or a duration/date/timestamp). Available via RC, CONDA_/MAMBA_ env vars, and CLI (--exclude-newer, --exclude-newer-package as a JSON/YAML dictionary).
  • ExcludeNewerPolicy: resolved cutoffs only (global / per_package); raw config stays on Context and is resolved at solve time via resolve_exclude_newer_policy.
  • Parsing: compact durations (7d, 3d12h), ISO 8601 durations (P7D), date-only / datetime values; uses std::chrono::parse when available, otherwise Howard Hinnant's date (needed on macOS). Unparseable values throw mamba_error.
  • Build/runtime: howardhinnant_date for macOS static/dev builds; declare msvcp140_atomic_wait.dll for Windows micromamba.

Background / cross-ecosystem tracking: conda/conda#15759

Type of Change

  • Bug fix
  • Feature / enhancement
  • CI / Documentation
  • Maintenance

Checklist

  • My code follows the general style and conventions of the codebase, ensuring consistency
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I have run pre-commit run --all locally in the source folder and confirmed that there are no linter errors.
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes

Test plan

  • Unit tests: test_exclude_newer.cpp, database exclude-newer sections, libmambapy exclude_newer_timestamp tests
  • Config: {CONDA,MAMBA}_EXCLUDE_NEWER{,_PACKAGE} and micromamba install --exclude-newer / --exclude-newer-package … --print-config-only
  • Smoke: install with --exclude-newer 7d and a per-package exemption; confirm newer builds are filtered and exempted packages remain
  • Confirm macOS static build picks up howardhinnant_date-static and Windows DLL allowlist includes msvcp140_atomic_wait.dll

@github-actions github-actions Bot added the release::enhancements For enhancements PRs or implementing features label Jul 1, 2026
@jjerphan
jjerphan force-pushed the feat/exclude-newer-policy branch from c3bbff2 to e197fc4 Compare July 1, 2026 11:02
@jjerphan
jjerphan force-pushed the feat/exclude-newer-policy branch 3 times, most recently from 6ce4cea to f8c7334 Compare July 21, 2026 13:04
@jjerphan
jjerphan marked this pull request as ready for review July 21, 2026 13:20
@jjerphan
jjerphan force-pushed the feat/exclude-newer-policy branch from f8c7334 to 88e0f91 Compare July 21, 2026 13:23

@Klaim Klaim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make another review pass later, I didnt reach half of the changes yet.

* Returns ``std::nullopt`` when parsing fails or trailing characters remain.
*/
template <typename T>
[[nodiscard]] auto parse_chrono(std::string_view value, const char* fmt) -> std::optional<T>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear: this is necessary only because MacOS's build toolchain doesnt implement std::chrono::parse yet?
If so, could you add a TODO about this in the documentation comments to replace it when std::chrono::parse becomes available everywhere?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a TODO to drop the Howard Hinnant fallback once std::chrono::parse is ubiquitous on supported platforms.

Comment thread libmamba/include/mamba/core/context.hpp Outdated
*
* See Configurable ``exclude_newer_package``.
*/
std::map<std::string, std::string> exclude_newer_package;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the end this is never used as a registry as resolve_exclude_newer_package_cutoffs will just go through elements one by one. I think it would be better if it was a vector of struct, or pair if that helps with CLI11 ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched Context::exclude_newer_package to std::vector<std::pair<std::string, std::string>>; added YAML convert + dump_json so CLI/env JSON still round-trips as an object.

namespace mamba
{
/**
* Resolved per-package ``exclude_newer`` cutoffs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kind of side question: why are you using double anti-quote instead of just normal anti-quote for code parts?
If my understanding is correct, markdown is automatically handled by our doxygen setup?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to single backticks for Doxygen Markdown.

*
* The public API exposes ``std::uint64_t`` seconds for compatibility with repodata
* timestamps. Internally, date and datetime values are parsed with
* ``std::chrono::parse`` when the standard library provides it, otherwise with

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid letting the details of the implementation appear in the description of the interface of a function when it's not a description of the general algorithm being implemented, so that changing the implementation does not make that comment/description obsolete without us noticing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed implementation details from resolve_exclude_newer_cutoff; kept semantic description only.

Comment thread libmamba/src/api/utils.cpp Outdated
const std::map<std::string, std::string>& exclude_newer_package
) -> solver::libsolv::Database::Settings
{
const auto now = static_cast<std::uint64_t>(std::time(nullptr));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we not using chrono to get this timepoint value?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reference time now uses std::chrono::system_clock.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I thought that libc++ did not implemented this part, which is not the case.)

Comment thread libmamba/src/core/exclude_newer.cpp Outdated
std::string message;
if (package_name.empty())
{
message = "Could not parse exclude_newer value '" + std::string(value) + "'; "

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using fmt instead of string concatenation for generating these messages.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parse errors now use fmt::format.

Comment thread libmamba/src/core/exclude_newer.cpp Outdated
static const std::regex compact_duration{ R"(^(\d+[yMwdhms])+$)" };
static const std::regex compact_segment{ R"((\d+)([yMwdhms]))" };

constexpr std::uint64_t seconds_per_minute = 60;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicated from the previous function.
Also I don't think "second per year/month" is correct (doesnt it changes depending on the year?), these values would be better deduced through chrono?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deduplicated unit constants; year/month use std::chrono::years/months via duration_cast. Tests updated accordingly.

Comment thread libmamba/src/core/exclude_newer.cpp Outdated
return std::nullopt;
}

std::uint64_t multiplier = 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use the facilities provided by std::chrono instead of doing it manually?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compact parser now accumulates std::chrono durations instead of manual multipliers.

@jjerphan
jjerphan force-pushed the feat/exclude-newer-policy branch from e5a8ef2 to 91ba717 Compare July 23, 2026 14:47
@jjerphan
jjerphan force-pushed the feat/exclude-newer-policy branch from f5b1fbf to b5a04f0 Compare July 31, 2026 08:50
jezdez and others added 18 commits August 4, 2026 16:54
Apply clang-format to ternary expression in database.cpp and
a pre-existing line-break issue in helpers.cpp.
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>

Co-authored-by: Hind Montassif <hind.montassif@gmail.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>

Co-authored-by: Hind Montassif <hind.montassif@gmail.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>

Co-authored-by: Hind Montassif <hind.montassif@gmail.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>

Co-authored-by: Hind Montassif <hind.montassif@gmail.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>

Co-authored-by: Hind Montassif <hind.montassif@gmail.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>

Co-authored-by: Hind Montassif <hind.montassif@gmail.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>

Co-authored-by: Johan Mabille <johan.mabille@gmail.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
jjerphan and others added 23 commits August 4, 2026 16:54
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Klaim <Klaim@users.noreply.github.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Klaim <Klaim@users.noreply.github.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Klaim <Klaim@users.noreply.github.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Klaim <Klaim@users.noreply.github.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Klaim <Klaim@users.noreply.github.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Klaim <Klaim@users.noreply.github.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Klaim <Klaim@users.noreply.github.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Co-authored-by: Klaim <Klaim@users.noreply.github.com>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
@jjerphan
jjerphan force-pushed the feat/exclude-newer-policy branch from b5a04f0 to 1e56c01 Compare August 4, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release::enhancements For enhancements PRs or implementing features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants