Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WinGet Source COM Api #4813

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
874c523
Implement skeleton for package catalog management
Madhusudhan-MSFT Sep 16, 2024
2ba2e77
Add new vector interfaces for package catalog operations
Madhusudhan-MSFT Sep 16, 2024
084e9a7
Add registration for AddPackageCatalogOptions COM class
Madhusudhan-MSFT Sep 16, 2024
8dbdbb8
Add C# WinRT Projection for AddPackageCatalogOptions class
Madhusudhan-MSFT Sep 16, 2024
fb402a1
[PR Feedback:] Refactor AddPackageCatalogOptions and update PackageMa…
Madhusudhan-MSFT Sep 17, 2024
bb0923b
[PR Feedback:] Refactor progress reporting for CatalogPackageAsync me…
Madhusudhan-MSFT Sep 17, 2024
a8e28b7
[PR Feedback:] Refactor package catalog operations to async methods
Madhusudhan-MSFT Sep 17, 2024
c5ccec2
Refactor PackageCatalogReference methods to remove params
Madhusudhan-MSFT Sep 24, 2024
16d41d0
Remove progress reporting from ResetPackageCatalogAsync
Madhusudhan-MSFT Sep 24, 2024
c2d3a0f
Eliminate ResetPackageCatalogAsync in favor of options for RemovePack…
Madhusudhan-MSFT Sep 27, 2024
aeb98ea
Merge branch 'master' of https://github.com/Madhusudhan-MSFT/winget-c…
Madhusudhan-MSFT Oct 9, 2024
e2021d7
[MergeConflictFix:] Add new NameCLSIDPair for AddPackageCatalogOptions
Madhusudhan-MSFT Oct 9, 2024
6410b49
Remove package catalog handling logic for the changes expected in the…
Madhusudhan-MSFT Oct 9, 2024
c41bb16
Apply API review feedback
Madhusudhan-MSFT Oct 14, 2024
aa6de76
Merge branch 'microsoft:master' into user/masudars/WinGet_Source_COM_API
Madhusudhan-MSFT Oct 14, 2024
ac4ae58
Fix typo in comment for AcceptSourceAgreements
Madhusudhan-MSFT Oct 14, 2024
0bf0ad4
Reformat RemovePackageCatalogAsync method declaration
Madhusudhan-MSFT Oct 14, 2024
f1a064a
Add new error codes and update method documentation
Madhusudhan-MSFT Oct 18, 2024
e988965
Add CallbackDispatcherSink class for progress updates
Madhusudhan-MSFT Oct 18, 2024
8bff63e
Add, Remove and Refresh package catalog operations with error handling
Madhusudhan-MSFT Oct 18, 2024
9f3fad3
Add PackageCatalogInterop class for E2E PackageCatalog test operations
Madhusudhan-MSFT Oct 18, 2024
8a39538
Merge branch 'microsoft:master' into user/masudars/WinGet_Source_COM_API
Madhusudhan-MSFT Oct 18, 2024
3853876
Merge branch 'user/masudars/WinGet_Source_COM_API' of https://github.…
Madhusudhan-MSFT Oct 18, 2024
7714865
Refactor status handling for Add, Remove and Refresh with a Template …
Madhusudhan-MSFT Oct 18, 2024
a0a91ba
Align RepairOptions struct with its UUID attribute
Madhusudhan-MSFT Oct 18, 2024
75c68a2
Update contract version to 12 in deployment namespaces for WinGet Pac…
Madhusudhan-MSFT Oct 18, 2024
fead163
[SpellCheck_Error] Fix typo in RemovePackageCatalogAsync method comment
Madhusudhan-MSFT Oct 18, 2024
9fef0f8
Improve clarity of RemoveNonExistingPackageCatalog comment
Madhusudhan-MSFT Oct 18, 2024
69462af
Fix for forbidden-pattern error by spellchecking bot.
Madhusudhan-MSFT Oct 18, 2024
016c618
Remove <Natvis> element from vcxproj.filters
Madhusudhan-MSFT Oct 18, 2024
b4db8df
Refactor error handling that includes logging and update test cases
Madhusudhan-MSFT Oct 21, 2024
28b0a12
Extend group policy tests to include package catalog management opera…
Madhusudhan-MSFT Oct 21, 2024
e1902d9
Merge branch 'microsoft:master' into user/masudars/WinGet_Source_COM_API
Madhusudhan-MSFT Oct 21, 2024
127b4c7
Simplify default source type retrieval in PackageManager
Madhusudhan-MSFT Oct 21, 2024
ea785f3
Remove AcceptSourceAgreements property and related logic
Madhusudhan-MSFT Oct 23, 2024
4dcdc2a
[PR Feedback]:Refactor error handling and add admin/system check func…
Madhusudhan-MSFT Oct 23, 2024
f92b947
Fix indentation in RemovePackageCatalogOptions clsid
Madhusudhan-MSFT Oct 23, 2024
10f92be
Refactor argument validation in AddPackageCatalogAsync & RemovePackag…
Madhusudhan-MSFT Oct 23, 2024
1244dd6
[PR Feedback:] Refactor progress reporting mechanism
Madhusudhan-MSFT Oct 24, 2024
2066dbf
[SpellCheck] Fix typo in `OnProgress` method parameter description
Madhusudhan-MSFT Oct 24, 2024
16ecf85
Add validation for progressReporter and improve map insertion
Madhusudhan-MSFT Oct 24, 2024
b5eae14
[PR Feedback] Refactor error handling and optimize data structures
Madhusudhan-MSFT Oct 25, 2024
340200a
Update PackageManager.idl comments for async operations
Madhusudhan-MSFT Oct 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public async Task AddRemovePackageCatalog()
public void AddPackageCatalogWithInvalidOptions()
{
// Add package catalog with null options.
Assert.ThrowsAsync<ArgumentException>(async () => await this.packageManager.AddPackageCatalogAsync(null));
Assert.ThrowsAsync<NullReferenceException>(async () => await this.packageManager.AddPackageCatalogAsync(null));

// Add package catalog with empty options.
Assert.ThrowsAsync<ArgumentException>(async () => await this.packageManager.AddPackageCatalogAsync(this.TestFactory.CreateAddPackageCatalogOptions()));
Expand Down Expand Up @@ -235,7 +235,7 @@ public async Task AddRemovePackageCatalogWithPreserveDataFiledSet()
public void RemovePackageCatalogWithInvalidOptions()
{
// Remove package catalog with null options.
Assert.ThrowsAsync<ArgumentException>(async () => await this.packageManager.RemovePackageCatalogAsync(null));
Assert.ThrowsAsync<NullReferenceException>(async () => await this.packageManager.RemovePackageCatalogAsync(null));

// Remove package catalog with empty options.
Assert.ThrowsAsync<ArgumentException>(async () => await this.packageManager.RemovePackageCatalogAsync(this.TestFactory.CreateRemovePackageCatalogOptions()));
Expand Down
1 change: 0 additions & 1 deletion src/AppInstallerCommonCore/Public/AppInstallerProgress.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <atomic>
#include <functional>
#include <string_view>
#include <mutex>

namespace AppInstaller
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ namespace winrt::Microsoft::Management::Deployment::implementation

#if !defined(INCLUDE_ONLY_INTERFACE_METHODS)
private:
std::wstring m_name = L"";
std::wstring m_sourceUri = L"";
std::wstring m_type = L"";
hstring m_name = L"";
hstring m_sourceUri = L"";
hstring m_type = L"";
winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel m_trustLevel = winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel::None;
std::wstring m_customHeader = L"";
hstring m_customHeader = L"";
bool m_explicit = false;
#endif
};
Expand Down
2 changes: 0 additions & 2 deletions src/Microsoft.Management.Deployment/Converters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation
case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS:
case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS:
return AddPackageCatalogStatus::InvalidOptions;
case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED:
return AddPackageCatalogStatus::CatalogError;
default:
return HandleCommonCatalogOperationStatus<AddPackageCatalogStatus>(hresult);
}
Expand Down
64 changes: 42 additions & 22 deletions src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ namespace winrt::Microsoft::Management::Deployment
if (sourceType.empty()
|| Utility::CaseInsensitiveEquals( Repository::Microsoft::PredefinedInstalledSourceFactory::Type(), sourceType))
{
std::unordered_map<AppInstaller::ProgressType, double> progressWeights;
std::vector<std::pair<AppInstaller::ProgressType, double>> progressWeights;

// There is no download operation for remove operation, so remove the download progress.
// There is no download operation for remove operation, so use only percentage based progress to account for uninstall.
if (removeOperation)
{
// it is percentage based progress.
progressWeights.insert_or_assign(AppInstaller::ProgressType::Bytes, 0);
progressWeights.push_back(std::make_pair(AppInstaller::ProgressType::Percent, 1.0));
}
else
{
// Add/Update operation has two progress types:
// 1. Bytes for downloading index and
// 2. Percent for index installation.
progressWeights.insert_or_assign(AppInstaller::ProgressType::Bytes, 0.7);
progressWeights.insert_or_assign(AppInstaller::ProgressType::Percent, 0.3);
progressWeights.push_back(std::make_pair(AppInstaller::ProgressType::Bytes, 0.7));
progressWeights.push_back(std::make_pair(AppInstaller::ProgressType::Percent, 0.3));
}

return std::make_shared<PreIndexedPackageCatalogProgressSink>(progressWeights, progressReporter);
Expand All @@ -46,38 +46,42 @@ namespace winrt::Microsoft::Management::Deployment
CompletionOnlyProgressSink::CompletionOnlyProgressSink(std::function<void(double)> progressReporter) :
m_progressReporter(progressReporter)
{
if (!m_progressReporter)
{
THROW_HR(E_INVALIDARG);
}
}

void CompletionOnlyProgressSink::OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type)
void CompletionOnlyProgressSink::OnProgress(uint64_t /*current*/, uint64_t /*maximum*/, AppInstaller::ProgressType /*type*/)
{
UNREFERENCED_PARAMETER(current);
UNREFERENCED_PARAMETER(maximum);
UNREFERENCED_PARAMETER(type);
}

