Skip to content

Commit 83f8a5f

Browse files
committed
Merge from master
2 parents c637f45 + ac226ee commit 83f8a5f

File tree

58 files changed

+1205
-364
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1205
-364
lines changed

.github/actions/spelling/expect.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ auxdata
4646
awgpm
4747
awgs
4848
azurewebsites
49+
bak
4950
Baz
51+
bbb
5052
bcp
5153
BEBOM
5254
BEFACEF
@@ -74,6 +76,7 @@ buildtrees
7476
cancelledbyuser
7577
casemap
7678
casemappings
79+
ccc
7780
cch
7881
centralus
7982
certmgr
@@ -395,6 +398,7 @@ packageinusebyapplication
395398
PACL
396399
PARAMETERMAP
397400
pathparts
401+
pathtree
398402
Patil
399403
pbstr
400404
pcb
@@ -604,7 +608,7 @@ website
604608
wesome
605609
wfsopen
606610
wgetenv
607-
Whatif
611+
whatif
608612
WIC
609613
wildcards
610614
WINAPI

samples/MinimalCallers/C++/WinGet-InProc/WinGet-InProc.vcxproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@
3838
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
3939
<PropertyGroup Label="Configuration">
4040
<ConfigurationType>Application</ConfigurationType>
41-
<PlatformToolset>v143</PlatformToolset>
42-
<CharacterSet>Unicode</CharacterSet>
4341
</PropertyGroup>
4442
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
4543
<UseDebugLibraries>true</UseDebugLibraries>

samples/MinimalCallers/C++/WinGet-OutOfProc/WinGet-OutOfProc.vcxproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@
3838
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
3939
<PropertyGroup Label="Configuration">
4040
<ConfigurationType>Application</ConfigurationType>
41-
<PlatformToolset>v143</PlatformToolset>
42-
<CharacterSet>Unicode</CharacterSet>
4341
</PropertyGroup>
4442
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
4543
<UseDebugLibraries>true</UseDebugLibraries>

samples/WinGetUWPCaller/WinGetUWPCaller/WinGetUWPCaller.vcxproj

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@
4646
</ItemGroup>
4747
<PropertyGroup Label="Configuration">
4848
<ConfigurationType>Application</ConfigurationType>
49-
<PlatformToolset>v140</PlatformToolset>
50-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
51-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
52-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '17.0'">v143</PlatformToolset>
53-
<CharacterSet>Unicode</CharacterSet>
5449
</PropertyGroup>
5550
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
5651
<UseDebugLibraries>true</UseDebugLibraries>

