dependabot-nuget 0.254.0 → 0.255.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/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +5 -0
- data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/PackageFolderReader.cs +270 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +71 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +11 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +38 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +103 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterHelperTests.cs +1 -1
- data/lib/dependabot/nuget/file_parser.rb +1 -0
- metadata +21 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1feb135ca2ebd58b0c7c96df96c8e3ad30b9f0dccd17b58c99d5670fb3ebf57b
|
|
4
|
+
data.tar.gz: 55e7d7d46b36738f198057ef6c83ea3f194d25623a65d6e719bf1fc5a6f44eb5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 13a3eae5d94249eba9a08cbe55c4c36ca3116881550e76a518e789bc7fe7e8ee6d13fcf910a25de365a2e00af96ce586a7f169a52cc1a6b2fc5fbd594d4b8ba5
|
|
7
|
+
data.tar.gz: 318e0d0cb22917a6198cd0c0821dba4a2456c23a4378f9387d645c205886cac7078119983772806313427e3ceaf52ec72f64f11f134ddb010b2e59e0bf8a2a36
|
|
@@ -19,6 +19,11 @@
|
|
|
19
19
|
|
|
20
20
|
<ItemGroup>
|
|
21
21
|
<Compile Include="$(NuGetSourceLocation)\src\NuGet.Core\NuGet.Packaging\**\*.cs" />
|
|
22
|
+
<!--
|
|
23
|
+
The `PackageFolderReader.GetFiles()` method is case-sensitive which doesn't work for some scenarios so this
|
|
24
|
+
directory contains a copy of that file with that method with a case-insensitive patch.
|
|
25
|
+
-->
|
|
26
|
+
<Compile Remove="$(NuGetSourceLocation)\src\NuGet.Core\NuGet.Packaging\PackageFolderReader.cs" />
|
|
22
27
|
</ItemGroup>
|
|
23
28
|
|
|
24
29
|
<ItemGroup>
|
|
@@ -0,0 +1,270 @@
|
|
|
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
|
+
|
|
4
|
+
using System;
|
|
5
|
+
using System.Collections.Generic;
|
|
6
|
+
using System.Globalization;
|
|
7
|
+
using System.IO;
|
|
8
|
+
using System.Linq;
|
|
9
|
+
using System.Text;
|
|
10
|
+
using System.Threading;
|
|
11
|
+
using System.Threading.Tasks;
|
|
12
|
+
|
|
13
|
+
using NuGet.Common;
|
|
14
|
+
using NuGet.Frameworks;
|
|
15
|
+
using NuGet.Packaging.Core;
|
|
16
|
+
using NuGet.Packaging.Signing;
|
|
17
|
+
|
|
18
|
+
namespace NuGet.Packaging
|
|
19
|
+
{
|
|
20
|
+
/// <summary>
|
|
21
|
+
/// Reads an unzipped nupkg folder.
|
|
22
|
+
/// </summary>
|
|
23
|
+
public class PackageFolderReader : PackageReaderBase
|
|
24
|
+
{
|
|
25
|
+
private readonly DirectoryInfo _root;
|
|
26
|
+
|
|
27
|
+
/// <summary>
|
|
28
|
+
/// Package folder reader
|
|
29
|
+
/// </summary>
|
|
30
|
+
public PackageFolderReader(string folderPath)
|
|
31
|
+
: this(folderPath, DefaultFrameworkNameProvider.Instance, DefaultCompatibilityProvider.Instance)
|
|
32
|
+
{
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// <summary>
|
|
36
|
+
/// Package folder reader
|
|
37
|
+
/// </summary>
|
|
38
|
+
/// <param name="folder">root directory of an extracted nupkg</param>
|
|
39
|
+
public PackageFolderReader(DirectoryInfo folder)
|
|
40
|
+
: this(folder, DefaultFrameworkNameProvider.Instance, DefaultCompatibilityProvider.Instance)
|
|
41
|
+
{
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// <summary>
|
|
45
|
+
/// Package folder reader
|
|
46
|
+
/// </summary>
|
|
47
|
+
/// <param name="folderPath">root directory of an extracted nupkg</param>
|
|
48
|
+
/// <param name="frameworkProvider">framework mappings</param>
|
|
49
|
+
/// <param name="compatibilityProvider">framework compatibility provider</param>
|
|
50
|
+
public PackageFolderReader(string folderPath, IFrameworkNameProvider frameworkProvider, IFrameworkCompatibilityProvider compatibilityProvider)
|
|
51
|
+
: this(new DirectoryInfo(folderPath), frameworkProvider, compatibilityProvider)
|
|
52
|
+
{
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// <summary>
|
|
56
|
+
/// Package folder reader
|
|
57
|
+
/// </summary>
|
|
58
|
+
/// <param name="folder">root directory of an extracted nupkg</param>
|
|
59
|
+
/// <param name="frameworkProvider">framework mappings</param>
|
|
60
|
+
/// <param name="compatibilityProvider">framework compatibility provider</param>
|
|
61
|
+
public PackageFolderReader(DirectoryInfo folder, IFrameworkNameProvider frameworkProvider, IFrameworkCompatibilityProvider compatibilityProvider)
|
|
62
|
+
: base(frameworkProvider, compatibilityProvider)
|
|
63
|
+
{
|
|
64
|
+
_root = folder;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public override string GetNuspecFile()
|
|
68
|
+
{
|
|
69
|
+
// This needs to be explicitly case insensitive in order to work on XPlat, since GetFiles is normally case sensitive on non-Windows
|
|
70
|
+
var nuspecFiles = _root.GetFiles("*.*", SearchOption.TopDirectoryOnly).Where(f => f.Name.EndsWith(".nuspec", StringComparison.OrdinalIgnoreCase)).ToArray();
|
|
71
|
+
|
|
72
|
+
if (nuspecFiles.Length == 0)
|
|
73
|
+
{
|
|
74
|
+
var message = new StringBuilder();
|
|
75
|
+
message.Append(Strings.Error_MissingNuspecFile);
|
|
76
|
+
message.AppendFormat(CultureInfo.CurrentCulture, Strings.Message_Path, _root.FullName);
|
|
77
|
+
throw new PackagingException(NuGetLogCode.NU5037, message.ToString());
|
|
78
|
+
}
|
|
79
|
+
else if (nuspecFiles.Length > 1)
|
|
80
|
+
{
|
|
81
|
+
throw new PackagingException(Strings.MultipleNuspecFiles);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return nuspecFiles[0].FullName;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// <summary>
|
|
88
|
+
/// Opens a local file in read only mode.
|
|
89
|
+
/// </summary>
|
|
90
|
+
public override Stream GetStream(string path)
|
|
91
|
+
{
|
|
92
|
+
return GetFile(path).OpenRead();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private FileInfo GetFile(string path)
|
|
96
|
+
{
|
|
97
|
+
var file = new FileInfo(Path.Combine(_root.FullName, path));
|
|
98
|
+
|
|
99
|
+
if (!file.FullName.StartsWith(_root.FullName, StringComparison.OrdinalIgnoreCase))
|
|
100
|
+
{
|
|
101
|
+
// the given path does not appear under the folder root
|
|
102
|
+
throw new FileNotFoundException(path);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return file;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public override IEnumerable<string> GetFiles()
|
|
109
|
+
{
|
|
110
|
+
// Read all files starting at the root.
|
|
111
|
+
return GetFiles(folder: null);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public override IEnumerable<string> GetFiles(string folder)
|
|
115
|
+
{
|
|
116
|
+
// Default to retrieve files and throwing if the root
|
|
117
|
+
// directory is not found.
|
|
118
|
+
var getFiles = true;
|
|
119
|
+
var searchFolder = new DirectoryInfo(_root.FullName);
|
|
120
|
+
|
|
121
|
+
if (!string.IsNullOrEmpty(folder))
|
|
122
|
+
{
|
|
123
|
+
// Search in the sub folder if one was specified
|
|
124
|
+
searchFolder = new DirectoryInfo(Path.Combine(_root.FullName, folder));
|
|
125
|
+
|
|
126
|
+
// For sub folders verify it exists
|
|
127
|
+
// The root is expected to exist and should throw if it does not
|
|
128
|
+
getFiles = searchFolder.Exists;
|
|
129
|
+
|
|
130
|
+
// try a case-insensitive search
|
|
131
|
+
if (!getFiles)
|
|
132
|
+
{
|
|
133
|
+
searchFolder = _root.GetDirectories().FirstOrDefault(d => d.Name.Equals(folder, StringComparison.OrdinalIgnoreCase));
|
|
134
|
+
getFiles = searchFolder?.Exists == true;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (getFiles)
|
|
139
|
+
{
|
|
140
|
+
// Enumerate root folder filtering out nupkg files
|
|
141
|
+
foreach (var file in searchFolder.GetFiles("*", SearchOption.AllDirectories))
|
|
142
|
+
{
|
|
143
|
+
var path = GetRelativePath(_root, file);
|
|
144
|
+
|
|
145
|
+
// disallow nupkgs in the root
|
|
146
|
+
if (!IsFileInRoot(path) || !IsNupkg(path))
|
|
147
|
+
{
|
|
148
|
+
yield return path;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
yield break;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/// <summary>
|
|
157
|
+
/// True if the path does not contain /
|
|
158
|
+
/// </summary>
|
|
159
|
+
private static bool IsFileInRoot(string path)
|
|
160
|
+
{
|
|
161
|
+
#if NETCOREAPP
|
|
162
|
+
return path.IndexOf('/', StringComparison.Ordinal) == -1;
|
|
163
|
+
#else
|
|
164
|
+
return path.IndexOf('/') == -1;
|
|
165
|
+
#endif
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/// <summary>
|
|
169
|
+
/// True if the path ends with .nupkg
|
|
170
|
+
/// </summary>
|
|
171
|
+
private static bool IsNupkg(string path)
|
|
172
|
+
{
|
|
173
|
+
return path.EndsWith(PackagingCoreConstants.NupkgExtension, StringComparison.OrdinalIgnoreCase) == true;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/// <summary>
|
|
177
|
+
/// Build the relative path in the same format that ZipArchive uses
|
|
178
|
+
/// </summary>
|
|
179
|
+
private static string GetRelativePath(DirectoryInfo root, FileInfo file)
|
|
180
|
+
{
|
|
181
|
+
var parents = new Stack<DirectoryInfo>();
|
|
182
|
+
|
|
183
|
+
var parent = file.Directory;
|
|
184
|
+
|
|
185
|
+
while (parent != null
|
|
186
|
+
&& !StringComparer.OrdinalIgnoreCase.Equals(parent.FullName, root.FullName))
|
|
187
|
+
{
|
|
188
|
+
parents.Push(parent);
|
|
189
|
+
parent = parent.Parent;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (parent == null)
|
|
193
|
+
{
|
|
194
|
+
// the given file path does not appear under root
|
|
195
|
+
throw new FileNotFoundException(file.FullName);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
var parts = parents.Select(d => d.Name).Concat(new string[] { file.Name });
|
|
199
|
+
|
|
200
|
+
return string.Join("/", parts);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
public override IEnumerable<string> CopyFiles(
|
|
204
|
+
string destination,
|
|
205
|
+
IEnumerable<string> packageFiles,
|
|
206
|
+
ExtractPackageFileDelegate extractFile,
|
|
207
|
+
ILogger logger,
|
|
208
|
+
CancellationToken token)
|
|
209
|
+
{
|
|
210
|
+
var filesCopied = new List<string>();
|
|
211
|
+
|
|
212
|
+
foreach (var packageFile in packageFiles)
|
|
213
|
+
{
|
|
214
|
+
token.ThrowIfCancellationRequested();
|
|
215
|
+
|
|
216
|
+
var sourceFile = GetFile(packageFile);
|
|
217
|
+
|
|
218
|
+
var targetPath = Path.Combine(destination, packageFile);
|
|
219
|
+
Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
|
|
220
|
+
|
|
221
|
+
using (var fileStream = sourceFile.OpenRead())
|
|
222
|
+
{
|
|
223
|
+
targetPath = extractFile(sourceFile.FullName, targetPath, fileStream);
|
|
224
|
+
if (targetPath != null)
|
|
225
|
+
{
|
|
226
|
+
ZipArchiveExtensions.UpdateFileTime(targetPath, sourceFile.LastWriteTimeUtc);
|
|
227
|
+
filesCopied.Add(targetPath);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return filesCopied;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
protected override void Dispose(bool disposing)
|
|
236
|
+
{
|
|
237
|
+
// do nothing here
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
public override Task<PrimarySignature> GetPrimarySignatureAsync(CancellationToken token)
|
|
241
|
+
{
|
|
242
|
+
return TaskResult.Null<PrimarySignature>();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
public override Task<bool> IsSignedAsync(CancellationToken token)
|
|
246
|
+
{
|
|
247
|
+
return TaskResult.False;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public override Task ValidateIntegrityAsync(SignatureContent signatureContent, CancellationToken token)
|
|
251
|
+
{
|
|
252
|
+
throw new NotImplementedException();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
public override Task<byte[]> GetArchiveHashAsync(HashAlgorithmName hashAlgorithm, CancellationToken token)
|
|
256
|
+
{
|
|
257
|
+
throw new NotImplementedException();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
public override bool CanVerifySignedPackages(SignedPackageVerifierSettings verifierSettings)
|
|
261
|
+
{
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
public override string GetContentHash(CancellationToken token, Func<string> GetUnsignedPackageHash = null)
|
|
266
|
+
{
|
|
267
|
+
throw new NotImplementedException();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
@@ -214,6 +214,77 @@ public partial class EntryPointTests
|
|
|
214
214
|
});
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
[Fact]
|
|
218
|
+
public async Task WithDuplicateDependenciesOfDifferentTypes()
|
|
219
|
+
{
|
|
220
|
+
var projectPath = "path/to/my.csproj";
|
|
221
|
+
var directoryBuildPropsPath = "path/Directory.Build.props";
|
|
222
|
+
await RunAsync(path =>
|
|
223
|
+
[
|
|
224
|
+
"discover",
|
|
225
|
+
"--repo-root",
|
|
226
|
+
path,
|
|
227
|
+
"--workspace",
|
|
228
|
+
path,
|
|
229
|
+
],
|
|
230
|
+
new[]
|
|
231
|
+
{
|
|
232
|
+
(projectPath, """
|
|
233
|
+
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
234
|
+
<PropertyGroup>
|
|
235
|
+
<TargetFramework>net8.0</TargetFramework>
|
|
236
|
+
</PropertyGroup>
|
|
237
|
+
<ItemGroup>
|
|
238
|
+
<PackageReference Include="Newtonsoft.Json" Version="7.0.1" />
|
|
239
|
+
</ItemGroup>
|
|
240
|
+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
241
|
+
</Project>
|
|
242
|
+
"""),
|
|
243
|
+
(directoryBuildPropsPath, """
|
|
244
|
+
<Project>
|
|
245
|
+
<ItemGroup Condition="'$(ManagePackageVersionsCentrally)' == 'true'">
|
|
246
|
+
<GlobalPackageReference Include="System.Text.Json" Version="8.0.3" />
|
|
247
|
+
</ItemGroup>
|
|
248
|
+
<ItemGroup Condition="'$(ManagePackageVersionsCentrally)' != 'true'">
|
|
249
|
+
<PackageReference Include="System.Text.Json" Version="8.0.3" />
|
|
250
|
+
</ItemGroup>
|
|
251
|
+
</Project>
|
|
252
|
+
""")
|
|
253
|
+
},
|
|
254
|
+
expectedResult: new()
|
|
255
|
+
{
|
|
256
|
+
FilePath = "",
|
|
257
|
+
Projects = [
|
|
258
|
+
new()
|
|
259
|
+
{
|
|
260
|
+
FilePath = projectPath,
|
|
261
|
+
TargetFrameworks = ["net8.0"],
|
|
262
|
+
ReferencedProjectPaths = [],
|
|
263
|
+
ExpectedDependencyCount = 2,
|
|
264
|
+
Dependencies = [
|
|
265
|
+
new("Newtonsoft.Json", "7.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
|
|
266
|
+
// $(ManagePackageVersionsCentrally) evaluates false by default, we only get a PackageReference
|
|
267
|
+
new("System.Text.Json", "8.0.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"])
|
|
268
|
+
],
|
|
269
|
+
Properties = [
|
|
270
|
+
new("TargetFramework", "net8.0", "path/to/my.csproj"),
|
|
271
|
+
],
|
|
272
|
+
},
|
|
273
|
+
new()
|
|
274
|
+
{
|
|
275
|
+
FilePath = directoryBuildPropsPath,
|
|
276
|
+
ReferencedProjectPaths = [],
|
|
277
|
+
ExpectedDependencyCount = 2,
|
|
278
|
+
Dependencies = [
|
|
279
|
+
new("System.Text.Json", "8.0.3", DependencyType.PackageReference, IsDirect: true),
|
|
280
|
+
new("System.Text.Json", "8.0.3", DependencyType.GlobalPackageReference, IsDirect: true)
|
|
281
|
+
],
|
|
282
|
+
Properties = [],
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
217
288
|
private static async Task RunAsync(
|
|
218
289
|
Func<string, string[]> getArgs,
|
|
219
290
|
TestFile[] initialFiles,
|
|
@@ -29,24 +29,25 @@ internal static class SdkProjectDiscovery
|
|
|
29
29
|
|
|
30
30
|
// The build file dependencies have the correct DependencyType and the TopLevelDependencies have the evaluated version.
|
|
31
31
|
// Combine them to have the set of dependencies that are directly referenced from the build file.
|
|
32
|
-
var fileDependencies = BuildFile.GetDependencies(buildFile)
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
var fileDependencies = BuildFile.GetDependencies(buildFile).ToImmutableArray();
|
|
33
|
+
var fileDependencyLookup = fileDependencies
|
|
34
|
+
.ToLookup(d => d.Name, StringComparer.OrdinalIgnoreCase);
|
|
35
|
+
var sdkDependencies = fileDependencies
|
|
35
36
|
.Where(d => d.Type == DependencyType.MSBuildSdk)
|
|
36
37
|
.ToImmutableArray();
|
|
37
38
|
var indirectDependencies = topLevelDependencies
|
|
38
|
-
.Where(d => !
|
|
39
|
+
.Where(d => !fileDependencyLookup.Contains(d.Name))
|
|
39
40
|
.ToImmutableArray();
|
|
40
41
|
var directDependencies = topLevelDependencies
|
|
41
|
-
.Where(d =>
|
|
42
|
-
.
|
|
42
|
+
.Where(d => fileDependencyLookup.Contains(d.Name))
|
|
43
|
+
.SelectMany(d =>
|
|
43
44
|
{
|
|
44
|
-
var
|
|
45
|
-
return d with
|
|
45
|
+
var dependencies = fileDependencyLookup[d.Name];
|
|
46
|
+
return dependencies.Select(fileDependency => d with
|
|
46
47
|
{
|
|
47
|
-
Type =
|
|
48
|
+
Type = fileDependency.Type,
|
|
48
49
|
IsDirect = true
|
|
49
|
-
};
|
|
50
|
+
});
|
|
50
51
|
}).ToImmutableArray();
|
|
51
52
|
|
|
52
53
|
if (buildFile.GetFileType() == ProjectBuildFileType.Project)
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
using System;
|
|
2
|
-
using System.Collections.Generic;
|
|
3
|
-
using System.IO;
|
|
4
|
-
using System.Linq;
|
|
5
1
|
using System.Text;
|
|
6
|
-
using System.
|
|
2
|
+
using System.Xml.Linq;
|
|
3
|
+
using System.Xml.XPath;
|
|
7
4
|
|
|
8
5
|
using Microsoft.Language.Xml;
|
|
9
6
|
|
|
@@ -23,7 +20,7 @@ internal static class PackagesConfigUpdater
|
|
|
23
20
|
string dependencyName,
|
|
24
21
|
string previousDependencyVersion,
|
|
25
22
|
string newDependencyVersion,
|
|
26
|
-
|
|
23
|
+
string packagesConfigPath,
|
|
27
24
|
Logger logger
|
|
28
25
|
)
|
|
29
26
|
{
|
|
@@ -33,7 +30,7 @@ internal static class PackagesConfigUpdater
|
|
|
33
30
|
|
|
34
31
|
// ensure local packages directory exists
|
|
35
32
|
var projectBuildFile = ProjectBuildFile.Open(repoRootPath, projectPath);
|
|
36
|
-
var packagesSubDirectory = GetPathToPackagesDirectory(projectBuildFile, dependencyName, previousDependencyVersion);
|
|
33
|
+
var packagesSubDirectory = GetPathToPackagesDirectory(projectBuildFile, dependencyName, previousDependencyVersion, packagesConfigPath);
|
|
37
34
|
if (packagesSubDirectory is null)
|
|
38
35
|
{
|
|
39
36
|
logger.Log($" Project [{projectPath}] does not reference this dependency.");
|
|
@@ -43,8 +40,6 @@ internal static class PackagesConfigUpdater
|
|
|
43
40
|
logger.Log($" Using packages directory [{packagesSubDirectory}] for project [{projectPath}].");
|
|
44
41
|
|
|
45
42
|
var projectDirectory = Path.GetDirectoryName(projectPath);
|
|
46
|
-
var packagesConfigPath = PathHelper.JoinPath(projectDirectory, NuGetHelper.PackagesConfigFileName);
|
|
47
|
-
|
|
48
43
|
var packagesDirectory = PathHelper.JoinPath(projectDirectory, packagesSubDirectory);
|
|
49
44
|
Directory.CreateDirectory(packagesDirectory);
|
|
50
45
|
|
|
@@ -83,7 +78,7 @@ internal static class PackagesConfigUpdater
|
|
|
83
78
|
|
|
84
79
|
using (new WebApplicationTargetsConditionPatcher(projectPath))
|
|
85
80
|
{
|
|
86
|
-
|
|
81
|
+
RunNugetUpdate(updateArgs, restoreArgs, projectDirectory ?? packagesDirectory, logger);
|
|
87
82
|
}
|
|
88
83
|
|
|
89
84
|
projectBuildFile = ProjectBuildFile.Open(repoRootPath, projectPath);
|
|
@@ -96,7 +91,7 @@ internal static class PackagesConfigUpdater
|
|
|
96
91
|
await projectBuildFile.SaveAsync();
|
|
97
92
|
}
|
|
98
93
|
|
|
99
|
-
private static void
|
|
94
|
+
private static void RunNugetUpdate(List<string> updateArgs, List<string> restoreArgs, string projectDirectory, Logger logger)
|
|
100
95
|
{
|
|
101
96
|
var outputBuilder = new StringBuilder();
|
|
102
97
|
var writer = new StringWriter(outputBuilder);
|
|
@@ -110,7 +105,7 @@ internal static class PackagesConfigUpdater
|
|
|
110
105
|
try
|
|
111
106
|
{
|
|
112
107
|
|
|
113
|
-
Environment.CurrentDirectory =
|
|
108
|
+
Environment.CurrentDirectory = projectDirectory;
|
|
114
109
|
var retryingAfterRestore = false;
|
|
115
110
|
|
|
116
111
|
doRestore:
|
|
@@ -122,13 +117,21 @@ internal static class PackagesConfigUpdater
|
|
|
122
117
|
logger.Log($" Output:\n{fullOutput}");
|
|
123
118
|
if (result != 0)
|
|
124
119
|
{
|
|
125
|
-
//
|
|
126
|
-
//
|
|
120
|
+
// The initial `update` command can fail for several reasons:
|
|
121
|
+
// 1. One possibility is that the `packages.config` file contains a delisted package. If that's the
|
|
122
|
+
// case, `update` will fail with the message "Existing packages must be restored before performing
|
|
123
|
+
// an install or update."
|
|
124
|
+
// 2. Another possibility is that the `update` command fails because the package contains no assemblies
|
|
125
|
+
// and doesn't appear in the cache. The message in this case will be "Could not install package
|
|
126
|
+
// '<name> <version>'...the package does not contain any assembly references or content files that
|
|
127
|
+
// are compatible with that framework.".
|
|
128
|
+
// The solution in all cases is to run `restore` then try the update again.
|
|
127
129
|
if (!retryingAfterRestore &&
|
|
128
|
-
fullOutput.Contains("Existing packages must be restored before performing an install or update.")
|
|
130
|
+
(fullOutput.Contains("Existing packages must be restored before performing an install or update.") ||
|
|
131
|
+
fullOutput.Contains("the package does not contain any assembly references or content files that are compatible with that framework.")))
|
|
129
132
|
{
|
|
130
|
-
logger.Log($" Running NuGet.exe with args: {string.Join(" ", restoreArgs)}");
|
|
131
133
|
retryingAfterRestore = true;
|
|
134
|
+
logger.Log($" Running NuGet.exe with args: {string.Join(" ", restoreArgs)}");
|
|
132
135
|
outputBuilder.Clear();
|
|
133
136
|
var exitCodeAgain = Program.Main(restoreArgs.ToArray());
|
|
134
137
|
var restoreOutput = outputBuilder.ToString();
|
|
@@ -157,7 +160,7 @@ internal static class PackagesConfigUpdater
|
|
|
157
160
|
}
|
|
158
161
|
}
|
|
159
162
|
|
|
160
|
-
internal static string? GetPathToPackagesDirectory(ProjectBuildFile projectBuildFile, string dependencyName, string dependencyVersion)
|
|
163
|
+
internal static string? GetPathToPackagesDirectory(ProjectBuildFile projectBuildFile, string dependencyName, string dependencyVersion, string packagesConfigPath)
|
|
161
164
|
{
|
|
162
165
|
// 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:
|
|
163
166
|
// <Project>
|
|
@@ -203,6 +206,24 @@ internal static class PackagesConfigUpdater
|
|
|
203
206
|
}
|
|
204
207
|
}
|
|
205
208
|
|
|
209
|
+
if (partialPathMatch is null)
|
|
210
|
+
{
|
|
211
|
+
// if we got this far, we couldn't find the packages directory for the specified dependency and there are 2 possibilities:
|
|
212
|
+
// 1. the dependency doesn't actually exist in this project
|
|
213
|
+
// 2. the dependency exists, but doesn't have any assemblies, e.g., jQuery
|
|
214
|
+
|
|
215
|
+
// first let's check the packages.config file to see if we actually need it.
|
|
216
|
+
XDocument packagesDocument = XDocument.Load(packagesConfigPath);
|
|
217
|
+
var hasPackage = packagesDocument.XPathSelectElements("/packages/package")
|
|
218
|
+
.Where(e => e.Attribute("id")?.Value.Equals(dependencyName, StringComparison.OrdinalIgnoreCase) == true).Any();
|
|
219
|
+
if (hasPackage)
|
|
220
|
+
{
|
|
221
|
+
// the dependency exists in the packages.config file, so it must be the second case
|
|
222
|
+
// the vast majority of projects found in the wild use this, and since we have nothing to look for, we'll just have to hope
|
|
223
|
+
partialPathMatch = "../packages";
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
206
227
|
return partialPathMatch;
|
|
207
228
|
}
|
|
208
229
|
|
|
@@ -134,9 +134,9 @@ public class UpdaterWorker
|
|
|
134
134
|
|
|
135
135
|
_logger.Log($"Updating project [{projectPath}]");
|
|
136
136
|
|
|
137
|
-
if (NuGetHelper.TryGetPackagesConfigFile(projectPath, out
|
|
137
|
+
if (NuGetHelper.TryGetPackagesConfigFile(projectPath, out var packagesConfigPath))
|
|
138
138
|
{
|
|
139
|
-
await PackagesConfigUpdater.UpdateDependencyAsync(repoRootPath, projectPath, dependencyName, previousDependencyVersion, newDependencyVersion,
|
|
139
|
+
await PackagesConfigUpdater.UpdateDependencyAsync(repoRootPath, projectPath, dependencyName, previousDependencyVersion, newDependencyVersion, packagesConfigPath, _logger);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// Some repos use a mix of packages.config and PackageReference
|
|
@@ -91,7 +91,7 @@ public class DiscoveryWorkerTestBase
|
|
|
91
91
|
|
|
92
92
|
foreach (var expectedDependency in expectedDependencies)
|
|
93
93
|
{
|
|
94
|
-
var actualDependency = actualDependencies.Single(d => d.Name == expectedDependency.Name);
|
|
94
|
+
var actualDependency = actualDependencies.Single(d => d.Name == expectedDependency.Name && d.Type == expectedDependency.Type);
|
|
95
95
|
Assert.Equal(expectedDependency.Name, actualDependency.Name);
|
|
96
96
|
Assert.Equal(expectedDependency.Version, actualDependency.Version);
|
|
97
97
|
Assert.Equal(expectedDependency.Type, actualDependency.Type);
|
|
@@ -9,7 +9,7 @@ public class PackagesConfigUpdaterTests : TestBase
|
|
|
9
9
|
public void PathToPackagesDirectoryCanBeDetermined(string projectContents, string dependencyName, string dependencyVersion, string expectedPackagesDirectoryPath)
|
|
10
10
|
{
|
|
11
11
|
var projectBuildFile = ProjectBuildFile.Parse("/", "project.csproj", projectContents);
|
|
12
|
-
var actualPackagesDirectorypath = PackagesConfigUpdater.GetPathToPackagesDirectory(projectBuildFile, dependencyName, dependencyVersion);
|
|
12
|
+
var actualPackagesDirectorypath = PackagesConfigUpdater.GetPathToPackagesDirectory(projectBuildFile, dependencyName, dependencyVersion, "packages.config");
|
|
13
13
|
Assert.Equal(expectedPackagesDirectoryPath, actualPackagesDirectorypath);
|
|
14
14
|
}
|
|
15
15
|
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
using System.Collections.Generic;
|
|
2
|
-
using System.Threading.Tasks;
|
|
3
|
-
|
|
4
1
|
using Xunit;
|
|
5
2
|
|
|
6
3
|
namespace NuGetUpdater.Core.Test.Update;
|
|
@@ -121,6 +118,109 @@ public partial class UpdateWorkerTests
|
|
|
121
118
|
""");
|
|
122
119
|
}
|
|
123
120
|
|
|
121
|
+
[Fact]
|
|
122
|
+
public async Task UpdateSingleDependencyInPackagesConfig_SpecifiedDependencyHasNoPackagesPath()
|
|
123
|
+
{
|
|
124
|
+
// update jQuery from 1.6.4 to 3.7.1
|
|
125
|
+
await TestUpdateForProject("jQuery", "1.6.4", "3.7.1",
|
|
126
|
+
// existing
|
|
127
|
+
projectContents: """
|
|
128
|
+
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
129
|
+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
130
|
+
<PropertyGroup>
|
|
131
|
+
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
|
132
|
+
</PropertyGroup>
|
|
133
|
+
<ItemGroup>
|
|
134
|
+
<None Include="packages.config" />
|
|
135
|
+
</ItemGroup>
|
|
136
|
+
<ItemGroup>
|
|
137
|
+
<Reference Include="Newtonsoft.Json">
|
|
138
|
+
<HintPath>packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
|
139
|
+
<Private>True</Private>
|
|
140
|
+
</Reference>
|
|
141
|
+
</ItemGroup>
|
|
142
|
+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
143
|
+
</Project>
|
|
144
|
+
""",
|
|
145
|
+
packagesConfigContents: """
|
|
146
|
+
<packages>
|
|
147
|
+
<package id="jQuery" version="1.6.4" targetFramework="net45" />
|
|
148
|
+
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
|
|
149
|
+
</packages>
|
|
150
|
+
""",
|
|
151
|
+
// expected
|
|
152
|
+
expectedProjectContents: """
|
|
153
|
+
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
154
|
+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
155
|
+
<PropertyGroup>
|
|
156
|
+
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
|
157
|
+
</PropertyGroup>
|
|
158
|
+
<ItemGroup>
|
|
159
|
+
<None Include="packages.config" />
|
|
160
|
+
</ItemGroup>
|
|
161
|
+
<ItemGroup>
|
|
162
|
+
<Reference Include="Newtonsoft.Json">
|
|
163
|
+
<HintPath>packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
|
164
|
+
<Private>True</Private>
|
|
165
|
+
</Reference>
|
|
166
|
+
</ItemGroup>
|
|
167
|
+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
168
|
+
</Project>
|
|
169
|
+
""",
|
|
170
|
+
expectedPackagesConfigContents: """
|
|
171
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
172
|
+
<packages>
|
|
173
|
+
<package id="jQuery" version="3.7.1" targetFramework="net46" />
|
|
174
|
+
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
|
|
175
|
+
</packages>
|
|
176
|
+
"""
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
[Fact]
|
|
181
|
+
public async Task UpdateSingleDependencyInPackagesConfig_NoPackagesPathCanBeFound()
|
|
182
|
+
{
|
|
183
|
+
// update jQuery from 3.7.0 to 3.7.1
|
|
184
|
+
await TestUpdateForProject("jQuery", "3.7.0", "3.7.1",
|
|
185
|
+
// existing
|
|
186
|
+
projectContents: """
|
|
187
|
+
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
188
|
+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
189
|
+
<PropertyGroup>
|
|
190
|
+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
|
191
|
+
</PropertyGroup>
|
|
192
|
+
<ItemGroup>
|
|
193
|
+
<None Include="packages.config" />
|
|
194
|
+
</ItemGroup>
|
|
195
|
+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
196
|
+
</Project>
|
|
197
|
+
""",
|
|
198
|
+
packagesConfigContents: """
|
|
199
|
+
<packages>
|
|
200
|
+
<package id="jQuery" version="3.7.0" targetFramework="net45" />
|
|
201
|
+
</packages>
|
|
202
|
+
""",
|
|
203
|
+
// expected
|
|
204
|
+
expectedProjectContents: """
|
|
205
|
+
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
206
|
+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
207
|
+
<PropertyGroup>
|
|
208
|
+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
|
209
|
+
</PropertyGroup>
|
|
210
|
+
<ItemGroup>
|
|
211
|
+
<None Include="packages.config" />
|
|
212
|
+
</ItemGroup>
|
|
213
|
+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
214
|
+
</Project>
|
|
215
|
+
""",
|
|
216
|
+
expectedPackagesConfigContents: """
|
|
217
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
218
|
+
<packages>
|
|
219
|
+
<package id="jQuery" version="3.7.1" targetFramework="net45" />
|
|
220
|
+
</packages>
|
|
221
|
+
""");
|
|
222
|
+
}
|
|
223
|
+
|
|
124
224
|
[Fact]
|
|
125
225
|
public async Task UpdateSingleDependencyInPackagesConfigButNotToLatest()
|
|
126
226
|
{
|
|
@@ -21,6 +21,7 @@ module Dependabot
|
|
|
21
21
|
def parse
|
|
22
22
|
workspace_path = project_files.first&.directory
|
|
23
23
|
return [] unless workspace_path
|
|
24
|
+
return [] unless repo_contents_path
|
|
24
25
|
|
|
25
26
|
# `workspace_path` is the only unique value here so we use it as the cache key
|
|
26
27
|
cache = T.let(CacheManager.cache("file_parser.parse"), T::Hash[String, T::Array[Dependabot::Dependency]])
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-nuget
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.255.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-05-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dependabot-common
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - '='
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
19
|
+
version: 0.255.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - '='
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
26
|
+
version: 0.255.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rubyzip
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -184,6 +184,20 @@ dependencies:
|
|
|
184
184
|
- - "~>"
|
|
185
185
|
- !ruby/object:Gem::Version
|
|
186
186
|
version: 0.8.1
|
|
187
|
+
- !ruby/object:Gem::Dependency
|
|
188
|
+
name: simplecov
|
|
189
|
+
requirement: !ruby/object:Gem::Requirement
|
|
190
|
+
requirements:
|
|
191
|
+
- - "~>"
|
|
192
|
+
- !ruby/object:Gem::Version
|
|
193
|
+
version: 0.22.0
|
|
194
|
+
type: :development
|
|
195
|
+
prerelease: false
|
|
196
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
197
|
+
requirements:
|
|
198
|
+
- - "~>"
|
|
199
|
+
- !ruby/object:Gem::Version
|
|
200
|
+
version: 0.22.0
|
|
187
201
|
- !ruby/object:Gem::Dependency
|
|
188
202
|
name: turbo_tests
|
|
189
203
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -270,6 +284,7 @@ files:
|
|
|
270
284
|
- helpers/lib/NuGetUpdater/NuGetProjects/NuGet.LibraryModel/NuGet.LibraryModel.csproj
|
|
271
285
|
- helpers/lib/NuGetUpdater/NuGetProjects/NuGet.PackageManagement/NuGet.PackageManagement.csproj
|
|
272
286
|
- helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj
|
|
287
|
+
- helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/PackageFolderReader.cs
|
|
273
288
|
- helpers/lib/NuGetUpdater/NuGetProjects/NuGet.ProjectModel/NuGet.ProjectModel.csproj
|
|
274
289
|
- helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Protocol/NuGet.Protocol.csproj
|
|
275
290
|
- helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Resolver/NuGet.Resolver.csproj
|
|
@@ -404,7 +419,7 @@ licenses:
|
|
|
404
419
|
- Nonstandard
|
|
405
420
|
metadata:
|
|
406
421
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
407
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
422
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.255.0
|
|
408
423
|
post_install_message:
|
|
409
424
|
rdoc_options: []
|
|
410
425
|
require_paths:
|
|
@@ -420,7 +435,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
420
435
|
- !ruby/object:Gem::Version
|
|
421
436
|
version: 3.1.0
|
|
422
437
|
requirements: []
|
|
423
|
-
rubygems_version: 3.
|
|
438
|
+
rubygems_version: 3.5.9
|
|
424
439
|
signing_key:
|
|
425
440
|
specification_version: 4
|
|
426
441
|
summary: Provides Dependabot support for .NET (NuGet)
|