Merge all changes
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using StellaOps.Scanner.Analyzers.Lang.Node.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Node.Tests.Node;
|
||||
|
||||
@@ -33,7 +34,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
public async Task LoadAsync_NoLockfiles_ReturnsEmpty()
|
||||
{
|
||||
// No lockfiles, no package.json
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Empty(result.DeclaredPackages);
|
||||
}
|
||||
@@ -56,7 +57,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
|
||||
Environment.CurrentDirectory = tempDirectory;
|
||||
|
||||
var result = await NodeLockData.LoadAsync(string.Empty, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(string.Empty, TestContext.Current.CancellationToken);
|
||||
Assert.Empty(result.DeclaredPackages);
|
||||
}
|
||||
finally
|
||||
@@ -79,7 +80,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.First();
|
||||
@@ -101,7 +102,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
var names = result.DeclaredPackages.Select(x => x.Name).ToArray();
|
||||
Assert.Equal(["alpha", "beta", "zeta"], names);
|
||||
@@ -131,7 +132,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.First();
|
||||
@@ -179,7 +180,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.First();
|
||||
@@ -203,7 +204,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("express", result.DeclaredPackages.First().Name);
|
||||
@@ -226,7 +227,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "@angular/core" && e.Version == "17.0.0");
|
||||
@@ -251,7 +252,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("valid", result.DeclaredPackages.First().Name);
|
||||
@@ -274,7 +275,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "parent");
|
||||
@@ -302,7 +303,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "parent");
|
||||
@@ -328,7 +329,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("actual-package", result.DeclaredPackages.First().Name);
|
||||
@@ -354,7 +355,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.First();
|
||||
@@ -381,7 +382,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "parent");
|
||||
@@ -402,7 +403,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("@babel/core", result.DeclaredPackages.First().Name);
|
||||
@@ -420,7 +421,7 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
""");
|
||||
|
||||
// Should continue with yarn.lock parsing
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("lodash", result.DeclaredPackages.First().Name);
|
||||
@@ -443,7 +444,7 @@ lodash@^4.17.21:
|
||||
integrity ""sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ""
|
||||
");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.First();
|
||||
@@ -464,7 +465,7 @@ lodash@^4.17.21:
|
||||
version ""20.10.0""
|
||||
");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "@babel/core");
|
||||
@@ -479,7 +480,7 @@ lodash@^4.17.21:
|
||||
version ""4.17.21""
|
||||
");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("lodash", result.DeclaredPackages.First().Name);
|
||||
@@ -493,7 +494,7 @@ lodash@^4.17.21:
|
||||
version ""4.18.2""
|
||||
");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("express", result.DeclaredPackages.First().Name);
|
||||
@@ -506,7 +507,7 @@ lodash@^4.17.21:
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "yarn.lock"),
|
||||
"lodash@^4.17.21:\n version \"4.17.21\"\n resolved \"https://example.com/lodash.tgz\"\n integrity \"sha512-abc\"");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("lodash", result.DeclaredPackages.First().Name);
|
||||
@@ -526,7 +527,7 @@ axios@^1.6.0:
|
||||
version ""1.6.2""
|
||||
");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(3, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "express");
|
||||
@@ -546,7 +547,7 @@ valid@^2.0.0:
|
||||
version ""2.0.0""
|
||||
");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "@scope/package");
|
||||
@@ -566,7 +567,7 @@ valid@^2.0.0:
|
||||
checksum: 10c0deadbeef
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.DoesNotContain(result.DeclaredPackages, e => e.Name == "__metadata");
|
||||
@@ -598,7 +599,7 @@ valid@^2.0.0:
|
||||
" resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.First();
|
||||
@@ -621,7 +622,7 @@ valid@^2.0.0:
|
||||
" resolution: {integrity: sha512-def456}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "@angular/core");
|
||||
@@ -638,7 +639,7 @@ valid@^2.0.0:
|
||||
" resolution: {integrity: sha512-xyz}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("4.18.2", result.DeclaredPackages.First().Version);
|
||||
@@ -653,7 +654,7 @@ valid@^2.0.0:
|
||||
" resolution: {integrity: sha512-xyz}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.Single();
|
||||
@@ -672,7 +673,7 @@ valid@^2.0.0:
|
||||
" resolution: {tarball: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz, integrity: sha512-abc}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Contains("lodash-4.17.21.tgz", result.DeclaredPackages.First().Resolved);
|
||||
@@ -687,7 +688,7 @@ valid@^2.0.0:
|
||||
" resolution: {tarball: file:../local-file-1.0.0.tgz}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.Single();
|
||||
@@ -706,7 +707,7 @@ valid@^2.0.0:
|
||||
" resolution: {integrity: sha512-snap}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.Single();
|
||||
@@ -725,7 +726,7 @@ valid@^2.0.0:
|
||||
" integrity: sha512-separate-line-integrity\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("sha512-separate-line-integrity", result.DeclaredPackages.First().Integrity);
|
||||
@@ -743,7 +744,7 @@ valid@^2.0.0:
|
||||
" resolution: {integrity: sha512-valid}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
|
||||
@@ -776,7 +777,7 @@ valid@^2.0.0:
|
||||
" resolution: {integrity: sha512-axios}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(3, result.DeclaredPackages.Count);
|
||||
}
|
||||
@@ -799,7 +800,7 @@ valid@^2.0.0:
|
||||
}
|
||||
""");
|
||||
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(lockData.TryGet("node_modules/lodash", "lodash", out var entry));
|
||||
Assert.NotNull(entry);
|
||||
@@ -814,7 +815,7 @@ valid@^2.0.0:
|
||||
version "4.17.21"
|
||||
""");
|
||||
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(lockData.TryGet("", "lodash", out var entry));
|
||||
Assert.NotNull(entry);
|
||||
@@ -835,7 +836,7 @@ valid@^2.0.0:
|
||||
}
|
||||
""");
|
||||
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.False(lockData.TryGet("node_modules/express", "express", out var entry));
|
||||
Assert.Null(entry);
|
||||
@@ -855,7 +856,7 @@ valid@^2.0.0:
|
||||
}
|
||||
""");
|
||||
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(lockData.TryGet("node_modules\\lodash", "lodash", out var entry));
|
||||
Assert.NotNull(entry);
|
||||
@@ -892,7 +893,7 @@ valid@^2.0.0:
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
var lodash = result.DeclaredPackages.First(e => e.Name == "lodash");
|
||||
Assert.Equal(NodeDependencyScope.Production, lodash.Scope);
|
||||
@@ -918,7 +919,7 @@ valid@^2.0.0:
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(result.DependencyIndex.TryGetScope("express", out var scope));
|
||||
Assert.Equal(NodeDependencyScope.Production, scope);
|
||||
@@ -938,7 +939,7 @@ valid@^2.0.0:
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Empty(result.DeclaredPackages);
|
||||
}
|
||||
@@ -963,7 +964,7 @@ valid@^2.0.0:
|
||||
" resolution: {integrity: sha512-pnpm}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), pnpmContent);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(3, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "from-npm");
|
||||
@@ -983,7 +984,7 @@ valid@^2.0.0:
|
||||
}
|
||||
""");
|
||||
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(lockData.TryGet("node_modules/lodash", "lodash", out var entry));
|
||||
Assert.NotNull(entry);
|
||||
@@ -1005,7 +1006,7 @@ valid@^2.0.0:
|
||||
version "4.0.0"
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
// Both entries are kept in DeclaredPackages with different version keys
|
||||
Assert.Equal(2, result.DeclaredPackages.Count(e => e.Name == "lodash"));
|
||||
@@ -1039,7 +1040,7 @@ valid@^2.0.0:
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("日本語", result.DeclaredPackages.First().Name);
|
||||
|
||||
Reference in New Issue
Block a user