void CompletionOnlyProgressSink::SetProgressMessage(std::string_view message)
void CompletionOnlyProgressSink::SetProgressMessage(std::string_view /*message*/)
{
UNREFERENCED_PARAMETER(message);
}

void CompletionOnlyProgressSink::BeginProgress()
{
m_progressReporter(0);
}

void CompletionOnlyProgressSink::EndProgress(bool hideProgressWhenDone)
void CompletionOnlyProgressSink::EndProgress(bool /*hideProgressWhenDone*/)
{
UNREFERENCED_PARAMETER(hideProgressWhenDone);
m_progressReporter(100);
}

PreIndexedPackageCatalogProgressSink::PreIndexedPackageCatalogProgressSink(std::unordered_map<AppInstaller::ProgressType, double> progressWeights, std::function<void(double)> progressReporter) :
PreIndexedPackageCatalogProgressSink::PreIndexedPackageCatalogProgressSink(std::vector<std::pair<AppInstaller::ProgressType, double>> progressWeights, std::function<void(double)> progressReporter) :
m_progressWeights(progressWeights), m_progressReporter(progressReporter)
{
if (!m_progressReporter)
{
THROW_HR(E_INVALIDARG);
}

// If no weights are provided, default to percent.
if (m_progressWeights.empty())
{
m_progressWeights[AppInstaller::ProgressType::Percent] = 1;
m_progressWeights.push_back(std::make_pair(AppInstaller::ProgressType::Percent, 1.0));
}

// Calculate the total weight.
Expand Down Expand Up @@ -108,30 +112,46 @@ namespace winrt::Microsoft::Management::Deployment
m_progressValues[type] = progress;

double totalProgress = 0.0;
double totalWeight = 0.0;

// Calculate the total progress.
for (const auto& [progressType, weight] : m_progressWeights)
{
double progressValue = m_progressValues[progressType];

// [NOTE:] Sequential execution assumption & Handling incomplete progress reports :
// This progress calculation assumes that each operation is executed sequentially, meaning the download must be complete before
// the installation begins.If the download fails, the installation will not proceed.However, there may be cases where the previous
// operation completes successfully, but its onprogress callback does not report 100% completion(e.g., the last progress report for
// the download was at 90%, but the download is complete, and the installation has started).This can result in the total progress not
// reaching 100% after the last operation completes due to the gap in the previous operation's progress report.To handle this, consider
// the progress for the last operation as complete by assigning its full weight while computing progress for the following operation.
// For example, while computing progress for the installation, consider the download operation complete even if it did not report progress
// exactly at 100%.
if (progressValue != 0)
{
totalProgress = totalWeight;
}

// Adjust the total progress value based on the weight.
totalProgress += m_progressValues[progressType] * weight;
totalWeight += weight;
totalProgress += progressValue * weight;
}

m_progressReporter(totalProgress * 100);
}

