Skip to content

Commit 3c6ff8f

Browse files
brettfoCopilot
andcommitted
Remove NuGet.Core package dependency
Replace all usages of the NuGet.Core (v2) package with local implementations: - Remove NuGet.Core from Directory.Packages.props, NuGet.CommandLine.csproj, and NuGetUpdater.Core.csproj - Add local AssemblyBinding and IAssembly types in NuGetUpdater.Core/Updater/ - Exclude 8 CoreV2-dependent files from NuGet.CommandLine and provide replacement stubs (Program.cs, Command.cs, UpdateCommand.cs, ProjectFactory.cs, SettingsCredentialProvider.cs) - Remove NU1701 warning suppression (no longer needed) - Add maintenance instructions for NuGetProjects directory - Add StreamExtensions.cs for pre-existing test gap Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a79d531 commit 3c6ff8f

18 files changed

Lines changed: 3080 additions & 25 deletions
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
applyTo: "nuget/helpers/lib/NuGetUpdater/NuGetProjects/**"
3+
---
4+
5+
# NuGetProjects Maintenance
6+
7+
## Submodule Update Checklist
8+
9+
When the `NuGet.Client` submodule is updated, all `*.cs` files under `NuGetProjects/` must be re-checked against their original files in the submodule to ensure they remain largely in line with the upstream content.
10+
11+
## Rules for modified files
12+
13+
1. **No references to `NuGet.Core`.** Remove all `extern alias CoreV2` usages and any other references to the legacy `NuGet.Core` (v2) package.
14+
2. **No .NET Framework-only APIs.** Remove or stub any APIs not compatible with .NET Core (e.g., `System.Data.Services`, WCF types, CoreV2's `PhysicalFileSystem`).
15+
3. **Preserve behavior where possible.** When removing or stubbing, keep surrounding logic intact so the project compiles and packages.config tests pass.
16+
4. **Document deviations.** If a file significantly diverges from upstream, add a comment at the top explaining what changed and why.

nuget/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,12 @@ Open the solution file at `helpers/lib/NuGetUpdater/NuGetUpdater.slnx` in your p
1919
[dependabot-core-dev] ~ $ cd nuget && rspec
2020
```
2121

22+
### Known limitations
23+
24+
#### Projects suppressing `NU1701`
25+
26+
If a project explicitly includes `NU1701` in its `<NoWarn>` property, Dependabot will likely be unable to process updates for that project. The `NU1701` warning indicates that a package's target framework may not be compatible with the project's target framework, and suppressing it allows NuGet to restore packages that would otherwise be rejected.
27+
28+
Dependabot cannot determine why or under what circumstances ignoring target framework compatibility is safe for a given project. As a result, the final package compatibility check will fail and Dependabot will err on the side of caution and not submit a pull request.
29+
2230
[core-repo]: https://github.com/dependabot/dependabot-core

nuget/helpers/lib/NuGetUpdater/Directory.Build.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
<PropertyGroup>
44
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
5-
<NoWarn>$(NoWarn);NU1701</NoWarn>
65
<Nullable>enable</Nullable>
76
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
87
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>

nuget/helpers/lib/NuGetUpdater/Directory.Packages.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
<PackageVersion Include="Microsoft.Web.Xdt" Version="3.2.3" />
2525
<PackageVersion Include="MSBuild.StructuredLogger" Version="2.3.17" />
2626
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
27-
<PackageVersion Include="NuGet.Core" Version="2.14.0" Aliases="CoreV2" />
2827
<PackageVersion Include="OpenTelemetry" Version="1.15.3" />
2928
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.15.3" />
3029
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.15.3" />

nuget/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Build.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
66
<NoWarn>$(NoWarn);CA1305</NoWarn><!-- behavior of StringBuilder could vary based on user's locale -->
77
<NoWarn>$(NoWarn);CA2022</NoWarn><!-- avoid inexact Stream.Read() -->
8-
<NoWarn>$(NoWarn);NU1701</NoWarn><!-- package target framework may not be compatible -->
98
<NoWarn>$(NoWarn);NU1903</NoWarn><!-- package has a known high severity vulnerability -->
109
<NoWarn>$(NoWarn);SYSLIB0014</NoWarn><!-- obsolete -->
1110
<NuGetSourceLocation>$(MSBuildThisFileDirectory)..\..\NuGet.Client</NuGetSourceLocation>
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
#nullable disable
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.ComponentModel.Composition;
8+
using System.Diagnostics.CodeAnalysis;
9+
using System.Globalization;
10+
using System.IO;
11+
using System.Linq;
12+
using System.Threading.Tasks;
13+
using NuGet.Common;
14+
using NuGet.Credentials;
15+
using NuGet.Protocol;
16+
using NuGet.Protocol.Core.Types;
17+
using NuGet.Protocol.Plugins;
18+
19+
namespace NuGet.CommandLine
20+
{
21+
public abstract class Command : ICommand
22+
{
23+
private const string CommandSuffix = "Command";
24+
private CommandAttribute _commandAttribute;
25+
private string _currentDirectory;
26+
27+
protected Command()
28+
{
29+
Arguments = new List<string>();
30+
}
31+
32+
public IList<string> Arguments { get; private set; }
33+
34+
[Import]
35+
public IConsole Console { get; set; }
36+
37+
[Import]
38+
public HelpCommand HelpCommand { get; set; }
39+
40+
[Import]
41+
public ICommandManager Manager { get; set; }
42+
43+
[Import]
44+
public Configuration.IMachineWideSettings MachineWideSettings { get; set; }
45+
46+
[Option(typeof(NuGetCommand), "Option_Help", AltName = "?")]
47+
public bool Help { get; set; }
48+
49+
[Option(typeof(NuGetCommand), "Option_Verbosity")]
50+
public Verbosity Verbosity { get; set; }
51+
52+
[Option(typeof(NuGetCommand), "Option_NonInteractive")]
53+
public bool NonInteractive { get; set; }
54+
55+
[Option(typeof(NuGetCommand), "Option_ConfigFile")]
56+
public string ConfigFile { get; set; }
57+
58+
[Option(typeof(NuGetCommand), "Option_ForceEnglishOutput")]
59+
public bool ForceEnglishOutput { get; set; }
60+
61+
protected Configuration.ICredentialService CredentialService { get; private set; }
62+
63+
public DeprecatedCommandAttribute DeprecatedCommandAttribute
64+
{
65+
get
66+
{
67+
var deprecatedAttrs = GetType().GetCustomAttributes(typeof(DeprecatedCommandAttribute), false);
68+
69+
if (deprecatedAttrs.Length > 0)
70+
{
71+
return deprecatedAttrs[0] as DeprecatedCommandAttribute;
72+
}
73+
74+
return null;
75+
}
76+
}
77+
78+
public string CurrentDirectory
79+
{
80+
get
81+
{
82+
return _currentDirectory ?? Directory.GetCurrentDirectory();
83+
}
84+
set
85+
{
86+
_currentDirectory = value;
87+
}
88+
}
89+
90+
protected internal Configuration.ISettings Settings { get; set; }
91+
92+
protected internal Configuration.IPackageSourceProvider SourceProvider { get; set; }
93+
94+
private Lazy<MsBuildToolset> MsBuildToolset
95+
{
96+
get
97+
{
98+
if (_defaultMsBuildToolset == null)
99+
{
100+
_defaultMsBuildToolset = MsBuildUtility.GetMsBuildDirectoryFromMsBuildPath(null, null, Console);
101+
102+
}
103+
return _defaultMsBuildToolset;
104+
}
105+
}
106+
107+
private Lazy<MsBuildToolset> _defaultMsBuildToolset;
108+
109+
public CommandAttribute CommandAttribute
110+
{
111+
get
112+
{
113+
if (_commandAttribute == null)
114+
{
115+
_commandAttribute = GetCommandAttribute();
116+
}
117+
return _commandAttribute;
118+
}
119+
}
120+
121+
public virtual bool IncludedInHelp(string optionName)
122+
{
123+
return true;
124+
}
125+
126+
public void Execute()
127+
{
128+
if (Help)
129+
{
130+
if (DeprecatedCommandAttribute != null)
131+
{
132+
var deprecationMessage = DeprecatedCommandAttribute.GetDeprecationMessage(CommandAttribute.CommandName);
133+
Console.WriteWarning(deprecationMessage);
134+
}
135+
136+
HelpCommand.ViewHelpForCommand(CommandAttribute.CommandName);
137+
}
138+
else
139+
{
140+
if (string.IsNullOrEmpty(ConfigFile))
141+
{
142+
string configFileName = null;
143+
144+
var packCommand = this as PackCommand;
145+
if (packCommand != null && !string.IsNullOrEmpty(packCommand.ConfigFile))
146+
{
147+
configFileName = packCommand.ConfigFile;
148+
}
149+
150+
Settings = Configuration.Settings.LoadDefaultSettings(
151+
CurrentDirectory,
152+
configFileName: configFileName,
153+
machineWideSettings: MachineWideSettings);
154+
}
155+
else
156+
{
157+
var configFileFullPath = Path.GetFullPath(ConfigFile);
158+
var directory = Path.GetDirectoryName(configFileFullPath);
159+
var configFileName = Path.GetFileName(configFileFullPath);
160+
Settings = Configuration.Settings.LoadDefaultSettings(
161+
directory,
162+
configFileName,
163+
MachineWideSettings);
164+
}
165+
166+
SourceProvider = PackageSourceBuilder.CreateSourceProvider(Settings);
167+
168+
SetDefaultCredentialProvider();
169+
170+
UserAgent.SetUserAgentString(new UserAgentStringBuilder(CommandLineConstants.UserAgent));
171+
172+
if (DeprecatedCommandAttribute != null)
173+
{
174+
var deprecationMessage = DeprecatedCommandAttribute.GetDeprecationMessage(CommandAttribute.CommandName);
175+
Console.WriteWarning(deprecationMessage);
176+
}
177+
178+
OutputNuGetVersion();
179+
ExecuteCommandAsync().GetAwaiter().GetResult();
180+
}
181+
}
182+
183+
/// <summary>
184+
/// Outputs the current NuGet version (by default, only when vebosity is detailed).
185+
/// </summary>
186+
private void OutputNuGetVersion()
187+
{
188+
if (ShouldOutputNuGetVersion)
189+
{
190+
var assemblyName = typeof(Command).Assembly.GetName();
191+
var assemblyLocation = typeof(Command).Assembly.Location;
192+
var version = System.Diagnostics.FileVersionInfo.GetVersionInfo(assemblyLocation).FileVersion;
193+
var message = string.Format(
194+
CultureInfo.CurrentCulture,
195+
LocalizedResourceManager.GetString("OutputNuGetVersion"),
196+
assemblyName.Name,
197+
version);
198+
Console.WriteLine(message);
199+
}
200+
}
201+
202+
protected virtual bool ShouldOutputNuGetVersion
203+
{
204+
get { return Console.Verbosity == Verbosity.Detailed; }
205+
}
206+
207+
protected virtual void SetDefaultCredentialProvider()
208+
{
209+
SetDefaultCredentialProvider(MsBuildToolset);
210+
}
211+
212+
/// <summary>
213+
/// Set default credential provider for the HttpClient, which is used by V2 sources.
214+
/// Also set up authenticated proxy handling for V3 sources.
215+
/// </summary>
216+
protected void SetDefaultCredentialProvider(Lazy<MsBuildToolset> msbuildDirectory)
217+
{
218+
PluginDiscoveryUtility.InternalPluginDiscoveryRoot = new Lazy<string>(() => PluginDiscoveryUtility.GetInternalPluginRelativeToMSBuildDirectory(msbuildDirectory.Value.Path));
219+
CredentialService = new CredentialService(new AsyncLazy<IEnumerable<ICredentialProvider>>(() => GetCredentialProvidersAsync()), NonInteractive, handlesDefaultCredentials: PreviewFeatureSettings.DefaultCredentialsAfterCredentialProviders);
220+
221+
HttpHandlerResourceV3.CredentialService = new Lazy<Configuration.ICredentialService>(() => CredentialService);
222+
223+
HttpHandlerResourceV3.CredentialsSuccessfullyUsed = (uri, credentials) =>
224+
{
225+
};
226+
}
227+
228+
private async Task<IEnumerable<ICredentialProvider>> GetCredentialProvidersAsync()
229+
{
230+
var extensionLocator = new ExtensionLocator();
231+
var providers = new List<ICredentialProvider>();
232+
var pluginProviders = new PluginCredentialProviderBuilder(extensionLocator, Settings, Console)
233+
.BuildAll(Verbosity.ToString())
234+
.ToList();
235+
var securePluginProviders = await (new SecurePluginCredentialProviderBuilder(PluginManager.Instance, canShowDialog: true, logger: Console)).BuildAllAsync();
236+
237+
providers.Add(new SettingsCredentialProvider(SourceProvider, Console));
238+
providers.AddRange(securePluginProviders);
239+
providers.AddRange(pluginProviders);
240+
241+
if (pluginProviders.Any() || securePluginProviders.Any())
242+
{
243+
if (PreviewFeatureSettings.DefaultCredentialsAfterCredentialProviders)
244+
{
245+
providers.Add(new DefaultNetworkCredentialsCredentialProvider());
246+
}
247+
}
248+
providers.Add(new ConsoleCredentialProvider(Console));
249+
250+
return providers;
251+
}
252+
253+
public virtual Task ExecuteCommandAsync()
254+
{
255+
ExecuteCommand();
256+
return Task.CompletedTask;
257+
}
258+
259+
public virtual void ExecuteCommand()
260+
{
261+
}
262+
263+
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does quite a bit of processing.")]
264+
public virtual CommandAttribute GetCommandAttribute()
265+
{
266+
var type = GetType();
267+
var attributes = type.GetCustomAttributes(typeof(CommandAttribute), true);
268+
var attribute = attributes.FirstOrDefault();
269+
if (attribute != null)
270+
{
271+
return (CommandAttribute)attribute;
272+
}
273+
274+
// Use the command name minus the suffix if present and default description
275+
var name = type.Name;
276+
var idx = name.LastIndexOf(CommandSuffix, StringComparison.OrdinalIgnoreCase);
277+
if (idx >= 0)
278+
{
279+
name = name.Substring(0, idx);
280+
}
281+
if (!string.IsNullOrEmpty(name))
282+
{
283+
return new CommandAttribute(name, LocalizedResourceManager.GetString("DefaultCommandDescription"));
284+
}
285+
return null;
286+
}
287+
}
288+
}

0 commit comments

Comments
 (0)