Visitar URL original
Refactor packaged index factory by JohnMcPMS · Pull Request #6584 · microsoft/winget-cli · GitHub
Skip to content

Refactor packaged index factory - #6584

Merged
JohnMcPMS merged 3 commits into
microsoft:masterfrom
JohnMcPMS:delta-prefactor
Oct 8, 2026
Merged

JohnMcPMS merged 3 commits into
microsoft:masterfrom
JohnMcPMS:delta-prefactor

Conversation

@JohnMcPMS

@JohnMcPMS JohnMcPMS commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

📖 Description

As a step before implementing the delta index client consumption, this change refactors the packaged index factory.

The responsibility is split between the "form", which defines the packages involved / their relationship, and the "store", which is how those packages are persisted to the system. This change only contains the full index form, the next will add the delta. It also contains both of the existing stores; deployed and local file.

Also changes the code to use the local file storage when the process is running non-interactively. Other than that and its mild knock on, the functionality is intended to be unchanged.

🔗 References

Fixes #6334
Inspired by Przemysław Kłys (@PrzemyslawKlys) and #6347 to fix as part of this other work

🔍 Validation

Regression only; the delta implementation will add more tests targeting this area.
This change should have little to no impact on existing functionality, only modifying the store when running non-interactively.

Microsoft Reviewers: Open in CodeFlow

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Cancellation, temporary-file cleanup, multi-package store resolution, and regression coverage need correction.

4 open findings
What changed in this PR

Refactors preindexed sources into separate index-form and package-store abstractions, enabling local storage for non-interactive packaged sessions.

Changes:

  • Separates full-index behavior from deployed and local-file persistence.
  • Selects storage based on packaged and interactive context.
  • Adds supporting runtime detection and project entries.
File Description
src/​AppInstallerSharedLib/​Runtime.cpp Detects interactive user tokens.
src/​AppInstallerSharedLib/​Public/​winget/​Runtime.h Exposes interactive-user detection.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexedPackageSourceFactory.cpp Orchestrates forms and stores.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexed/​RemotePackage.h Defines remote package discovery APIs.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexed/​RemotePackage.cpp Implements package location and version probing.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexed/​PackageStore.h Defines package-store abstractions.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexed/​PackageStore.cpp Implements acquisition, locking, composition, and store selection.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexed/​LocalFilePackageStore.cpp Implements local-file persistence.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexed/​IndexForm.h Defines index-form contracts.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexed/​FullIndexForm.cpp Implements full-index updates and opening.
src/​AppInstallerRepositoryCore/​Microsoft/​PreIndexed/​DeployedPackageStore.cpp Implements deployed-package persistence.
src/​AppInstallerRepositoryCore/​AppInstallerRepositoryCore.vcxproj.filters Organizes new files in Visual Studio.
src/​AppInstallerRepositoryCore/​AppInstallerRepositoryCore.vcxproj Adds new files to the build.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

ranm-msft
ranm-msft previously approved these changes Oct 8, 2026

@ranm-msft ranm-msft left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the full diff - all 13 files, including the eight new files under Microsoft/PreIndexed/, the factory rewrite, and the Runtime delta. The form/store split is clean and the invariants I went looking for all hold. Approving.

What I checked, in case it is useful to anyone reading later:

Lock semantics are preserved. PreIndexedFactoryBase::LockExclusive is gone, but PackageStoreBase::Lock keeps the identical shape - TryAcquireNoWait() on the background path, Acquire(progress) otherwise - and FullIndexForm::Update calls store.Lock(progress, isBackground). Remove takes store->Lock(progress) at the factory level. CompositePackageStore::Lock delegates to m_stores.front(), and because the lock name is derived from the source identity rather than the storage mechanism, every store over the same source shares one lock. That is the part that would have been easy to get wrong in a refactor this size, and it did not get got wrong.

Lifetime of AcquiredPackage is sound. Move-only, with a hand-written move-assign that clears other.m_isTemporary and other.Path, so no double-delete. The destructor releases the FileLock before std::filesystem::remove. MarkTemporary is set before the download rather than after, so a partial download is still cleaned up.

