Skip to content

fix(match_spec)!: Make name in MatchSpec non-optional#2079

Closed
KartikDua1504 wants to merge 24 commits intoconda:mainfrom
KartikDua1504:feat/matchspec-glob-star
Closed

fix(match_spec)!: Make name in MatchSpec non-optional#2079
KartikDua1504 wants to merge 24 commits intoconda:mainfrom
KartikDua1504:feat/matchspec-glob-star

Conversation

@KartikDua1504
Copy link
Copy Markdown
Contributor

@KartikDua1504 KartikDua1504 commented Feb 19, 2026

Description

This PR updates the MatchSpec parser to handle the * package name as a native glob matcher (PackageNameMatcher::Glob) instead of silently dropping it to None.

This leverages the glob support recently added in PR #2036, which simplifies the mental model and allows us to remove legacy "if name.is_none()" checks throughout the codebase.

Changes made:

Removed the trimmed_package_name == "*" early-return hack in strip_package_name.

The * string now successfully falls through to PackageNameMatcher::from_str, which correctly identifies it as a Glob.

58c09e4f-b8b0-4da2-a7a5-24655c77e2c4

Fixes #2039

How Has This Been Tested?

I updated the existing tests and added new strict edge-case coverage:

Updated test_name_asterisk: Configured the parser options to allow globs (with_exact_names_only(false)) and asserted that the parsed name is now explicitly Some(PackageNameMatcher::from_str("*")) rather than None.

Added test_name_asterisk_edge_cases:

Verified the security boundary: Proved that running the parser in Strict mode correctly catches and blocks the * glob (throwing OnlyExactPackageNameMatchersAllowedGlob).

Verified complex parsing: Proved that a * glob parses flawlessly when buried inside a highly complex MatchSpec string with a channel, subdir, version, and build string.

AI Disclosure

  • This PR contains AI-generated content.
  • I have tested any AI-generated content in my PR.
  • I take responsibility for any AI-generated content in my PR.

Tools: Gemini 3.0 Pro (For generating edge cases of complex parsing, documentation, syntax correction.)
PROMPT : Generate a skeleton test in Rust for verifying complex string parsing and their edge conditions while using the '*' operator.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added sufficient tests to cover my changes.

@KartikDua1504 KartikDua1504 changed the title fix(match_spec):parse '*' as a native glob matchspec instead of None fix(match_spec): parse asterisk as a native glob matchspec Feb 19, 2026
@KartikDua1504 KartikDua1504 reopened this Feb 19, 2026
@KartikDua1504
Copy link
Copy Markdown
Contributor Author

This change enforces that * is rejected in Strict mode (as tested in Rust).
However, this causes a failure in the Python doctest where MatchSpec("* 12.5") is expected to work.

Should the Python bindings default to Lenient parsing (allowing globs), or should this be considered a breaking change in the Python API?

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 does not need to be an Option anymore

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 also assume that refactoring this to the end will lead to

// todo: remove after https://github.com/conda/rattler/issues/2039
#[error("the match spec '{0}' does not have a package name")]
MatchSpecWithoutName(Box<MatchSpec>),
being removed

@pavelzw
Copy link
Copy Markdown
Member

pavelzw commented Feb 20, 2026

This change enforces that * is rejected in Strict mode (as tested in Rust). However, this causes a failure in the Python doctest where MatchSpec("* 12.5") is expected to work.

Should the Python bindings default to Lenient parsing (allowing globs), or should this be considered a breaking change in the Python API?

I think we should fail in MatchSpec("* 12.5"), so best adjust the doctest. WDYT @baszalmstra?

@KartikDua1504
Copy link
Copy Markdown
Contributor Author

Thanks for pointing these out! If it sounds good to you, I'd be happy to go ahead and work on removing those.

Regarding the Python doctest, I'll hold off on making any changes there until you and @baszalmstra decide on the best path forward. Just let me know what direction you'd both prefer for the Python bindings, and I can update the PR accordingly

@baszalmstra
Copy link
Copy Markdown
Collaborator

I think we should fail in MatchSpec("* 12.5"), so best adjust the doctest

In lenient mode, this should only succeed if globs are enabled through the constructor, otherwise fail.

@KartikDua1504 KartikDua1504 force-pushed the feat/matchspec-glob-star branch 2 times, most recently from 7c72962 to be4c828 Compare February 20, 2026 21:31
@KartikDua1504
Copy link
Copy Markdown
Contributor Author

