Skip to content

Commit ab7d0d6

Browse files
authored
Fix dotnet add package --no-restore ignoring Central Package Management (#7148)
1 parent 8deb76a commit ab7d0d6

3 files changed

Lines changed: 143 additions & 1 deletion

File tree

src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/MSBuildAPIUtility.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ private static Project GetProject(string projectCSProjPath, IDictionary<string,
8383
return new Project(projectRootElement, globalProperties, toolsVersion: null);
8484
}
8585

86+
private static bool IsCentralPackageManagementEnabled(Project project)
87+
{
88+
return StringComparer.OrdinalIgnoreCase.Equals(
89+
project.GetPropertyValue("ManagePackageVersionsCentrally"),
90+
"true");
91+
}
92+
8693
internal static IEnumerable<string> GetProjectsFromSolution(string solutionPath)
8794
{
8895
var sln = SolutionFile.Parse(solutionPath);
@@ -318,8 +325,11 @@ private void AddPackageReference(Project project,
318325
bool noVersion,
319326
string framework = null)
320327
{
328+
// Determine CPM status from the loaded project so callers don't need to check separately.
329+
bool isCentralPackageManagementEnabled = IsCentralPackageManagementEnabled(project);
330+
321331
// Add packageReference to the project file only if it does not exist.
322-
if (!libraryDependency.VersionCentrallyManaged)
332+
if (!isCentralPackageManagementEnabled)
323333
{
324334
if (!existingPackageReferences.Any())
325335
{

test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatAddPkgTests.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,55 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
573573
}
574574
}
575575

576+
[Theory]
577+
[InlineData("net46", "net46", "1.0.0")]
578+
[InlineData("net46; netcoreapp1.0", "net46; netcoreapp1.0", "1.0.0")]
579+
public async Task AddPkg_NoRestoreWithCPM_AddsVersionlessPackageReferenceAndPackageVersion(string packageFrameworks,
580+
string projectFrameworks,
581+
string userInputVersion)
582+
{
583+
// Arrange
584+
using (var pathContext = new SimpleTestPathContext())
585+
{
586+
var projectA = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFrameworks);
587+
var packageX = XPlatTestUtils.CreatePackage(frameworkString: packageFrameworks);
588+
589+
// Generate Package
590+
await SimpleTestPackageUtility.CreateFolderFeedV3Async(
591+
pathContext.PackageSource,
592+
PackageSaveMode.Defaultv3,
593+
packageX);
594+
595+
// Create Directory.Packages.props to enable CPM
596+
var directoryPackagesPropsPath = Path.Combine(pathContext.SolutionRoot, "Directory.Packages.props");
597+
File.WriteAllText(directoryPackagesPropsPath,
598+
@"<Project>
599+
<PropertyGroup>
600+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
601+
</PropertyGroup>
602+
</Project>");
603+
604+
var logger = new TestCommandOutputLogger(_testOutputHelper);
605+
var packageArgs = XPlatTestUtils.GetPackageReferenceArgs(logger, packageX.Id, userInputVersion, projectA, noRestore: true);
606+
var commandRunner = new AddPackageReferenceCommandRunner();
607+
608+
// Act
609+
var result = await commandRunner.ExecuteCommand(packageArgs, new MSBuildAPIUtility(logger));
610+
var projectXml = File.ReadAllText(projectA.ProjectPath);
611+
var propsXml = File.ReadAllText(directoryPackagesPropsPath);
612+
613+
// Assert
614+
Assert.Equal(0, result);
615+
616+
// .csproj should contain versionless PackageReference
617+
Assert.Contains($"<PackageReference Include=\"{packageX.Id}\"", projectXml);
618+
Assert.DoesNotContain("Version=", projectXml);
619+
620+
// Directory.Packages.props should contain PackageVersion with version
621+
Assert.Contains($"<PackageVersion Include=\"{packageX.Id}\" Version=\"{userInputVersion}\"", propsXml);
622+
}
623+
}
624+
576625
[Fact]
577626
public async Task AddPkg_UnconditionalAddWithoutVersion_Success()
578627
{

test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/MSBuildAPIUtilityTests.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,89 @@ public void UpdateVersionOverrideInPropsFileWhenItExists_Success()
461461
Assert.DoesNotContain(@$"<PackageVersion Include=""X"" VersionOverride=""3.0.0"" />", updatedPropsFile);
462462
}
463463

464+
[PlatformFact(Platform.Windows)]
465+
public void AddPackageReference_WithCPMEnabled_AddsPackageVersionToProps()
466+
{
467+
// Arrange
468+
using var testDirectory = TestDirectory.Create();
469+
470+
var propsFile =
471+
@"<Project>
472+
<PropertyGroup>
473+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
474+
</PropertyGroup>
475+
</Project>";
476+
File.WriteAllText(Path.Combine(testDirectory, "Directory.Packages.props"), propsFile);
477+
478+
string projectContent =
479+
@"<Project Sdk=""Microsoft.NET.Sdk"">
480+
<PropertyGroup>
481+
<TargetFramework>net6.0</TargetFramework>
482+
</PropertyGroup>
483+
</Project>";
484+
var projectPath = Path.Combine(testDirectory, "projectA.csproj");
485+
File.WriteAllText(projectPath, projectContent);
486+
487+
var libraryDependency = new LibraryDependency
488+
{
489+
LibraryRange = new LibraryRange(
490+
name: "X",
491+
versionRange: VersionRange.Parse("1.0.0"),
492+
typeConstraint: LibraryDependencyTarget.Package)
493+
};
494+
495+
var msObject = new MSBuildAPIUtility(logger: new TestLogger());
496+
497+
// Act
498+
msObject.AddPackageReference(projectPath, libraryDependency, noVersion: false);
499+
500+
// Assert
501+
string updatedProjectFile = File.ReadAllText(projectPath);
502+
string updatedPropsFile = File.ReadAllText(Path.Combine(testDirectory, "Directory.Packages.props"));
503+
504+
// .csproj should contain versionless PackageReference
505+
Assert.Contains(@"<PackageReference Include=""X""", updatedProjectFile);
506+
Assert.DoesNotContain("Version=", updatedProjectFile);
507+
508+
// Directory.Packages.props should contain PackageVersion with version
509+
Assert.Contains(@"<PackageVersion Include=""X"" Version=""1.0.0""", updatedPropsFile);
510+
}
511+
512+
[PlatformFact(Platform.Windows)]
513+
public void AddPackageReference_WithoutCPM_AddsVersionedPackageReference()
514+
{
515+
// Arrange
516+
using var testDirectory = TestDirectory.Create();
517+
518+
string projectContent =
519+
@"<Project Sdk=""Microsoft.NET.Sdk"">
520+
<PropertyGroup>
521+
<TargetFramework>net6.0</TargetFramework>
522+
</PropertyGroup>
523+
</Project>";
524+
var projectPath = Path.Combine(testDirectory, "projectA.csproj");
525+
File.WriteAllText(projectPath, projectContent);
526+
527+
var libraryDependency = new LibraryDependency
528+
{
529+
LibraryRange = new LibraryRange(
530+
name: "X",
531+
versionRange: VersionRange.Parse("1.0.0"),
532+
typeConstraint: LibraryDependencyTarget.Package)
533+
};
534+
535+
var msObject = new MSBuildAPIUtility(logger: new TestLogger());
536+
537+
// Act
538+
msObject.AddPackageReference(projectPath, libraryDependency, noVersion: false);
539+
540+
// Assert
541+
string updatedProjectFile = File.ReadAllText(projectPath);
542+
543+
// .csproj should contain PackageReference with version
544+
Assert.Contains(@"<PackageReference Include=""X"" Version=""1.0.0""", updatedProjectFile);
545+
}
546+
464547
[Fact]
465548
public void GetListOfProjectsFromPathArgument_WithProjectFile_ReturnsCorrectPaths()
466549
{

0 commit comments

Comments
 (0)