dependabot-nuget 0.265.0 → 0.266.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +6 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalysisResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +73 -77
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +21 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +24 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +33 -16
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -25
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +18 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationResult.cs +5 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +62 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +19 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +6 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +448 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/CompatibilityCheckerTests.cs +23 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +148 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestHttpServer.cs +81 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +27 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +32 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +87 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +88 -0
- data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -0
- data/lib/dependabot/nuget/file_fetcher.rb +1 -1
- data/lib/dependabot/nuget/metadata_finder.rb +160 -2
- data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +3 -0
- data/lib/dependabot/nuget/native_helpers.rb +34 -3
- data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +1 -0
- data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +3 -0
- metadata +11 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4669e522f1ce196d5657096bdf738e6ab353c5a697ea1b0acb1f0c87f9815a44
|
4
|
+
data.tar.gz: 33657445578fcd52b0370490b3c1f4b2fe165ad9f00e22d831d6a216b89458f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ca40a2a42e55b376edc0694253f81a54eb30d75748c3a5572e3a754b64aab96fe86b34f753d0f4566bdf66816da3318aed0eba31fc195581cb2072f89c0d8cb
|
7
|
+
data.tar.gz: 115640e60d1b2a59edb5b6956c9e8d3c35105dafa6ce00d60aa5de52561da96670606af7862d1a24ab1f24bc4fd91651b4856eeb4b7fc545ca230cc72a529493
|
@@ -1,6 +1,4 @@
|
|
1
|
-
using System;
|
2
1
|
using System.CommandLine;
|
3
|
-
using System.IO;
|
4
2
|
|
5
3
|
using NuGetUpdater.Core;
|
6
4
|
|
@@ -15,6 +13,7 @@ internal static class UpdateCommand
|
|
15
13
|
internal static readonly Option<string> PreviousVersionOption = new("--previous-version") { IsRequired = true };
|
16
14
|
internal static readonly Option<bool> IsTransitiveOption = new("--transitive", getDefaultValue: () => false);
|
17
15
|
internal static readonly Option<bool> VerboseOption = new("--verbose", getDefaultValue: () => false);
|
16
|
+
internal static readonly Option<string?> ResultOutputPathOption = new("--result-output-path", getDefaultValue: () => null);
|
18
17
|
|
19
18
|
internal static Command GetCommand(Action<int> setExitCode)
|
20
19
|
{
|
@@ -26,17 +25,18 @@ internal static class UpdateCommand
|
|
26
25
|
NewVersionOption,
|
27
26
|
PreviousVersionOption,
|
28
27
|
IsTransitiveOption,
|
29
|
-
VerboseOption
|
28
|
+
VerboseOption,
|
29
|
+
ResultOutputPathOption
|
30
30
|
};
|
31
31
|
|
32
32
|
command.TreatUnmatchedTokensAsErrors = true;
|
33
33
|
|
34
|
-
command.SetHandler(async (repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, verbose) =>
|
34
|
+
command.SetHandler(async (repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, verbose, resultOutputPath) =>
|
35
35
|
{
|
36
36
|
var worker = new UpdaterWorker(new Logger(verbose));
|
37
|
-
await worker.RunAsync(repoRoot.FullName, solutionOrProjectFile.FullName, dependencyName, previousVersion, newVersion, isTransitive);
|
37
|
+
await worker.RunAsync(repoRoot.FullName, solutionOrProjectFile.FullName, dependencyName, previousVersion, newVersion, isTransitive, resultOutputPath);
|
38
38
|
setExitCode(0);
|
39
|
-
}, RepoRootOption, SolutionOrProjectFileOption, DependencyNameOption, NewVersionOption, PreviousVersionOption, IsTransitiveOption, VerboseOption);
|
39
|
+
}, RepoRootOption, SolutionOrProjectFileOption, DependencyNameOption, NewVersionOption, PreviousVersionOption, IsTransitiveOption, VerboseOption, ResultOutputPathOption);
|
40
40
|
|
41
41
|
return command;
|
42
42
|
}
|
@@ -1,8 +1,8 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
|
+
using System.Net;
|
2
3
|
using System.Text.Json;
|
3
4
|
using System.Text.Json.Serialization;
|
4
5
|
|
5
|
-
using NuGet.Configuration;
|
6
6
|
using NuGet.Frameworks;
|
7
7
|
using NuGet.Versioning;
|
8
8
|
|
@@ -57,70 +57,87 @@ public partial class AnalyzeWorker
|
|
57
57
|
ImmutableArray<Dependency> updatedDependencies = [];
|
58
58
|
|
59
59
|
bool isUpdateNecessary = IsUpdateNecessary(dependencyInfo, projectsWithDependency);
|
60
|
-
|
60
|
+
using var nugetContext = new NuGetContext(startingDirectory);
|
61
|
+
AnalysisResult result;
|
62
|
+
try
|
61
63
|
{
|
62
|
-
|
63
|
-
if (!Directory.Exists(nugetContext.TempPackageDirectory))
|
64
|
+
if (isUpdateNecessary)
|
64
65
|
{
|
65
|
-
Directory.
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
var multiDependencies = DetermineMultiDependencyDetails(
|
70
|
-
discovery,
|
71
|
-
dependencyInfo.Name,
|
72
|
-
propertyBasedDependencies);
|
73
|
-
|
74
|
-
usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
|
75
|
-
var dependenciesToUpdate = usesMultiDependencyProperty
|
76
|
-
? multiDependencies
|
77
|
-
.SelectMany(md => md.DependencyNames)
|
78
|
-
.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
|
79
|
-
: [dependencyInfo.Name];
|
80
|
-
var applicableTargetFrameworks = usesMultiDependencyProperty
|
81
|
-
? multiDependencies
|
82
|
-
.SelectMany(md => md.TargetFrameworks)
|
83
|
-
.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
|
84
|
-
.Select(NuGetFramework.Parse)
|
85
|
-
.ToImmutableArray()
|
86
|
-
: projectFrameworks;
|
87
|
-
|
88
|
-
_logger.Log($" Finding updated version.");
|
89
|
-
updatedVersion = await FindUpdatedVersionAsync(
|
90
|
-
startingDirectory,
|
91
|
-
dependencyInfo,
|
92
|
-
dependenciesToUpdate,
|
93
|
-
applicableTargetFrameworks,
|
94
|
-
nugetContext,
|
95
|
-
_logger,
|
96
|
-
CancellationToken.None);
|
66
|
+
if (!Directory.Exists(nugetContext.TempPackageDirectory))
|
67
|
+
{
|
68
|
+
Directory.CreateDirectory(nugetContext.TempPackageDirectory);
|
69
|
+
}
|
97
70
|
|
98
|
-
|
99
|
-
|
100
|
-
? await FindUpdatedDependenciesAsync(
|
101
|
-
repoRoot,
|
71
|
+
_logger.Log($" Determining multi-dependency property.");
|
72
|
+
var multiDependencies = DetermineMultiDependencyDetails(
|
102
73
|
discovery,
|
74
|
+
dependencyInfo.Name,
|
75
|
+
propertyBasedDependencies);
|
76
|
+
|
77
|
+
usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
|
78
|
+
var dependenciesToUpdate = usesMultiDependencyProperty
|
79
|
+
? multiDependencies
|
80
|
+
.SelectMany(md => md.DependencyNames)
|
81
|
+
.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
|
82
|
+
: [dependencyInfo.Name];
|
83
|
+
var applicableTargetFrameworks = usesMultiDependencyProperty
|
84
|
+
? multiDependencies
|
85
|
+
.SelectMany(md => md.TargetFrameworks)
|
86
|
+
.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
|
87
|
+
.Select(NuGetFramework.Parse)
|
88
|
+
.ToImmutableArray()
|
89
|
+
: projectFrameworks;
|
90
|
+
|
91
|
+
_logger.Log($" Finding updated version.");
|
92
|
+
updatedVersion = await FindUpdatedVersionAsync(
|
93
|
+
startingDirectory,
|
94
|
+
dependencyInfo,
|
103
95
|
dependenciesToUpdate,
|
104
|
-
|
96
|
+
applicableTargetFrameworks,
|
105
97
|
nugetContext,
|
106
98
|
_logger,
|
107
|
-
CancellationToken.None)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
99
|
+
CancellationToken.None);
|
100
|
+
|
101
|
+
_logger.Log($" Finding updated peer dependencies.");
|
102
|
+
updatedDependencies = updatedVersion is not null
|
103
|
+
? await FindUpdatedDependenciesAsync(
|
104
|
+
repoRoot,
|
105
|
+
discovery,
|
106
|
+
dependenciesToUpdate,
|
107
|
+
updatedVersion,
|
108
|
+
nugetContext,
|
109
|
+
_logger,
|
110
|
+
CancellationToken.None)
|
111
|
+
: [];
|
112
|
+
|
113
|
+
//TODO: At this point we should add the peer dependencies to a queue where
|
114
|
+
// we will analyze them one by one to see if they themselves are part of a
|
115
|
+
// multi-dependency property. Basically looping this if-body until we have
|
116
|
+
// emptied the queue and have a complete list of updated dependencies. We
|
117
|
+
// should track the dependenciesToUpdate as they have already been analyzed.
|
118
|
+
}
|
116
119
|
|
117
|
-
|
120
|
+
result = new AnalysisResult
|
121
|
+
{
|
122
|
+
UpdatedVersion = updatedVersion?.ToNormalizedString() ?? dependencyInfo.Version,
|
123
|
+
CanUpdate = updatedVersion is not null,
|
124
|
+
VersionComesFromMultiDependencyProperty = usesMultiDependencyProperty,
|
125
|
+
UpdatedDependencies = updatedDependencies,
|
126
|
+
};
|
127
|
+
}
|
128
|
+
catch (HttpRequestException ex)
|
129
|
+
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
118
130
|
{
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
131
|
+
// TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
|
132
|
+
result = new AnalysisResult
|
133
|
+
{
|
134
|
+
ErrorType = ErrorType.AuthenticationFailure,
|
135
|
+
ErrorDetails = "(" + string.Join("|", nugetContext.PackageSources.Select(s => s.Source)) + ")",
|
136
|
+
UpdatedVersion = string.Empty,
|
137
|
+
CanUpdate = false,
|
138
|
+
UpdatedDependencies = [],
|
139
|
+
};
|
140
|
+
}
|
124
141
|
|
125
142
|
await WriteResultsAsync(analysisDirectory, dependencyInfo.Name, result, _logger);
|
126
143
|
|
@@ -314,27 +331,6 @@ public partial class AnalyzeWorker
|
|
314
331
|
return true;
|
315
332
|
}
|
316
333
|
|
317
|
-
internal static async Task<ImmutableDictionary<NuGetFramework, ImmutableArray<Dependency>>> GetDependenciesAsync(
|
318
|
-
string workspacePath,
|
319
|
-
string projectPath,
|
320
|
-
IEnumerable<NuGetFramework> frameworks,
|
321
|
-
Dependency package,
|
322
|
-
Logger logger)
|
323
|
-
{
|
324
|
-
var result = ImmutableDictionary.CreateBuilder<NuGetFramework, ImmutableArray<Dependency>>();
|
325
|
-
foreach (var framework in frameworks)
|
326
|
-
{
|
327
|
-
var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(
|
328
|
-
workspacePath,
|
329
|
-
projectPath,
|
330
|
-
framework.ToString(),
|
331
|
-
[package],
|
332
|
-
logger);
|
333
|
-
result.Add(framework, [.. dependencies]);
|
334
|
-
}
|
335
|
-
return result.ToImmutable();
|
336
|
-
}
|
337
|
-
|
338
334
|
internal static async Task<ImmutableArray<Dependency>> FindUpdatedDependenciesAsync(
|
339
335
|
string repoRoot,
|
340
336
|
WorkspaceDiscoveryResult discovery,
|
@@ -54,6 +54,11 @@ internal static class CompatibilityChecker
|
|
54
54
|
|
55
55
|
var compatibilityService = new FrameworkCompatibilityService();
|
56
56
|
var compatibleFrameworks = compatibilityService.GetCompatibleFrameworks(packageFrameworks);
|
57
|
+
var packageSupportsAny = compatibleFrameworks.Any(f => f.IsAny);
|
58
|
+
if (packageSupportsAny)
|
59
|
+
{
|
60
|
+
return true;
|
61
|
+
}
|
57
62
|
|
58
63
|
var incompatibleFrameworks = projectFrameworks.Where(f => !compatibleFrameworks.Contains(f)).ToArray();
|
59
64
|
if (incompatibleFrameworks.Length > 0)
|
@@ -141,15 +146,23 @@ internal static class CompatibilityChecker
|
|
141
146
|
throw new NotSupportedException($"Failed to get FindPackageByIdResource for {source.SourceUri}");
|
142
147
|
}
|
143
148
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
149
|
+
try
|
150
|
+
{
|
151
|
+
// a non-compliant v2 API returning 404 can cause this to throw
|
152
|
+
var exists = await feed.DoesPackageExistAsync(
|
153
|
+
package.Id,
|
154
|
+
package.Version,
|
155
|
+
context.SourceCacheContext,
|
156
|
+
NullLogger.Instance,
|
157
|
+
cancellationToken);
|
158
|
+
if (!exists)
|
159
|
+
{
|
160
|
+
continue;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
catch (FatalProtocolException)
|
152
164
|
{
|
165
|
+
// if anything goes wrong here, the package source obviously doesn't contain the requested package
|
153
166
|
continue;
|
154
167
|
}
|
155
168
|
|
@@ -47,6 +47,13 @@ internal record NuGetContext : IDisposable
|
|
47
47
|
|
48
48
|
private readonly Dictionary<PackageIdentity, string?> _packageInfoUrlCache = new();
|
49
49
|
|
50
|
+
public static string[] GetPackageSourceUrls(string currentDirectory)
|
51
|
+
{
|
52
|
+
using var context = new NuGetContext(currentDirectory);
|
53
|
+
var sourceUrls = context.PackageSources.Select(s => s.Source).ToArray();
|
54
|
+
return sourceUrls;
|
55
|
+
}
|
56
|
+
|
50
57
|
public async Task<string?> GetPackageInfoUrlAsync(string packageId, string packageVersion, CancellationToken cancellationToken)
|
51
58
|
{
|
52
59
|
var packageIdentity = new PackageIdentity(packageId, NuGetVersion.Parse(packageVersion));
|
@@ -86,15 +93,24 @@ internal record NuGetContext : IDisposable
|
|
86
93
|
continue;
|
87
94
|
}
|
88
95
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
+
try
|
97
|
+
{
|
98
|
+
// a non-compliant v2 API returning 404 can cause this to throw
|
99
|
+
var existsInFeed = await feed.Exists(
|
100
|
+
packageIdentity,
|
101
|
+
includeUnlisted: false,
|
102
|
+
SourceCacheContext,
|
103
|
+
NullLogger.Instance,
|
104
|
+
cancellationToken);
|
105
|
+
if (!existsInFeed)
|
106
|
+
{
|
107
|
+
message.AppendLine($" package {packageIdentity} does not exist in {source.Name}");
|
108
|
+
continue;
|
109
|
+
}
|
110
|
+
}
|
111
|
+
catch (FatalProtocolException)
|
96
112
|
{
|
97
|
-
|
113
|
+
// if anything goes wrong here, the package source obviously doesn't contain the requested package
|
98
114
|
continue;
|
99
115
|
}
|
100
116
|
|
@@ -66,15 +66,24 @@ internal static class VersionFinder
|
|
66
66
|
continue;
|
67
67
|
}
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
69
|
+
try
|
70
|
+
{
|
71
|
+
// a non-compliant v2 API returning 404 can cause this to throw
|
72
|
+
var existsInFeed = await feed.Exists(
|
73
|
+
packageId,
|
74
|
+
includePrerelease,
|
75
|
+
includeUnlisted: false,
|
76
|
+
nugetContext.SourceCacheContext,
|
77
|
+
NullLogger.Instance,
|
78
|
+
cancellationToken);
|
79
|
+
if (!existsInFeed)
|
80
|
+
{
|
81
|
+
continue;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
catch (FatalProtocolException)
|
77
85
|
{
|
86
|
+
// if anything goes wrong here, the package source obviously doesn't contain the requested package
|
78
87
|
continue;
|
79
88
|
}
|
80
89
|
|
@@ -162,15 +171,23 @@ internal static class VersionFinder
|
|
162
171
|
continue;
|
163
172
|
}
|
164
173
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
174
|
+
try
|
175
|
+
{
|
176
|
+
// a non-compliant v2 API returning 404 can cause this to throw
|
177
|
+
var existsInFeed = await feed.Exists(
|
178
|
+
new PackageIdentity(packageId, version),
|
179
|
+
includeUnlisted: false,
|
180
|
+
nugetContext.SourceCacheContext,
|
181
|
+
NullLogger.Instance,
|
182
|
+
cancellationToken);
|
183
|
+
if (existsInFeed)
|
184
|
+
{
|
185
|
+
return true;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
catch (FatalProtocolException)
|
172
189
|
{
|
173
|
-
|
190
|
+
// if anything goes wrong here, the package source obviously doesn't contain the requested package
|
174
191
|
}
|
175
192
|
}
|
176
193
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
|
+
using System.Net;
|
2
3
|
using System.Text.Json;
|
3
4
|
using System.Text.Json.Serialization;
|
4
5
|
|
@@ -6,6 +7,7 @@ using Microsoft.Build.Construction;
|
|
6
7
|
using Microsoft.Build.Definition;
|
7
8
|
using Microsoft.Build.Evaluation;
|
8
9
|
|
10
|
+
using NuGetUpdater.Core.Analyze;
|
9
11
|
using NuGetUpdater.Core.Utilities;
|
10
12
|
|
11
13
|
namespace NuGetUpdater.Core.Discover;
|
@@ -47,43 +49,60 @@ public partial class DiscoveryWorker
|
|
47
49
|
DirectoryPackagesPropsDiscoveryResult? directoryPackagesPropsDiscovery = null;
|
48
50
|
|
49
51
|
ImmutableArray<ProjectDiscoveryResult> projectResults = [];
|
52
|
+
WorkspaceDiscoveryResult result;
|
50
53
|
|
51
|
-
|
54
|
+
try
|
52
55
|
{
|
53
|
-
|
56
|
+
if (Directory.Exists(workspacePath))
|
57
|
+
{
|
58
|
+
_logger.Log($"Discovering build files in workspace [{workspacePath}].");
|
54
59
|
|
55
|
-
|
56
|
-
|
60
|
+
dotNetToolsJsonDiscovery = DotNetToolsJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
|
61
|
+
globalJsonDiscovery = GlobalJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
|
57
62
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
63
|
+
if (globalJsonDiscovery is not null)
|
64
|
+
{
|
65
|
+
await TryRestoreMSBuildSdksAsync(repoRootPath, workspacePath, globalJsonDiscovery.Dependencies, _logger);
|
66
|
+
}
|
62
67
|
|
63
|
-
|
68
|
+
// this next line should throw or something
|
69
|
+
projectResults = await RunForDirectoryAsnyc(repoRootPath, workspacePath);
|
64
70
|
|
65
|
-
|
71
|
+
directoryPackagesPropsDiscovery = DirectoryPackagesPropsDiscovery.Discover(repoRootPath, workspacePath, projectResults, _logger);
|
66
72
|
|
67
|
-
|
73
|
+
if (directoryPackagesPropsDiscovery is not null)
|
74
|
+
{
|
75
|
+
projectResults = projectResults.Remove(projectResults.First(p => p.FilePath.Equals(directoryPackagesPropsDiscovery.FilePath, StringComparison.OrdinalIgnoreCase)));
|
76
|
+
}
|
77
|
+
}
|
78
|
+
else
|
68
79
|
{
|
69
|
-
|
80
|
+
_logger.Log($"Workspace path [{workspacePath}] does not exist.");
|
70
81
|
}
|
82
|
+
|
83
|
+
result = new WorkspaceDiscoveryResult
|
84
|
+
{
|
85
|
+
Path = initialWorkspacePath,
|
86
|
+
DotNetToolsJson = dotNetToolsJsonDiscovery,
|
87
|
+
GlobalJson = globalJsonDiscovery,
|
88
|
+
DirectoryPackagesProps = directoryPackagesPropsDiscovery,
|
89
|
+
Projects = projectResults.OrderBy(p => p.FilePath).ToImmutableArray(),
|
90
|
+
};
|
71
91
|
}
|
72
|
-
|
92
|
+
catch (HttpRequestException ex)
|
93
|
+
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
73
94
|
{
|
74
|
-
|
95
|
+
// TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
|
96
|
+
result = new WorkspaceDiscoveryResult
|
97
|
+
{
|
98
|
+
ErrorType = ErrorType.AuthenticationFailure,
|
99
|
+
ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(workspacePath)) + ")",
|
100
|
+
Path = initialWorkspacePath,
|
101
|
+
Projects = [],
|
102
|
+
};
|
75
103
|
}
|
76
104
|
|
77
|
-
|
78
|
-
{
|
79
|
-
Path = initialWorkspacePath,
|
80
|
-
DotNetToolsJson = dotNetToolsJsonDiscovery,
|
81
|
-
GlobalJson = globalJsonDiscovery,
|
82
|
-
DirectoryPackagesProps = directoryPackagesPropsDiscovery,
|
83
|
-
Projects = projectResults.OrderBy(p => p.FilePath).ToImmutableArray(),
|
84
|
-
};
|
85
|
-
|
86
|
-
await WriteResults(repoRootPath, outputPath, result);
|
105
|
+
await WriteResultsAsync(repoRootPath, outputPath, result);
|
87
106
|
|
88
107
|
_logger.Log("Discovery complete.");
|
89
108
|
|
@@ -293,7 +312,7 @@ public partial class DiscoveryWorker
|
|
293
312
|
return [.. results.Values];
|
294
313
|
}
|
295
314
|
|
296
|
-
|
315
|
+
internal static async Task WriteResultsAsync(string repoRootPath, string outputPath, WorkspaceDiscoveryResult result)
|
297
316
|
{
|
298
317
|
var resultPath = Path.IsPathRooted(outputPath)
|
299
318
|
? outputPath
|
@@ -2,7 +2,7 @@ using System.Collections.Immutable;
|
|
2
2
|
|
3
3
|
namespace NuGetUpdater.Core.Discover;
|
4
4
|
|
5
|
-
public sealed record WorkspaceDiscoveryResult
|
5
|
+
public sealed record WorkspaceDiscoveryResult : NativeResult
|
6
6
|
{
|
7
7
|
public required string Path { get; init; }
|
8
8
|
public bool IsSuccess { get; init; } = true;
|
@@ -93,11 +93,11 @@ internal sealed class ProjectBuildFile : XmlBuildFile
|
|
93
93
|
{
|
94
94
|
var isUpdate = false;
|
95
95
|
|
96
|
-
var name = element.GetAttributeOrSubElementValue("Include", StringComparison.OrdinalIgnoreCase);
|
96
|
+
var name = element.GetAttributeOrSubElementValue("Include", StringComparison.OrdinalIgnoreCase)?.Trim();
|
97
97
|
if (name is null)
|
98
98
|
{
|
99
99
|
isUpdate = true;
|
100
|
-
name = element.GetAttributeOrSubElementValue("Update", StringComparison.OrdinalIgnoreCase);
|
100
|
+
name = element.GetAttributeOrSubElementValue("Update", StringComparison.OrdinalIgnoreCase)?.Trim();
|
101
101
|
}
|
102
102
|
|
103
103
|
if (name is null || name.StartsWith("@("))
|
@@ -1,3 +1,4 @@
|
|
1
|
+
using System.Diagnostics;
|
1
2
|
using System.Text;
|
2
3
|
using System.Xml.Linq;
|
3
4
|
using System.Xml.XPath;
|
@@ -102,9 +103,9 @@ internal static class PackagesConfigUpdater
|
|
102
103
|
Console.SetError(writer);
|
103
104
|
|
104
105
|
var currentDir = Environment.CurrentDirectory;
|
106
|
+
var existingSpawnedProcesses = GetLikelyNuGetSpawnedProcesses();
|
105
107
|
try
|
106
108
|
{
|
107
|
-
|
108
109
|
Environment.CurrentDirectory = projectDirectory;
|
109
110
|
var retryingAfterRestore = false;
|
110
111
|
|
@@ -144,6 +145,7 @@ internal static class PackagesConfigUpdater
|
|
144
145
|
goto doRestore;
|
145
146
|
}
|
146
147
|
|
148
|
+
MSBuildHelper.ThrowOnUnauthenticatedFeed(fullOutput);
|
147
149
|
throw new Exception(fullOutput);
|
148
150
|
}
|
149
151
|
}
|
@@ -157,9 +159,24 @@ internal static class PackagesConfigUpdater
|
|
157
159
|
Environment.CurrentDirectory = currentDir;
|
158
160
|
Console.SetOut(originalOut);
|
159
161
|
Console.SetError(originalError);
|
162
|
+
|
163
|
+
// NuGet.exe can spawn processes that hold on to the temporary directory, so we need to kill them
|
164
|
+
var currentSpawnedProcesses = GetLikelyNuGetSpawnedProcesses();
|
165
|
+
var deltaSpawnedProcesses = currentSpawnedProcesses.Except(existingSpawnedProcesses).ToArray();
|
166
|
+
foreach (var credProvider in deltaSpawnedProcesses)
|
167
|
+
{
|
168
|
+
logger.Log($"Ending spawned credential provider process");
|
169
|
+
credProvider.Kill();
|
170
|
+
}
|
160
171
|
}
|
161
172
|
}
|
162
173
|
|
174
|
+
private static Process[] GetLikelyNuGetSpawnedProcesses()
|
175
|
+
{
|
176
|
+
var processes = Process.GetProcesses().Where(p => p.ProcessName.StartsWith("CredentialProvider", StringComparison.OrdinalIgnoreCase) == true).ToArray();
|
177
|
+
return processes;
|
178
|
+
}
|
179
|
+
|
163
180
|
internal static string? GetPathToPackagesDirectory(ProjectBuildFile projectBuildFile, string dependencyName, string dependencyVersion, string packagesConfigPath)
|
164
181
|
{
|
165
182
|
// the packages directory can be found from the hint path of the matching dependency, e.g., when given "Newtonsoft.Json", "7.0.1", and a project like this:
|
@@ -228,6 +228,7 @@ internal static class SdkPackageUpdater
|
|
228
228
|
|
229
229
|
// see https://learn.microsoft.com/nuget/consume-packages/install-use-packages-dotnet-cli
|
230
230
|
var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", $"add {projectPath} package {dependencyName} --version {newDependencyVersion}", workingDirectory: Path.GetDirectoryName(projectPath));
|
231
|
+
MSBuildHelper.ThrowOnUnauthenticatedFeed(stdout);
|
231
232
|
if (exitCode != 0)
|
232
233
|
{
|
233
234
|
logger.Log($" Transitive dependency [{dependencyName}/{newDependencyVersion}] was not added.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}");
|
@@ -594,7 +595,7 @@ internal static class SdkPackageUpdater
|
|
594
595
|
string packageName)
|
595
596
|
=> buildFile.PackageItemNodes.Where(e =>
|
596
597
|
string.Equals(
|
597
|
-
e.GetAttributeOrSubElementValue("Include", StringComparison.OrdinalIgnoreCase) ?? e.GetAttributeOrSubElementValue("Update", StringComparison.OrdinalIgnoreCase),
|
598
|
+
(e.GetAttributeOrSubElementValue("Include", StringComparison.OrdinalIgnoreCase) ?? e.GetAttributeOrSubElementValue("Update", StringComparison.OrdinalIgnoreCase))?.Trim(),
|
598
599
|
packageName,
|
599
600
|
StringComparison.OrdinalIgnoreCase) &&
|
600
601
|
(e.GetAttributeOrSubElementValue("Version", StringComparison.OrdinalIgnoreCase) ?? e.GetAttributeOrSubElementValue("VersionOverride", StringComparison.OrdinalIgnoreCase)) is not null);
|