dependabot-nuget 0.370.0 → 0.371.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +14 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +31 -16
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/GetProperty.targets +9 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/XmlFileWriter.cs +41 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +55 -51
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +62 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +0 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +96 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +0 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +2 -49
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +0 -77
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +0 -58
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/EndToEndTests.cs +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +0 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/FileWriterTestsBase.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/XmlFileWriterTests.cs +64 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/XmlFileWriterTests_GetDocumentIndentationCharactersTests.cs +120 -0
- metadata +6 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Property.cs +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1d7916c7661919bee90276b975fe46847c6289fa45de9cc7ebe2d1dc12799685
|
|
4
|
+
data.tar.gz: c05e7678dab3e9baa32a75a38f535dca02fd692c5562e7898756c2ffc2acbfee
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fc5b580e70c49c5a2b0c13887cac6140be5e4bf642e4d6c4e3f43455b57cc0599c76cb6170f75ef949f76aab23fdefa66488f16cb948aa15fa7871c593ebe935
|
|
7
|
+
data.tar.gz: 9301c2888824bac12674380195add8516a43b247205329d2fb8524c9e2bfa5e03734c0ddd30afe91acf0f7fb3851181563b5c70b81a3e72ff4dbc70d17eb5292
|
|
@@ -318,7 +318,20 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
|
318
318
|
private async Task<ImmutableArray<ProjectDiscoveryResult>> RunForProjectPathsAsync(string repoRootPath, string workspacePath, IEnumerable<string> projectPaths)
|
|
319
319
|
{
|
|
320
320
|
var normalizedProjectPaths = projectPaths.SelectMany(p => PathHelper.ResolveCaseInsensitivePathsInsideRepoRoot(p, repoRootPath) ?? []).Distinct().ToImmutableArray();
|
|
321
|
-
|
|
321
|
+
|
|
322
|
+
// Find all MSBuild files that may contain special imports
|
|
323
|
+
var enumerationOptions = new EnumerationOptions()
|
|
324
|
+
{
|
|
325
|
+
RecurseSubdirectories = true,
|
|
326
|
+
IgnoreInaccessible = true,
|
|
327
|
+
AttributesToSkip = FileAttributes.ReparsePoint,
|
|
328
|
+
};
|
|
329
|
+
var msbuildExtensions = new[] { ".props", ".targets", ".proj", ".csproj", ".vbproj", ".fsproj" };
|
|
330
|
+
var filesToPatch = Directory.GetFiles(repoRootPath, "*.*", enumerationOptions)
|
|
331
|
+
.Where(f => msbuildExtensions.Contains(Path.GetExtension(f), StringComparer.OrdinalIgnoreCase))
|
|
332
|
+
.ToImmutableArray();
|
|
333
|
+
|
|
334
|
+
var disposables = filesToPatch.Select(p => new SpecialImportsConditionPatcher(p)).ToImmutableArray();
|
|
322
335
|
var results = new Dictionary<string, ProjectDiscoveryResult>(StringComparer.Ordinal);
|
|
323
336
|
|
|
324
337
|
try
|
|
@@ -411,10 +424,6 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
|
411
424
|
var mergedDependencies = mergedDependenciesSet.Values
|
|
412
425
|
.OrderBy(d => d.Name, StringComparer.OrdinalIgnoreCase)
|
|
413
426
|
.ToImmutableArray();
|
|
414
|
-
var mergedProperties = result1.Properties.Concat(result2.Properties)
|
|
415
|
-
.DistinctBy(p => p.Name, StringComparer.OrdinalIgnoreCase)
|
|
416
|
-
.OrderBy(p => p.Name)
|
|
417
|
-
.ToImmutableArray();
|
|
418
427
|
var mergedTargetFrameworks = result1.TargetFrameworks.Concat(result2.TargetFrameworks)
|
|
419
428
|
.Select(t =>
|
|
420
429
|
{
|
|
@@ -450,7 +459,6 @@ public partial class DiscoveryWorker : IDiscoveryWorker
|
|
|
450
459
|
Dependencies = mergedDependencies,
|
|
451
460
|
IsSuccess = result1.IsSuccess && result2.IsSuccess,
|
|
452
461
|
Error = result1.Error ?? result2.Error,
|
|
453
|
-
Properties = mergedProperties,
|
|
454
462
|
TargetFrameworks = mergedTargetFrameworks,
|
|
455
463
|
ReferencedProjectPaths = mergedReferencedProjects,
|
|
456
464
|
ImportedFiles = mergedImportedFiles,
|
|
@@ -10,7 +10,6 @@ public record ProjectDiscoveryResult : IDiscoveryResultWithDependencies
|
|
|
10
10
|
public required ImmutableArray<Dependency> Dependencies { get; init; }
|
|
11
11
|
public bool IsSuccess { get; init; } = true;
|
|
12
12
|
public JobErrorBase? Error { get; init; } = null;
|
|
13
|
-
public ImmutableArray<Property> Properties { get; init; } = [];
|
|
14
13
|
public ImmutableArray<string> TargetFrameworks { get; init; } = [];
|
|
15
14
|
public ImmutableArray<string> ReferencedProjectPaths { get; init; } = [];
|
|
16
15
|
public required ImmutableArray<string> ImportedFiles { get; init; }
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
using System.Collections.Immutable;
|
|
2
2
|
using System.Text.Json;
|
|
3
3
|
using System.Xml.Linq;
|
|
4
|
-
using System.Xml.XPath;
|
|
5
4
|
|
|
6
5
|
using Microsoft.Build.Logging.StructuredLogger;
|
|
7
6
|
|
|
@@ -63,6 +62,12 @@ internal static class SdkProjectDiscovery
|
|
|
63
62
|
"GenerateBuildDependencyFile"
|
|
64
63
|
];
|
|
65
64
|
|
|
65
|
+
// these targets are required to evaluate a legacy project with a single operation
|
|
66
|
+
private static readonly ImmutableArray<string> LegacyProjectSingleRestoreTargetNames = ["ResolveProjectReferences"];
|
|
67
|
+
|
|
68
|
+
// this property evaluates to a version number in an SDK-style project and is unset or empty otherwise
|
|
69
|
+
private const string NETCoreSdkVersionPropertyName = "NETCoreSdkVersion";
|
|
70
|
+
|
|
66
71
|
// this seems to be the maximum number of TFMs that can be restored in parallel without running into race conditions
|
|
67
72
|
private const int MaximumParallelTargetFrameworkRestores = 2;
|
|
68
73
|
|
|
@@ -138,20 +143,39 @@ internal static class SdkProjectDiscovery
|
|
|
138
143
|
var binLogPath = Path.Combine(Path.GetTempPath(), $"msbuild_{Guid.NewGuid():d}.binlog");
|
|
139
144
|
try
|
|
140
145
|
{
|
|
141
|
-
// when using single restore, we can directly invoke the relevant targets
|
|
146
|
+
// when using single restore, we can directly invoke the relevant targets...
|
|
142
147
|
var args = new List<string>() { "msbuild", startingProjectPath };
|
|
143
|
-
|
|
144
|
-
|
|
148
|
+
|
|
149
|
+
// ...but determining what the relevant targets are can be complicated
|
|
150
|
+
|
|
151
|
+
// For SDK-style projects the targets `Restore`, `ResolveProjectReferences`, and `GenerateBuildDependencyFile`
|
|
152
|
+
// are necessary. If the project has a single target framework, those magic targets will all be present and can
|
|
153
|
+
// be directly invoked, but if the project has multiple target frameworks, those targets will _NOT_ be directly
|
|
154
|
+
// present and we instead have to invoke the `Build` target and specify the three magic values as `InnerTargets`.
|
|
155
|
+
|
|
156
|
+
// If the project is legacy then those three magic targets will not be present, but we shouldn't use the `Build`
|
|
157
|
+
// and `InnerTargets` trick because that's an SDK-only mechanism, so we instead only need to invoke
|
|
158
|
+
// `ResolveProjectReferences` to gather all `PackageReference` items and further down we re-build the transitive
|
|
159
|
+
// dependency set. Without the legacy project check, we could incorrectly invoke `Build` which eventually tries
|
|
160
|
+
// to call `csc.exe` which is unnecessary and can be slow.
|
|
161
|
+
var netCoreSdkVersionValue = await MSBuildHelper.GetProjectPropertyAsync(startingProjectPath, NETCoreSdkVersionPropertyName, logger);
|
|
162
|
+
var isLegacyProject = string.IsNullOrEmpty(netCoreSdkVersionValue);
|
|
163
|
+
var requiredTargets = isLegacyProject
|
|
164
|
+
? LegacyProjectSingleRestoreTargetNames
|
|
165
|
+
: SingleRestoreTargetNames;
|
|
166
|
+
|
|
167
|
+
var actualTargets = await MSBuildHelper.GetProjectTargetsAsync(startingProjectPath, logger);
|
|
168
|
+
var useDirectRestore = requiredTargets.All(actualTargets.Contains);
|
|
145
169
|
if (useDirectRestore || isIndividualTfmRestore)
|
|
146
170
|
{
|
|
147
171
|
// directly call the required targets
|
|
148
|
-
args.Add($"/t:{string.Join(",",
|
|
172
|
+
args.Add($"/t:{string.Join(",", requiredTargets)}");
|
|
149
173
|
}
|
|
150
174
|
else
|
|
151
175
|
{
|
|
152
176
|
// delegate to the inner build and call those targets
|
|
153
177
|
args.Add("/t:Build");
|
|
154
|
-
args.Add($"/p:InnerTargets=\"{string.Join(";",
|
|
178
|
+
args.Add($"/p:InnerTargets=\"{string.Join(";", requiredTargets)}\"");
|
|
155
179
|
}
|
|
156
180
|
|
|
157
181
|
// inject various props and targets to help with discovery
|
|
@@ -385,7 +409,7 @@ internal static class SdkProjectDiscovery
|
|
|
385
409
|
foreach (var projectPath in resolvedProperties.Keys)
|
|
386
410
|
{
|
|
387
411
|
var projectProperties = resolvedProperties[projectPath];
|
|
388
|
-
var isProjectLegacy = !projectProperties.ContainsKey(
|
|
412
|
+
var isProjectLegacy = !projectProperties.ContainsKey(NETCoreSdkVersionPropertyName); // legacy projects don't contain this property
|
|
389
413
|
if (isProjectLegacy)
|
|
390
414
|
{
|
|
391
415
|
logger.Info($"Project {projectPath} is legacy");
|
|
@@ -482,9 +506,6 @@ internal static class SdkProjectDiscovery
|
|
|
482
506
|
}
|
|
483
507
|
|
|
484
508
|
var projectFullDirectory = Path.GetDirectoryName(projectPath)!;
|
|
485
|
-
var doc = XDocument.Load(projectPath);
|
|
486
|
-
var localPropertyDefinitionElements = doc.Root!.XPathSelectElements("/Project/PropertyGroup/*");
|
|
487
|
-
var projectPropertyNames = localPropertyDefinitionElements.Select(e => e.Name.LocalName).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
488
509
|
var projectRelativePath = Path.GetRelativePath(workspacePath, projectPath);
|
|
489
510
|
|
|
490
511
|
var propertiesForProject = resolvedProperties.GetOrAdd(projectPath, () => new(StringComparer.OrdinalIgnoreCase));
|
|
@@ -611,11 +632,6 @@ internal static class SdkProjectDiscovery
|
|
|
611
632
|
|
|
612
633
|
// others
|
|
613
634
|
var projectProperties = resolvedProperties[projectPath];
|
|
614
|
-
var properties = projectProperties
|
|
615
|
-
.Where(pkvp => projectPropertyNames.Contains(pkvp.Key))
|
|
616
|
-
.Select(pkvp => new Property(pkvp.Key, pkvp.Value, Path.GetRelativePath(repoRootPath, projectPath).NormalizePathToUnix()))
|
|
617
|
-
.OrderBy(p => p.Name)
|
|
618
|
-
.ToImmutableArray();
|
|
619
635
|
var referenced = referencedProjects.GetOrAdd(projectPath, () => new(PathComparer.Instance))
|
|
620
636
|
.Select(p => Path.GetRelativePath(projectFullDirectory, p).NormalizePathToUnix())
|
|
621
637
|
.OrderBy(p => p)
|
|
@@ -640,7 +656,6 @@ internal static class SdkProjectDiscovery
|
|
|
640
656
|
FilePath = projectRelativePath,
|
|
641
657
|
Dependencies = dependencies,
|
|
642
658
|
TargetFrameworks = tfms,
|
|
643
|
-
Properties = properties,
|
|
644
659
|
ReferencedProjectPaths = referenced,
|
|
645
660
|
ImportedFiles = imported,
|
|
646
661
|
AdditionalFiles = additional,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<Project>
|
|
2
|
+
<Target Name="_Dependabot_GetProperty">
|
|
3
|
+
<PropertyGroup>
|
|
4
|
+
<!-- the following value will get copied and replaced at runtime -->
|
|
5
|
+
<_DependabotPropertyValue>%RequestedPropertyName%</_DependabotPropertyValue>
|
|
6
|
+
</PropertyGroup>
|
|
7
|
+
<Message Importance="High" Text="__PROPERTY_VALUE:$(_DependabotPropertyValue)" />
|
|
8
|
+
</Target>
|
|
9
|
+
</Project>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<None Include="DependencyDiscovery.props" CopyToOutputDirectory="PreserveNewest" />
|
|
12
12
|
<None Include="DependencyDiscoveryTargetingPacks.props" CopyToOutputDirectory="PreserveNewest" />
|
|
13
13
|
<None Include="DependencyDiscovery.targets" CopyToOutputDirectory="PreserveNewest" />
|
|
14
|
+
<None Include="GetProperty.targets" CopyToOutputDirectory="PreserveNewest" />
|
|
14
15
|
<None Include="TargetFrameworkReporter.targets" CopyToOutputDirectory="PreserveNewest" />
|
|
15
16
|
</ItemGroup>
|
|
16
17
|
|
|
@@ -150,29 +150,35 @@ public class XmlFileWriter : IFileWriter
|
|
|
150
150
|
// find last `<ItemGroup>` in the project...
|
|
151
151
|
Action addItemGroup = () => { }; // adding an ItemGroup to the project isn't always necessary, but it's much easier to prepare for it here
|
|
152
152
|
var projectDocument = filesAndContents[projectRelativePath];
|
|
153
|
-
var
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
var indentation = GetDocumentIndentationCharacters(projectDocument);
|
|
154
|
+
var itemGroups = projectDocument.RootSyntax.Elements
|
|
155
|
+
.Where(e => e.Name.Equals(ItemGroupElementName, StringComparison.OrdinalIgnoreCase))
|
|
156
|
+
.ToArray();
|
|
157
|
+
var itemGroupsWithPackageReferences = itemGroups
|
|
158
|
+
.Where(e => e.Elements.Any(c => c.Name.Equals(PackageReferenceElementName, StringComparison.OrdinalIgnoreCase)))
|
|
159
|
+
.ToArray();
|
|
160
|
+
var itemGroupForInsertion = itemGroupsWithPackageReferences.LastOrDefault() ?? itemGroups.LastOrDefault();
|
|
161
|
+
if (itemGroupForInsertion is null)
|
|
156
162
|
{
|
|
157
163
|
_logger.Info($"No `<{ItemGroupElementName}>` element found in project; adding one.");
|
|
158
|
-
|
|
159
|
-
new SyntaxList<SyntaxNode>([SyntaxFactory.EndOfLineTrivia("\n"), SyntaxFactory.WhitespaceTrivia(
|
|
164
|
+
itemGroupForInsertion = XmlExtensions.CreateOpenCloseXmlElementSyntax(ItemGroupElementName,
|
|
165
|
+
new SyntaxList<SyntaxNode>([SyntaxFactory.EndOfLineTrivia("\n"), SyntaxFactory.WhitespaceTrivia(indentation)]),
|
|
160
166
|
insertIntermediateNewline: false);
|
|
161
167
|
addItemGroup = () =>
|
|
162
168
|
{
|
|
163
169
|
// add the new element
|
|
164
|
-
var updatedRootSyntax = projectDocument.RootSyntax.AddChild(
|
|
170
|
+
var updatedRootSyntax = projectDocument.RootSyntax.AddChild(itemGroupForInsertion);
|
|
165
171
|
var updatedProjectDocument = projectDocument.ReplaceNode(projectDocument.RootSyntax.AsNode, updatedRootSyntax.AsNode);
|
|
166
172
|
|
|
167
173
|
// reset well-known variables
|
|
168
174
|
projectDocument = updatedProjectDocument;
|
|
169
175
|
filesAndContents[projectRelativePath] = updatedProjectDocument;
|
|
170
|
-
|
|
176
|
+
itemGroupForInsertion = updatedProjectDocument.RootSyntax.Elements.Last(e => e.Name.Equals(ItemGroupElementName, StringComparison.OrdinalIgnoreCase));
|
|
171
177
|
};
|
|
172
178
|
}
|
|
173
179
|
|
|
174
180
|
// ...find where the new item should go...
|
|
175
|
-
var elementsBeforeNew = GetOrderedElementsBeforeSpecified(
|
|
181
|
+
var elementsBeforeNew = GetOrderedElementsBeforeSpecified(itemGroupForInsertion, PackageReferenceElementName, [IncludeAttributeName, UpdateAttributeName], requiredPackageVersion.Name);
|
|
176
182
|
|
|
177
183
|
// ...prepare a new `<PackageReference>` element...
|
|
178
184
|
var newElement = XmlExtensions.CreateSingleLineXmlElementSyntax(PackageReferenceElementName, leadingTrivia: new SyntaxList<SyntaxNode>())
|
|
@@ -221,18 +227,18 @@ public class XmlFileWriter : IFileWriter
|
|
|
221
227
|
else
|
|
222
228
|
{
|
|
223
229
|
// no prior package references; add to the front
|
|
224
|
-
var itemGroupTrivia =
|
|
230
|
+
var itemGroupTrivia = itemGroupForInsertion.AsNode.GetLeadingTrivia().ToList();
|
|
225
231
|
var priorEolIndex = itemGroupTrivia.FindLastIndex(t => t.Kind == SyntaxKind.EndOfLineTrivia);
|
|
226
232
|
var indentTrivia = itemGroupTrivia
|
|
227
233
|
.Skip(priorEolIndex + 1)
|
|
228
234
|
.Select(t => SyntaxFactory.WhitespaceTrivia(t.ToFullString()))
|
|
229
235
|
.ToArray();
|
|
230
|
-
var newTrivia = new SyntaxTriviaList([SyntaxFactory.EndOfLineTrivia("\n"), SyntaxFactory.WhitespaceTrivia(
|
|
236
|
+
var newTrivia = new SyntaxTriviaList([SyntaxFactory.EndOfLineTrivia("\n"), SyntaxFactory.WhitespaceTrivia(indentation), .. indentTrivia]);
|
|
231
237
|
newElement = (IXmlElementSyntax)newElement.AsNode.WithLeadingTrivia(newTrivia);
|
|
232
238
|
var updatedItemGroup = (IXmlElementSyntax)ReplaceNode(
|
|
233
239
|
projectRelativePath,
|
|
234
|
-
|
|
235
|
-
|
|
240
|
+
itemGroupForInsertion.AsNode,
|
|
241
|
+
itemGroupForInsertion.InsertChild(newElement, 0).AsNode
|
|
236
242
|
);
|
|
237
243
|
newElement = (IXmlElementSyntax)updatedItemGroup.Content[0];
|
|
238
244
|
}
|
|
@@ -353,7 +359,9 @@ public class XmlFileWriter : IFileWriter
|
|
|
353
359
|
.Skip(priorEolIndex + 1)
|
|
354
360
|
.Select(t => SyntaxFactory.WhitespaceTrivia(t.ToFullString()))
|
|
355
361
|
.ToArray();
|
|
356
|
-
var
|
|
362
|
+
var packageVersionDocument = filesAndContents[filePath];
|
|
363
|
+
var packageVersionIndentation = GetDocumentIndentationCharacters(packageVersionDocument);
|
|
364
|
+
var newTrivia = new SyntaxTriviaList([SyntaxFactory.EndOfLineTrivia("\n"), SyntaxFactory.WhitespaceTrivia(packageVersionIndentation), .. indentTrivia]);
|
|
357
365
|
newVersionElement = (IXmlElementSyntax)newVersionElement.AsNode.WithLeadingTrivia(newTrivia).WithoutTrailingTrivia();
|
|
358
366
|
var insertionIndex = 0;
|
|
359
367
|
var replacementPackageVersionGroup = packageVersionGroup
|
|
@@ -581,7 +589,7 @@ public class XmlFileWriter : IFileWriter
|
|
|
581
589
|
return elementsBeforeNew;
|
|
582
590
|
}
|
|
583
591
|
|
|
584
|
-
|
|
592
|
+
internal static async Task<XmlDocumentSyntax> ReadFileContentsAsync(DirectoryInfo repoContentsPath, string path)
|
|
585
593
|
{
|
|
586
594
|
var fullPath = Path.Join(repoContentsPath.FullName, path);
|
|
587
595
|
var contents = await File.ReadAllTextAsync(fullPath);
|
|
@@ -696,4 +704,23 @@ public class XmlFileWriter : IFileWriter
|
|
|
696
704
|
|
|
697
705
|
return newRange.ToString();
|
|
698
706
|
}
|
|
707
|
+
|
|
708
|
+
public static string GetDocumentIndentationCharacters(XmlDocumentSyntax document)
|
|
709
|
+
{
|
|
710
|
+
// find the first element with leading whitespace and assume that's the document indentation
|
|
711
|
+
var nodeLeadingLineTrivias = document.DescendantNodes()
|
|
712
|
+
.Select(n => n.GetLeadingTrivia().ToList())
|
|
713
|
+
.Select(l =>
|
|
714
|
+
{
|
|
715
|
+
var priorEolIndex = l.FindLastIndex(t => t.Kind == SyntaxKind.EndOfLineTrivia);
|
|
716
|
+
var leadingTriviaParts = l.Skip(priorEolIndex + 1)
|
|
717
|
+
.Select(t => t.ToFullString());
|
|
718
|
+
var leadingTrivia = string.Concat(leadingTriviaParts);
|
|
719
|
+
return leadingTrivia;
|
|
720
|
+
})
|
|
721
|
+
.ToArray();
|
|
722
|
+
var nodeLeadingLineTrivia = nodeLeadingLineTrivias
|
|
723
|
+
.FirstOrDefault(t => !string.IsNullOrEmpty(t));
|
|
724
|
+
return nodeLeadingLineTrivia ?? " ";
|
|
725
|
+
}
|
|
699
726
|
}
|
|
@@ -19,12 +19,12 @@ namespace NuGetUpdater.Core;
|
|
|
19
19
|
// Data type to store information of a given package
|
|
20
20
|
public class PackageToUpdate
|
|
21
21
|
{
|
|
22
|
-
public string PackageName { get; set; }
|
|
23
|
-
public string CurrentVersion { get; set; }
|
|
24
|
-
public string NewVersion { get; set; }
|
|
22
|
+
public required string PackageName { get; set; }
|
|
23
|
+
public string? CurrentVersion { get; set; }
|
|
24
|
+
public string? NewVersion { get; set; }
|
|
25
25
|
|
|
26
26
|
// Second version in case there's a "bounds" on the package version
|
|
27
|
-
public string SecondVersion { get; set; }
|
|
27
|
+
public string? SecondVersion { get; set; }
|
|
28
28
|
|
|
29
29
|
// Bool to determine if a package has to be a specific version
|
|
30
30
|
public bool IsSpecific { get; set; }
|
|
@@ -122,7 +122,7 @@ public class PackageManager
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
// Method to find the best match framework of a given package's target framework availability
|
|
125
|
-
public static NuGetFramework FindBestMatchFramework(IEnumerable<NuGet.Packaging.PackageDependencyGroup> dependencySet, string targetFrameworkString)
|
|
125
|
+
public static NuGetFramework? FindBestMatchFramework(IEnumerable<NuGet.Packaging.PackageDependencyGroup> dependencySet, string targetFrameworkString)
|
|
126
126
|
{
|
|
127
127
|
// Parse the given target framework string into a NuGetFramework object
|
|
128
128
|
var targetFramework = NuGetFramework.ParseFolder(targetFrameworkString);
|
|
@@ -136,7 +136,7 @@ public class PackageManager
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
// Method to get the dependencies of a package
|
|
139
|
-
public async Task<List<PackageToUpdate
|
|
139
|
+
public async Task<List<PackageToUpdate>?> GetDependenciesAsync(PackageToUpdate package, string targetFramework, string projectDirectory, ILogger logger)
|
|
140
140
|
{
|
|
141
141
|
if (!NuGetVersion.TryParse(package.NewVersion, out var otherVersion))
|
|
142
142
|
{
|
|
@@ -166,47 +166,46 @@ public class PackageManager
|
|
|
166
166
|
|
|
167
167
|
foreach (var packageDependency in bestMatchGroup.Packages)
|
|
168
168
|
{
|
|
169
|
-
string version = packageDependency.VersionRange.OriginalString;
|
|
170
|
-
string
|
|
171
|
-
string SecondVersion = null;
|
|
169
|
+
string? version = packageDependency.VersionRange.OriginalString;
|
|
170
|
+
string? SecondVersion = null;
|
|
172
171
|
|
|
173
172
|
// Conditions to check if the version has bounds specified
|
|
174
|
-
if (version.StartsWith("[") && version.EndsWith("]"))
|
|
173
|
+
if (version is not null && version.StartsWith("[") && version.EndsWith("]"))
|
|
175
174
|
{
|
|
176
175
|
version = version.Trim('[', ']');
|
|
177
176
|
var versions = version.Split(',');
|
|
178
|
-
version = versions.
|
|
177
|
+
version = versions[0].Trim();
|
|
179
178
|
if (versions.Length > 1)
|
|
180
179
|
{
|
|
181
180
|
SecondVersion = versions.LastOrDefault()?.Trim();
|
|
182
181
|
}
|
|
183
182
|
specific = true;
|
|
184
183
|
}
|
|
185
|
-
else if (version.StartsWith("[") && version.EndsWith(")"))
|
|
184
|
+
else if (version is not null && version.StartsWith("[") && version.EndsWith(")"))
|
|
186
185
|
{
|
|
187
186
|
version = version.Trim('[', ')');
|
|
188
187
|
var versions = version.Split(',');
|
|
189
|
-
version = versions.
|
|
188
|
+
version = versions[0].Trim();
|
|
190
189
|
if (versions.Length > 1)
|
|
191
190
|
{
|
|
192
191
|
SecondVersion = versions.LastOrDefault()?.Trim();
|
|
193
192
|
}
|
|
194
193
|
}
|
|
195
|
-
else if (version.StartsWith("(") && version.EndsWith("]"))
|
|
194
|
+
else if (version is not null && version.StartsWith("(") && version.EndsWith("]"))
|
|
196
195
|
{
|
|
197
196
|
version = version.Trim('(', ']');
|
|
198
197
|
var versions = version.Split(',');
|
|
199
|
-
version = versions.
|
|
198
|
+
version = versions[0].Trim();
|
|
200
199
|
if (versions.Length > 1)
|
|
201
200
|
{
|
|
202
201
|
SecondVersion = versions.LastOrDefault()?.Trim();
|
|
203
202
|
}
|
|
204
203
|
}
|
|
205
|
-
else if (version.StartsWith("(") && version.EndsWith(")"))
|
|
204
|
+
else if (version is not null && version.StartsWith("(") && version.EndsWith(")"))
|
|
206
205
|
{
|
|
207
206
|
version = version.Trim('(', ')');
|
|
208
207
|
var versions = version.Split(',');
|
|
209
|
-
version = versions.
|
|
208
|
+
version = versions[0].Trim();
|
|
210
209
|
if (versions.Length > 1)
|
|
211
210
|
{
|
|
212
211
|
SecondVersion = versions.LastOrDefault()?.Trim();
|
|
@@ -292,7 +291,7 @@ public class PackageManager
|
|
|
292
291
|
// Loop through each package and get their dependencies
|
|
293
292
|
foreach (PackageToUpdate package in packages)
|
|
294
293
|
{
|
|
295
|
-
List<PackageToUpdate
|
|
294
|
+
List<PackageToUpdate>? dependencies = await GetDependenciesAsync(package, targetFramework, projectDirectory, logger);
|
|
296
295
|
|
|
297
296
|
if (dependencies == null)
|
|
298
297
|
{
|
|
@@ -302,7 +301,7 @@ public class PackageManager
|
|
|
302
301
|
// Add each dependency based off if it exists or not
|
|
303
302
|
foreach (PackageToUpdate dependency in dependencies)
|
|
304
303
|
{
|
|
305
|
-
PackageToUpdate checkInExisting = packages.FirstOrDefault(p => string.Compare(p.PackageName, dependency.PackageName, StringComparison.OrdinalIgnoreCase) == 0);
|
|
304
|
+
PackageToUpdate? checkInExisting = packages.FirstOrDefault(p => string.Compare(p.PackageName, dependency.PackageName, StringComparison.OrdinalIgnoreCase) == 0);
|
|
306
305
|
if (checkInExisting != null)
|
|
307
306
|
{
|
|
308
307
|
checkInExisting.IsSpecific = dependency.IsSpecific;
|
|
@@ -356,17 +355,17 @@ public class PackageManager
|
|
|
356
355
|
|
|
357
356
|
try
|
|
358
357
|
{
|
|
359
|
-
NuGetVersion CurrentVersion = new NuGetVersion(package.CurrentVersion);
|
|
360
|
-
NuGetVersion newerVersion = new NuGetVersion(package.NewVersion);
|
|
358
|
+
NuGetVersion CurrentVersion = new NuGetVersion(package.CurrentVersion!);
|
|
359
|
+
NuGetVersion newerVersion = new NuGetVersion(package.NewVersion!);
|
|
361
360
|
|
|
362
361
|
// If the CurrentVersion is less than or equal to the newerVersion, proceed with the update
|
|
363
362
|
if (CurrentVersion <= newerVersion)
|
|
364
363
|
{
|
|
365
|
-
string currentVersiontemp = package.CurrentVersion;
|
|
364
|
+
string? currentVersiontemp = package.CurrentVersion;
|
|
366
365
|
package.CurrentVersion = package.NewVersion;
|
|
367
366
|
|
|
368
367
|
// Check if the current package has dependencies
|
|
369
|
-
List<PackageToUpdate
|
|
368
|
+
List<PackageToUpdate>? dependencyList = await GetDependenciesAsync(package, targetFramework, projectDirectory, logger);
|
|
370
369
|
|
|
371
370
|
// If there are dependencies
|
|
372
371
|
if (dependencyList != null)
|
|
@@ -379,14 +378,14 @@ public class PackageManager
|
|
|
379
378
|
// If you find the dependency
|
|
380
379
|
if (string.Equals(dependency.PackageName, existingPackage.PackageName, StringComparison.OrdinalIgnoreCase))
|
|
381
380
|
{
|
|
382
|
-
NuGetVersion existingCurrentVersion = new NuGetVersion(existingPackage.CurrentVersion);
|
|
383
|
-
NuGetVersion dependencyCurrentVersion = new NuGetVersion(dependency.CurrentVersion);
|
|
381
|
+
NuGetVersion existingCurrentVersion = new NuGetVersion(existingPackage.CurrentVersion!);
|
|
382
|
+
NuGetVersion dependencyCurrentVersion = new NuGetVersion(dependency.CurrentVersion!);
|
|
384
383
|
|
|
385
384
|
// Check if the existing version is less than the dependency's existing version
|
|
386
385
|
if (existingCurrentVersion < dependencyCurrentVersion)
|
|
387
386
|
{
|
|
388
387
|
// Create temporary copy of the current version and of the existing package
|
|
389
|
-
string dependencyOldVersion = existingPackage.CurrentVersion;
|
|
388
|
+
string? dependencyOldVersion = existingPackage.CurrentVersion;
|
|
390
389
|
|
|
391
390
|
// Susbtitute the current version of the existingPackage with the dependency current version
|
|
392
391
|
existingPackage.CurrentVersion = dependency.CurrentVersion;
|
|
@@ -411,7 +410,7 @@ public class PackageManager
|
|
|
411
410
|
}
|
|
412
411
|
|
|
413
412
|
// If the dependency has brackets or parenthesis, it's a specific version
|
|
414
|
-
if (dependency.CurrentVersion.Contains('[') || dependency.CurrentVersion.Contains(']') || dependency.CurrentVersion.Contains('{') || dependency.CurrentVersion.Contains('}'))
|
|
413
|
+
if (dependency.CurrentVersion is not null && (dependency.CurrentVersion.Contains('[') || dependency.CurrentVersion.Contains(']') || dependency.CurrentVersion.Contains('{') || dependency.CurrentVersion.Contains('}')))
|
|
415
414
|
{
|
|
416
415
|
dependency.IsSpecific = true;
|
|
417
416
|
}
|
|
@@ -433,7 +432,7 @@ public class PackageManager
|
|
|
433
432
|
if (!isCompatible)
|
|
434
433
|
{
|
|
435
434
|
// Attempt to find and update to a compatible version between the two
|
|
436
|
-
NuGetVersion compatibleVersion = await FindCompatibleVersionAsync(existingPackages, parent, package, targetFramework, logger);
|
|
435
|
+
NuGetVersion? compatibleVersion = await FindCompatibleVersionAsync(existingPackages, parent, package, targetFramework, logger);
|
|
437
436
|
if (compatibleVersion == null)
|
|
438
437
|
{
|
|
439
438
|
return "Failed to update";
|
|
@@ -447,32 +446,32 @@ public class PackageManager
|
|
|
447
446
|
// If it's compatible and the package you updated wasn't in the existing package, check if the parent's dependencies version is the same as the current version
|
|
448
447
|
else if (isCompatible == true && inExisting == false)
|
|
449
448
|
{
|
|
450
|
-
List<PackageToUpdate
|
|
449
|
+
List<PackageToUpdate>? dependencyListParent = await GetDependenciesAsync(parent, targetFramework, projectDirectory, logger);
|
|
451
450
|
|
|
452
|
-
PackageToUpdate parentDependency = dependencyListParent
|
|
451
|
+
PackageToUpdate? parentDependency = dependencyListParent?.FirstOrDefault(p => string.Compare(p.PackageName, package.PackageName, StringComparison.OrdinalIgnoreCase) == 0);
|
|
453
452
|
|
|
454
453
|
// If the parent's dependency current version is not the same as the current version of the package
|
|
455
|
-
if (parentDependency.CurrentVersion != package.CurrentVersion)
|
|
454
|
+
if (parentDependency is not null && parentDependency.CurrentVersion != package.CurrentVersion)
|
|
456
455
|
{
|
|
457
456
|
// Create a NugetContext instance to get the latest versions of the parent
|
|
458
457
|
NuGetContext nugetContext = new NuGetContext(Path.GetDirectoryName(projectPath));
|
|
459
458
|
|
|
460
|
-
string currentVersionString = parent.CurrentVersion;
|
|
461
|
-
NuGetVersion currentVersionParent = NuGetVersion.Parse(currentVersionString);
|
|
459
|
+
string? currentVersionString = parent.CurrentVersion;
|
|
460
|
+
NuGetVersion currentVersionParent = NuGetVersion.Parse(currentVersionString!);
|
|
462
461
|
|
|
463
462
|
var result = await VersionFinder.GetVersionsByNameAsync([projectFramework], parent.PackageName, currentVersionParent, nugetContext, logger, CancellationToken.None);
|
|
464
463
|
var versions = result.GetVersions();
|
|
465
|
-
NuGetVersion latestVersion = versions.Where(v => !v.IsPrerelease).Max();
|
|
464
|
+
NuGetVersion? latestVersion = versions.Where(v => !v.IsPrerelease).Max();
|
|
466
465
|
|
|
467
466
|
// Loop from the current version to the latest version, use next patch as a limit (unless there's a limit) so it doesn't look for versions that don't exist
|
|
468
|
-
for (NuGetVersion? version = currentVersionParent; version is not null && version <= latestVersion; version = NextPatch(version, versions))
|
|
467
|
+
for (NuGetVersion? version = currentVersionParent; version is not null && latestVersion is not null && version <= latestVersion; version = NextPatch(version, versions))
|
|
469
468
|
{
|
|
470
469
|
// Check if the parent needs to be updated since the child isn't in the existing package list and the parent can update to a newer version to remove the dependency
|
|
471
|
-
List<PackageToUpdate
|
|
472
|
-
PackageToUpdate parentDependencyTemp = dependencyListParentTemp
|
|
470
|
+
List<PackageToUpdate>? dependencyListParentTemp = await GetDependenciesAsync(parent, targetFramework, projectDirectory, logger);
|
|
471
|
+
PackageToUpdate? parentDependencyTemp = dependencyListParentTemp?.FirstOrDefault(p => string.Compare(p.PackageName, package.PackageName, StringComparison.OrdinalIgnoreCase) == 0);
|
|
473
472
|
|
|
474
473
|
// If the newer package version of the parent has the same version as the parent's previous dependency, update
|
|
475
|
-
if (parentDependencyTemp.CurrentVersion == package.CurrentVersion)
|
|
474
|
+
if (parentDependencyTemp is not null && parentDependencyTemp.CurrentVersion == package.CurrentVersion)
|
|
476
475
|
{
|
|
477
476
|
parent.NewVersion = version.ToString();
|
|
478
477
|
parent.CurrentVersion = null;
|
|
@@ -504,7 +503,12 @@ public class PackageManager
|
|
|
504
503
|
public async Task<bool> IsCompatibleAsync(PackageToUpdate parent, PackageToUpdate child, string targetFramework, string projectDirectory, ILogger logger)
|
|
505
504
|
{
|
|
506
505
|
// Get the dependencies of the parent
|
|
507
|
-
List<PackageToUpdate
|
|
506
|
+
List<PackageToUpdate>? dependencies = await GetDependenciesAsync(parent, targetFramework, projectDirectory, logger);
|
|
507
|
+
|
|
508
|
+
if (dependencies is null)
|
|
509
|
+
{
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
508
512
|
|
|
509
513
|
foreach (PackageToUpdate dependency in dependencies)
|
|
510
514
|
{
|
|
@@ -512,8 +516,8 @@ public class PackageManager
|
|
|
512
516
|
// If the child is present
|
|
513
517
|
if (string.Equals(dependency.PackageName, child.PackageName, StringComparison.OrdinalIgnoreCase))
|
|
514
518
|
{
|
|
515
|
-
NuGetVersion dependencyVersion = new NuGetVersion(dependency.CurrentVersion);
|
|
516
|
-
NuGetVersion childVersion = new NuGetVersion(child.CurrentVersion);
|
|
519
|
+
NuGetVersion dependencyVersion = new NuGetVersion(dependency.CurrentVersion!);
|
|
520
|
+
NuGetVersion childVersion = new NuGetVersion(child.CurrentVersion!);
|
|
517
521
|
|
|
518
522
|
// If the dependency version of the parent and the childversion is the same, or if the child version can be >=
|
|
519
523
|
if (dependencyVersion == childVersion || (childVersion > dependencyVersion && dependency.IsSpecific != true))
|
|
@@ -538,13 +542,13 @@ public class PackageManager
|
|
|
538
542
|
}
|
|
539
543
|
|
|
540
544
|
// Method to find a compatible version with the child for the parent to update to
|
|
541
|
-
public async Task<NuGetVersion
|
|
545
|
+
public async Task<NuGetVersion?> FindCompatibleVersionAsync(List<PackageToUpdate> existingPackages, PackageToUpdate possibleParent, PackageToUpdate possibleDependency, string targetFramework, ILogger logger)
|
|
542
546
|
{
|
|
543
547
|
string packageId = possibleParent.PackageName;
|
|
544
|
-
string currentVersionString = possibleParent.CurrentVersion;
|
|
545
|
-
NuGetVersion CurrentVersion = NuGetVersion.Parse(currentVersionString);
|
|
546
|
-
string currentVersionStringDependency = possibleDependency.CurrentVersion;
|
|
547
|
-
NuGetVersion currentVersionDependency = NuGetVersion.Parse(currentVersionStringDependency);
|
|
548
|
+
string? currentVersionString = possibleParent.CurrentVersion;
|
|
549
|
+
NuGetVersion CurrentVersion = NuGetVersion.Parse(currentVersionString!);
|
|
550
|
+
string? currentVersionStringDependency = possibleDependency.CurrentVersion;
|
|
551
|
+
NuGetVersion currentVersionDependency = NuGetVersion.Parse(currentVersionStringDependency!);
|
|
548
552
|
|
|
549
553
|
// Create a NugetContext instance to get the latest versions of the parent
|
|
550
554
|
NuGetContext nugetContext = new NuGetContext(Path.GetDirectoryName(projectPath));
|
|
@@ -559,7 +563,7 @@ public class PackageManager
|
|
|
559
563
|
return null;
|
|
560
564
|
}
|
|
561
565
|
|
|
562
|
-
NuGetVersion latestVersion = versions
|
|
566
|
+
NuGetVersion? latestVersion = versions
|
|
563
567
|
.Where(v => !v.IsPrerelease)
|
|
564
568
|
.Max();
|
|
565
569
|
|
|
@@ -577,7 +581,7 @@ public class PackageManager
|
|
|
577
581
|
}
|
|
578
582
|
|
|
579
583
|
// Loop from the current version to the latest version, use next patch as a limit (unless there's a limit) so it doesn't look for versions that don't exist
|
|
580
|
-
for (NuGetVersion? version = CurrentVersion; version is not null && version <= latestVersion; version = NextPatch(version, versions))
|
|
584
|
+
for (NuGetVersion? version = CurrentVersion; version is not null && latestVersion is not null && version <= latestVersion; version = NextPatch(version, versions))
|
|
581
585
|
{
|
|
582
586
|
possibleParent.NewVersion = version.ToString();
|
|
583
587
|
|
|
@@ -588,7 +592,7 @@ public class PackageManager
|
|
|
588
592
|
if (await AreAllParentsCompatibleAsync(existingPackages, possibleParent, targetFramework, nugetContext.CurrentDirectory, logger))
|
|
589
593
|
{
|
|
590
594
|
// If compatible, return the new version
|
|
591
|
-
if (Regex.IsMatch(possibleParent.NewVersion
|
|
595
|
+
if (Regex.IsMatch(possibleParent.NewVersion!, @"[a-zA-Z]"))
|
|
592
596
|
{
|
|
593
597
|
possibleParent.IsSpecific = true;
|
|
594
598
|
}
|
|
@@ -616,7 +620,7 @@ public class PackageManager
|
|
|
616
620
|
if (!isCompatible)
|
|
617
621
|
{
|
|
618
622
|
// Find a compatible version if possible
|
|
619
|
-
NuGetVersion compatibleVersion = await FindCompatibleVersionAsync(existingPackages, parent, possibleParent, targetFramework, logger);
|
|
623
|
+
NuGetVersion? compatibleVersion = await FindCompatibleVersionAsync(existingPackages, parent, possibleParent, targetFramework, logger);
|
|
620
624
|
if (compatibleVersion == null)
|
|
621
625
|
{
|
|
622
626
|
return false;
|
|
@@ -641,7 +645,7 @@ public class PackageManager
|
|
|
641
645
|
{
|
|
642
646
|
foreach (PackageToUpdate packageToUpdate in packagesToUpdate)
|
|
643
647
|
{
|
|
644
|
-
PackageToUpdate existingPackage = existingPackages.FirstOrDefault(p => string.Compare(p.PackageName, packageToUpdate.PackageName, StringComparison.OrdinalIgnoreCase) == 0);
|
|
648
|
+
PackageToUpdate? existingPackage = existingPackages.FirstOrDefault(p => string.Compare(p.PackageName, packageToUpdate.PackageName, StringComparison.OrdinalIgnoreCase) == 0);
|
|
645
649
|
|
|
646
650
|
if (existingPackage != null)
|
|
647
651
|
{
|