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

Implement package pinning #2813

Merged
merged 62 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
92b78f6
Add pin index
florelis Dec 12, 2022
a24c0de
Complete pinning index; implement workflow tasks
florelis Dec 15, 2022
964a201
Apply suggestions from code review
florelis Dec 15, 2022
4cc9238
Merge branch 'master' into pinningImplementation
florelis Dec 15, 2022
27167a8
Spelling
florelis Dec 15, 2022
ad6d007
Add tests for pinning index
florelis Dec 15, 2022
f5ea9ce
Store version in all types of pins
florelis Dec 16, 2022
0055a1e
Merge branch 'master' into pinningImplementation
florelis Dec 16, 2022
0a48976
Tests for pin add
florelis Dec 20, 2022
2e8a057
Add more tests
florelis Dec 20, 2022
44123df
Handle pins and multiple sources in composite packages
florelis Dec 30, 2022
2c889fc
Fixes
florelis Dec 30, 2022
4c97b0d
Fix failing composite source tests
florelis Jan 3, 2023
83f27f4
Fix remaining failing tests
florelis Jan 3, 2023
93c0fa9
Typos & prevent unneeded op
florelis Jan 3, 2023
43653df
Add version gating
florelis Jan 3, 2023
035f949
Fix compilation errors
florelis Jan 3, 2023
dca6f92
PR comments
florelis Jan 3, 2023
4ffe0eb
Typo
florelis Jan 3, 2023
4af7d5d
Update src/AppInstallerCommonCore/Errors.cpp
florelis Jan 3, 2023
ec20b7f
Add --include-pinned argument
florelis Jan 3, 2023
dc42e4d
Resolve TODOs
florelis Jan 4, 2023
1a244f2
Add tests
florelis Jan 4, 2023
48f1961
Add more tests
florelis Jan 5, 2023
766aafa
Typo
florelis Jan 5, 2023
97b6fea
Apply suggestions from code review
florelis Jan 9, 2023
177ee73
PR comments
florelis Jan 10, 2023
9d63c89
Update src/AppInstallerRepositoryCore/Microsoft/Schema/Pinning_1_0/Pi…
florelis Jan 10, 2023
ef09f68
Apply suggestions from code review
florelis Jan 10, 2023
0aceec3
Spelling
florelis Jan 10, 2023
8f3d96b
PR comments
florelis Jan 10, 2023
19d87b1
Move log
florelis Jan 10, 2023
f452776
Open read only
florelis Jan 10, 2023
18ba330
Move openpinningindex
florelis Jan 10, 2023
cb25736
Merge branch 'master' into pinningImplementation
florelis Jan 10, 2023
1f6fe62
Catch errors when opening the pinning index
florelis Jan 10, 2023
533c2c9
Update tests after merging master
florelis Jan 10, 2023
d05cc63
Merge branch 'pinningImplementation' into pinningLogic
florelis Jan 10, 2023
51c25be
Fix errors from merge
florelis Jan 10, 2023
1ff27eb
Merge branch 'master' into pinningLogic
florelis Jan 12, 2023
395a9f3
Fix errors from merge
florelis Jan 12, 2023
88ef0f1
Update src/AppInstallerRepositoryCore/Microsoft/PinningIndex.cpp
florelis Jan 18, 2023
9f6f325
Apply suggestions from code review
florelis Jan 18, 2023
3fbb35b
Move ignoring pinned packages out of CompositePackage for better repo…
florelis Jan 25, 2023
b25c43f
Add more reporting around pinned packages
florelis Jan 25, 2023
3b28e60
Merge branch 'master' into pinningLogic
florelis Jan 25, 2023
9c5d03f
Show latest available for upgrade
florelis Jan 25, 2023
a7c4493
Add missing expected value
florelis Jan 28, 2023
2e656e8
Support --force argument
florelis Jan 28, 2023
f15df73
Remove code duplication
florelis Jan 28, 2023
6910211
Add e2e tests
florelis Jan 30, 2023
ea17640
Respect pins in dependencies
florelis Jan 30, 2023
8011710
Keep single available package if not using pinning
florelis Jan 30, 2023
a9c5644
Change search order for properties
florelis Jan 30, 2023
16cb8ad
Fix tests again...
florelis Jan 30, 2023
ea902ac
Fix test data file inclusion
florelis Jan 31, 2023
4b853f8
Use different product code for test zip installer
florelis Feb 6, 2023
676e7d9
Merge branch 'master' into pinningLogic
florelis Feb 6, 2023
21247a4
update -> upgrade; remove TODO
florelis Feb 7, 2023
90ff9b0
Update E2E tests
florelis Feb 7, 2023
c35e0d9
Fix whitespace
florelis Feb 7, 2023
1aa5369
PR comments
florelis Feb 8, 2023
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
1 change: 1 addition & 0 deletions src/AppInstallerCLICore/Commands/UpgradeCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ namespace AppInstaller::CLI
Argument::ForType(Execution::Args::Type::CustomHeader),
Argument{ "all"_liv, 'r', "recurse"_liv, Args::Type::All, Resource::String::UpdateAllArgumentDescription, ArgumentType::Flag },
Argument{ "include-unknown"_liv, 'u', "unknown"_liv, Args::Type::IncludeUnknown, Resource::String::IncludeUnknownArgumentDescription, ArgumentType::Flag },
Argument{ "include-pinned"_liv, Argument::NoAlias, "pinned"_liv, Args::Type::IncludePinned, Resource::String::IncludePinnedArgumentDescription, ArgumentType::Flag},
Argument::ForType(Args::Type::UninstallPrevious),
Argument::ForType(Args::Type::Force),
};
Expand Down
1 change: 1 addition & 0 deletions src/AppInstallerCLICore/ExecutionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ namespace AppInstaller::CLI::Execution
// Upgrade command
All, // Used in Update command to update all installed packages to latest
IncludeUnknown, // Used in Upgrade command to allow upgrades of packages with unknown versions
IncludePinned, // Used in Upgrade command to allow upgrades to pinned packages (only for pinning type of pins)
UninstallPrevious, // Used in Upgrade command to override the default manifest behavior to UninstallPrevious