void PreIndexedPackageCatalogProgressSink::SetProgressMessage(std::string_view message)
void PreIndexedPackageCatalogProgressSink::SetProgressMessage(std::string_view /*message*/)
{
UNREFERENCED_PARAMETER(message);
}

void PreIndexedPackageCatalogProgressSink::BeginProgress()
{
OnProgress(0, 1, AppInstaller::ProgressType::None);
m_progressReporter(0);
}

void PreIndexedPackageCatalogProgressSink::EndProgress(bool hideProgressWhenDone)
void PreIndexedPackageCatalogProgressSink::EndProgress(bool /*hideProgressWhenDone*/)
{
UNREFERENCED_PARAMETER(hideProgressWhenDone);
OnProgress(1, 1, AppInstaller::ProgressType::None);
m_progressReporter(100);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace winrt::Microsoft::Management::Deployment
/// </summary>
/// <param name="progressWeights">ProgressType weight map.</param>
/// <param name="progressReporter">Callback function that reports progress to caller.</param>
PreIndexedPackageCatalogProgressSink(std::unordered_map<AppInstaller::ProgressType, double> progressWeights, std::function<void(double)> progressReporter);
PreIndexedPackageCatalogProgressSink(std::vector<std::pair<AppInstaller::ProgressType, double>> progressWeights, std::function<void(double)> progressReporter);

/// <summary>
/// Reports combined progress to caller when configured for multiple progress types.
Expand All @@ -66,7 +66,7 @@ namespace winrt::Microsoft::Management::Deployment
void EndProgress(bool hideProgressWhenDone) override;

private:
std::unordered_map<AppInstaller::ProgressType, double> m_progressWeights;
std::vector<std::pair<AppInstaller::ProgressType, double>> m_progressWeights;
std::function<void(double)> m_progressReporter;
std::unordered_map<AppInstaller::ProgressType, double> m_progressValues;
};
Expand Down
29 changes: 5 additions & 24 deletions src/Microsoft.Management.Deployment/PackageManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,29 +114,11 @@ namespace winrt::Microsoft::Management::Deployment::implementation
source.SetCustomHeader(customHeader);
}

