Skip to content

Commit d69a91d

Browse files
authored
Fix version handling in dotnet add file.cs package (#50924)
1 parent 47161ae commit d69a91d

File tree

2 files changed

+84
-40
lines changed

2 files changed

+84
-40
lines changed

src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,12 @@ private int ExecuteForFileBasedApp(string path)
163163
}
164164
}
165165

166-
bool hasVersion = _packageId.HasVersion;
166+
string? specifiedVersion = _packageId.HasVersion
167+
? _packageId.VersionRange?.OriginalString ?? string.Empty
168+
: _parseResult.GetValue(PackageAddCommandParser.VersionOption);
167169
bool prerelease = _parseResult.GetValue(PackageAddCommandParser.PrereleaseOption);
168170

169-
if (hasVersion && prerelease)
171+
if (specifiedVersion != null && prerelease)
170172
{
171173
throw new GracefulException(CliCommandStrings.PrereleaseAndVersionAreNotSupportedAtTheSameTime);
172174
}
@@ -193,11 +195,7 @@ private int ExecuteForFileBasedApp(string path)
193195

194196
// Set initial version to Directory.Packages.props and/or C# file
195197
// (we always need to add the package reference to the C# file but when CPM is enabled, it's added without a version).
196-
string version = hasVersion
197-
? _packageId.VersionRange?.OriginalString ?? string.Empty
198-
: (prerelease
199-
? "*-*"
200-
: "*");
198+
string version = specifiedVersion ?? (prerelease ? "*-*" : "*");
201199
bool skipUpdate = false;
202200
var central = SetCentralVersion(version);
203201
var local = SetLocalVersion(central != null ? null : version);
@@ -214,7 +212,7 @@ private int ExecuteForFileBasedApp(string path)
214212
}
215213

216214
// If no version was specified by the user, save the actually restored version.
217-
if (!hasVersion && !skipUpdate)
215+
if (specifiedVersion == null && !skipUpdate)
218216
{
219217
var projectAssetsFile = projectInstance.GetProperty("ProjectAssetsFile")?.EvaluatedValue;
220218
if (!File.Exists(projectAssetsFile))
@@ -306,7 +304,7 @@ void Update(string value)
306304

307305
// If user didn't specify a version and a version is already specified in Directory.Packages.props,
308306
// don't update the Directory.Packages.props (that's how the project-based equivalent behaves as well).
309-
if (!hasVersion)
307+
if (specifiedVersion == null)
310308
{
311309
skipUpdate = true;
312310
return (Revert: NoOp, Update: Unreachable, Save: Revert);

test/dotnet.Tests/CommandTests/Package/Add/GivenDotnetPackageAdd.cs

Lines changed: 77 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -290,16 +290,45 @@ public void VersionRange(bool asArgument)
290290
cmd.StdErr.Should().BeEmpty();
291291
}
292292

293-
[Fact]
294-
public void FileBasedApp()
293+
private string[]? GetFileBasedAppArgs(bool legacyForm, bool? versionOption, bool fileOption, bool noRestore, string packageName = "Humanizer")
295294
{
295+
if (!legacyForm && !fileOption)
296+
{
297+
Log.WriteLine("Skipping invalid combination of parameters");
298+
return null;
299+
}
300+
301+
(string, string) commandArgs = legacyForm
302+
? ("add", "package")
303+
: ("package", "add");
304+
305+
return [
306+
commandArgs.Item1,
307+
.. (ReadOnlySpan<string>)(fileOption ? [] : ["Program.cs"]),
308+
commandArgs.Item2,
309+
.. (ReadOnlySpan<string>)(versionOption switch
310+
{
311+
true => [packageName, "--version", "2.14.1"],
312+
false => [$"{packageName}@2.14.1"],
313+
null => [packageName],
314+
}),
315+
.. (ReadOnlySpan<string>)(fileOption ? ["--file", "Program.cs"] : []),
316+
.. (ReadOnlySpan<string>)(noRestore ? ["--no-restore"] : []),
317+
];
318+
}
319+
320+
[Theory, CombinatorialData]
321+
public void FileBasedApp(bool legacyForm, bool versionOption, bool fileOption, bool noRestore)
322+
{
323+
if (GetFileBasedAppArgs(legacyForm, versionOption, fileOption, noRestore) is not { } args) return;
324+
296325
var testInstance = _testAssetsManager.CreateTestDirectory();
297326
var file = Path.Join(testInstance.Path, "Program.cs");
298327
File.WriteAllText(file, """
299328
Console.WriteLine();
300329
""");
301330

302-
new DotnetCommand(Log, "package", "add", "[email protected]", "--file", "Program.cs")
331+
new DotnetCommand(Log, args)
303332
.WithWorkingDirectory(testInstance.Path)
304333
.Execute()
305334
.Should().Pass();
@@ -311,20 +340,21 @@ public void FileBasedApp()
311340
""");
312341
}
313342

314-
[Theory]
315-
[InlineData("Humanizer")]
316-
[InlineData("humanizer")]
343+
[Theory, CombinatorialData]
317344
public void FileBasedApp_ReplaceExisting(
318-
string sourceFilePackageId)
345+
[CombinatorialValues("Humanizer", "humanizer")] string sourceFilePackageId,
346+
bool legacyForm, bool versionOption, bool fileOption, bool noRestore)
319347
{
348+
if (GetFileBasedAppArgs(legacyForm, versionOption, fileOption, noRestore) is not { } args) return;
349+
320350
var testInstance = _testAssetsManager.CreateTestDirectory();
321351
var file = Path.Join(testInstance.Path, "Program.cs");
322352
File.WriteAllText(file, $"""
323353
#:package {sourceFilePackageId}@2.9.9
324354
Console.WriteLine();
325355
""");
326356

327-
new DotnetCommand(Log, "package", "add", "[email protected]", "--file", "Program.cs")
357+
new DotnetCommand(Log, args)
328358
.WithWorkingDirectory(testInstance.Path)
329359
.Execute()
330360
.Should().Pass();
@@ -400,16 +430,18 @@ public void FileBasedApp_NoVersion_Prerelease(string[] inputVersions, string? _,
400430
""");
401431
}
402432

