Skip to content

Commit

Permalink
Use ProjectReference items in inbox src projects
Browse files Browse the repository at this point in the history
There are numerous benefits in using ProjectReferences consistently
in all libraries:

1. An upfront "libs" build isn't required anymore and sfx libraries
   can now directly be built from a fresh clone (with dotnet build or inside
   VS). I.e. `dotnet.cmd pack src/libraries/System.Text.Json/src/` is
   now possible from a fresh clone.
2. Because of 1), we can now add a solution file for the whole sfx that
   can directly be opened and worked with from a fresh clone.
3. The overall root build is faster. Without this change, the build
   order was sfx-ref -> (sfx-src & sfx-gen) so the shared framework
   reference projects first had to be built and only then the sfx src
   and gen projects could be built. Now with this change, everything
   gets built in parallel.
4. Using P2Ps means that we now follow the common and well supported
   msbuild and SDK path instead of repo customization.

The downside of doing this is that the dependency graph gets bigger,
meaning that more projects get incrementally built when doing a "dotnet
build". This is nothing new and the SDK team recommends to pass the
"--no-dependencies" flag to "dotnet build" if incrementally (no-op)
building the additional dependency nodes is noticeable.
This is less of a concern inside VS as that has a "fast up-to-date check"
feature that doesn't even attempt to build projects that didn't change.

For VS, really the only noticeable change is that the solution explorer
now lists more projects and that when opening a solution, more projects
need to be evaluated. But, that should be fast enough when using an
up-to-date version of VS.

-

A few observations that make the change more involved:

There's a NuGet client bug that requires a few workarounds:
NuGet/Home#10368
Because of that, direct package refs to System.Numerics.Vectors
and in a few cases to System.Memory are required.

We should fix the NuGet tooling issue to eventually get rid of the
workarounds introduced with this commit. There was already a PR
in NuGet.Client open but it was closed because of staleness.

-

System.Data.Common.csproj is a weird project as it references CoreLib
and reference assemblies. I had to disable transitive project references
in order for type universes to not clash and explicitly set
CompileUsingReferenceAssemblies=true as that gets set to false when the
library explicitly references CoreLib.
  • Loading branch information
ViktorHofer committed Aug 17, 2024
1 parent 2691fc8 commit 8a94707
Show file tree
Hide file tree
Showing 104 changed files with 860 additions and 837 deletions.
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
<SystemDrawingCommonVersion>8.0.0</SystemDrawingCommonVersion>
<SystemIOFileSystemAccessControlVersion>5.0.0</SystemIOFileSystemAccessControlVersion>
<SystemMemoryVersion>4.5.5</SystemMemoryVersion>
<SystemNumericsVectorsVersion>4.5.0</SystemNumericsVectorsVersion>
<SystemReflectionMetadataVersion>9.0.0-rc.1.24410.5</SystemReflectionMetadataVersion>
<SystemReflectionMetadataLoadContextVersion>9.0.0-rc.1.24410.5</SystemReflectionMetadataLoadContextVersion>
<SystemSecurityAccessControlVersion>6.0.0</SystemSecurityAccessControlVersion>
Expand Down
6 changes: 5 additions & 1 deletion eng/generators.targets
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
'$(DisableImplicitFrameworkReferences)' == 'true' and
(
'@(Reference->AnyHaveMetadataValue('Identity', 'System.Runtime.InteropServices'))' == 'true' or
'@(ProjectReference->AnyHaveMetadataValue('Filename', 'System.Runtime.InteropServices'))' == 'true' or
'@(ProjectReference->AnyHaveMetadataValue('Identity', '$(CoreLibProject)'))' == 'true'
)
)
Expand All @@ -39,7 +40,10 @@
'$(MSBuildProjectExtension)' == '.csproj' and
(
'$(DisableImplicitFrameworkReferences)' == 'true' and
'@(Reference->AnyHaveMetadataValue('Identity', 'System.Runtime.InteropServices'))' == 'true'
(
'@(Reference->AnyHaveMetadataValue('Identity', 'System.Runtime.InteropServices'))' == 'true' or
'@(ProjectReference->AnyHaveMetadataValue('Filename', 'System.Runtime.InteropServices'))' == 'true'
)
)" />
</ItemGroup>

