Skip to content

allow @ syntax for package versions in package add #47961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 31, 2025

Conversation

baronfel
Copy link
Member

@baronfel baronfel commented Mar 28, 2025

Fixes #47981

Adds support for syntax like [email protected] in dotnet package add. When this syntax is used, we should disallow the --version option.

This also pushes up a UX fix to the --project option of this command - it no longer requires specifying the project in order to work on the current directory. The previous code was trying to make CWD-based usage work but didn't quite get there.

> dotnet package add [email protected]

Build succeeded in 1.2s
info : X.509 certificate chain validation will use the default trust store selected by .NET for code signing.
info : X.509 certificate chain validation will use the default trust store selected by .NET for timestamping.
info : Adding PackageReference for package 'Newtonsoft.Json' into project 'E:\Code\sdk-container-demo\src\sdk-container-demo\sdk-container-demo.csproj'.
info : Restoring packages for E:\Code\sdk-container-demo\src\sdk-container-demo\sdk-container-demo.csproj...
info :   CACHE https://api.nuget.org/v3/vulnerabilities/index.json
info :   CACHE https://api.nuget.org/v3-vulnerabilities/2025.03.26.23.24.54/vulnerability.base.json
info :   CACHE https://api.nuget.org/v3-vulnerabilities/2025.03.26.23.24.54/2025.03.27.23.24.57/vulnerability.update.json
info : Package 'Newtonsoft.Json' is compatible with all the specified frameworks in project 'E:\Code\sdk-container-demo\src\sdk-container-demo\sdk-container-demo.csproj'.
info : PackageReference for package 'Newtonsoft.Json' version '13.0.3' added to file 'E:\Code\sdk-container-demo\src\sdk-container-demo\sdk-container-demo.csproj'.
info : Writing assets file to disk. Path: E:\Code\sdk-container-demo\artifacts\obj\sdk-container-demo\project.assets.json
log  : Restored E:\Code\sdk-container-demo\src\sdk-container-demo\sdk-container-demo.csproj (in 365 ms).
> dotnet package add [email protected] --project . --version 130.0
Cannot specify --version when the package argument already has a version.

Description:
  Add a NuGet package reference to the project.

Usage:
  dotnet package add <PACKAGE_NAME> [options]

Arguments:
  <PACKAGE_NAME>  The package reference to add.

Options:
  -v, --version <VERSION>            The version of the package to add.
  -f, --framework <FRAMEWORK>        Add the reference only when targeting a specific framework.
  -n, --no-restore                   Add the reference without performing restore preview and compatibility check.
  -s, --source <SOURCE>              The NuGet package source to use during the restore.
  --package-directory <PACKAGE_DIR>  The directory to restore packages to.
  --interactive                      Allows the command to stop and wait for user input or action (for example to complete authentication). [default: False]
  --prerelease                       Allows prerelease packages to be installed.
  --project <project>
  -?, -h, --help                     Show command line help.

@Copilot Copilot AI review requested due to automatic review settings March 28, 2025 01:52
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-CLI untriaged Request triage from a team member labels Mar 28, 2025
@baronfel baronfel marked this pull request as draft March 28, 2025 01:52
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 introduces support for the @ syntax to specify package versions in the dotnet package add command and prevents users from manually providing a --version option when a version is already embedded in the package string.

  • Update Program.cs to use PackageIdentity instead of a simple string for handling packages and transform arguments.
  • Enhance PackageAddCommandParser to include a custom parser for package identity extraction and a validator that disallows the --version option when a version is provided via the @ syntax.

Reviewed Changes

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

File Description
src/Cli/dotnet/Commands/Package/Add/Program.cs Refactored to use PackageIdentity for package parsing and updated TransformArgs method to conditionally add the version argument.
src/Cli/dotnet/Commands/Package/Add/PackageAddCommandParser.cs Added a custom parser for handling package identity with @ syntax and introduced a validator to enforce the disallowance of --version when a version is provided.

@baronfel baronfel marked this pull request as ready for review March 28, 2025 03:50
@baronfel baronfel force-pushed the package-add-at-support branch from 0217d9e to 3b099aa Compare March 28, 2025 04:12
@am11
Copy link
Member

am11 commented Mar 28, 2025

The help message could also reflect the new syntax:

- dotnet package add <PACKAGE_NAME> [options]
+ dotnet package add <PACKAGE_NAME>[@<PACKAGE_VERSION>] [OPTIONS]

@baronfel
Copy link
Member Author

The help message could also reflect the new syntax:

