Skip to content

Conversation

jjonescz
Copy link
Member

Fixes #50913.

@jjonescz jjonescz added the Area-run-file Items related to the "dotnet run <file>" effort label Sep 19, 2025
@jjonescz jjonescz marked this pull request as ready for review September 19, 2025 13:29
@jjonescz jjonescz requested a review from a team as a code owner September 19, 2025 13:29
@jjonescz jjonescz requested review from a team and Copilot September 19, 2025 13:29
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes version handling in the dotnet add file.cs package command by addressing an issue where the --version option was not properly considered when determining if a version was specified.

  • Replaces the hasVersion boolean logic with a unified specifiedVersion string that captures both @version syntax and --version option values
  • Refactors file-based package add tests to use parameterized testing with combinatorial data to cover more command variations
  • Consolidates duplicate test methods into a single helper method that generates appropriate command arguments

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs Updates version detection logic to consider both @version syntax and --version option
test/dotnet.Tests/CommandTests/Package/Add/GivenDotnetPackageAdd.cs Refactors tests to use combinatorial data and shared helper method for better coverage

@jjonescz
Copy link
Member Author

@RikkiGibson @333fred @MiYanni for reviews, thanks

: (prerelease
? "*-*"
: "*");
string version = specifiedVersion ?? (prerelease ? "*-*" : "*");
Copy link
Contributor

Choose a reason for hiding this comment

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

fyi this will add unlisted packages as well NuGet/Home#7466

Just in case you get an issue around it.

Referencing NuGet/Home#14390 to make it easier for when NuGet starts operating on msbuild projects.

Copy link
Member

Choose a reason for hiding this comment

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

So wildcards/floats will resolve unlisted versions? That's undesirable. Is this also true for regular <PackageReference /> items, or just in the CLIs' add commands?

Copy link
Contributor

Choose a reason for hiding this comment

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

That's how floating versions work in general.

The trick is that file based add package is using a floating version to determine the latest version, while regular add package does a separate call.

Copy link
Member

Choose a reason for hiding this comment

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

while regular add package does a separate call.

So should we be doing the same for file-based apps then?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ideally yes, but the issue NuGet/Home#14390 which @nkolev92 linked tracks moving this logic to NuGet so that will resolve the problem.

@jjonescz
Copy link
Member Author

@RikkiGibson @333fred @MiYanni for reviews, thanks

bool hasVersion = _packageId.HasVersion;
string? specifiedVersion = _packageId.HasVersion
? _packageId.VersionRange?.OriginalString ?? string.Empty
: _parseResult.GetValue(PackageAddCommandParser.VersionOption);
Copy link
Member

Choose a reason for hiding this comment

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

nit: This makes me think that we should change the VersionOption to be a proper type instead of a string. We should be tightening these things up as we go.

{
if (!legacyForm && !fileOption)
{
Log.WriteLine("Skipping invalid combination of parameters");
Copy link
Member

Choose a reason for hiding this comment

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

nit: one thing I really love about TUnit is you can declare a specific combination of test theory parameters as an exclusion. Wish we had that here. Would be lovely to be able to use xunitv3 or something more modern.


[Fact]
public void FileBasedApp_CentralPackageManagement_NoVersionSpecified_KeepExisting()
[Theory, CombinatorialData]
Copy link
Member

Choose a reason for hiding this comment

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

love to see the more theory-driven samples here!

Copy link
Member

Choose a reason for hiding this comment

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

There isn't a need to make a change in this PR, but, I would caution about complex use of CombinatorialData, and potential effect on execution time of the whole suite over time. 32 cases for a theory is far from the worst in that regard--that's the most I think I saw in this PR--but, compiler tests have inadvertently created 1000 or so combinatorial cases for a single theory in the past, IIRC.

But, if we don't have a reason to think that every single combination of the arguments is exercising an interesting aspect of the system, it can be worthwhile to consider methods like pairwise testing. This can be a good supplement to determining the cases which are thought to be interesting solely based on the meaning of the respective inputs.

Copy link
Member

Choose a reason for hiding this comment

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

It looks like Andrew actually implemented pairwise testing in the same library that implements CombinatorialDataAttribute: https://aarnott.github.io/Xunit.Combinatorial/docs/combinatorial-vs-pairwise.html#pairwise-testing.

@baronfel baronfel enabled auto-merge (squash) September 22, 2025 13:41
@jjonescz jjonescz disabled auto-merge September 22, 2025 13:45
bool hasVersion = _packageId.HasVersion;
string? specifiedVersion = _packageId.HasVersion
? _packageId.VersionRange?.OriginalString ?? string.Empty
: _parseResult.GetValue(PackageAddCommandParser.VersionOption);
Copy link
Member

Choose a reason for hiding this comment

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

Is anything blocking both CmdPackageArgument and VersionOption specifying a version at once?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, there is a validator on the VersionOption for that.

public void FileBasedApp()
private string[]? GetFileBasedAppArgs(bool legacyForm, bool? versionOption, bool fileOption, bool noRestore, string packageName = "Humanizer")
{
if (!legacyForm && !fileOption)
Copy link
Member

Choose a reason for hiding this comment

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

Does this mean that when the "legacy form" add package is used, it can automatically find and update Program.cs?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, but it can specify the file as an argument (dotnet add file.cs package) whereas the current form can specify it only as an option (dotnet package add --file file.cs)


[Fact]
public void FileBasedApp_CentralPackageManagement_NoVersionSpecified_KeepExisting()
[Theory, CombinatorialData]
Copy link
Member

Choose a reason for hiding this comment

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

There isn't a need to make a change in this PR, but, I would caution about complex use of CombinatorialData, and potential effect on execution time of the whole suite over time. 32 cases for a theory is far from the worst in that regard--that's the most I think I saw in this PR--but, compiler tests have inadvertently created 1000 or so combinatorial cases for a single theory in the past, IIRC.

But, if we don't have a reason to think that every single combination of the arguments is exercising an interesting aspect of the system, it can be worthwhile to consider methods like pairwise testing. This can be a good supplement to determining the cases which are thought to be interesting solely based on the meaning of the respective inputs.

@jjonescz jjonescz requested a review from 333fred September 22, 2025 17:19
@333fred 333fred merged commit d69a91d into dotnet:release/10.0.1xx Sep 22, 2025
29 checks passed
@jjonescz jjonescz deleted the sprint-package-add branch September 23, 2025 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-run-file Items related to the "dotnet run <file>" effort

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants