Skip to content

Commit 68fc9e7

Browse files
committed
Add a parameter for project content file
1 parent d730f85 commit 68fc9e7

44 files changed

Lines changed: 725 additions & 162 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/Package/Update/IPackageUpdateIO.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ internal interface IPackageUpdateIO
2424
/// Loads a project or solution and gets the restore inputs as a DependencyGraphSpec.
2525
/// </summary>
2626
/// <param name="project">The project or solution requested.</param>
27+
/// <param name="projectContentFile">Path to a file with the XML content of the project (used for virtual projects).</param>
2728
/// <returns>A DependencyGraphSpec representing the restore inputs.</returns>
28-
DependencyGraphSpec? GetDependencyGraphSpec(string project);
29+
DependencyGraphSpec? GetDependencyGraphSpec(string project, string? projectContentFile = null);
2930

3031
/// <summary>
3132
/// Performs a restore preview operation without committing the result.
@@ -57,12 +58,14 @@ Task<RestoreResult> PreviewUpdatePackageReferenceAsync(
5758
/// <param name="restorePreviewResult">The restore preview result containing resolved package information.</param>
5859
/// <param name="packageDependency">Package dependency information.</param>
5960
/// <param name="logger">Logger for the operation.</param>
61+
/// <param name="projectContentFile">Path to a file with the XML content of the project (used for virtual projects).</param>
6062
void UpdatePackageReference(
6163
PackageSpec updatedPackageSpec,
6264
RestoreResult restorePreviewResult,
6365
List<string> packageTfmAliases,
6466
PackageToUpdate packageDependency,
65-
ILogger logger);
67+
ILogger logger,
68+
string? projectContentFile = null);
6669

6770
/// <summary>
6871
/// Gets the latest version of a package from package sources.

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/Package/Update/PackageUpdateArgs.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,10 @@ internal record PackageUpdateArgs
1919
public required LogLevel LogLevel { get; init; }
2020