Expand Down
5 changes: 3 additions & 2 deletions eng/resolveContract.targets
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
<!-- Allow P2Ps that target a source project to build against the corresponding ref project. -->
<Target Name="AnnotateTargetPathWithTargetPlatformMonikerWithReferenceAssembly"
Condition="'$(AnnotateTargetPathWithContract)' == 'true'"
DependsOnTargets="ResolveProjectReferences"
AfterTargets="GetTargetPathWithTargetPlatformMoniker">
DependsOnTargets="ResolveProjectReferences;GetTargetPathWithTargetPlatformMoniker"
BeforeTargets="GetTargetPath">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker ReferenceAssembly="@(ResolvedMatchingContract)" />
</ItemGroup>
Expand Down Expand Up @@ -119,6 +119,7 @@
<PropertyGroup>
<!-- Let GenFacades use roslyn from the toolset package as it loads sources which might require newer language features. -->
<GenFacadesUseRoslynToolsetPackagePath>true</GenFacadesUseRoslynToolsetPackagePath>
<GenFacadesReferencePathItemName>ReferencePathWithRefAssemblies</GenFacadesReferencePathItemName>
</PropertyGroup>

<!-- ##### GenAPI settings ##### -->
Expand Down
20 changes: 0 additions & 20 deletions eng/targetingpacks.targets
Original file line number Diff line number Diff line change
Expand Up @@ -89,26 +89,6 @@
Condition="'$(UseLocalAppHostPack)' == 'true' and '@(KnownAppHostPack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))' != 'true'" />
</ItemGroup>

<!-- Simple name references will be resolved from the targeting pack folders and should never be copied to the output. -->
<ItemGroup>
<Reference Update="@(Reference)">
<Private Condition="'%(Reference.Extension)' != '.dll'">false</Private>
</Reference>
</ItemGroup>