src/AppInstallerCLI.sln

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Project", "Project", "{8D53
3838
..\azure-pipelines.yml = ..\azure-pipelines.yml
3939
..\cgmanifest.json = ..\cgmanifest.json
4040
Directory.Build.props = Directory.Build.props
41+
Get-VcxprojNugetPackageVersions.ps1 = Get-VcxprojNugetPackageVersions.ps1
4142
..\README.md = ..\README.md
4243
..\doc\ReleaseNotes.md = ..\doc\ReleaseNotes.md
4344
..\doc\Settings.md = ..\doc\Settings.md
45+
Update-VcxprojNugetPackageVersions.ps1 = Update-VcxprojNugetPackageVersions.ps1
4446
..\WinGetInProcCom.nuspec = ..\WinGetInProcCom.nuspec
4547
..\WinGetUtil.nuspec = ..\WinGetUtil.nuspec
4648
EndProjectSection

src/AppInstallerCLI/AppInstallerCLI.vcxproj

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3-
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props')" />
3+
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" />
44
<PropertyGroup Label="Globals">
55
<CppWinRTOptimized>true</CppWinRTOptimized>
66
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
@@ -42,11 +42,6 @@
4242
</ItemGroup>
4343
<PropertyGroup Label="Configuration">
4444
<ConfigurationType>Application</ConfigurationType>
45-
<PlatformToolset>v140</PlatformToolset>
46-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
47-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
48-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '17.0'">v143</PlatformToolset>
49-
<CharacterSet>Unicode</CharacterSet>
5045
</PropertyGroup>
5146
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
5247
<UseDebugLibraries>true</UseDebugLibraries>
@@ -252,13 +247,13 @@
252247
</ItemGroup>
253248
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
254249
<ImportGroup Label="ExtensionTargets">
255-
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
250+
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
256251
</ImportGroup>
257252
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
258253
<PropertyGroup>
259254
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
260255
</PropertyGroup>
261-
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
262-
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
256+
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
257+
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
263258
</Target>
264-
</Project>
259+
</Project>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3-
<package id="Microsoft.Windows.CppWinRT" version="2.0.230706.1" targetFramework="native" />
3+
<package id="Microsoft.Windows.CppWinRT" version="2.0.250303.1" targetFramework="native" />
44
</packages>

src/AppInstallerCLICore/AppInstallerCLICore.vcxproj

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3-
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props')" />
3+
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" />
44
<PropertyGroup Label="Globals">
55
<CppWinRTOptimized>true</CppWinRTOptimized>
66
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
@@ -54,11 +54,6 @@
5454
</ItemGroup>
5555
<PropertyGroup Label="Configuration">
5656
<ConfigurationType>StaticLibrary</ConfigurationType>
57-
<PlatformToolset>v140</PlatformToolset>
58-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
59-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
60-
<PlatformToolset Condition="'$(VisualStudioVersion)' == '17.0'">v143</PlatformToolset>
61-
<CharacterSet>Unicode</CharacterSet>
6257
</PropertyGroup>
6358
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
6459
<UseDebugLibraries>true</UseDebugLibraries>
@@ -482,15 +477,16 @@
482477
</ItemGroup>
483478
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
484479
<ImportGroup Label="ExtensionTargets">
485-
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.231028.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.231028.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
486-
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
480+
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
481+
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
487482
</ImportGroup>
488483
<Target Name="EnsureBuildImports" BeforeTargets="PrepareForBuild">
489484
<PropertyGroup>
490485
<ErrorTextNuget>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorTextNuget>
491486
</PropertyGroup>
492-
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.231028.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.231028.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
493-
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
494-
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
487+
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
488+
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
489+
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
495490
</Target>
496-
</Project>
491+
</Project>
492+

src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp

Lines changed: 99 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <AppInstallerStrings.h>
1818
#include <winget/ExperimentalFeature.h>
1919
#include <winget/SelfManagement.h>
20+
#include <winget/PathTree.h>
2021
#include <winrt/Microsoft.Management.Configuration.h>
2122

2223
using namespace AppInstaller::CLI::Execution;
@@ -1678,6 +1679,80 @@ namespace AppInstaller::CLI::Workflow
16781679
}
16791680
}
16801681

1682+
// Contains a tree of all unit processors by their path.
1683+
struct UnitProcessorTree
1684+
{
1685+
private:
1686+
struct SourceAndPackage
1687+
{
1688+
PackageCollection::Source Source;
1689+
PackageCollection::Package Package;
1690+
};
1691+
1692+
struct Node
1693+
{
1694+
// Packages whose installed location is at this node
1695+
std::vector<SourceAndPackage> Packages;
1696+
1697+
// Units whose location is at this node.
1698+
std::vector<IConfigurationUnitProcessorDetails> Units;
1699+
};
1700+
1701+
Filesystem::PathTree<Node> m_pathTree;
1702+
1703+
Node& FindNodeForFilePath(const winrt::hstring& filePath)
1704+
{
1705+
std::filesystem::path path{ std::wstring{ filePath } };
1706+
return m_pathTree.FindOrInsert(path.parent_path());
1707+
}
1708+
1709+
public:
1710+
UnitProcessorTree(std::vector<IConfigurationUnitProcessorDetails>&& unitProcessors)
1711+
{
1712+
for (auto&& unit : unitProcessors)
1713+
{
1714+
IConfigurationUnitProcessorDetails3 unitProcessor3;
1715+
if (unit.try_as(unitProcessor3))
1716+
{
1717+
winrt::hstring unitPath = unitProcessor3.Path();
1718+
AICLI_LOG(Config, Verbose, << "Found unit `" << Utility::ConvertToUTF8(unit.UnitType()) << "` at: " << Utility::ConvertToUTF8(unitPath));
1719+
Node& node = FindNodeForFilePath(unitPath);
1720+
node.Units.emplace_back(std::move(unit));
1721+
}
1722+
}
1723+
}
1724+
1725+
void PlacePackage(const PackageCollection::Source& source, const PackageCollection::Package& package)
1726+
{
1727+
Node* node = m_pathTree.Find(package.InstalledLocation);
1728+
if (node)
1729+
{
1730+
node->Packages.emplace_back(SourceAndPackage{ source, package });
1731+
}
1732+
}
1733+
1734+
std::vector<IConfigurationUnitProcessorDetails> GetResourcesForPackage(const PackageCollection::Package& package) const
1735+
{
1736+
std::vector<IConfigurationUnitProcessorDetails> result;
1737+
1738+
m_pathTree.VisitIf(
1739+
package.InstalledLocation,
1740+
[&](const Node& node)
1741+
{
1742+
for (const auto& unit : node.Units)
1743+
{
1744+
result.emplace_back(unit);
1745+
}
1746+
},
1747+
[](const Node& node)
1748+
{
1749+
return node.Packages.empty();
1750+
});
1751+
1752+
return result;
1753+
}
1754+
};
1755+
16811756
void ProcessPackagesForConfigurationExportAll(Execution::Context& context)
16821757
{
16831758
ConfigurationContext& configContext = context.Get<Data::ConfigurationContext>();
@@ -1718,6 +1793,17 @@ namespace AppInstaller::CLI::Workflow
17181793
}
17191794
}
17201795

