Skip to content

Commit

Permalink
Target net7.0 (#7790)
Browse files Browse the repository at this point in the history
Update target framework in MSBuild and related places (consolidating MSBuild references).

Add NoWarn for deprecation warnings (#7902) and API-stability analyzer problems (#7903).

Fix a issues around crypto API simplifications on .NET Core spotted by new analzyers.

Co-authored-by: Rainer Sigwald <[email protected]>
  • Loading branch information
benvillalobos and rainersigwald authored Sep 19, 2022
1 parent 4a26ca3 commit cc3db35
Show file tree
Hide file tree
Showing 20 changed files with 81 additions and 38 deletions.
16 changes: 15 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@

<PropertyGroup>
<FullFrameworkTFM>net472</FullFrameworkTFM>

<!--
When updating the version of .NET Core for MSBuild, this property is the 'source of truth'.
Other locations to update the version number:
global.json
eng/cibuild_bootstrapped_msbuild.ps1
eng/cibuild_bootstrapped_msbuild.sh
scripts/Deploy-MSBuild.ps1
src/Framework/README.md
src/Utilities/README.md
-->
<LatestDotNetCoreForMSBuild>net7.0</LatestDotNetCoreForMSBuild>
</PropertyGroup>

<PropertyGroup>
Expand All @@ -36,9 +48,11 @@
CS1701 and CS1702 are by default ignored by Microsoft.NET.Sdk, but if you define the NoWarn property in Directory.Build.props,
you don't get those defaults.
SYSLIB0011: Removing binary formatter will happen as part of a larger .NET-wide effort.
SYSLIB0037 & SYSLIB0044: The deprecated AssemblyName members could require a bigger refactor for us: https://github.com/dotnet/msbuild/issues/7902
RS0016 & RS0017: Roslyn analyzers seem to be bugged, claiming that API's that exist don't and vise-versa: https://github.com/dotnet/msbuild/issues/7903
-->

<NoWarn>$(NoWarn);NU1603;NU5105;1701;1702;SYSLIB0011</NoWarn>
<NoWarn>$(NoWarn);NU1603;NU5105;1701;1702;SYSLIB0011;SYSLIB0037;SYSLIB0044;RS0016;RS0017;</NoWarn>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Debug-MONO'">
Expand Down
2 changes: 1 addition & 1 deletion eng/BootStrapMSBuild.targets
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@
Copy it from "next to MSBuild" in the pre-bootstrap SDK to our little weirdo bootstrap
layout next to the SDK tasks, so it can get loaded by the SDK tasks that need it. -->
<Copy SourceFiles="$(DOTNET_INSTALL_DIR)\sdk\$(DotNetCliVersion)\Microsoft.Extensions.DependencyModel.dll"
DestinationFolder="$(BootstrapDestination)Sdks\Microsoft.NET.Sdk\tools\net6.0" />
DestinationFolder="$(BootstrapDestination)Sdks\Microsoft.NET.Sdk\tools\$(LatestDotNetCoreForMSBuild)" />

<Copy SourceFiles="@(InstalledExtensions)"
DestinationFolder="$(BootstrapDestination)Current\%(RecursiveDir)" />
Expand Down
2 changes: 1 addition & 1 deletion eng/cibuild_bootstrapped_msbuild.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ try {
else
{
$buildToolPath = $dotnetExePath
$buildToolCommand = Join-Path $bootstrapRoot "net6.0\MSBuild\MSBuild.dll"
$buildToolCommand = Join-Path $bootstrapRoot "net7.0\MSBuild\MSBuild.dll"
$buildToolFramework = "netcoreapp3.1"
}

Expand Down
2 changes: 1 addition & 1 deletion eng/cibuild_bootstrapped_msbuild.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ bootstrapRoot="$Stage1Dir/bin/bootstrap"
if [ $host_type = "core" ]
then
_InitializeBuildTool="$_InitializeDotNetCli/dotnet"
_InitializeBuildToolCommand="$bootstrapRoot/net6.0/MSBuild/MSBuild.dll"
_InitializeBuildToolCommand="$bootstrapRoot/net7.0/MSBuild/MSBuild.dll"
_InitializeBuildToolFramework="netcoreapp3.1"
elif [ $host_type = "mono" ]
then
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"allowPrerelease": true
},
"tools": {
"dotnet": "6.0.401",
"dotnet": "7.0.100-rc.1.22431.12",
"vs": {
"version": "17.2.1"
},
Expand Down
2 changes: 1 addition & 1 deletion scripts/Deploy-MSBuild.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ else {
if ($runtime -eq "Desktop") {
$targetFramework = "net472"
} else {
$targetFramework = "net6.0"
$targetFramework = "net7.0"
}

$bootstrapBinDirectory = "artifacts\bin\MSBuild.Bootstrap\$configuration\$targetFramework"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,32 +85,32 @@ public static IList<RMock> ExportCollection<T, RMock>(this ProjectCollectionLink
}


public static IDictionary<key, T> ImportDictionary<key, T, RMock>(this ProjectCollectionLinker importer, IDictionary<key, RMock> source)
where T : class
where RMock : MockLinkRemoter<T>, new()
public static IDictionary<TKey, TValue> ImportDictionary<TKey, TValue, RMock>(this ProjectCollectionLinker importer, IDictionary<TKey, RMock> source)
where TValue : class
where RMock : MockLinkRemoter<TValue>, new()
{
if (source == null) return null;
// Just copy ...
Dictionary<key, T> result = new Dictionary<key, T>();
Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();
foreach (var sRemoter in source)
{
var value = importer.Import<T, RMock>(sRemoter.Value);
var value = importer.Import<TValue, RMock>(sRemoter.Value);
result.Add(sRemoter.Key, value);
}

return result;
}

public static IDictionary<key, RMock> ExportDictionary<key, T, RMock>(this ProjectCollectionLinker exporter, IDictionary<key, T> source)
where T : class
where RMock : MockLinkRemoter<T>, new()
public static IDictionary<TKey, RMock> ExportDictionary<TKey, TValue, RMock>(this ProjectCollectionLinker exporter, IDictionary<TKey, TValue> source)
where TValue : class
where RMock : MockLinkRemoter<TValue>, new()
{
if (source == null) return null;
// Just copy ...
Dictionary<key, RMock> result = new Dictionary<key, RMock>();
Dictionary<TKey, RMock> result = new Dictionary<TKey, RMock>();
foreach (var s in source)
{
var valueRemoter = exporter.Export<T, RMock>(s.Value);
var valueRemoter = exporter.Export<TValue, RMock>(s.Value);
result.Add(s.Key, valueRemoter);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@
<ProjectReference Include="..\Samples\TaskWithDependency\TaskWithDependency.csproj" Private="false" ReferenceOutputAssembly="false" OutputItemType="TaskWithDependencyResolvedProjectReferencePath">
<SetTargetFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">TargetFramework=$(FullFrameworkTFM)</SetTargetFramework>
<SetTargetFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework' and '$(MonoBuild)' == 'true'">TargetFramework=$(FullFrameworkTFM)</SetTargetFramework>
<SetTargetFramework Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">TargetFramework=net6.0</SetTargetFramework>
<SetTargetFramework Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">TargetFramework=$(LatestDotNetCoreForMSBuild)</SetTargetFramework>
</ProjectReference>
<ProjectReference Include="..\Samples\PortableTask\PortableTask.csproj" Private="false" ReferenceOutputAssembly="false" OutputItemType="PortableTaskResolvedProjectReferencePath" />

<ProjectReference Include="..\Samples\ProjectCachePlugin\ProjectCachePlugin.csproj" Private="false" ReferenceOutputAssembly="false">
<SetTargetFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">TargetFramework=$(FullFrameworkTFM)</SetTargetFramework>
<SetTargetFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework' and '$(MonoBuild)' == 'true'">TargetFramework=$(FullFrameworkTFM)</SetTargetFramework>
<SetTargetFramework Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">TargetFramework=net6.0</SetTargetFramework>
<SetTargetFramework Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">TargetFramework=$(LatestDotNetCoreForMSBuild)</SetTargetFramework>
</ProjectReference>
</ItemGroup>

Expand Down
4 changes: 2 additions & 2 deletions src/Build/Definition/ToolsetReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
using Microsoft.Build.Framework;
using Microsoft.Build.Internal;
using Microsoft.Build.Shared.FileSystem;
using error = Microsoft.Build.Shared.ErrorUtilities;
using ErrorUtils = Microsoft.Build.Shared.ErrorUtilities;
using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
using InvalidToolsetDefinitionException = Microsoft.Build.Exceptions.InvalidToolsetDefinitionException;
using ReservedPropertyNames = Microsoft.Build.Internal.ReservedPropertyNames;
Expand Down Expand Up @@ -366,7 +366,7 @@ internal string ReadToolsets
out string defaultOverrideToolsVersion
)
{
error.VerifyThrowArgumentNull(toolsets, "Toolsets");
ErrorUtils.VerifyThrowArgumentNull(toolsets, "Toolsets");

ReadEachToolset(toolsets, globalProperties, initialProperties, accumulateProperties);

Expand Down
2 changes: 1 addition & 1 deletion src/Build/Microsoft.Build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Import Project="..\Shared\DebuggingSources.proj" />

<PropertyGroup>
<TargetFrameworks>$(FullFrameworkTFM);net6.0</TargetFrameworks>
<TargetFrameworks>$(FullFrameworkTFM);$(LatestDotNetCoreForMSBuild)</TargetFrameworks>
<TargetFrameworks Condition="'$(MonoBuild)'=='true'">$(RuntimeOutputTargetFrameworks)</TargetFrameworks>
<RootNamespace>Microsoft.Build</RootNamespace>
<AssemblyName>Microsoft.Build</AssemblyName>
Expand Down
3 changes: 2 additions & 1 deletion src/Directory.BeforeCommon.targets
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<DefineConstants Condition="'$(MonoBuild)' != 'true'">$(DefineConstants);FEATURE_COMPILE_IN_TESTS</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_CONSTRAINED_EXECUTION</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_CODETASKFACTORY</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_CRYPTOGRAPHIC_FACTORY_ALGORITHM_NAMES</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_CULTUREINFO_GETCULTURES</DefineConstants>
<DefineConstants Condition="'$(MonoBuild)' != 'true' and '$(MachineIndependentBuild)' != 'true'">$(DefineConstants);FEATURE_ENCODING_DEFAULT</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_ENVIRONMENT_SYSTEMDIRECTORY</DefineConstants>
Expand Down Expand Up @@ -93,7 +94,7 @@
<DefineConstants>$(DefineConstants);FEATURE_SYMLINK_TARGET</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1' or '$(TargetFramework)' == 'net6.0'">
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1' or '$(TargetFramework)' == '$(LatestDotNetCoreForMSBuild)'">
<DefineConstants>$(DefineConstants);FEATURE_PIPEOPTIONS_CURRENTUSERONLY</DefineConstants>
<DefineConstants Condition="'$(MachineIndependentBuild)' != 'true'">$(DefineConstants);FEATURE_NODE_REUSE</DefineConstants>
</PropertyGroup>
Expand Down
6 changes: 3 additions & 3 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@
<Platforms>AnyCPU;x64;arm64</Platforms>

<!-- Defaults for target frameworks and architecture -->
<LibraryTargetFrameworks>$(FullFrameworkTFM);net6.0;netstandard2.0</LibraryTargetFrameworks>
<LibraryTargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">net6.0;netstandard2.0</LibraryTargetFrameworks>
<LibraryTargetFrameworks>$(FullFrameworkTFM);$(LatestDotNetCoreForMSBuild);netstandard2.0</LibraryTargetFrameworks>
<LibraryTargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(LatestDotNetCoreForMSBuild);netstandard2.0</LibraryTargetFrameworks>
<LibraryTargetFrameworks Condition="'$(MonoBuild)'=='true'">$(FullFrameworkTFM);netstandard2.0</LibraryTargetFrameworks>
<PlatformTarget>AnyCPU</PlatformTarget>

<!-- Target frameworks for Exe and unit test projects (ie projects with runtime output) -->
<RuntimeOutputTargetFrameworks>net6.0</RuntimeOutputTargetFrameworks>
<RuntimeOutputTargetFrameworks>net7.0</RuntimeOutputTargetFrameworks>
<RuntimeOutputTargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(FullFrameworkTFM);$(RuntimeOutputTargetFrameworks)</RuntimeOutputTargetFrameworks>
<RuntimeOutputTargetFrameworks Condition="'$(MonoBuild)' == 'true'">$(FullFrameworkTFM)</RuntimeOutputTargetFrameworks>

Expand Down
2 changes: 1 addition & 1 deletion src/Framework/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ The items in this namespace are primarily base-level classes and interfaces shar
[`ITask`](https://docs.microsoft.com/dotnet/api/microsoft.build.framework.itask), and [`ILogger`](https://docs.microsoft.com/dotnet/api/microsoft.build.framework.ilogger).

### netstandard2.0 target
The `netstandard2.0` target of this build is configured only to output reference assemblies; at runtime MSBuild will be `net6.0` or `net472`. Please use the `net6.0`-targeted assemblies for .NET Core 6+ scenarios.
The `netstandard2.0` target of this build is configured only to output reference assemblies; at runtime MSBuild will be `net7.0` or `net472`. Please use the `net7.0`-targeted assemblies for .NET Core 6+ scenarios.

For context, see https://github.com/dotnet/msbuild/pull/6148
2 changes: 1 addition & 1 deletion src/MSBuild.Bootstrap/MSBuild.Bootstrap.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<Target Name="UpdateMSBuildDepsFile" AfterTargets="Build" Condition="'$(MonoBuild)' != 'true' and ($([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'netcoreapp2.1')) or '$(TargetFramework)' == 'netstandard2.0')">
<Copy SourceFiles="$(OutputPath)$(AssemblyName).deps.json" DestinationFiles="$(OutputPath)MSBuild.deps.json" />
</Target>
<Target Name="UpdatePublishedMSBuildDepsFile" AfterTargets="Publish" Condition="'$(TargetFramework)' == 'net6.0'">
<Target Name="UpdatePublishedMSBuildDepsFile" AfterTargets="Publish" Condition="'$(TargetFramework)' == '$(LatestDotNetCoreForMSBuild)'">
<Copy SourceFiles="$(PublishDir)$(AssemblyName).deps.json" DestinationFiles="$(PublishDir)MSBuild.deps.json" />
</Target>

Expand Down
2 changes: 1 addition & 1 deletion src/Package/Localization/Localization.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework Condition="$(MonoBuild) != 'true'">net6.0</TargetFramework>
<TargetFramework Condition="$(MonoBuild) != 'true'">$(LatestDotNetCoreForMSBuild)</TargetFramework>
<TargetFramework Condition="$(MonoBuild) == 'true'">net472</TargetFramework>
<NuspecFile>Microsoft.Build.Localization.nuspec</NuspecFile>
<IsShipping>false</IsShipping>
Expand Down
4 changes: 2 additions & 2 deletions src/Samples/ProjectCachePlugin/ProjectCachePlugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<CopyNuGetImplementations>false</CopyNuGetImplementations>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(FullFrameworkTFM);net6.0</TargetFrameworks>
<TargetFrameworks>$(LatestDotNetCoreForMSBuild)</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(FullFrameworkTFM);$(LatestDotNetCoreForMSBuild)</TargetFrameworks>
<TargetFrameworks Condition="'$(MonoBuild)'=='true'">$(RuntimeOutputTargetFrameworks)</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
Expand Down
6 changes: 5 additions & 1 deletion src/Tasks/BootstrapperUtil/BootstrapperBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1645,7 +1645,11 @@ private static string GetFileHash(string filePath)
// the .NET Framework we are targeting. In ideal situations, bootstrapper files will be
// pre-signed anwyay; this is a fallback in case we ever encounter a bootstrapper that is
// not signed.
System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create("System.Security.Cryptography.SHA256CryptoServiceProvider");
System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create(
#if FEATURE_CRYPTOGRAPHIC_FACTORY_ALGORITHM_NAMES
"System.Security.Cryptography.SHA256CryptoServiceProvider"
#endif
);

using (Stream s = fi.OpenRead())
{
Expand Down
12 changes: 10 additions & 2 deletions src/Tasks/ManifestUtil/Util.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,19 @@ private static void GetFileInfoImpl(string path, string targetFrameWorkVersion,

if (string.IsNullOrEmpty(targetFrameWorkVersion) || CompareFrameworkVersions(targetFrameWorkVersion, Constants.TargetFrameworkVersion40) <= 0)
{
hashAlg = SHA1.Create("System.Security.Cryptography.SHA1CryptoServiceProvider");
hashAlg = SHA1.Create(
#if FEATURE_CRYPTOGRAPHIC_FACTORY_ALGORITHM_NAMES
"System.Security.Cryptography.SHA1CryptoServiceProvider"
#endif
);
}
else
{
hashAlg = SHA256.Create("System.Security.Cryptography.SHA256CryptoServiceProvider");
hashAlg = SHA256.Create(
#if FEATURE_CRYPTOGRAPHIC_FACTORY_ALGORITHM_NAMES
"System.Security.Cryptography.SHA256CryptoServiceProvider"
#endif
);
}
byte[] hashBytes = hashAlg.ComputeHash(s);
hash = Convert.ToBase64String(hashBytes);
Expand Down
24 changes: 20 additions & 4 deletions src/Tasks/ManifestUtil/mansign2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,11 @@ private static byte[] ComputeHashFromManifest(XmlDocument manifestDom, bool oldF

if (useSha256)
{
using (SHA256 sha2 = SHA256.Create("System.Security.Cryptography.SHA256CryptoServiceProvider"))
using (SHA256 sha2 = SHA256.Create(
#if FEATURE_CRYPTOGRAPHIC_FACTORY_ALGORITHM_NAMES
"System.Security.Cryptography.SHA256CryptoServiceProvider"
#endif
))
{
byte[] hash = sha2.ComputeHash(exc.GetOutput() as MemoryStream);
if (hash == null)
Expand All @@ -568,7 +572,11 @@ private static byte[] ComputeHashFromManifest(XmlDocument manifestDom, bool oldF
}
else
{
using (SHA1 sha1 = SHA1.Create("System.Security.Cryptography.SHA1CryptoServiceProvider"))
using (SHA1 sha1 = SHA1.Create(
#if FEATURE_CRYPTOGRAPHIC_FACTORY_ALGORITHM_NAMES
"System.Security.Cryptography.SHA1CryptoServiceProvider"
#endif
))
{
byte[] hash = sha1.ComputeHash(exc.GetOutput() as MemoryStream);
if (hash == null)
Expand Down Expand Up @@ -603,7 +611,11 @@ private static byte[] ComputeHashFromManifest(XmlDocument manifestDom, bool oldF

if (useSha256)
{
using (SHA256 sha2 = SHA256.Create("System.Security.Cryptography.SHA256CryptoServiceProvider"))
using (SHA256 sha2 = SHA256.Create(
#if FEATURE_CRYPTOGRAPHIC_FACTORY_ALGORITHM_NAMES
"System.Security.Cryptography.SHA256CryptoServiceProvider"
#endif
))
{
byte[] hash = sha2.ComputeHash(exc.GetOutput() as MemoryStream);
if (hash == null)
Expand All @@ -616,7 +628,11 @@ private static byte[] ComputeHashFromManifest(XmlDocument manifestDom, bool oldF
}
else
{
using (SHA1 sha1 = SHA1.Create("System.Security.Cryptography.SHA1CryptoServiceProvider"))
using (SHA1 sha1 = SHA1.Create(
#if FEATURE_CRYPTOGRAPHIC_FACTORY_ALGORITHM_NAMES
"System.Security.Cryptography.SHA1CryptoServiceProvider"
#endif
))
{
byte[] hash = sha1.ComputeHash(exc.GetOutput() as MemoryStream);
if (hash == null)
Expand Down
2 changes: 1 addition & 1 deletion src/Utilities/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ This package contains `Microsoft.Build.Utilities.Core.dll`, which defines helper
* [`Logger`](https://docs.microsoft.com/dotnet/api/microsoft.build.utilities.logger), a base class for custom logging functionality.

### netstandard2.0 target
The `netstandard2.0` target of this build is configured only to output reference assemblies; at runtime MSBuild will be `net6.0` or `net472`. Please use the `net6.0`-targeted assemblies for .NET Core 6+ scenarios.
The `netstandard2.0` target of this build is configured only to output reference assemblies; at runtime MSBuild will be `net7.0` or `net472`. Please use the `net7.0`-targeted assemblies for .NET Core 6+ scenarios.

For context, see https://github.com/dotnet/msbuild/pull/6148

0 comments on commit cc3db35

Please sign in to comment.