// Show command
Expand Down
3 changes: 3 additions & 0 deletions src/AppInstallerCLICore/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ImportPackageAlreadyInstalled);
WINGET_DEFINE_RESOURCE_STRINGID(ImportSearchFailed);
WINGET_DEFINE_RESOURCE_STRINGID(ImportSourceNotInstalled);
WINGET_DEFINE_RESOURCE_STRINGID(IncludePinnedArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(IncludeUnknownArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(IncompatibleArgumentsProvided);
WINGET_DEFINE_RESOURCE_STRINGID(InstallAndUpgradeCommandsReportDependencies);
Expand Down Expand Up @@ -258,6 +259,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(PinNoPinsExist);
WINGET_DEFINE_RESOURCE_STRINGID(PinRemoveCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(PinRemoveCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(PinRemovedSuccessfully);
WINGET_DEFINE_RESOURCE_STRINGID(PinResetCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(PinResetCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(PinResetSuccessful);
Expand Down Expand Up @@ -430,6 +432,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(UpdateAllArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(UpdateNotApplicable);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeAvailableForPinned);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeBlockingPinCount);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeDifferentInstallTechnology);
Expand Down
4 changes: 2 additions & 2 deletions src/AppInstallerCLICore/Workflows/CompletionFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ namespace AppInstaller::CLI::Workflow
const std::string& word = context.Get<Data::CompletionData>().Word();
auto stream = context.Reporter.Completion();

for (const auto& vc : context.Get<Execution::Data::Package>()->GetAvailableVersionKeys())
for (const auto& vc : context.Get<Execution::Data::Package>()->GetAvailableVersionKeys(Repository::PinBehavior::IgnorePins))
{
if (word.empty() || Utility::ICUCaseInsensitiveStartsWith(vc.Version, word))
{
Expand All @@ -86,7 +86,7 @@ namespace AppInstaller::CLI::Workflow

std::vector<std::string> channels;

for (const auto& vc : context.Get<Execution::Data::Package>()->GetAvailableVersionKeys())
for (const auto& vc : context.Get<Execution::Data::Package>()->GetAvailableVersionKeys(Repository::PinBehavior::IgnorePins))
{
if ((word.empty() || Utility::ICUCaseInsensitiveStartsWith(vc.Channel, word)) &&
std::find(channels.begin(), channels.end(), vc.Channel) == channels.end())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace AppInstaller::CLI::Workflow
const auto& package = match.Package;
auto packageId = package->GetProperty(PackageProperty::Id);
m_nodePackageInstalledVersion = package->GetInstalledVersion();
m_nodePackageLatestVersion = package->GetLatestAvailableVersion();
m_nodePackageLatestVersion = package->GetLatestAvailableVersion(PinBehavior::ConsiderPins);
florelis marked this conversation as resolved.
Show resolved Hide resolved

if (m_nodePackageInstalledVersion && dependencyNode.IsVersionOk(Utility::Version(m_nodePackageInstalledVersion->GetProperty(PackageVersionProperty::Version))))
{
Expand Down
6 changes: 3 additions & 3 deletions src/AppInstallerCLICore/Workflows/ImportExportFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ namespace AppInstaller::CLI::Workflow
{
if (!checkVersion)
{
return package->GetLatestAvailableVersion();
return package->GetLatestAvailableVersion(PinBehavior::IgnorePins);
}

auto availablePackageVersion = package->GetAvailableVersion({ "", version, channel });
auto availablePackageVersion = package->GetAvailableVersion({ "", version, channel }, PinBehavior::IgnorePins);
if (!availablePackageVersion)
{
availablePackageVersion = package->GetLatestAvailableVersion();
availablePackageVersion = package->GetLatestAvailableVersion(PinBehavior::IgnorePins);
if (availablePackageVersion)
{
// Warn installed version is not available.
Expand Down
170 changes: 116 additions & 54 deletions src/AppInstallerCLICore/Workflows/PinFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,26 @@ namespace AppInstaller::CLI::Workflow
{
auto package = context.Get<Execution::Data::Package>();
std::vector<Pinning::Pin> pins;

// TODO: We should support querying the multiple sources for a package, instead of just one
auto availableVersion = package->GetLatestAvailableVersion();
std::set<std::string> sources;

auto pinningIndex = context.Get<Execution::Data::PinningIndex>();
auto pin = pinningIndex->GetPin({
availableVersion->GetProperty(PackageVersionProperty::Id).get(),
availableVersion->GetProperty(PackageVersionProperty::SourceIdentifier).get() });
if (pin)

auto packageVersionKeys = package->GetAvailableVersionKeys(PinBehavior::IgnorePins);
florelis marked this conversation as resolved.
Show resolved Hide resolved
for (auto versionKey : packageVersionKeys)
florelis marked this conversation as resolved.
Show resolved Hide resolved
{
pins.emplace_back(std::move(pin.value()));
auto availableVersion = package->GetAvailableVersion(versionKey, PinBehavior::IgnorePins);
Pinning::PinKey pinKey{
availableVersion->GetProperty(PackageVersionProperty::Id).get(),
availableVersion->GetProperty(PackageVersionProperty::SourceIdentifier).get() };

if (sources.insert(pinKey.SourceId).second)
{
auto pin = pinningIndex->GetPin(pinKey);
if (pin)
{
pins.emplace_back(std::move(pin.value()));
}
}
}

context.Add<Execution::Data::Pins>(std::move(pins));
Expand All @@ -78,49 +87,71 @@ namespace AppInstaller::CLI::Workflow
auto package = context.Get<Execution::Data::Package>();
auto installedVersion = context.Get<Execution::Data::InstalledPackageVersion>();

std::vector<Pinning::Pin> pins;

// TODO: We should support querying the multiple sources for a package, instead of just one
auto availableVersion = package->GetLatestAvailableVersion();

Pinning::PinKey pinKey{
availableVersion->GetProperty(PackageVersionProperty::Id).get(),
availableVersion->GetProperty(PackageVersionProperty::SourceIdentifier).get() };
auto pin = CreatePin(context, pinKey.PackageId, pinKey.SourceId);
AICLI_LOG(CLI, Info, << "Adding pin with type " << ToString(pin.GetType()) << " for package [" << pin.GetPackageId() << "] from source [" << pin.GetSourceId() << "]");
auto installedVersionString = installedVersion->GetProperty(PackageVersionProperty::Version);

std::vector<Pinning::Pin> pinsToAddOrUpdate;
std::set<std::string> sources;

auto pinningIndex = context.Get<Execution::Data::PinningIndex>();
auto existingPin = pinningIndex->GetPin(pinKey);

if (existingPin)
auto packageVersionKeys = package->GetAvailableVersionKeys(PinBehavior::IgnorePins);
florelis marked this conversation as resolved.
Show resolved Hide resolved
for (auto versionKey : packageVersionKeys)
florelis marked this conversation as resolved.
Show resolved Hide resolved
{
// Pin already exists.
// If it is the same, we do nothing. If it is different, check for the --force arg
if (pin == existingPin)
auto availableVersion = package->GetAvailableVersion(versionKey, PinBehavior::IgnorePins);
Pinning::PinKey pinKey{
availableVersion->GetProperty(PackageVersionProperty::Id).get(),
availableVersion->GetProperty(PackageVersionProperty::SourceIdentifier).get() };

if (!sources.insert(pinKey.SourceId).second)
{
AICLI_LOG(CLI, Info, << "Pin already exists");
context.Reporter.Info() << Resource::String::PinAlreadyExists << std::endl;
return;
// We already considered the pin for this source
continue;
}

AICLI_LOG(CLI, Info, << "Another pin already exists for the package");
if (context.Args.Contains(Execution::Args::Type::Force))
auto pin = CreatePin(context, pinKey.PackageId, pinKey.SourceId);
AICLI_LOG(CLI, Info, << "Evaluating pin with type " << ToString(pin.GetType()) << " for package [" << pin.GetPackageId() << "] from source [" << pin.GetSourceId() << "]");

auto existingPin = pinningIndex->GetPin(pinKey);

if (existingPin)
{
AICLI_LOG(CLI, Info, << "Overwriting pin due to --force argument");
context.Reporter.Warn() << Resource::String::PinExistsOverwriting << std::endl;
pinningIndex->UpdatePin(pin);
auto packageName = availableVersion->GetProperty(PackageVersionProperty::Name);

// Pin already exists.
// If it is the same, we do nothing. If it is different, check for the --force arg
if (pin == existingPin)
{
AICLI_LOG(CLI, Info, << "Pin already exists");
context.Reporter.Info() << Resource::String::PinAlreadyExists(packageName) << std::endl;
continue;
}

AICLI_LOG(CLI, Info, << "Another pin already exists for the package for source " << pinKey.SourceId);
if (context.Args.Contains(Execution::Args::Type::Force))
{
AICLI_LOG(CLI, Info, << "Overwriting pin due to --force argument");
context.Reporter.Warn() << Resource::String::PinExistsOverwriting(packageName) << std::endl;
pinsToAddOrUpdate.push_back(std::move(pin));
}
else
{
context.Reporter.Error() << Resource::String::PinExistsUseForceArg(packageName) << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_PIN_ALREADY_EXISTS);
}
}
else
{
context.Reporter.Error() << Resource::String::PinExistsUseForceArg << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_PIN_ALREADY_EXISTS);
pinsToAddOrUpdate.push_back(std::move(pin));
}
}
else

if (!pinsToAddOrUpdate.empty())
{
pinningIndex->AddPin(pin);
AICLI_LOG(CLI, Info, << "Finished adding pin");
for (auto pin : pinsToAddOrUpdate)
florelis marked this conversation as resolved.
Show resolved Hide resolved
{
pinningIndex->AddOrUpdatePin(pin);
}

context.Reporter.Info() << Resource::String::PinAdded << std::endl;
}
}
Expand All @@ -129,23 +160,41 @@ namespace AppInstaller::CLI::Workflow
{
auto package = context.Get<Execution::Data::Package>();
std::vector<Pinning::Pin> pins;

// TODO: We should support querying the multiple sources for a package, instead of just one
auto availableVersion = package->GetLatestAvailableVersion();
std::set<std::string> sources;

auto pinningIndex = context.Get<Execution::Data::PinningIndex>();
Pinning::PinKey pinKey{
availableVersion->GetProperty(PackageVersionProperty::Id).get(),
availableVersion->GetProperty(PackageVersionProperty::SourceIdentifier).get() };
AICLI_LOG(CLI, Info, << "Removing pin for package [" << pinKey.PackageId << "] from source [" << pinKey.SourceId << "]");
if (!pinningIndex->GetPin(pinKey))
bool pinExists = false;

// Note that if a source was specified in the command line,
// that will be the only one we get version keys from.
// So, we remove pins from all sources unless one was provided.
auto packageVersionKeys = package->GetAvailableVersionKeys(PinBehavior::IgnorePins);
florelis marked this conversation as resolved.
Show resolved Hide resolved
for (auto versionKey : packageVersionKeys)
florelis marked this conversation as resolved.
Show resolved Hide resolved
{
auto availableVersion = package->GetAvailableVersion(versionKey, PinBehavior::IgnorePins);
Pinning::PinKey pinKey{
availableVersion->GetProperty(PackageVersionProperty::Id).get(),
availableVersion->GetProperty(PackageVersionProperty::SourceIdentifier).get() };

if (sources.insert(pinKey.SourceId).second)
{
if (pinningIndex->GetPin(pinKey))
{
AICLI_LOG(CLI, Info, << "Removing pin for package [" << pinKey.PackageId << "] from source [" << pinKey.SourceId << "]");
pinningIndex->RemovePin(pinKey);
pinExists = true;
}
}
}

if (!pinExists)
{
AICLI_LOG(CLI, Warning, << "Pin does not exist");
context.Reporter.Warn() << Resource::String::PinDoesNotExist(pinKey.PackageId) << std::endl;
context.Reporter.Warn() << Resource::String::PinDoesNotExist(package->GetProperty(PackageProperty::Name)) << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_PIN_DOES_NOT_EXIST);
}

pinningIndex->RemovePin(pinKey);
context.Reporter.Info() << Resource::String::PinRemovedSuccessfully << std::endl;
}

void ReportPins(Execution::Context& context)
Expand All @@ -157,7 +206,13 @@ namespace AppInstaller::CLI::Workflow
return;
}

// TODO: Use package and source names
// Get a mapping of source IDs to names so that we can show something nicer
std::map<std::string, std::string> sourceNames;
for (const auto& source : Repository::Source::GetCurrentSources())
{
sourceNames[source.Identifier] = source.Name;
}

Execution::TableOutput<4> table(context.Reporter,
{
Resource::String::SearchId,
Expand All @@ -168,12 +223,11 @@ namespace AppInstaller::CLI::Workflow

for (const auto& pin : pins)
{
// TODO: Avoid these conversions to string
table.OutputLine({
pin.GetPackageId(),
std::string{ pin.GetSourceId() },
pin.GetGatedVersion().ToString(),
sourceNames[pin.GetSourceId()],
std::string{ ToString(pin.GetType()) },
pin.GetGatedVersion().ToString(),
});
}

Expand Down Expand Up @@ -216,14 +270,22 @@ namespace AppInstaller::CLI::Workflow
const auto& source = context.Get<Execution::Data::Source>();

std::vector<Pinning::Pin> matchingPins;
std::copy_if(pins.begin(), pins.end(), std::back_inserter(matchingPins), [&](Pinning::Pin pin) {
// TODO: Filter to source
for (const auto pin : pins)
florelis marked this conversation as resolved.
Show resolved Hide resolved
{
SearchRequest searchRequest;
searchRequest.Filters.emplace_back(PackageMatchField::Id, MatchType::CaseInsensitive, pin.GetPackageId());
auto searchResult = source.Search(searchRequest);

return !searchResult.Matches.empty();
});
// Ensure the match comes from the right source
for (const auto& match : searchResult.Matches)
{
auto availableVersion = match.Package->GetAvailableVersion({ pin.GetSourceId(), "", "" }, PinBehavior::IgnorePins);
if (availableVersion)
{
matchingPins.push_back(pin);
}
}
}

context.Add<Execution::Data::Pins>(std::move(matchingPins));
}
Expand Down
4 changes: 2 additions & 2 deletions src/AppInstallerCLICore/Workflows/PinFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace AppInstaller::CLI::Workflow
// There may be several if a package is available from multiple sources.
// Required Args: None
// Inputs: PinningIndex, Package
// Outputs Pins
// Outputs: Pins
void SearchPin(Execution::Context& context);

// Adds a pin for the current package.
Expand Down Expand Up @@ -57,7 +57,7 @@ namespace AppInstaller::CLI::Workflow
// Outputs: None
void ResetAllPins(Execution::Context& context);

// Updates the list of pins to include only those matching the current open source
// Updates the list of pins to include only those matching the current open source.
// Required Args: None
// Inputs: Pins, Source
// Outputs: None
Expand Down
2 changes: 1 addition & 1 deletion src/AppInstallerCLICore/Workflows/ShowFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ namespace AppInstaller::CLI::Workflow

void ShowAppVersions(Execution::Context& context)
{
auto versions = context.Get<Execution::Data::Package>()->GetAvailableVersionKeys();
auto versions = context.Get<Execution::Data::Package>()->GetAvailableVersionKeys(PinBehavior::IgnorePins);

Execution::TableOutput<2> table(context.Reporter, { Resource::String::ShowVersion, Resource::String::ShowChannel });
for (const auto& version : versions)
Expand Down
4 changes: 2 additions & 2 deletions src/AppInstallerCLICore/Workflows/UninstallFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,9 @@ namespace AppInstaller::CLI::Workflow
correlatedSources.AddIfRemoteAndNotPresent(package->GetInstalledVersion());

// Then look through all available versions
for (const auto& versionKey : package->GetAvailableVersionKeys())
for (const auto& versionKey : package->GetAvailableVersionKeys(PinBehavior::IgnorePins))
{
correlatedSources.AddIfRemoteAndNotPresent(package->GetAvailableVersion(versionKey));
correlatedSources.AddIfRemoteAndNotPresent(package->GetAvailableVersion(versionKey, PinBehavior::IgnorePins));
}

// Finally record the uninstall for each found value
Expand Down
Loading