1796+
// Build a tree of the unit processors and place packages onto it to indicate nearest ownership.
1797+
UnitProcessorTree unitProcessorTree{ std::move(unitProcessors) };
1798+
1799+
for (const auto& source : context.Get<Execution::Data::PackageCollection>().Sources)
1800+
{
1801+
for (const auto& package : source.Packages)
1802+
{
1803+
unitProcessorTree.PlacePackage(source, package);
1804+
}
1805+
}
1806+
17211807
for (const auto& source : context.Get<Execution::Data::PackageCollection>().Sources)
17221808
{
17231809
// Create WinGetSource unit for non well known source.
@@ -1730,34 +1816,28 @@ namespace AppInstaller::CLI::Workflow
17301816

17311817
for (const auto& package : source.Packages)
17321818
{
1819+
AICLI_LOG(Config, Verbose, << "Exporting package `" << package.Id << "` at: " << package.InstalledLocation);
1820+
17331821
auto packageUnit = anon::CreateWinGetPackageUnit(package, source, context.Args.Contains(Args::Type::IncludeVersions), sourceUnit, packageUnitType);
17341822
configContext.Set().Units().Append(packageUnit);
17351823

17361824
// Try package settings export.
1737-
for (auto itr = unitProcessors.begin(); itr != unitProcessors.end(); /* itr incremented in the logic */)
1825+
auto unitsForPackage = unitProcessorTree.GetResourcesForPackage(package);
1826+
for (const auto& unit : unitsForPackage)
17381827
{
1739-
IConfigurationUnitProcessorDetails3 unitProcessor3;
1740-
itr->try_as(unitProcessor3);
1741-
if (Filesystem::IsParentPath(std::filesystem::path{ std::wstring{ unitProcessor3.Path() } }, package.InstalledLocation))
1742-
{
1743-
ConfigurationUnit configUnit = anon::CreateConfigurationUnitFromUnitType(
1744-
unitProcessor3.UnitType(),
1745-
Utility::ConvertToUTF8(packageUnit.Identifier()));
1828+
winrt::hstring unitType = unit.UnitType();
1829+
AICLI_LOG(Config, Verbose, << " exporting unit `" << Utility::ConvertToUTF8(unitType));
17461830

1747-
auto exportedUnits = anon::ExportUnit(context, configUnit);
1748-
anon::AddDependentUnit(exportedUnits, packageUnit);
1831+
ConfigurationUnit configUnit = anon::CreateConfigurationUnitFromUnitType(
1832+
unitType,
1833+
Utility::ConvertToUTF8(packageUnit.Identifier()));
17491834

1750-
for (auto exportedUnit : exportedUnits)
1751-
{
1752-
configContext.Set().Units().Append(exportedUnit);
1753-
}
1835+
auto exportedUnits = anon::ExportUnit(context, configUnit);
1836+
anon::AddDependentUnit(exportedUnits, packageUnit);
17541837

1755-
// Remove the unit processor from the list after export.
1756-
itr = unitProcessors.erase(itr);
1757-
}
1758-
else
1838+
for (const auto& exportedUnit : exportedUnits)
17591839
{
1760-
itr++;
1840+
configContext.Set().Units().Append(exportedUnit);
17611841
}
17621842
}
17631843
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3-
<package id="Microsoft.Windows.CppWinRT" version="2.0.230706.1" targetFramework="native" />
4-
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231028.1" targetFramework="native" />
3+
<package id="Microsoft.Windows.CppWinRT" version="2.0.250303.1" targetFramework="native" />
4+
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.250325.1" targetFramework="native" />
55
</packages>

0 commit comments

Comments
 (0)