dependabot-nuget 0.242.1 → 0.243.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/.editorconfig +37 -28
- data/helpers/lib/NuGetUpdater/.gitignore +1 -0
- data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.CommandLine/AssemblyMetadataExtractor.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +178 -176
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +5 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/FrameworkCompatibilityService.cs +10 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/SupportedFrameworks.cs +16 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +18 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectResolver.cs +7 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +13 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +9 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +32 -16
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +42 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +32 -13
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/WebApplicationTargetsConditionPatcher.cs +47 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/XmlFilePreAndPostProcessor.cs +55 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +12 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +49 -42
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +16 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +6 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/XmlExtensions.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/ProjectBuildFileTests.cs +18 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/FrameworkChecker/CompatibilityCheckerFacts.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/FrameworkChecker/FrameworkCompatibilityServiceFacts.cs +7 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/FrameworkChecker/SupportedFrameworkFacts.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +9 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorker.DirsProj.cs +81 -80
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +22 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +140 -104
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +25 -25
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +8 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +198 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +401 -399
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/JsonHelperTests.cs +17 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +111 -42
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterTests.cs +103 -87
- data/lib/dependabot/nuget/file_parser/project_file_parser.rb +45 -19
- data/lib/dependabot/nuget/file_parser.rb +21 -3
- data/lib/dependabot/nuget/file_updater.rb +42 -6
- data/lib/dependabot/nuget/native_helpers.rb +27 -8
- data/lib/dependabot/nuget/nuget_client.rb +66 -23
- data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +7 -3
- data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +63 -59
- data/lib/dependabot/nuget/update_checker/dependency_finder.rb +2 -2
- data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +1 -1
- data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +22 -17
- data/lib/dependabot/nuget/update_checker/repository_finder.rb +292 -270
- data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +11 -13
- data/lib/dependabot/nuget/update_checker/tfm_finder.rb +80 -82
- data/lib/dependabot/nuget/update_checker/version_finder.rb +3 -2
- data/lib/dependabot/nuget/version.rb +18 -7
- data/lib/dependabot/nuget.rb +0 -2
- metadata +7 -5
@@ -5,7 +5,7 @@ using System.Threading.Tasks;
|
|
5
5
|
|
6
6
|
namespace NuGetUpdater.Core;
|
7
7
|
|
8
|
-
public
|
8
|
+
public class UpdaterWorker
|
9
9
|
{
|
10
10
|
private readonly Logger _logger;
|
11
11
|
private readonly HashSet<string> _processedGlobalJsonPaths = new(StringComparer.OrdinalIgnoreCase);
|
@@ -15,33 +15,33 @@ public partial class UpdaterWorker
|
|
15
15
|
_logger = logger;
|
16
16
|
}
|
17
17
|
|
18
|
-
public async Task RunAsync(string repoRootPath, string
|
18
|
+
public async Task RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTransitive)
|
19
19
|
{
|
20
20
|
MSBuildHelper.RegisterMSBuild();
|
21
21
|
|
22
|
-
if (!Path.IsPathRooted(
|
22
|
+
if (!Path.IsPathRooted(workspacePath) || !File.Exists(workspacePath))
|
23
23
|
{
|
24
|
-
|
24
|
+
workspacePath = Path.GetFullPath(Path.Join(repoRootPath, workspacePath));
|
25
25
|
}
|
26
26
|
|
27
27
|
if (!isTransitive)
|
28
28
|
{
|
29
|
-
await DotNetToolsJsonUpdater.UpdateDependencyAsync(repoRootPath, dependencyName, previousDependencyVersion, newDependencyVersion, _logger);
|
29
|
+
await DotNetToolsJsonUpdater.UpdateDependencyAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, _logger);
|
30
30
|
}
|
31
31
|
|
32
|
-
var extension = Path.GetExtension(
|
32
|
+
var extension = Path.GetExtension(workspacePath).ToLowerInvariant();
|
33
33
|
switch (extension)
|
34
34
|
{
|
35
35
|
case ".sln":
|
36
|
-
await RunForSolutionAsync(repoRootPath,
|
36
|
+
await RunForSolutionAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
37
37
|
break;
|
38
38
|
case ".proj":
|
39
|
-
await RunForProjFileAsync(repoRootPath,
|
39
|
+
await RunForProjFileAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
40
40
|
break;
|
41
41
|
case ".csproj":
|
42
42
|
case ".fsproj":
|
43
43
|
case ".vbproj":
|
44
|
-
await RunForProjectAsync(repoRootPath,
|
44
|
+
await RunForProjectAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
45
45
|
break;
|
46
46
|
default:
|
47
47
|
_logger.Log($"File extension [{extension}] is not supported.");
|
@@ -51,7 +51,13 @@ public partial class UpdaterWorker
|
|
51
51
|
_processedGlobalJsonPaths.Clear();
|
52
52
|
}
|
53
53
|
|
54
|
-
private async Task RunForSolutionAsync(
|
54
|
+
private async Task RunForSolutionAsync(
|
55
|
+
string repoRootPath,
|
56
|
+
string solutionPath,
|
57
|
+
string dependencyName,
|
58
|
+
string previousDependencyVersion,
|
59
|
+
string newDependencyVersion,
|
60
|
+
bool isTransitive)
|
55
61
|
{
|
56
62
|
_logger.Log($"Running for solution [{Path.GetRelativePath(repoRootPath, solutionPath)}]");
|
57
63
|
var projectPaths = MSBuildHelper.GetProjectPathsFromSolution(solutionPath);
|
@@ -61,7 +67,13 @@ public partial class UpdaterWorker
|
|
61
67
|
}
|
62
68
|
}
|
63
69
|
|
64
|
-
private async Task RunForProjFileAsync(
|
70
|
+
private async Task RunForProjFileAsync(
|
71
|
+
string repoRootPath,
|
72
|
+
string projFilePath,
|
73
|
+
string dependencyName,
|
74
|
+
string previousDependencyVersion,
|
75
|
+
string newDependencyVersion,
|
76
|
+
bool isTransitive)
|
65
77
|
{
|
66
78
|
_logger.Log($"Running for proj file [{Path.GetRelativePath(repoRootPath, projFilePath)}]");
|
67
79
|
if (!File.Exists(projFilePath))
|
@@ -69,6 +81,7 @@ public partial class UpdaterWorker
|
|
69
81
|
_logger.Log($"File [{projFilePath}] does not exist.");
|
70
82
|
return;
|
71
83
|
}
|
84
|
+
|
72
85
|
var projectFilePaths = MSBuildHelper.GetProjectPathsFromProject(projFilePath);
|
73
86
|
foreach (var projectFullPath in projectFilePaths)
|
74
87
|
{
|
@@ -80,12 +93,18 @@ public partial class UpdaterWorker
|
|
80
93
|
}
|
81
94
|
}
|
82
95
|
|
83
|
-
private async Task RunForProjectAsync(
|
96
|
+
private async Task RunForProjectAsync(
|
97
|
+
string repoRootPath,
|
98
|
+
string projectPath,
|
99
|
+
string dependencyName,
|
100
|
+
string previousDependencyVersion,
|
101
|
+
string newDependencyVersion,
|
102
|
+
bool isTransitive)
|
84
103
|
{
|
85
104
|
_logger.Log($"Running for project [{projectPath}]");
|
86
105
|
|
87
106
|
if (!isTransitive
|
88
|
-
&& MSBuildHelper.GetGlobalJsonPath(repoRootPath, projectPath) is
|
107
|
+
&& MSBuildHelper.GetGlobalJsonPath(repoRootPath, projectPath) is { } globalJsonPath
|
89
108
|
&& !_processedGlobalJsonPaths.Contains(globalJsonPath))
|
90
109
|
{
|
91
110
|
_processedGlobalJsonPaths.Add(globalJsonPath);
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/WebApplicationTargetsConditionPatcher.cs
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
using System;
|
2
|
+
using System.IO;
|
3
|
+
using System.Linq;
|
4
|
+
|
5
|
+
using Microsoft.Language.Xml;
|
6
|
+
|
7
|
+
namespace NuGetUpdater.Core.Updater
|
8
|
+
{
|
9
|
+
internal class WebApplicationTargetsConditionPatcher : IDisposable
|
10
|
+
{
|
11
|
+
private string? _capturedCondition;
|
12
|
+
private readonly XmlFilePreAndPostProcessor _processor;
|
13
|
+
|
14
|
+
public WebApplicationTargetsConditionPatcher(string projectFilePath)
|
15
|
+
{
|
16
|
+
_processor = new XmlFilePreAndPostProcessor(
|
17
|
+
getContent: () => File.ReadAllText(projectFilePath),
|
18
|
+
setContent: s => File.WriteAllText(projectFilePath, s),
|
19
|
+
nodeFinder: doc => doc.Descendants()
|
20
|
+
.FirstOrDefault(e => e.Name == "Import" && e.GetAttributeValue("Project") == @"$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets")
|
21
|
+
as XmlNodeSyntax,
|
22
|
+
preProcessor: n =>
|
23
|
+
{
|
24
|
+
var element = (IXmlElementSyntax)n;
|
25
|
+
_capturedCondition = element.GetAttributeValue("Condition");
|
26
|
+
return (XmlNodeSyntax)element.RemoveAttributeByName("Condition").WithAttribute("Condition", "false");
|
27
|
+
},
|
28
|
+
postProcessor: n =>
|
29
|
+
{
|
30
|
+
var element = (IXmlElementSyntax)n;
|
31
|
+
var newElement = element.RemoveAttributeByName("Condition");
|
32
|
+
if (_capturedCondition is not null)
|
33
|
+
{
|
34
|
+
newElement = newElement.WithAttribute("Condition", _capturedCondition);
|
35
|
+
}
|
36
|
+
|
37
|
+
return (XmlNodeSyntax)newElement;
|
38
|
+
}
|
39
|
+
);
|
40
|
+
}
|
41
|
+
|
42
|
+
public void Dispose()
|
43
|
+
{
|
44
|
+
_processor.Dispose();
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
using System;
|
2
|
+
|
3
|
+
using Microsoft.Language.Xml;
|
4
|
+
|
5
|
+
namespace NuGetUpdater.Core.Updater
|
6
|
+
{
|
7
|
+
internal class XmlFilePreAndPostProcessor : IDisposable
|
8
|
+
{
|
9
|
+
public Func<string> GetContent { get; }
|
10
|
+
public Action<string> SetContent { get; }
|
11
|
+
public Func<XmlDocumentSyntax, XmlNodeSyntax?> NodeFinder { get; }
|
12
|
+
public Func<XmlNodeSyntax, XmlNodeSyntax> PreProcessor { get; }
|
13
|
+
public Func<XmlNodeSyntax, XmlNodeSyntax> PostProcessor { get; }
|
14
|
+
|
15
|
+
public XmlFilePreAndPostProcessor(Func<string> getContent, Action<string> setContent, Func<XmlDocumentSyntax, XmlNodeSyntax?> nodeFinder, Func<XmlNodeSyntax, XmlNodeSyntax> preProcessor, Func<XmlNodeSyntax, XmlNodeSyntax> postProcessor)
|
16
|
+
{
|
17
|
+
GetContent = getContent;
|
18
|
+
SetContent = setContent;
|
19
|
+
NodeFinder = nodeFinder;
|
20
|
+
PreProcessor = preProcessor;
|
21
|
+
PostProcessor = postProcessor;
|
22
|
+
PreProcess();
|
23
|
+
}
|
24
|
+
|
25
|
+
public void Dispose()
|
26
|
+
{
|
27
|
+
PostProcess();
|
28
|
+
}
|
29
|
+
|
30
|
+
private void PreProcess() => RunProcessor(PreProcessor);
|
31
|
+
|
32
|
+
private void PostProcess() => RunProcessor(PostProcessor);
|
33
|
+
|
34
|
+
private void RunProcessor(Func<XmlNodeSyntax, XmlNodeSyntax> processor)
|
35
|
+
{
|
36
|
+
var content = GetContent();
|
37
|
+
var xml = Parser.ParseText(content);
|
38
|
+
if (xml is null)
|
39
|
+
{
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
|
43
|
+
var node = NodeFinder(xml);
|
44
|
+
if (node is null)
|
45
|
+
{
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
|
49
|
+
var replacementElement = processor(node);
|
50
|
+
var replacementXml = xml.ReplaceNode(node, replacementElement);
|
51
|
+
var replacementString = replacementXml.ToFullString();
|
52
|
+
SetContent(replacementString);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
@@ -4,6 +4,7 @@ using System.IO;
|
|
4
4
|
using System.Linq;
|
5
5
|
using System.Runtime.InteropServices;
|
6
6
|
using System.Text;
|
7
|
+
using System.Text.Encodings.Web;
|
7
8
|
using System.Text.Json;
|
8
9
|
using System.Text.Json.Nodes;
|
9
10
|
|
@@ -11,7 +12,7 @@ namespace NuGetUpdater.Core.Utilities
|
|
11
12
|
{
|
12
13
|
internal static class JsonHelper
|
13
14
|
{
|
14
|
-
public static JsonDocumentOptions DocumentOptions { get; } = new JsonDocumentOptions
|
15
|
+
public static JsonDocumentOptions DocumentOptions { get; } = new JsonDocumentOptions
|
15
16
|
{
|
16
17
|
CommentHandling = JsonCommentHandling.Skip,
|
17
18
|
};
|
@@ -24,16 +25,16 @@ namespace NuGetUpdater.Core.Utilities
|
|
24
25
|
|
25
26
|
public static string UpdateJsonProperty(string json, string[] propertyPath, string newValue, StringComparison comparisonType = StringComparison.Ordinal)
|
26
27
|
{
|
27
|
-
var readerOptions = new JsonReaderOptions
|
28
|
+
var readerOptions = new JsonReaderOptions
|
28
29
|
{
|
29
30
|
CommentHandling = JsonCommentHandling.Allow,
|
30
31
|
};
|
31
32
|
var bytes = Encoding.UTF8.GetBytes(json);
|
32
33
|
var reader = new Utf8JsonReader(bytes, readerOptions);
|
33
34
|
using var ms = new MemoryStream();
|
34
|
-
var writerOptions = new JsonWriterOptions
|
35
|
+
var writerOptions = new JsonWriterOptions
|
35
36
|
{
|
36
|
-
Encoder =
|
37
|
+
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
37
38
|
Indented = true,
|
38
39
|
};
|
39
40
|
var writer = new Utf8JsonWriter(ms, writerOptions);
|
@@ -70,6 +71,7 @@ namespace NuGetUpdater.Core.Utilities
|
|
70
71
|
// let the default block comment writer handle it
|
71
72
|
writer.WriteCommentValue(reader.GetComment());
|
72
73
|
}
|
74
|
+
|
73
75
|
break;
|
74
76
|
case JsonTokenType.EndArray:
|
75
77
|
writer.WriteEndArray();
|
@@ -126,7 +128,7 @@ namespace NuGetUpdater.Core.Utilities
|
|
126
128
|
{
|
127
129
|
currentPath.RemoveAt(currentPath.Count - 1);
|
128
130
|
}
|
129
|
-
|
131
|
+
|
130
132
|
currentPath[pathDepth] = pathValue;
|
131
133
|
if (IsPathMatch(currentPath, propertyPath, comparisonType))
|
132
134
|
{
|
@@ -187,18 +189,19 @@ namespace NuGetUpdater.Core.Utilities
|
|
187
189
|
// quit at newline, modulo some special cases
|
188
190
|
if (c == '\n')
|
189
191
|
{
|
190
|
-
// check for
|
192
|
+
// check for preceding CR
|
191
193
|
if (IsPreceedingCharacterEqual(originalJson, prefixStart, '\r'))
|
192
194
|
{
|
193
195
|
prefixStart--;
|
194
196
|
}
|
195
197
|
}
|
196
198
|
|
197
|
-
// check for
|
199
|
+
// check for preceding comma
|
198
200
|
if (IsPreceedingCharacterEqual(originalJson, prefixStart, ','))
|
199
201
|
{
|
200
202
|
prefixStart--;
|
201
203
|
}
|
204
|
+
|
202
205
|
goto done;
|
203
206
|
default:
|
204
207
|
// found regular character; move forward one and quit
|
@@ -215,8 +218,8 @@ namespace NuGetUpdater.Core.Utilities
|
|
215
218
|
private static bool IsPreceedingCharacterEqual(string originalText, int currentIndex, char expectedCharacter)
|
216
219
|
{
|
217
220
|
return currentIndex > 0
|
218
|
-
|
219
|
-
|
221
|
+
&& currentIndex < originalText.Length
|
222
|
+
&& originalText[currentIndex - 1] == expectedCharacter;
|
220
223
|
}
|
221
224
|
}
|
222
225
|
}
|
@@ -145,11 +145,11 @@ internal static partial class MSBuildHelper
|
|
145
145
|
var projectRoot = CreateProjectRootElement(buildFile);
|
146
146
|
|
147
147
|
foreach (var packageItem in projectRoot.Items
|
148
|
-
|
148
|
+
.Where(i => (i.ItemType == "PackageReference" || i.ItemType == "GlobalPackageReference")))
|
149
149
|
{
|
150
150
|
var versionSpecification = packageItem.Metadata.FirstOrDefault(m => m.Name.Equals("Version", StringComparison.OrdinalIgnoreCase))?.Value
|
151
|
-
|
152
|
-
|
151
|
+
?? packageItem.Metadata.FirstOrDefault(m => m.Name.Equals("VersionOverride", StringComparison.OrdinalIgnoreCase))?.Value
|
152
|
+
?? string.Empty;
|
153
153
|
foreach (var attributeValue in new[] { packageItem.Include, packageItem.Update })
|
154
154
|
{
|
155
155
|
if (!string.IsNullOrWhiteSpace(attributeValue))
|
@@ -175,10 +175,10 @@ internal static partial class MSBuildHelper
|
|
175
175
|
}
|
176
176
|
|
177
177
|
foreach (var packageItem in projectRoot.Items
|
178
|
-
|
178
|
+
.Where(i => i.ItemType == "PackageVersion" && !string.IsNullOrEmpty(i.Include)))
|
179
179
|
{
|
180
180
|
packageVersionInfo[packageItem.Include] = packageItem.Metadata.FirstOrDefault(m => m.Name.Equals("Version", StringComparison.OrdinalIgnoreCase))?.Value
|
181
|
-
|
181
|
+
?? string.Empty;
|
182
182
|
}
|
183
183
|
|
184
184
|
foreach (var property in projectRoot.Properties)
|
@@ -187,7 +187,8 @@ internal static partial class MSBuildHelper
|
|
187
187
|
// going to be used, and even then we might not be able to update it. As a best guess, we'll simply
|
188
188
|
// skip any property that has a condition _or_ where the condition is checking for an empty string.
|
189
189
|
var hasEmptyCondition = string.IsNullOrEmpty(property.Condition);
|
190
|
-
var conditionIsCheckingForEmptyString = string.Equals(property.Condition, $"$({property.Name}) == ''", StringComparison.OrdinalIgnoreCase)
|
190
|
+
var conditionIsCheckingForEmptyString = string.Equals(property.Condition, $"$({property.Name}) == ''", StringComparison.OrdinalIgnoreCase) ||
|
191
|
+
string.Equals(property.Condition, $"'$({property.Name})' == ''", StringComparison.OrdinalIgnoreCase);
|
191
192
|
if (hasEmptyCondition || conditionIsCheckingForEmptyString)
|
192
193
|
{
|
193
194
|
propertyInfo[property.Name] = property.Value;
|
@@ -285,7 +286,12 @@ internal static partial class MSBuildHelper
|
|
285
286
|
return projectRoot;
|
286
287
|
}
|
287
288
|
|
288
|
-
private static async Task<string> CreateTempProjectAsync(
|
289
|
+
private static async Task<string> CreateTempProjectAsync(
|
290
|
+
DirectoryInfo tempDir,
|
291
|
+
string repoRoot,
|
292
|
+
string projectPath,
|
293
|
+
string targetFramework,
|
294
|
+
IReadOnlyCollection<Dependency> packages)
|
289
295
|
{
|
290
296
|
var projectDirectory = Path.GetDirectoryName(projectPath);
|
291
297
|
projectDirectory ??= repoRoot;
|
@@ -299,39 +305,40 @@ internal static partial class MSBuildHelper
|
|
299
305
|
var packageReferences = string.Join(
|
300
306
|
Environment.NewLine,
|
301
307
|
packages
|
302
|
-
|
308
|
+
// empty `Version` attributes will cause the temporary project to not build
|
309
|
+
.Where(p => !string.IsNullOrWhiteSpace(p.Version))
|
303
310
|
// If all PackageReferences for a package are update-only mark it as such, otherwise it can cause package incoherence errors which do not exist in the repo.
|
304
311
|
.Select(static p => $"<PackageReference {(p.IsUpdate ? "Update" : "Include")}=\"{p.Name}\" Version=\"[{p.Version}]\" />"));
|
305
312
|
|
306
313
|
var projectContents = $"""
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
314
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
315
|
+
<PropertyGroup>
|
316
|
+
<TargetFramework>{targetFramework}</TargetFramework>
|
317
|
+
<GenerateDependencyFile>true</GenerateDependencyFile>
|
318
|
+
<RunAnalyzers>false</RunAnalyzers>
|
319
|
+
</PropertyGroup>
|
320
|
+
<ItemGroup>
|
321
|
+
{packageReferences}
|
322
|
+
</ItemGroup>
|
323
|
+
<Target Name="_CollectDependencies" DependsOnTargets="GenerateBuildDependencyFile">
|
324
|
+
<ItemGroup>
|
325
|
+
<_NuGetPackageData Include="@(NativeCopyLocalItems)" />
|
326
|
+
<_NuGetPackageData Include="@(ResourceCopyLocalItems)" />
|
327
|
+
<_NuGetPackageData Include="@(RuntimeCopyLocalItems)" />
|
328
|
+
<_NuGetPackageData Include="@(ResolvedAnalyzers)" />
|
329
|
+
<_NuGetPackageData Include="@(_PackageDependenciesDesignTime)">
|
330
|
+
<NuGetPackageId>%(_PackageDependenciesDesignTime.Name)</NuGetPackageId>
|
331
|
+
<NuGetPackageVersion>%(_PackageDependenciesDesignTime.Version)</NuGetPackageVersion>
|
332
|
+
</_NuGetPackageData>
|
333
|
+
</ItemGroup>
|
334
|
+
</Target>
|
335
|
+
<Target Name="_ReportDependencies" DependsOnTargets="_CollectDependencies">
|
336
|
+
<Message Text="NuGetData::Package=%(_NuGetPackageData.NuGetPackageId), Version=%(_NuGetPackageData.NuGetPackageVersion)"
|
337
|
+
Condition="'%(_NuGetPackageData.NuGetPackageId)' != '' AND '%(_NuGetPackageData.NuGetPackageVersion)' != ''"
|
338
|
+
Importance="High" />
|
339
|
+
</Target>
|
340
|
+
</Project>
|
341
|
+
""";
|
335
342
|
var tempProjectPath = Path.Combine(tempDir.FullName, "Project.csproj");
|
336
343
|
await File.WriteAllTextAsync(tempProjectPath, projectContents);
|
337
344
|
|
@@ -344,7 +351,7 @@ internal static partial class MSBuildHelper
|
|
344
351
|
}
|
345
352
|
|
346
353
|
internal static async Task<Dependency[]> GetAllPackageDependenciesAsync(
|
347
|
-
string repoRoot, string projectPath, string targetFramework, Dependency
|
354
|
+
string repoRoot, string projectPath, string targetFramework, IReadOnlyCollection<Dependency> packages, Logger? logger = null)
|
348
355
|
{
|
349
356
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-resolution_");
|
350
357
|
try
|
@@ -368,7 +375,7 @@ internal static partial class MSBuildHelper
|
|
368
375
|
else
|
369
376
|
{
|
370
377
|
logger?.Log($"dotnet build in {nameof(GetAllPackageDependenciesAsync)} failed. STDOUT: {stdout} STDERR: {stderr}");
|
371
|
-
return
|
378
|
+
return [];
|
372
379
|
}
|
373
380
|
}
|
374
381
|
finally
|
@@ -390,7 +397,7 @@ internal static partial class MSBuildHelper
|
|
390
397
|
|
391
398
|
internal static async Task<ImmutableArray<ProjectBuildFile>> LoadBuildFiles(string repoRootPath, string projectPath)
|
392
399
|
{
|
393
|
-
var buildFileList = new List<string>
|
400
|
+
var buildFileList = new List<string>
|
394
401
|
{
|
395
402
|
projectPath.NormalizePathToUnix() // always include the starting project
|
396
403
|
};
|
@@ -409,12 +416,12 @@ internal static partial class MSBuildHelper
|
|
409
416
|
// create a safe version with only certain top-level keys
|
410
417
|
var globalJsonContent = await File.ReadAllTextAsync(safeGlobalJsonName);
|
411
418
|
var json = JsonHelper.ParseNode(globalJsonContent);
|
412
|
-
var sdks = json["msbuild-sdks"];
|
419
|
+
var sdks = json?["msbuild-sdks"];
|
413
420
|
if (sdks is not null)
|
414
421
|
{
|
415
422
|
var newObject = new Dictionary<string, object>()
|
416
423
|
{
|
417
|
-
|
424
|
+
["msbuild-sdks"] = sdks,
|
418
425
|
};
|
419
426
|
var newContent = JsonSerializer.Serialize(newObject);
|
420
427
|
await File.WriteAllTextAsync(globalJsonPath, newContent);
|
@@ -426,7 +433,7 @@ internal static partial class MSBuildHelper
|
|
426
433
|
// load the project even if it imports a file that doesn't exist (e.g. a file that's generated at restore
|
427
434
|
// or build time).
|
428
435
|
using var projectCollection = new ProjectCollection(); // do this in a one-off instance and don't pollute the global collection
|
429
|
-
var project = Project.FromFile(projectPath, new ProjectOptions
|
436
|
+
var project = Project.FromFile(projectPath, new ProjectOptions
|
430
437
|
{
|
431
438
|
LoadSettings = ProjectLoadSettings.IgnoreMissingImports,
|
432
439
|
ProjectCollection = projectCollection,
|
@@ -10,6 +10,7 @@ internal static class PathHelper
|
|
10
10
|
{
|
11
11
|
MatchCasing = MatchCasing.CaseInsensitive,
|
12
12
|
};
|
13
|
+
|
13
14
|
private static readonly EnumerationOptions _caseSensitiveEnumerationOptions = new()
|
14
15
|
{
|
15
16
|
MatchCasing = MatchCasing.CaseSensitive,
|
@@ -39,6 +40,11 @@ internal static class PathHelper
|
|
39
40
|
/// <returns>The path of the found file or null.</returns>
|
40
41
|
public static string? GetFileInDirectoryOrParent(string initialPath, string rootPath, string fileName, bool caseSensitive = true)
|
41
42
|
{
|
43
|
+
if (File.Exists(initialPath))
|
44
|
+
{
|
45
|
+
initialPath = Path.GetDirectoryName(initialPath)!;
|
46
|
+
}
|
47
|
+
|
42
48
|
var candidatePaths = new List<string>();
|
43
49
|
var rootDirectory = new DirectoryInfo(rootPath);
|
44
50
|
var candidateDirectory = new DirectoryInfo(initialPath);
|
@@ -56,11 +62,18 @@ internal static class PathHelper
|
|
56
62
|
|
57
63
|
foreach (var candidatePath in candidatePaths)
|
58
64
|
{
|
59
|
-
|
65
|
+
try
|
66
|
+
{
|
67
|
+
var files = Directory.EnumerateFiles(candidatePath, fileName, caseSensitive ? _caseSensitiveEnumerationOptions : _caseInsensitiveEnumerationOptions);
|
60
68
|
|
61
|
-
|
69
|
+
if (files.Any())
|
70
|
+
{
|
71
|
+
return files.First();
|
72
|
+
}
|
73
|
+
}
|
74
|
+
catch (DirectoryNotFoundException)
|
62
75
|
{
|
63
|
-
|
76
|
+
// When searching for a file in a directory that doesn't exist, Directory.EnumerateFiles throws a DirectoryNotFoundException.
|
64
77
|
}
|
65
78
|
}
|
66
79
|
|
@@ -45,14 +45,14 @@ public static class ProcessEx
|
|
45
45
|
// than enter right back into the Process type and start a wait which isn't guaranteed to be safe.
|
46
46
|
Task.Run(() =>
|
47
47
|
{
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
redirectInitiated.Wait();
|
49
|
+
redirectInitiated.Dispose();
|
50
|
+
redirectInitiated = null;
|
51
51
|
|
52
|
-
|
52
|
+
process.WaitForExit();
|
53
53
|
|
54
|
-
|
55
|
-
|
54
|
+
tcs.TrySetResult((process.ExitCode, stdout.ToString(), stderr.ToString()));
|
55
|
+
process.Dispose();
|
56
56
|
});
|
57
57
|
};
|
58
58
|
|
@@ -30,6 +30,17 @@ public static class XmlExtensions
|
|
30
30
|
return element.Attributes.FirstOrDefault(a => a.Name.Equals(name, comparisonType));
|
31
31
|
}
|
32
32
|
|
33
|
+
public static IXmlElementSyntax RemoveAttributeByName(this IXmlElementSyntax element, string attributeName, StringComparison comparisonType = StringComparison.Ordinal)
|
34
|
+
{
|
35
|
+
var attribute = element.GetAttribute(attributeName, comparisonType);
|
36
|
+
if (attribute is null)
|
37
|
+
{
|
38
|
+
return element;
|
39
|
+
}
|
40
|
+
|
41
|
+
return element.RemoveAttribute(attribute);
|
42
|
+
}
|
43
|
+
|
33
44
|
public static string GetAttributeValue(this IXmlElementSyntax element, string name, StringComparison comparisonType)
|
34
45
|
{
|
35
46
|
return element.Attributes.First(a => a.Name.Equals(name, comparisonType)).Value;
|
@@ -133,17 +133,26 @@ public class ProjectBuildFileTests
|
|
133
133
|
}
|
134
134
|
|
135
135
|
[Theory]
|
136
|
-
|
137
|
-
|
138
|
-
|
136
|
+
// no change made
|
137
|
+
[InlineData(
|
138
|
+
// language=csproj
|
139
|
+
@"<Project><ItemGroup><Reference><HintPath>path\to\file.dll</HintPath></Reference></ItemGroup></Project>",
|
140
|
+
// language=csproj
|
141
|
+
@"<Project><ItemGroup><Reference><HintPath>path\to\file.dll</HintPath></Reference></ItemGroup></Project>"
|
139
142
|
)]
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
+
// change from `/` to `\`
|
144
|
+
[InlineData(
|
145
|
+
// language=csproj
|
146
|
+
"<Project><ItemGroup><Reference><HintPath>path/to/file.dll</HintPath></Reference></ItemGroup></Project>",
|
147
|
+
// language=csproj
|
148
|
+
@"<Project><ItemGroup><Reference><HintPath>path\to\file.dll</HintPath></Reference></ItemGroup></Project>"
|
143
149
|
)]
|
144
|
-
|
145
|
-
|
146
|
-
|
150
|
+
// multiple changes made
|
151
|
+
[InlineData(
|
152
|
+
// language=csproj
|
153
|
+
"<Project><ItemGroup><Reference><HintPath>path1/to1/file1.dll</HintPath></Reference><Reference><HintPath>path2/to2/file2.dll</HintPath></Reference></ItemGroup></Project>",
|
154
|
+
// language=csproj
|
155
|
+
@"<Project><ItemGroup><Reference><HintPath>path1\to1\file1.dll</HintPath></Reference><Reference><HintPath>path2\to2\file2.dll</HintPath></Reference></ItemGroup></Project>"
|
147
156
|
)]
|
148
157
|
public void ReferenceHintPathsCanBeNormalized(string originalXml, string expectedXml)
|
149
158
|
{
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/FrameworkChecker/CompatibilityCheckerFacts.cs
CHANGED
@@ -20,7 +20,7 @@ public class CompatibilityCheckerFacts
|
|
20
20
|
[InlineData("net4.8", "netstandard1.3")]
|
21
21
|
public void PackageContainsCompatibleFramework(string projectTfm, string packageTfm)
|
22
22
|
{
|
23
|
-
var result = CompatibilityChecker.IsCompatible(
|
23
|
+
var result = CompatibilityChecker.IsCompatible([projectTfm], [packageTfm], new Logger(verbose: true));
|
24
24
|
|
25
25
|
Assert.True(result);
|
26
26
|
}
|
@@ -37,7 +37,7 @@ public class CompatibilityCheckerFacts
|
|
37
37
|
[InlineData("net7.0", "net48")]
|
38
38
|
public void PackageContainsIncompatibleFramework(string projectTfm, string packageTfm)
|
39
39
|
{
|
40
|
-
var result = CompatibilityChecker.IsCompatible(
|
40
|
+
var result = CompatibilityChecker.IsCompatible([projectTfm], [packageTfm], new Logger(verbose: true));
|
41
41
|
|
42
42
|
Assert.False(result);
|
43
43
|
}
|