dependabot-nuget 0.254.0 → 0.255.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|