try
{
auto sourceInfo = source.GetInformation();
auto sourceInfo = source.GetInformation();

if (sourceInfo.Authentication.Type == ::AppInstaller::Authentication::AuthenticationType::Unknown)
{
throw winrt::hresult_error(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED);
}
}
catch (const winrt::hresult_error& hre)
{
if (hre.code() == APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED)
{
THROW_HR(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED);
}
else
{
THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED);
}
}
catch (...) // Catch all exceptions
if (sourceInfo.Authentication.Type == ::AppInstaller::Authentication::AuthenticationType::Unknown)
Madhusudhan-MSFT marked this conversation as resolved.
Show resolved Hide resolved
{
THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED);
THROW_HR(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED);
}

return source;
Expand Down Expand Up @@ -1314,7 +1296,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
LogStartupIfApplicable();

// options must be set.
THROW_HR_IF_NULL(E_INVALIDARG, options);
THROW_HR_IF_NULL(E_POINTER, options);
THROW_HR_IF(E_INVALIDARG, options.Name().empty());
THROW_HR_IF(E_INVALIDARG, options.SourceUri().empty());

Expand Down Expand Up @@ -1352,7 +1334,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
LogStartupIfApplicable();

// options must be set.
THROW_HR_IF_NULL(E_INVALIDARG, options);
THROW_HR_IF_NULL(E_POINTER, options);
THROW_HR_IF(E_INVALIDARG, options.Name().empty());

HRESULT terminationHR = S_OK;
Expand All @@ -1379,7 +1361,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation
if (options.PreserveData())
{
THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST, !sourceToRemove.DropSource(matchingSource.value().Name));
packageCatalogProgressSink->OnProgress(100, 100, AppInstaller::ProgressType::Percent);
}
else
{
Expand Down
14 changes: 14 additions & 0 deletions src/Microsoft.Management.Deployment/PackageManager.idl
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,11 @@ namespace Microsoft.Management.Deployment
[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)]
{
/// Updates the package catalog.
/// The progress value, represented as a double, indicates the percentage of operation completion.
/// For "Microsoft.PreIndexed.Package" Package Catalogs, it reflects the progress of downloading and
/// installing the index. When there is no meaningful progress to report for other Package Catalogs,
/// the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion.
/// The progress range is from 0 to 100.
Madhusudhan-MSFT marked this conversation as resolved.
Show resolved Hide resolved
Windows.Foundation.IAsyncOperationWithProgress<RefreshPackageCatalogResult, Double> RefreshPackageCatalogAsync();
}
}
Expand Down Expand Up @@ -1495,9 +1500,18 @@ namespace Microsoft.Management.Deployment
[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)]
{
/// Add a catalog to the Windows Package Catalogs.
Madhusudhan-MSFT marked this conversation as resolved.
Show resolved Hide resolved
/// The progress value, represented as a double, indicates the percentage of operation completion.
/// For "Microsoft.PreIndexed.Package" Package Catalogs, it reflects the progress of downloading and
/// installing the index. When there is no meaningful progress to report for other Package Catalogs,
/// the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion.
/// The progress range is from 0 to 100.
Windows.Foundation.IAsyncOperationWithProgress<AddPackageCatalogResult, Double> AddPackageCatalogAsync(AddPackageCatalogOptions options);

/// Unregisters a Package Catalog from the Windows Package Catalogs and eliminates the system artifacts based on the provided options.
/// The progress value, represented as a double, indicates the percentage of operation completion.For "Microsoft.PreIndexed.Package"
/// Package Catalogs, it reflects the progress of uninstalling the index. When there is no meaningful progress to report for
/// other Package Catalogs, the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion.
/// The progress range is from 0 to 100.
Windows.Foundation.IAsyncOperationWithProgress<RemovePackageCatalogResult, Double> RemovePackageCatalogAsync(RemovePackageCatalogOptions options);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation

#if !defined(INCLUDE_ONLY_INTERFACE_METHODS)
private:
std::wstring m_name = L"";
hstring m_name = L"";
bool m_preserveData = false;
#endif
};
Expand Down
Loading