Kindly review the pull request.

Comment thread crates/rattler_conda_types/src/match_spec/mod.rs
Comment thread crates/rattler_conda_types/src/match_spec/parse.rs Outdated
@KartikDua1504 KartikDua1504 force-pushed the feat/matchspec-glob-star branch 3 times, most recently from 41bdb2b to e51b468 Compare February 21, 2026 07:17
@KartikDua1504
Copy link
Copy Markdown
Contributor Author

I updated the PR accordingly. Just wanted to leave a quick note about some of the things i tweaked and if its okay.

The Option wrapper in mod.rs : I updated the function name signature (dropping the Some()), but internally the core Matchspec struct defines the name field as an Option under the hood. Changing the core struct would be massive breaking API changes.

@KartikDua1504 KartikDua1504 force-pushed the feat/matchspec-glob-star branch from e51b468 to ff54e6f Compare February 21, 2026 07:31
@KartikDua1504 KartikDua1504 marked this pull request as ready for review February 21, 2026 08:39
@pavelzw
Copy link
Copy Markdown
Member

pavelzw commented Feb 21, 2026

Changing the core struct would be massive breaking API changes

This was the whole idea of #2039. we introduced Option back then to support * as a nameless MatchSpec. Now, * MatchSpecs can be expressed through glob MatchSpecs. Thus, we don't need the additional complexity of the Option.

@KartikDua1504
Copy link
Copy Markdown
Contributor Author

Changing the core struct would be massive breaking API changes

This was the whole idea of #2039. we introduced Option back then to support * as a nameless MatchSpec. Now, * MatchSpecs can be expressed through glob MatchSpecs. Thus, we don't need the additional complexity of the Option.

Sure, I'll get to it then.

…Option wrapper

Previously, the `name` field in `MatchSpec` was wrapped in an `Option` as a workaround to support the nameless `*` wildcard. Since `*` can now be expressed properly through glob `PackageNameMatcher`s, this workaround is no longer necessary and adds redundant complexity.

This commit removes the `Option` wrapper from the core `MatchSpec` struct, making `name` a guaranteed field, and implements the `Default` trait to automatically fallback to the `*` wildcard glob when a name is not explicitly provided.

This required a workspace-wide architectural cleanup, including:
- rattler_conda_types: Updated struct definitions, parsing logic, and formatting traits.
- rattler_solve: Cleaned up `libsolv_c` and `resolvo` backends by removing redundant `if let Some(...)` and `.as_ref()` checks.
- rattler_repodata_gateway & rattler_lock: Streamlined package matching and queries.
- rattler (core): Updated installer logic.
- py-rattler: Updated Python bindings to seamlessly handle the strict struct across the FFI boundary.
- tests: Updated hundreds of assertions across all crates to remove obsolete `Some()` wrappers and `.unwrap()` calls.
…tream conflicts