- dotnet package add <PACKAGE_NAME> [options]
+ dotnet package add <PACKAGE_NAME>[@<PACKAGE_VERSION>] [OPTIONS]

this is actually pretty hard to do - S.CL has support for rearranging help sections, but the usage is harder to customize. I did make the help descriptions for the argument call out the new format.

@am11
Copy link
Member

am11 commented Mar 28, 2025

Agreed. The current way seems to be using the ordered evaluation and to replace the usage, it requires overwriting the delegate in second iteration without actually checking its contents (there is no way to do so?).

using System.CommandLine;
using System.CommandLine.Help;

new CliConfiguration(
    new MyCommand(args)
    .UseExtendedHelp(MyCommand.GetExtendedHelp)
).Invoke(args);

static class Ext
{
    // copy of https://github.com/dotnet/runtime/blob/fbb0f14b33394bc55f90de7c2b75c99ce1f9eea6/src/coreclr/tools/Common/CommandLineHelpers.cs#L132-L132
    public static CliRootCommand UseExtendedHelp(this CliRootCommand command, Func<HelpContext, IEnumerable<Func<HelpContext, bool>>> customizer)
    {
        foreach (CliOption option in command.Options)
        {
            if (option is HelpOption helpOption)
            {
                HelpBuilder builder = new();
                builder.CustomizeLayout(customizer);
                helpOption.Action = new HelpAction { Builder = builder };
                break;
            }
        }

        return command;
    }
}

internal class MyCommand : CliRootCommand
{
    public CliArgument<Dictionary<string, string>> InputFilePaths { get; } =
        new("input-file-path") { Description = "Input file(s)", Arity = ArgumentArity.OneOrMore };
    public CliOption<string> InstructionSet { get; } =
           new("--instruction-set") { Description = "SR.InstructionSets" };

    public MyCommand(string[] args) : base("SR.CommandShortDescription")
    {
        Arguments.Add(InputFilePaths);
        Options.Add(InstructionSet);
        // ...
    }

    public static IEnumerable<Func<HelpContext, bool>> GetExtendedHelp(HelpContext ctx)
    {
        int i = 1;
        foreach (Func<HelpContext, bool> sectionDelegate in HelpBuilder.Default.GetLayout())
        {
            if (i++ == 2)
                yield return _ =>
                {
                    Console.WriteLine("Usage:\n  dotnet package add <PACKAGE_NAME>[@<PACKAGE_VERSION>] [OPTIONS]");
                    return true;
                };
            else
                yield return sectionDelegate;
        }
    }
}

based on the .Skip(1) /* Skip the boring default description section... */ example in dotnet/command-line-api#1537. Would be nice to have CustomizeCommandUsage() or something like Symbol.Usage to update predefined sections.
cc @adamsitnik (if they know of any better/idiomatic approach)

@baronfel
Copy link
Member Author

I took a pass at doing just that this morning (marker interfaces on commands to signal that they override the layout, swapping out specific sub-layouts, etc), but there are a lot of layout smarts that are hidden knowledge behind private members in S.CL. It would be quite a lot of code duplication right now :(

Copy link
Member

@Forgind Forgind left a comment

Choose a reason for hiding this comment

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

Beautiful PR, thank you!

@baronfel baronfel force-pushed the package-add-at-support branch from 9e763d6 to 8b87b86 Compare March 28, 2025 19:25
@baronfel baronfel force-pushed the package-add-at-support branch from 1393492 to 8fee280 Compare March 31, 2025 14:17
@baronfel
Copy link
Member Author

@dotnet/domestic-cat is something wonky with the fullframework build? It suddenly started throwing tons of test errors unrelated to this PR.

@Forgind
Copy link
Member

Forgind commented Mar 31, 2025

@dotnet/domestic-cat is something wonky with the fullframework build? It suddenly started throwing tons of test errors unrelated to this PR.

Looking at another PR, I see:

C:\h\w\A0E90994\p\d\sdk\10.0.100-ci\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.targets(305,5): error MSB4018: System.TypeInitializationException: The type initializer for 'System.Text.Encodings.Web.DefaultJavaScriptEncoder' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=6.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

I'll try to see where that's coming from.

@baronfel baronfel force-pushed the package-add-at-support branch from 8fee280 to d73c742 Compare March 31, 2025 18:50
@baronfel baronfel merged commit 6136ab0 into dotnet:main Mar 31, 2025
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-CLI Document for new feature untriaged Request triage from a team member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support package@version syntax in dotnet package add
3 participants