2121
public required bool Vulnerable { get; init; }
22+
23+
/// <summary>
24+
/// Path to a file with the XML content of the project (used for virtual projects).
25+
/// </summary>
26+
public string? ProjectContentFile { get; init; }
2227
}
2328
}

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/Package/Update/PackageUpdateCommand.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ internal static void Register(Command packageCommand, Option<bool> interactiveOp
3636
projectOption.Description = Strings.PackageUpdateCommand_ProjectOptionDescription;
3737
command.Options.Add(projectOption);
3838

39+
var projectContentFileOption = new Option<FileSystemInfo>("--project-content-file")
40+
{
41+
Description = Strings.Pkg_ProjectContentFileDescription,
42+
Arity = ArgumentArity.ZeroOrOne,
43+
}
44+
.AcceptExistingOnly();
45+
command.Options.Add(projectContentFileOption);
46+
3947
var vulnerableOption = new Option<bool>("--vulnerable");
4048
vulnerableOption.Description = Strings.PackageUpdateCommand_VulnerableOptionDescription;
4149
command.Options.Add(vulnerableOption);
@@ -55,13 +63,18 @@ internal static void Register(Command packageCommand, Option<bool> interactiveOp
5563
LogLevel logLevel = verbosity.ToLogLevel();
5664
bool vulnerable = args.GetValue(vulnerableOption);
5765

66+
var projectPath = project?.FullName ?? Environment.CurrentDirectory;
67+
var projectContentFile = args.GetValue(projectContentFileOption)?.FullName;
68+
projectPath = MSBuildAPIUtility.ChangeProjectPath(projectPath, projectContentFile);
69+
5870
var commandArgs = new PackageUpdateArgs
5971
{
60-
Project = project?.FullName ?? Environment.CurrentDirectory,
72+
Project = projectPath,
6173
Packages = packages,
6274
Interactive = interactive,
6375
LogLevel = logLevel,
6476
Vulnerable = vulnerable,
77+
ProjectContentFile = projectContentFile,
6578
};
6679

6780
return await action(commandArgs, cancellationToken);

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/Package/Update/PackageUpdateCommandRunner.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ internal static async Task<int> Run(PackageUpdateArgs args, ILoggerWithColor log
5656

5757
// 1. Get DGSpec for project/solution
5858
logger.LogVerbose(Strings.PackageUpdate_LoadingDGSpec);
59-
var dgSpec = packageUpdateIO.GetDependencyGraphSpec(args.Project);
59+
var dgSpec = packageUpdateIO.GetDependencyGraphSpec(args.Project, args.ProjectContentFile);
6060

6161
if (dgSpec is null || dgSpec.Restore is null || dgSpec.Restore.Count == 0)
6262
{
@@ -106,10 +106,12 @@ internal static async Task<int> Run(PackageUpdateArgs args, ILoggerWithColor log
106106

107107
var updatedPackageSpec = updatedDgSpec.GetProjectSpec(projectPath);
108108

109+
string? projectContentFile = projectPath == args.Project ? args.ProjectContentFile : null;
110+
109111
foreach (var packageResult in packagesToUpdate)
110112
{
111113
logger.LogInformation($" {Format.PackageUpdate_UpdatedMessage(packageResult.Package.Id, packageResult.Package.CurrentVersion.ToShortString(), packageResult.Package.NewVersion.ToShortString())}");
112-
packageUpdateIO.UpdatePackageReference(updatedPackageSpec, restorePreviewResult, packageResult.TargetFrameworkAliases, packageResult.Package, logger);
114+
packageUpdateIO.UpdatePackageReference(updatedPackageSpec, restorePreviewResult, packageResult.TargetFrameworkAliases, packageResult.Package, logger, projectContentFile);
113115
uniquePackagesUpdated.Add(packageResult.Package.Id);
114116
}
115117
}

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/Package/Update/PackageUpdateIO.cs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ public void Dispose()
6161
GC.SuppressFinalize(this);
6262
}
6363

64-
/// <inheritdoc cref="IPackageUpdateIO.GetDependencyGraphSpec(string)"/>
65-
public DependencyGraphSpec? GetDependencyGraphSpec(string project)
64+
/// <inheritdoc cref="IPackageUpdateIO.GetDependencyGraphSpec(string, string?)"/>
65+
public DependencyGraphSpec? GetDependencyGraphSpec(string project, string? projectContentFile = null)
6666
{
6767
string tempFile = Path.GetTempFileName();
6868
try
6969
{
70-
if (!RunMsbuildTarget(project, tempFile))
70+
if (!RunMsbuildTarget(project, tempFile, projectContentFile))
7171
{
7272
return null;
7373
}
@@ -81,7 +81,7 @@ public void Dispose()
8181
File.Delete(tempFile);
8282
}
8383

84-
bool RunMsbuildTarget(string project, string tempFile)
84+
bool RunMsbuildTarget(string project, string tempFile, string? projectContentFile)
8585
{
8686
// When being run from the dotnet CLI, use the same dotnet executable, just in case the dotnet on the PATH is different
8787
// But when NuGet.CommandLine.XPlat is being called directly, call dotnet on the path, so this code is debuggable.
@@ -90,17 +90,19 @@ bool RunMsbuildTarget(string project, string tempFile)
9090
// don't redirect stdout or stderr, so errors are output. But use quiet verbosity, so that success has no output.
9191
ProcessStartInfo processStartInfo = new ProcessStartInfo(dotnetPath)
9292
{
93-
Arguments = $"msbuild " +
94-
$"\"{project}\" " +
95-
$"-restore:false " +
93+
Arguments = $"build " +
94+
$"\"{(projectContentFile is null ? project : Path.ChangeExtension(project, ".cs"))}\" " +
95+
$"--no-restore " +
9696
$"-target:GenerateRestoreGraphFile " +
9797
$"-property:RestoreGraphOutputPath=\"{tempFile}\" " +
9898
$"-property:RestoreRecursive=false " +
99-
$"-nologo " +
10099
$"-verbosity:quiet " +
101-
$"-tl:false " +
102-
$"-noautoresponse",
100+
(projectContentFile is null ? $"-noautoresponse" : null), // currently not supported for file-based apps
103101
UseShellExecute = false,
102+
Environment =
103+
{
104+
{ "MSBUILDTERMINALLOGGER", "off" },
105+
},
104106
};
105107

106108
using var process = Process.Start(processStartInfo);
@@ -164,8 +166,8 @@ public async Task CommitAsync(IPackageUpdateIO.RestoreResult restorePreviewResul
164166
}
165167
}
166168

167-
/// <inheritdoc cref="IPackageUpdateIO.UpdatePackageReference(PackageSpec, IPackageUpdateIO.RestoreResult, List{string}, PackageToUpdate, ILogger)"/>
168-
public void UpdatePackageReference(PackageSpec updatedPackageSpec, IPackageUpdateIO.RestoreResult restorePreviewResult, List<string> packageTfmAliases, PackageToUpdate packageToUpdate, ILogger logger)
169+
/// <inheritdoc cref="IPackageUpdateIO.UpdatePackageReference(PackageSpec, IPackageUpdateIO.RestoreResult, List{string}, PackageToUpdate, ILogger, string?)"/>
170+
public void UpdatePackageReference(PackageSpec updatedPackageSpec, IPackageUpdateIO.RestoreResult restorePreviewResult, List<string> packageTfmAliases, PackageToUpdate packageToUpdate, ILogger logger, string? projectContentFile = null)
169171
{
170172
PackageDependency packageDependency = new PackageDependency(packageToUpdate.Id, packageToUpdate.NewVersion);
171173

@@ -203,15 +205,15 @@ public void UpdatePackageReference(PackageSpec updatedPackageSpec, IPackageUpdat
203205
if (packageTfms.Count == updatedPackageSpec.TargetFrameworks.Count)
204206
{
205207
// package is used by all project TFMs (no condition)
206-
_msbuildUtility.AddPackageReference(updatedPackageSpec.FilePath, libraryDependency, noVersion);
208+
_msbuildUtility.AddPackageReference(updatedPackageSpec.FilePath, libraryDependency, noVersion, projectContentFile);
207209
}
208210
else
209211
{
210212
var frameworkAliases = packageTfms
211213
.Select(e => AddPackageReferenceCommandRunner.GetAliasForFramework(updatedPackageSpec, e))
212214
.Where(originalFramework => originalFramework != null);
213215

214-
_msbuildUtility.AddPackageReferencePerTFM(updatedPackageSpec.FilePath, libraryDependency, frameworkAliases, noVersion);
216+
_msbuildUtility.AddPackageReferencePerTFM(updatedPackageSpec.FilePath, libraryDependency, frameworkAliases, noVersion, projectContentFile);
215217
}
216218
}
217219

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PackageReferenceCommands/AddPackageReferenceCommand.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ public static void Register(CommandLineApplication app, Func<ILogger> getLogger,
4747
Strings.AddPkg_ProjectPathDescription,
4848
CommandOptionType.SingleValue);
4949

50+
var projectContentFile = addpkg.Option(
51+
"--project-content-file",
52+
Strings.Pkg_ProjectContentFileDescription,
53+
CommandOptionType.SingleValue);
54+
5055
var frameworks = addpkg.Option(
5156
"-f|--framework",
5257
Strings.AddPkg_FrameworksDescription,
@@ -81,7 +86,7 @@ public static void Register(CommandLineApplication app, Func<ILogger> getLogger,
8186
{
8287
ValidateArgument(id, addpkg.Name);
8388
ValidateArgument(projectPath, addpkg.Name);
84-
ValidateProjectPath(projectPath, addpkg.Name);
89+
ValidateProjectPath(projectPath, projectContentFile, addpkg.Name);
8590
if (!noRestore.HasValue())
8691
{
8792
ValidateArgument(dgFilePath, addpkg.Name);
@@ -90,8 +95,11 @@ public static void Register(CommandLineApplication app, Func<ILogger> getLogger,
9095
var noVersion = !version.HasValue();
9196
var packageVersion = version.HasValue() ? version.Value() : null;
9297
ValidatePrerelease(prerelease.HasValue(), noVersion, addpkg.Name);
93-
var packageRefArgs = new PackageReferenceArgs(projectPath.Value(), logger)
98+
var projectContentFileValue = projectContentFile.Value();
99+
var projectPathValue = MSBuildAPIUtility.ChangeProjectPath(projectPath.Value(), projectContentFileValue);
100+
var packageRefArgs = new PackageReferenceArgs(projectPathValue, logger)
94101
{
102+
ProjectContentFile = projectContentFileValue,
95103
Frameworks = CommandLineUtility.SplitAndJoinAcrossMultipleValues(frameworks.Values),
96104
Sources = CommandLineUtility.SplitAndJoinAcrossMultipleValues(sources.Values),
97105
PackageDirectory = packageDirectory.Value(),
@@ -132,9 +140,9 @@ private static void ValidateArgument(CommandOption arg, string commandName)
132140
}
133141
}
134142

135-
private static void ValidateProjectPath(CommandOption projectPath, string commandName)
143+
private static void ValidateProjectPath(CommandOption projectPath, CommandOption projectContentFile, string commandName)
136144
{
137-
if (!File.Exists(projectPath.Value()) || !projectPath.Value().EndsWith("proj", StringComparison.OrdinalIgnoreCase))
145+
if (!File.Exists(projectPath.Value()) || (!projectContentFile.HasValue() && !projectPath.Value().EndsWith("proj", StringComparison.OrdinalIgnoreCase)))
138146
{
139147
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
140148
Strings.Error_PkgMissingOrInvalidProjectFile,

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PackageReferenceCommands/AddPackageReferenceCommandRunner.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public async Task<int> ExecuteCommand(PackageReferenceArgs packageReferenceArgs,
6060
typeConstraint: LibraryDependencyTarget.Package)
6161
};
6262

63-
msBuild.AddPackageReference(packageReferenceArgs.ProjectPath, libraryDependency, packageReferenceArgs.NoVersion);
63+
msBuild.AddPackageReference(packageReferenceArgs.ProjectPath, libraryDependency, packageReferenceArgs.NoVersion, packageReferenceArgs.ProjectContentFile);
6464
return 0;
6565
}
6666

@@ -249,7 +249,7 @@ public async Task<int> ExecuteCommand(PackageReferenceArgs packageReferenceArgs,
249249
// generate a library dependency with all the metadata like Include, Exclude and SuppressParent
250250
var libraryDependency = GenerateLibraryDependency(updatedPackageSpec, packageReferenceArgs.PackageDirectory, packageDependency, resolvedVersion);
251251

252-
msBuild.AddPackageReference(packageReferenceArgs.ProjectPath, libraryDependency, packageReferenceArgs.NoVersion);
252+
msBuild.AddPackageReference(packageReferenceArgs.ProjectPath, libraryDependency, packageReferenceArgs.NoVersion, packageReferenceArgs.ProjectContentFile);
253253
}
254254
else
255255
{
@@ -270,7 +270,8 @@ public async Task<int> ExecuteCommand(PackageReferenceArgs packageReferenceArgs,
270270
msBuild.AddPackageReferencePerTFM(packageReferenceArgs.ProjectPath,
271271
libraryDependency,
272272
compatibleOriginalFrameworks,
273-
packageReferenceArgs.NoVersion);
273+
packageReferenceArgs.NoVersion,
274+
packageReferenceArgs.ProjectContentFile);
274275
}
275276

276277
// 6. Commit restore result

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PackageReferenceCommands/ListPackage/ListPackageArgs.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ internal class ListPackageArgs
3030
public CancellationToken CancellationToken { get; }
3131
public IReadOnlyList<PackageSource> AuditSources { get; }
3232

33+
/// <summary>
34+
/// Path to a file with the XML content of the project (used for virtual projects).
35+
/// </summary>
36+
public string? ProjectContentFile { get; init; }
37+
3338
/// <summary>
3439
/// A constructor for the arguments of list package
3540
/// command. This is used to execute the runner's
@@ -119,7 +124,7 @@ private string GetReportParameters()
119124

120125
if (HighestPatch)
121126
{
122-
sb.Append("--highest-patch");
127+
sb.Append(" --highest-patch");
123128
}
124129

125130
return sb.ToString().Trim();

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PackageReferenceCommands/ListPackage/ListPackageCommand.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ public static void Register(
8282
Strings.ListPkg_HighestMinorDescription,
8383
CommandOptionType.NoValue);
8484

85+
var projectContentFile = listpkg.Option(
86+
"--project-content-file",
87+
Strings.Pkg_ProjectContentFileDescription,
88+
CommandOptionType.SingleValue);
89+
8590
var source = listpkg.Option(
8691
"--source",
8792
Strings.ListPkg_SourceDescription,
@@ -130,10 +135,12 @@ public static void Register(
130135
isDeprecated: deprecatedReport.HasValue(),
131136
isVulnerable: vulnerableReport.HasValue());
132137

133-
IReportRenderer reportRenderer = GetOutputType(outputFormat.Value(), outputVersionOption: outputVersion.Value());
138+
IReportRenderer reportRenderer = GetOutputType(app.Out, app.Error, outputFormat.Value(), outputVersionOption: outputVersion.Value());
134139
var provider = new PackageSourceProvider(settings);
140+
var projectContentFileValue = projectContentFile.Value();
141+
var pathValue = MSBuildAPIUtility.ChangeProjectPath(path.Value, projectContentFileValue);
135142
var packageRefArgs = new ListPackageArgs(
136-
path.Value,
143+
pathValue,
137144
packageSources,
138145
framework.Values,
139146
reportType,
@@ -144,7 +151,10 @@ public static void Register(
144151
highestMinor.HasValue(),
145152
provider.LoadAuditSources(),
146153
logger,
147-
CancellationToken.None);
154+
CancellationToken.None)
155+
{
156+
ProjectContentFile = projectContentFileValue,
157+
};
148158

149159
WarnAboutIncompatibleOptions(packageRefArgs, reportRenderer);
150160

@@ -174,7 +184,7 @@ private static ReportType GetReportType(bool isDeprecated, bool isOutdated, bool
174184
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.ListPkg_InvalidOptions));
175185
}
176186

177-
private static IReportRenderer GetOutputType(string outputFormatOption, string outputVersionOption)
187+
private static IReportRenderer GetOutputType(TextWriter consoleOut, TextWriter consoleError, string outputFormatOption, string outputVersionOption)
178188
{
179189
ReportOutputFormat outputFormat = ReportOutputFormat.Console;
180190
if (!string.IsNullOrEmpty(outputFormatOption) &&
@@ -190,7 +200,7 @@ private static IReportRenderer GetOutputType(string outputFormatOption, string o
190200
{
191201
throw new ArgumentException(string.Format(Strings.ListPkg_OutputVersionNotApplicable));
192202
}
193-
return new ListPackageConsoleRenderer();
203+
return new ListPackageConsoleRenderer(consoleOut, consoleError);
194204
}
195205

196206
IReportRenderer jsonReportRenderer;
@@ -203,7 +213,7 @@ private static IReportRenderer GetOutputType(string outputFormatOption, string o
203213
}
204214
else
205215
{
206-
jsonReportRenderer = new ListPackageJsonRenderer();
216+
jsonReportRenderer = new ListPackageJsonRenderer(consoleOut);
207217
}
208218

209219
return jsonReportRenderer;

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PackageReferenceCommands/ListPackage/ListPackageCommandRunner.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public async Task<int> ExecuteCommandAsync(ListPackageArgs listPackageArgs)
5050
{
5151
// It's important not to print anything to console from below methods and sub method calls, because it'll affect both json/console outputs.
5252
var listPackageReportModel = new ListPackageReportModel(listPackageArgs);
53-
if (!File.Exists(listPackageArgs.Path))
53+
if (listPackageArgs.ProjectContentFile is null && !File.Exists(listPackageArgs.Path))
5454
{
5555
listPackageArgs.Renderer.AddProblem(problemType: ProblemType.Error,
5656
text: string.Format(CultureInfo.CurrentCulture,
@@ -95,7 +95,7 @@ private async Task GetProjectMetadataAsync(
9595
{
9696
//Open project to evaluate properties for the assets
9797
//file and the name of the project
98-
Project project = MSBuildAPIUtility.GetProject(projectPath);
98+
Project project = MSBuildAPIUtility.GetProject(projectPath, projectPath == listPackageArgs.Path ? listPackageArgs.ProjectContentFile : null).Project;
9999
var projectName = project.GetPropertyValue(ProjectName);
100100
ListPackageProjectModel projectModel = listPackageReportModel.CreateProjectReportData(projectPath: projectPath, projectName);
101101

0 commit comments

Comments
 (0)