The test 'test_nameless_matchspec_error_without_url' is no longer valid since MatchSpec names now safely default to a '*' glob wildcard instead of throwing an error for being 'None'. Also removes leftover Option wrappers from recently merged upstream tests.
@KartikDua1504 KartikDua1504 force-pushed the feat/matchspec-glob-star branch from 0740ce7 to 5ab6f3c Compare February 24, 2026 15:25
Comment thread crates/rattler_conda_types/src/match_spec/mod.rs
Comment on lines 399 to 406
fn matches(&self, spec: &MatchSpec) -> bool {
// Check if the name matches
if let Some(name) = &spec.name {
{
let name = &spec.name;
if !name.matches(&self.record().name) {
return false;
}
}
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 not resolved yet.

@KartikDua1504
Copy link
Copy Markdown
Contributor Author

Some checks are failing due to Network Errors, I think

Comment thread crates/rattler_lock/src/conda.rs
Comment thread crates/rattler_conda_types/src/match_spec/parse.rs Outdated
Comment thread crates/rattler_conda_types/src/match_spec/parse.rs
Comment thread crates/rattler_conda_types/src/match_spec/parse.rs
Comment thread crates/rattler_lock/src/conda.rs Outdated
Comment thread crates/rattler_lock/src/conda.rs Outdated
Comment thread crates/rattler_solve/tests/backends/main.rs Outdated
Comment thread crates/rattler_solve/tests/backends/main.rs Outdated
Comment thread crates/rattler_solve/tests/backends/main.rs Outdated
Comment thread py-rattler/src/match_spec.rs Outdated
@@ -63,7 +63,7 @@ impl PyMatchSpec {
/// The name of the package
#[getter]
pub fn name(&self) -> Option<PyPackageNameMatcher> {
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 not resolved yet

Comment thread py-rattler/src/solver.rs Outdated
.name
.as_ref()
.and_then(|n| Option::<PackageName>::from(n.clone()))
Some(&match_spec.inner.name).and_then(|n| Option::<PackageName>::from(n.clone()))
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 not resolved

KartikDua1504 and others added 5 commits February 25, 2026 12:09
Co-authored-by: Pavel Zwerschke <pavelzw@gmail.com>
Co-authored-by: Pavel Zwerschke <pavelzw@gmail.com>
Co-authored-by: Pavel Zwerschke <pavelzw@gmail.com>
Copy link
Copy Markdown
Member

@pavelzw pavelzw left a comment

Choose a reason for hiding this comment

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

for the next time, please go yourself through all changes in https://github.com/conda/rattler/pull/2079/changes, and think for each changed line: "is this line necessary? can it be made simpler?" if it is, change it.

this was definitely not the case in a lot of lines here.

Image

i feel like i need to re-open a lot of comments because they were not actually addressed. i now pushed all changes myself to this branch as this was simpler than doing another round of reviews. the amount of time i needed to comment "this is not resolved yet" was way too many.

please also look at our AI Policy.

feel free to also let a second pair of eyes (i.e., a fresh session in your favorite agent) review the pr changes for irrelevant changes before submitting the fixes. it's frustrating for package maintainers to need to do this, especially with the rising quantity of ai-generated prs. the less unnecessary code i need to review, the better.

Comment thread crates/rattler_repodata_gateway/src/gateway/query.rs
Comment thread crates/rattler_repodata_gateway/src/sparse/mod.rs Outdated
@pavelzw pavelzw changed the title fix(match_spec): parse asterisk as a native glob matchspec fix(match_spec)!: parse asterisk as a native glob matchspec Feb 25, 2026
@pavelzw pavelzw changed the title fix(match_spec)!: parse asterisk as a native glob matchspec fix(match_spec)!: Make name in MatchSpec non-optional Feb 25, 2026
Copy link
Copy Markdown
Member

@pavelzw pavelzw left a comment

Choose a reason for hiding this comment

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

looks good now

@KartikDua1504
Copy link
Copy Markdown
Contributor Author

I want to sincerely apologize for the frustration and extra work my recent commits caused you. I see now that I was rushing through the fixes which ended up wasting your time. That was definitely not my intention.

I’ve taken your feedback to heart—especially regarding the 'AI-generated PR' quality and the need to manually review every single changed line for necessity before pushing. This has been a huge learning experience for me in terms of maintaining professional code quality and respecting the maintainer's review cycle.

Thank you for stepping in to push the final fixes yourself to get this over the line. I’m going to be much more rigorous with my self-reviews moving forward to ensure I don't repeat these mistakes. I really appreciate your patience while I'm learning here.

@pavelzw
Copy link
Copy Markdown
Member

pavelzw commented Feb 26, 2026

sorry but answering with an AI generated message on this is not respectful.

@pavelzw
Copy link
Copy Markdown
Member

pavelzw commented Feb 26, 2026

denounce

prefix-dev-vouch Bot pushed a commit to prefix-dev/vouched that referenced this pull request Feb 26, 2026
@pavelzw
Copy link
Copy Markdown
Member

pavelzw commented Feb 26, 2026

/recheck

@github-actions
Copy link
Copy Markdown
Contributor

This PR has been automatically closed because the author is explicitly blocked in the vouch list.

@github-actions github-actions Bot closed this Feb 26, 2026
@KartikDua1504
Copy link
Copy Markdown
Contributor Author

@pavelzw @baszalmstra
I am really sorry for the message above. I did use AI to frame / correct messages in a formal way as i was unsure in how to respond respectfully.
I fully understand how this comes out as, and this is not good practice.
I really do appreciate all the work you put in cleaning up the mess I created in the code base, and it was never my intention to be disrespectful.
Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace MatchSpec with no name (*) with glob matchspec

3 participants