403-
[Fact]
404-
public void FileBasedApp_NoVersionAndNoRestore()
433+
[Theory, CombinatorialData]
434+
public void FileBasedApp_NoVersionAndNoRestore(bool legacyForm, bool fileOption)
405435
{
436+
if (GetFileBasedAppArgs(legacyForm, versionOption: null, fileOption, noRestore: true) is not { } args) return;
437+
406438
var testInstance = _testAssetsManager.CreateTestDirectory();
407439
var file = Path.Join(testInstance.Path, "Program.cs");
408440
File.WriteAllText(file, """
409441
Console.WriteLine();
410442
""");
411443

412-
new DotnetCommand(Log, "package", "add", "Humanizer", "--file", "Program.cs", "--no-restore")
444+
new DotnetCommand(Log, args)
413445
.WithWorkingDirectory(testInstance.Path)
414446
.Execute()
415447
.Should().Pass();
@@ -421,17 +453,19 @@ public void FileBasedApp_NoVersionAndNoRestore()
421453
""");
422454
}
423455

424-
[Fact]
425-
public void FileBasedApp_VersionAndPrerelease()
456+
[Theory, CombinatorialData]
457+
public void FileBasedApp_VersionAndPrerelease(bool legacyForm, bool versionOption, bool fileOption, bool noRestore)
426458
{
459+
if (GetFileBasedAppArgs(legacyForm, versionOption, fileOption, noRestore) is not { } args) return;
460+
427461
var testInstance = _testAssetsManager.CreateTestDirectory();
428462
var file = Path.Join(testInstance.Path, "Program.cs");
429463
var source = """
430464
Console.WriteLine();
431465
""";
432466
File.WriteAllText(file, source);
433467

434-
new DotnetCommand(Log, "package", "add", "[email protected]", "--file", "Program.cs", "--prerelease")
468+
new DotnetCommand(Log, [.. args, "--prerelease"])
435469
.WithWorkingDirectory(testInstance.Path)
436470
.Execute()
437471
.Should().Fail()
@@ -440,34 +474,38 @@ public void FileBasedApp_VersionAndPrerelease()
440474
File.ReadAllText(file).Should().Be(source);
441475
}
442476

443-
[Fact]
444-
public void FileBasedApp_InvalidPackage()
477+
[Theory, CombinatorialData]
478+
public void FileBasedApp_InvalidPackage(bool legacyForm, bool fileOption)
445479
{
480+
if (GetFileBasedAppArgs(legacyForm, versionOption: null, fileOption, noRestore: false, packageName: "Microsoft.ThisPackageDoesNotExist") is not { } args) return;
481+
446482
var testInstance = _testAssetsManager.CreateTestDirectory();
447483
var file = Path.Join(testInstance.Path, "Program.cs");
448484
var source = """
449485
Console.WriteLine();
450486
""";
451487
File.WriteAllText(file, source);
452488

453-
new DotnetCommand(Log, "package", "add", "Microsoft.ThisPackageDoesNotExist", "--file", "Program.cs")
489+
new DotnetCommand(Log, args)
454490
.WithWorkingDirectory(testInstance.Path)
455491
.Execute()
456492
.Should().Fail();
457493

458494
File.ReadAllText(file).Should().Be(source);
459495
}
460496

461-
[Fact]
462-
public void FileBasedApp_InvalidPackage_NoRestore()
497+
[Theory, CombinatorialData]
498+
public void FileBasedApp_InvalidPackage_NoRestore(bool legacyForm, bool fileOption)
463499
{
500+
if (GetFileBasedAppArgs(legacyForm, versionOption: null, fileOption, noRestore: true, packageName: "Microsoft.ThisPackageDoesNotExist") is not { } args) return;
501+
464502
var testInstance = _testAssetsManager.CreateTestDirectory();
465503
var file = Path.Join(testInstance.Path, "Program.cs");
466504
File.WriteAllText(file, """
467505
Console.WriteLine();
468506
""");
469507

470-
new DotnetCommand(Log, "package", "add", "Microsoft.ThisPackageDoesNotExist", "--file", "Program.cs", "--no-restore")
508+
new DotnetCommand(Log, args)
471509
.WithWorkingDirectory(testInstance.Path)
472510
.Execute()
473511
.Should().Pass();
@@ -479,9 +517,11 @@ public void FileBasedApp_InvalidPackage_NoRestore()
479517
""");
480518
}
481519