What gets persisted is what got validated. Acquire takes the WriteLockedMsixFile lock at validation time and hands it to the store, so there is no window between trust validation and persist. LocalFilePackageStore::Persist stages beside the destination and then renames, with a wil::scope_exit that is .release()d on success.

The composite is symmetric. When CanUseDeployedPackage() is false but the process is still packaged, the deployed store is still added - just second. Combined with Resolve only moving off the primary for a strictly newer version, and Remove clearing every store, I could not construct a case where the non-interactive behavior change orphans an existing deployed index. That was my main concern going in and the design already answers it.

One non-blocking nit: the new files are inconsistent about the anonymous-namespace idiom. DeployedPackageStore.cpp uses a real namespace { }, while FullIndexForm.cpp, LocalFilePackageStore.cpp, and PackageStore.cpp use a named namespace anon { }. Not worth another round on its own - just worth picking one before the next form lands on top of these files.

Noting that mergeable_state is blocked, so this still needs whatever other gate is outstanding. All nine checks on 229181a are green.

@ranm-msft ranm-msft left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-read the delta since the approval your last push dismissed. The two cancellation additions look right to me.

LocalFilePackageStore.cpp:135 is the one that matters: that check had gone missing in the move out of PreIndexedPackageSourceFactory.cpp, and I did not catch it the first time through. Walking the four IsCancelledBy sites master had, they are all accounted for now - FullIndexForm.cpp:93, PreIndexedPackageSourceFactory.cpp:112, LocalFilePackageStore.cpp:135, PackageStore.cpp:123 - plus the two new ones. And putting the FullIndexForm.cpp:133 check ahead of the !extracted throw is the right order, so a cancelled extraction does not get reported as missing source data.

One thing is holding up my re-approval: the packaged-process / Interactive SID storage selection that actually fixes #6334 has no coverage in this PR, and the plan on that thread is to pick it up with the test infrastructure work next time. Is there an existing test that exercises that selection today? If the follow-up really is the first time it gets covered, I would rather wait for it than sign off on the part of this change I cannot see tested.

@JohnMcPMS

Copy link
Copy Markdown
Member Author

One thing is holding up my re-approval: the packaged-process / Interactive SID storage selection that actually fixes #6334 has no coverage in this PR, and the plan on that thread is to pick it up with the test infrastructure work next time. Is there an existing test that exercises that selection today? If the follow-up really is the first time it gets covered, I would rather wait for it than sign off on the part of this change I cannot see tested.

No, it is new. Adding the tests here would rely on bringing in significant infrastructure and the refactor itself was the primary goal. I have the tests, they are passing already. But that branch is built on this one, so the followup will not be published until this is merged.

Comment thread src/AppInstallerRepositoryCore/Microsoft/PreIndexed/RemotePackage.h
Comment on lines +26 to +30
// Gets the set of package locations that should be tried, in order.
// Every relative location is tried against the primary arg before any is tried against the
// alternate, so that a source stays on its primary location whenever that location can
// serve the request at all.
std::vector<std::string> GetPackageLocations(const SourceDetails& details, const std::vector<std::string_view>& relativeLocations);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I did not understand what this would do from the comment until I went to read the source. Maybe worth rewriting it? Maybe

Suggested change
// Gets the set of package locations that should be tried, in order.
// Every relative location is tried against the primary arg before any is tried against the
// alternate, so that a source stays on its primary location whenever that location can
// serve the request at all.
std::vector<std::string> GetPackageLocations(const SourceDetails& details, const std::vector<std::string_view>& relativeLocations);
// Gets the set of locations that should be tried, in order, to find one of the listed packages.
// Every relative package path is tried against the primary arg before any is tried against the
// alternate, so that a source stays on its primary location whenever that location can
// serve the request at all.
std::vector<std::string> GetPackageLocations(const SourceDetails& details, const std::vector<std::string_view>& relativePackagePaths);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will revise it in the next PR to prevent the need for an entirely new build.

@JohnMcPMS
JohnMcPMS merged commit 3d9083c into microsoft:master Oct 8, 2026
9 checks passed
@JohnMcPMS
JohnMcPMS deleted the delta-prefactor branch October 8, 2026 23:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failing to add WinGet Source in non-interactive session

4 participants