<!-- Add the resolved targeting pack to the assembly search path. -->
<Target Name="UseTargetingPackForAssemblySearchPaths"
BeforeTargets="ResolveAssemblyReferences;
DesignTimeResolveAssemblyReferences"
Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
'$(TargetFrameworkVersion)' == 'v$(NetCoreAppCurrentVersion)' and
'$(DisableImplicitFrameworkReferences)' == 'true'">
<PropertyGroup>
<AssemblySearchPaths>$(AssemblySearchPaths);$(MicrosoftNetCoreAppRefPackRefDir.TrimEnd('/\'))</AssemblySearchPaths>
<DesignTimeAssemblySearchPaths>$(DesignTimeAssemblySearchPaths);$(MicrosoftNetCoreAppRefPackRefDir.TrimEnd('/\'))</DesignTimeAssemblySearchPaths>
</PropertyGroup>
</Target>

<!--
SDK tries to download the ILCompiler runtime packs.
TODO: Remove this target when a 9.0.100 SDK is consumed that respects EnableRuntimePackDownload for the ILCompiler.
Expand Down
7 changes: 7 additions & 0 deletions src/libraries/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,11 @@
</ItemGroup>
</When>
</Choose>

<!-- Required to work around https://github.com/NuGet/Home/issues/10368. -->
<ItemGroup Condition="('$(IsTestProject)' == 'true' or '$(IsTestSupportProject)' == 'true') and '$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" PrivateAssets="all" Condition="'@(PackageReference->AnyHaveMetadataValue('Identity', 'System.Memory'))' != 'true'" />
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" PrivateAssets="all" Condition="'@(PackageReference->AnyHaveMetadataValue('Identity', 'System.Numerics.Vectors'))' != 'true'" />
</ItemGroup>

</Project>
30 changes: 16 additions & 14 deletions src/libraries/Microsoft.CSharp/src/Microsoft.CSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -238,23 +238,25 @@
<Compile Include="Microsoft\CSharp\RuntimeBinder\ComInterop\VariantArgBuilder.cs" />
<Compile Include="Microsoft\CSharp\RuntimeBinder\ComInterop\VariantArray.cs" />
<Compile Include="Microsoft\CSharp\RuntimeBinder\ComInterop\VariantBuilder.cs" />

<Reference Include="System.Reflection.Emit" />
<Reference Include="System.Reflection.Emit.ILGeneration" />
<Reference Include="System.Reflection.Emit.Lightweight" />
<Reference Include="System.Reflection.Primitives" />
</ItemGroup>

<ItemGroup>
<Reference Include="System.Collections" />
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.Linq" />
<Reference Include="System.Linq.Expressions" />
<Reference Include="System.Memory" />
<Reference Include="System.ObjectModel" />
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.InteropServices" />
<Reference Include="System.Threading" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Collections\src\System.Collections.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Collections.Concurrent\src\System.Collections.Concurrent.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Linq\src\System.Linq.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Linq.Expressions\src\System.Linq.Expressions.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Memory\src\System.Memory.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.ObjectModel\src\System.ObjectModel.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Runtime\src\System.Runtime.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Runtime.InteropServices\src\System.Runtime.InteropServices.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Threading\src\System.Threading.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(EnableComBinder)'=='true'">
<ProjectReference Include="$(LibrariesProjectRoot)System.Reflection.Emit\src\System.Reflection.Emit.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Reflection.Emit.ILGeneration\src\System.Reflection.Emit.ILGeneration.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Reflection.Emit.Lightweight\src\System.Reflection.Emit.Lightweight.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Reflection.Primitives\src\System.Reflection.Primitives.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@
<ProjectReference Include="$(LibrariesProjectRoot)System.Text.Json\src\System.Text.Json.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<!-- Required to workaround https://github.com/NuGet/Home/issues/10368. -->
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" PrivateAssets="all" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
Link="Common\System\ThrowHelper.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<!-- Required to workaround https://github.com/NuGet/Home/issues/10368. -->
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<Content Include="buildTransitive\$(MSBuildProjectName).*"
PackagePath="buildTransitive\netstandard2.0\;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ By default, the dependency manifest contains information about the application's
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<PackageReference Include="System.Buffers" Version="$(SystemBuffersVersion)" />
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
<!-- Required to workaround https://github.com/NuGet/Home/issues/10368. -->
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" PrivateAssets="all" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Logging.EventLog\src\Microsoft.Extensions.Logging.EventLog.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<!-- Required to workaround https://github.com/NuGet/Home/issues/10368. -->
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" PrivateAssets="all" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">
<ProjectReference Include="$(LibrariesProjectRoot)System.ServiceProcess.ServiceController\src\System.ServiceProcess.ServiceController.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Bcl.AsyncInterfaces\src\Microsoft.Bcl.AsyncInterfaces.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<!-- Required to workaround https://github.com/NuGet/Home/issues/10368. -->
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" PrivateAssets="all" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<Reference Include="System.Runtime" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,11 @@
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Bcl.AsyncInterfaces\src\Microsoft.Bcl.AsyncInterfaces.csproj" />
<PackageReference Include="System.Buffers" Version="$(SystemBuffersVersion)" />
<!-- Required to workaround https://github.com/NuGet/Home/issues/10368. -->
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" PrivateAssets="all" />

<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Bcl.AsyncInterfaces\src\Microsoft.Bcl.AsyncInterfaces.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Bcl.AsyncInterfaces\src\Microsoft.Bcl.AsyncInterfaces.csproj" />
<!-- Required to workaround https://github.com/NuGet/Home/issues/10368. -->
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" PrivateAssets="all" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemRuntimeCompilerServicesUnsafeVersion)" />

<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Bcl.AsyncInterfaces\src\Microsoft.Bcl.AsyncInterfaces.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)</TargetFrameworks>
<NoVbRuntimeReference>true</NoVbRuntimeReference>
<VBRuntime>None</VBRuntime>
<OptionStrict>On</OptionStrict>
<OptionExplicit>On</OptionExplicit>
<OptionInfer>Off</OptionInfer>
<MyType>Empty</MyType>
<OptionCompare>Binary</OptionCompare>
<WarningsNotAsErrors>42025</WarningsNotAsErrors>
<WarningsNotAsErrors>$(WarningsNotAsErrors),42025</WarningsNotAsErrors>
<DefineConstants>$(DefineConstants),LATEBINDING=True</DefineConstants>
<NoWarn>$(NoWarn),CA1052,CA1510,CA1810,CA1822,CA2200</NoWarn>
<!-- Avoid unused fields warnings in Unix build -->
<AssemblyName>Microsoft.VisualBasic.Core</AssemblyName>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<RootNamespace />
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppCurrent)-windows</TargetFrameworks>
<Nullable>disable</Nullable>
<UseCompilerGeneratedDocXmlFile>false</UseCompilerGeneratedDocXmlFile>
</PropertyGroup>

<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
<PropertyGroup>
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
<ILLinkDescriptorsXml Condition="'$(TargetPlatformIdentifier)' == 'windows'">$(MSBuildProjectDirectory)\ILLink\ILLink.Descriptors.Windows.xml</ILLinkDescriptorsXml>
<DefineConstants Condition="'$(TargetPlatformIdentifier)' == 'windows'">$(DefineConstants),TARGET_WINDOWS=True</DefineConstants>
<NoWarn Condition="'$(TargetPlatformIdentifier)' != 'windows'">$(NoWarn);CA1823</NoWarn>
</PropertyGroup>

<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'">
<Compile Include="Microsoft\VisualBasic\Helpers\NativeMethods.vb" />
<Compile Include="Microsoft\VisualBasic\Helpers\NativeTypes.vb" />
<Compile Include="Microsoft\VisualBasic\Helpers\SafeNativeMethods.vb" />
<Compile Include="Microsoft\VisualBasic\Helpers\UnsafeNativeMethods.vb" />
</ItemGroup>

<ItemGroup>
<Compile Include="Microsoft\VisualBasic\Collection.vb" />
<Compile Include="Microsoft\VisualBasic\ComClassAttribute.vb" />
Expand Down Expand Up @@ -100,25 +104,27 @@
<Compile Include="Microsoft\VisualBasic\VBFixedStringAttribute.vb" />
<Compile Include="Microsoft\VisualBasic\VBMath.vb" />
</ItemGroup>

<ItemGroup>
<Reference Include="Microsoft.Win32.Primitives" />
<Reference Include="Microsoft.Win32.Registry" />
<Reference Include="System.Collections" />
<Reference Include="System.Collections.NonGeneric" />
<Reference Include="System.Collections.Specialized" />
<Reference Include="System.ComponentModel.Primitives" />
<Reference Include="System.Diagnostics.Process" />
<Reference Include="System.IO.FileSystem.DriveInfo" />
<Reference Include="System.Linq" />
<Reference Include="System.Linq.Expressions" />
<Reference Include="System.ObjectModel" />
<Reference Include="System.Reflection.Emit.ILGeneration" />
<Reference Include="System.Reflection.Emit.Lightweight" />
<Reference Include="System.Reflection.Primitives" />
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.InteropServices" />
<Reference Include="System.Text.RegularExpressions" />
<Reference Include="System.Threading" />
<Reference Include="System.Threading.Thread" />
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Win32.Primitives\src\Microsoft.Win32.Primitives.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Win32.Registry\src\Microsoft.Win32.Registry.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Collections.NonGeneric\src\System.Collections.NonGeneric.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Collections.Specialized\src\System.Collections.Specialized.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Collections\src\System.Collections.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.ComponentModel.Primitives\src\System.ComponentModel.Primitives.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Diagnostics.Process\src\System.Diagnostics.Process.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.IO.FileSystem.DriveInfo\src\System.IO.FileSystem.DriveInfo.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Linq.Expressions\src\System.Linq.Expressions.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Linq\src\System.Linq.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.ObjectModel\src\System.ObjectModel.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Reflection.Emit.ILGeneration\src\System.Reflection.Emit.ILGeneration.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Reflection.Emit.Lightweight\src\System.Reflection.Emit.Lightweight.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Reflection.Primitives\src\System.Reflection.Primitives.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Runtime.InteropServices\src\System.Runtime.InteropServices.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Runtime\src\System.Runtime.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Text.RegularExpressions\src\System.Text.RegularExpressions.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Threading.Thread\src\System.Threading.Thread.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Threading\src\System.Threading.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -732,19 +732,19 @@ EmptyFindString:
While Start < ExpressionLength
If Replacements = Count Then
'We've made all the replacements the caller wanted so append the remaining string
Builder.Append(Expression.Substring(Start))
Builder.Append(Expression.AsSpan(Start))
Exit While
End If

FindLocation = Comparer.IndexOf(Expression, Find, Start, CompareFlags)
If FindLocation < 0 Then
'We didn't find the Find string append the rest of the string
Builder.Append(Expression.Substring(Start))
Builder.Append(Expression.AsSpan(Start))
Exit While
Else
'Append to our string builder everything up to the found string, then
'append the replacement
Builder.Append(Expression.Substring(Start, FindLocation - Start))
Builder.Append(Expression.AsSpan(Start, FindLocation - Start))
Builder.Append(Replacement)
Replacements += 1

Expand Down
Loading

0 comments on commit 8a94707

Please sign in to comment.