Skip to content

Add EnableDefaultItems=false optimization for restore operations #49424

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
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
55 changes: 55 additions & 0 deletions src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

namespace Microsoft.DotNet.Cli.Utils;

public static class Constants
Expand Down Expand Up @@ -29,4 +31,57 @@ public static class Constants

public static readonly string RestoreInteractiveOption = "--interactive";
public static readonly string workloadSetVersionFileName = "workloadVersion.txt";

/// <summary>
/// Adds performance optimizations to restore by disabling default item globbing
/// if the user hasn't already specified EnableDefaultItems.
/// </summary>
public static IEnumerable<string> AddRestoreOptimizations(IEnumerable<string> msbuildArgs)
{
var args = msbuildArgs.ToList();

// Check if user has already specified EnableDefaultItems
bool userSpecifiedEnableDefaultItems = HasUserSpecifiedProperty(args, EnableDefaultItems);

if (!userSpecifiedEnableDefaultItems)
{
// Add EnableDefaultItems=false to improve restore performance by disabling default item globbing
args.Insert(0, $"-property:{EnableDefaultItems}=false");
}

return args;
}

/// <summary>
/// Checks if the user has already specified a given property in the MSBuild arguments.
/// </summary>
private static bool HasUserSpecifiedProperty(IEnumerable<string> args, string propertyName)
{
foreach (var arg in args)
{
// Check for -property:PropertyName=, -p:PropertyName=, --property:PropertyName=, etc.
if (arg.StartsWith("-property:", StringComparison.OrdinalIgnoreCase) ||
arg.StartsWith("-p:", StringComparison.OrdinalIgnoreCase) ||
arg.StartsWith("--property:", StringComparison.OrdinalIgnoreCase))
{
// Extract the property part after the prefix
var colonIndex = arg.IndexOf(':');
if (colonIndex > 0 && colonIndex < arg.Length - 1)
{
var propertyPart = arg.Substring(colonIndex + 1);
var equalsIndex = propertyPart.IndexOf('=');
if (equalsIndex > 0)
{
var propName = propertyPart.Substring(0, equalsIndex);
if (string.Equals(propName, propertyName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
}
}

return false;
}
}
3 changes: 2 additions & 1 deletion src/Cli/dotnet/Commands/Restore/RestoreCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public static CommandBase FromParseResult(ParseResult result, string? msbuildPat

public static MSBuildForwardingApp CreateForwarding(IEnumerable<string> msbuildArgs, string? msbuildPath = null)
{
var forwardingApp = new MSBuildForwardingApp(msbuildArgs, msbuildPath);
var argsWithOptimizations = Constants.AddRestoreOptimizations(msbuildArgs);
var forwardingApp = new MSBuildForwardingApp(argsWithOptimizations, msbuildPath);
NuGetSignatureVerificationEnabler.ConditionallyEnable(forwardingApp);
return forwardingApp;
}
Expand Down
4 changes: 4 additions & 0 deletions src/Cli/dotnet/Commands/Restore/RestoringCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.DotNet.Cli.Commands.MSBuild;
using Microsoft.DotNet.Cli.Commands.Workload.Install;
using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.Cli.Utils;

namespace Microsoft.DotNet.Cli.Commands.Restore;

Expand Down Expand Up @@ -65,6 +66,9 @@ private static MSBuildForwardingApp GetSeparateRestoreCommand(
(var newArgumentsToAdd, var existingArgumentsToForward) = ProcessForwardedArgumentsForSeparateRestore(arguments);
restoreArguments = [.. restoreArguments, .. newArgumentsToAdd, .. existingArgumentsToForward];

// Add restore performance optimizations
restoreArguments = Constants.AddRestoreOptimizations(restoreArguments);

return RestoreCommand.CreateForwarding(restoreArguments, msbuildPath);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable disable

using Microsoft.DotNet.Cli.Commands.Restore;

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TestBuild: linux (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TestBuild: linux (arm64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [ubuntu2204DebPkg])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TemplateEngine: linux (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [fedora39])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [debian12Amd64])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [alpine322Amd64])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [centosStream9])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TestBuild: macOS (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TemplateEngine: macOS (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build AoT: macOS (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 6 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L6

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(6,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Commands.Build;

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TestBuild: linux (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TestBuild: linux (arm64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [ubuntu2204DebPkg])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TemplateEngine: linux (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [fedora39])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [debian12Amd64])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [alpine322Amd64])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build ContainerBased: linux (x64) [centosStream9])

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TestBuild: macOS (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TemplateEngine: macOS (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build AoT: macOS (x64))

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

Check failure on line 8 in test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs#L8

test/Microsoft.NET.Restore.Tests/GivenThatWeWantRestoreOptimizations.cs(8,28): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Commands' does not exist in the namespace 'Microsoft.DotNet.Cli' (are you missing an assembly reference?)

namespace Microsoft.NET.Restore.Tests
{
public class GivenThatWeWantRestoreOptimizations : SdkTest
{
public GivenThatWeWantRestoreOptimizations(ITestOutputHelper log) : base(log)
{
}

[Fact]
public void It_adds_EnableDefaultItems_false_by_default()
{
// Arrange
var originalArgs = new[] { "-target:Restore", "MyProject.csproj" };

// Act
var optimizedArgs = Constants.AddRestoreOptimizations(originalArgs);

// Assert
optimizedArgs.Should().Contain($"-property:{Constants.EnableDefaultItems}=false");
}

[Fact]
public void It_does_not_add_EnableDefaultItems_false_when_user_specified_EnableDefaultItems_true()
{
// Arrange
var originalArgs = new[] { "-target:Restore", "-property:EnableDefaultItems=true", "MyProject.csproj" };

// Act
var optimizedArgs = Constants.AddRestoreOptimizations(originalArgs);

// Assert
optimizedArgs.Should().NotContain($"-property:{Constants.EnableDefaultItems}=false");
optimizedArgs.Should().Contain("-property:EnableDefaultItems=true");
}

[Fact]
public void It_does_not_add_EnableDefaultItems_false_when_user_specified_EnableDefaultItems_false()
{
// Arrange
var originalArgs = new[] { "-target:Restore", "-property:EnableDefaultItems=false", "MyProject.csproj" };

// Act
var optimizedArgs = Constants.AddRestoreOptimizations(originalArgs);

// Assert
var enableDefaultItemsArgs = optimizedArgs.Where(arg => arg.Contains("EnableDefaultItems")).ToList();
enableDefaultItemsArgs.Should().ContainSingle();
enableDefaultItemsArgs.Single().Should().Be("-property:EnableDefaultItems=false");
}

[Fact]
public void It_respects_user_EnableDefaultItems_with_short_property_syntax()
{
// Arrange
var originalArgs = new[] { "-target:Restore", "-p:EnableDefaultItems=true", "MyProject.csproj" };

// Act
var optimizedArgs = Constants.AddRestoreOptimizations(originalArgs);

// Assert
optimizedArgs.Should().NotContain($"-property:{Constants.EnableDefaultItems}=false");
optimizedArgs.Should().Contain("-p:EnableDefaultItems=true");
}

[Fact]
public void It_respects_user_EnableDefaultItems_with_double_dash_syntax()
{
// Arrange
var originalArgs = new[] { "-target:Restore", "--property:EnableDefaultItems=true", "MyProject.csproj" };

// Act
var optimizedArgs = Constants.AddRestoreOptimizations(originalArgs);

// Assert
optimizedArgs.Should().NotContain($"-property:{Constants.EnableDefaultItems}=false");
optimizedArgs.Should().Contain("--property:EnableDefaultItems=true");
}

[Fact]
public void It_handles_case_insensitive_property_names()
{
// Arrange
var originalArgs = new[] { "-target:Restore", "-property:enabledefaultitems=true", "MyProject.csproj" };

// Act
var optimizedArgs = Constants.AddRestoreOptimizations(originalArgs);

// Assert
optimizedArgs.Should().NotContain($"-property:{Constants.EnableDefaultItems}=false");
optimizedArgs.Should().Contain("-property:enabledefaultitems=true");
}

[Fact]
public void RestoreCommand_CreateForwarding_includes_optimization()
{
// Arrange
var originalArgs = new[] { "-target:Restore", "MyProject.csproj" };

// Act
var restoreCommand = RestoreCommand.CreateForwarding(originalArgs);

// Assert
var msbuildArgs = restoreCommand.MSBuildArguments;
msbuildArgs.Should().Contain($"-property:{Constants.EnableDefaultItems}=false");
}

[Fact]
public void RestoreCommand_CreateForwarding_respects_user_EnableDefaultItems()
{
// Arrange
var originalArgs = new[] { "-target:Restore", "-property:EnableDefaultItems=true", "MyProject.csproj" };

// Act
var restoreCommand = RestoreCommand.CreateForwarding(originalArgs);

// Assert
var msbuildArgs = restoreCommand.MSBuildArguments;
msbuildArgs.Should().NotContain($"-property:{Constants.EnableDefaultItems}=false");
msbuildArgs.Should().Contain("-property:EnableDefaultItems=true");
}

[Fact]
public void SeparateRestoreCommand_includes_optimization_when_needed()
{
// This tests the optimization in the separate restore command path
// which is used when certain properties are excluded from the main restore

// Arrange - use args that trigger separate restore (like specifying TargetFramework)
var args = new[] { "-f", "net6.0", "MyProject.csproj" };

// Act
var buildCommand = (RestoringCommand)BuildCommand.FromArgs(args, "msbuildpath");

// Assert
buildCommand.SeparateRestoreCommand.Should().NotBeNull();
var restoreArgs = buildCommand.SeparateRestoreCommand.MSBuildArguments;
restoreArgs.Should().Contain($"-property:{Constants.EnableDefaultItems}=false");
}

[Fact]
public void SeparateRestoreCommand_respects_user_EnableDefaultItems()
{
// Arrange - use args that trigger separate restore and specify EnableDefaultItems
var args = new[] { "-f", "net6.0", "-property:EnableDefaultItems=true", "MyProject.csproj" };

// Act
var buildCommand = (RestoringCommand)BuildCommand.FromArgs(args, "msbuildpath");

// Assert
buildCommand.SeparateRestoreCommand.Should().NotBeNull();
var restoreArgs = buildCommand.SeparateRestoreCommand.MSBuildArguments;
restoreArgs.Should().NotContain($"-property:{Constants.EnableDefaultItems}=false");
restoreArgs.Should().Contain("-property:EnableDefaultItems=true");
}

[Fact]
public void Optimization_only_affects_restore_operations()
{
// This test verifies that the optimization is only applied in restore contexts
// and doesn't affect other MSBuild operations

// The optimization should only be applied in:
// 1. RestoreCommand.CreateForwarding (explicit restore)
// 2. RestoringCommand.GetSeparateRestoreCommand (implicit restore)
//
// It should NOT be applied to regular build commands that don't involve restore

// For now, this is verified by code inspection since our optimization is only
// applied in restore-specific code paths. If in the future other commands
// start using Constants.AddRestoreOptimizations, we would need to ensure
// they only do so in restore contexts.

// This test serves as documentation of the intended scope
Assert.True(true, "Optimization scope is currently limited to restore commands by design");
}
}
}
Loading