482-
[Fact]
483-
public void FileBasedApp_CentralPackageManagement()
520+
[Theory, CombinatorialData]
521+
public void FileBasedApp_CentralPackageManagement(bool legacyForm, bool versionOption, bool fileOption, bool noRestore)
484522
{
523+
if (GetFileBasedAppArgs(legacyForm, versionOption, fileOption, noRestore) is not { } args) return;
524+
485525
var testInstance = _testAssetsManager.CreateTestDirectory();
486526
var file = Path.Join(testInstance.Path, "Program.cs");
487527
var source = """
@@ -498,7 +538,7 @@ public void FileBasedApp_CentralPackageManagement()
498538
</Project>
499539
""");
500540

501-
new DotnetCommand(Log, "package", "add", "[email protected]", "--file", "Program.cs")
541+
new DotnetCommand(Log, args)
502542
.WithWorkingDirectory(testInstance.Path)
503543
.Execute()
504544
.Should().Pass();
@@ -522,8 +562,10 @@ public void FileBasedApp_CentralPackageManagement()
522562
}
523563

524564
[Theory, CombinatorialData]
525-
public void FileBasedApp_CentralPackageManagement_ReplaceExisting(bool wasInFile)
565+
public void FileBasedApp_CentralPackageManagement_ReplaceExisting(bool wasInFile, bool legacyForm, bool versionOption, bool fileOption, bool noRestore)
526566
{
567+
if (GetFileBasedAppArgs(legacyForm, versionOption, fileOption, noRestore) is not { } args) return;
568+
527569
var testInstance = _testAssetsManager.CreateTestDirectory();
528570
var file = Path.Join(testInstance.Path, "Program.cs");
529571
var source = """
@@ -553,7 +595,7 @@ public void FileBasedApp_CentralPackageManagement_ReplaceExisting(bool wasInFile
553595
</Project>
554596
""");
555597

556-
new DotnetCommand(Log, "package", "add", "[email protected]", "--file", "Program.cs")
598+
new DotnetCommand(Log, args)
557599
.WithWorkingDirectory(testInstance.Path)
558600
.Execute()
559601
.Should().Pass();
@@ -576,9 +618,11 @@ public void FileBasedApp_CentralPackageManagement_ReplaceExisting(bool wasInFile
576618
""");
577619
}
578620

579-
[Fact]
580-
public void FileBasedApp_CentralPackageManagement_NoVersionSpecified()
621+
[Theory, CombinatorialData]
622+
public void FileBasedApp_CentralPackageManagement_NoVersionSpecified(bool legacyForm, bool fileOption)
581623
{
624+
if (GetFileBasedAppArgs(legacyForm, versionOption: null, fileOption, noRestore: false, packageName: "A") is not { } args) return;
625+
582626
var testInstance = _testAssetsManager.CreateTestDirectory();
583627

584628
string[] versions = ["0.0.5", "0.9.0", "1.0.0-preview.3"];
@@ -602,7 +646,7 @@ public void FileBasedApp_CentralPackageManagement_NoVersionSpecified()
602646
</Project>
603647
""");
604648

605-
new DotnetCommand(Log, "package", "add", "A", "--file", "Program.cs")
649+
new DotnetCommand(Log, args)
606650
.WithWorkingDirectory(testInstance.Path)
607651
.Execute()
608652
.Should().Pass();
@@ -624,9 +668,11 @@ public void FileBasedApp_CentralPackageManagement_NoVersionSpecified()
624668
""");
625669
}
626670

627-
[Fact]
628-
public void FileBasedApp_CentralPackageManagement_NoVersionSpecified_KeepExisting()
671+
[Theory, CombinatorialData]
672+
public void FileBasedApp_CentralPackageManagement_NoVersionSpecified_KeepExisting(bool legacyForm, bool fileOption, bool noRestore)
629673
{
674+
if (GetFileBasedAppArgs(legacyForm, versionOption: null, fileOption, noRestore) is not { } args) return;
675+
630676
var testInstance = _testAssetsManager.CreateTestDirectory();
631677
var file = Path.Join(testInstance.Path, "Program.cs");
632678
var source = """
@@ -648,7 +694,7 @@ public void FileBasedApp_CentralPackageManagement_NoVersionSpecified_KeepExistin
648694
""";
649695
File.WriteAllText(directoryPackagesProps, directoryPackagesPropsSource);
650696

651-
new DotnetCommand(Log, "package", "add", "Humanizer", "--file", "Program.cs")
697+
new DotnetCommand(Log, args)
652698
.WithWorkingDirectory(testInstance.Path)
653699
.Execute()
654700
.Should().Pass();

0 commit comments

Comments
 (0)