-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Bring Pinning to PowerShell Cmdlets #6190
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
Open
Trenly
wants to merge
62
commits into
microsoft:master
Choose a base branch
from
Trenly:PinPlus
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
62 commits
Select commit
Hold shift + click to select a range
32b17d4
Add note, date created, and show subcommand
Trenly 697ca1d
Add tests
Trenly b6502ef
Add pinning to COM APIs
Trenly ae483b0
Add IsPinned propery for Get-WingetPackage
Trenly fac4ec4
Add pinning to PowerShell Cmdlets
Trenly 7ce3b27
Spelling
Trenly 35322e7
Inherit from 1.0 Interface
Trenly 236e667
Contract 29 is not released yet
Trenly 1c89957
Adddress comments about resource strings
Trenly fa617a6
Update comment to indicate the appropriate contract version
Trenly 7f33f56
Make methods public
Trenly 3c7d4a6
Adjust how new schema is created
Trenly 99a8760
Reduce duplicated code through inheritance
Trenly e336194
Use statement builder, savepoints, and tuples for ownership
Trenly 0cb653b
Use a time point instead of strings
Trenly 29d6203
Guard against non-existent source
Trenly 184cc7a
Cache IsPinned
Trenly 952e56e
Merge default pin add behavior into single test
Trenly e823b75
Ensure table is not created in a partial state
Trenly 195846f
Add an alternate function for optional parms
Trenly 0468b34
Move to PackageCatalogReference
Trenly 4bfde99
Move functionality to converters
Trenly 243798b
Remove version comment
Trenly 4b7b8ef
Update filters so 1.1 schema is visible
Trenly e93e3d1
Create the correct interface and migrate only if newer
Trenly ae87ff1
Use correct version info
Trenly 917db77
Move invariants outside try catch
Trenly 34a727c
Add TryRemovePin for simplicity
Trenly 01aad8e
Refactor to use -Blocking and -GatedVersion
Trenly ad9932f
Spelling
Trenly a96e43e
Add Pester Tests
Trenly fde7382
Tests should now be part of default creation test
Trenly d5f682c
Further abstract the interface
Trenly 8f819c1
Update test name
Trenly 91f532a
Add comment
Trenly 595abca
Appease our AI overlords with an update to their tomes
Trenly 7e83a83
Unify on AssignValue to avoid future confusion
Trenly 615ddca
Ensure pin writes always record the last updated time
Trenly 1f8932d
Use original symbol for creation
Trenly df55096
Add missing System namepace
Trenly 6d085dd
Restore conditional setting of date
Trenly ea9f0d8
Ensure ShouldProcess is always respected
Trenly d207c77
Fix minor issue in copilot instructions
Trenly 349a0a1
Validate provided pin types
Trenly 840e5ae
Cache all pins and only fall back to get if set is empty
Trenly 65f8373
Change file name to remove override
Trenly a53f6c7
Merge remote-tracking branch 'upstream/master' into PinPlus
Trenly e2315ad
Merge remote tracking branch master from microsoft/winget-cli
Trenly 2792834
Rename back to PinTable.h
Trenly b350a91
Update filters for file name
Trenly 04b5210
Move SQLite builder instructions to separate file
Trenly e350988
Make adds flow through 1.0 into 1.1
Trenly 3d92b41
Use shared column names
Trenly 37344ea
Add SQLIte Nullopt test
Trenly d061054
Remove protected
Trenly b939b8e
Lazy load all pins for catalog packages
Trenly ff12245
Contract version 30
Trenly c920cdd
Remove pin show - move into pin list with details
Trenly 41e10af
Update release notes
Trenly f05bcc8
Revert instructions edit
Trenly fdcd860
Run renormalize
Trenly 19406e9
Fix release notes
Trenly File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| --- | ||
| applyTo: "src/AppInstallerRepositoryCore/Microsoft/Schema/*, src/Microsoft.Management.Configuration/Database/Schema/*" | ||
| --- | ||
|
|
||
| ## SQLite Statement Builder | ||
|
|
||
| **Always use `AppInstaller::SQLite::Builder::StatementBuilder` when writing SQLite database code. Never write raw SQL strings.** | ||
|
|
||
| The builder is in `<winget/SQLiteStatementBuilder.h>` (namespace `AppInstaller::SQLite::Builder`). It generates type-safe, parameterized SQL and ensures symbolic names are used for tables and columns throughout. | ||
|
|
||
| ### Key conventions | ||
|
|
||
| - Define table and column names as `constexpr std::string_view` constants, then pass them to the builder. | ||
| - Use `ColumnBuilder` with chained modifiers (`.NotNull()`, `.Unique()`, `.Default(value)`) when creating tables. | ||
| - Use `IntegerPrimaryKey()` for auto-increment rowid primary keys. | ||
| - Use `Unbound` as a placeholder and bind values later via `Statement::Bind()`, or pass values directly to have them bound automatically. | ||
|
|
||
| ### Common operations | ||
|
|
||
| ```cpp | ||
| using namespace AppInstaller::SQLite::Builder; | ||
|
|
||
| // Symbolic names | ||
| static constexpr std::string_view s_MyTable = "my_table"sv; | ||
| static constexpr std::string_view s_Col_Id = "id"sv; | ||
| static constexpr std::string_view s_Col_Name = "name"sv; | ||
| static constexpr std::string_view s_Col_Value = "value"sv; | ||
|
|
||
| // CREATE TABLE | ||
| StatementBuilder builder; | ||
| builder.CreateTable(s_MyTable).Columns({ | ||
| IntegerPrimaryKey(), | ||
| ColumnBuilder(s_Col_Name, Type::Text).NotNull().Unique(), | ||
| ColumnBuilder(s_Col_Value, Type::Int64).NotNull().Default(0), | ||
| }); | ||
| builder.Execute(connection); | ||
|
|
||
| // SELECT | ||
| StatementBuilder builder; | ||
| builder.Select({ s_Col_Id, s_Col_Name }) | ||
| .From(s_MyTable) | ||
| .Where(s_Col_Name).Equals(nameValue); | ||
| auto stmt = builder.Prepare(connection); | ||
| while (stmt.Step()) { /* stmt.GetColumn<T>(index) */ } | ||
|
|
||
| // INSERT | ||
| StatementBuilder builder; | ||
| builder.InsertInto(s_MyTable) | ||
| .Columns({ s_Col_Name, s_Col_Value }) | ||
| .Values(nameValue, intValue); | ||
| builder.Execute(connection); | ||
|
|
||
| // UPDATE | ||
| StatementBuilder builder; | ||
| builder.Update(s_MyTable).Set() | ||
| .Column(s_Col_Value).AssignValue(newValue) | ||
| .Where(s_Col_Id).Equals(rowId); | ||
| builder.Execute(connection); | ||
|
|
||
| // DELETE | ||
| StatementBuilder builder; | ||
| builder.DeleteFrom(s_MyTable) | ||
| .Where(s_Col_Id).Equals(rowId); | ||
| builder.Execute(connection); | ||
|
|
||
| // ALTER TABLE – add a column | ||
| StatementBuilder builder; | ||
| builder.AlterTable(s_MyTable).Add(s_Col_NewCol, Type::Text).NotNull().Default(0); | ||
| builder.Execute(connection); | ||
| ``` | ||
|
|
||
| ### Nullable values: `Equals()` vs `AssignValue()` | ||
|
|
||
| Both accept `std::optional<T>`, but they behave differently when the optional is empty and must be used in the right context: | ||
|
|
||
| | Method | Empty optional emits | Use in | | ||
| |---|---|---| | ||
| | `Equals(optional<T>)` | `IS NULL` | **WHERE** / filter clauses | | ||
| | `AssignValue(optional<T>)` | `= ?` (binds NULL) | **UPDATE SET** assignments | | ||
|
|
||
| Using `Equals(optional)` in an UPDATE SET clause is a bug — SQLite does not accept `col = IS NULL`. | ||
|
|
||
| ```cpp | ||
| // ✅ Correct: Equals for WHERE filter, AssignValue for SET assignment | ||
| std::optional<int64_t> maybeEpoch = ...; | ||
| std::optional<std::string> maybeNote = ...; | ||
|
|
||
| builder.Update(s_MyTable).Set() | ||
| .Column(s_Col_Name).AssignValue(requiredName) // non-optional: AssignValue in SET | ||
| .Column(s_Col_Epoch).AssignValue(maybeEpoch) // nullable: must use AssignValue in SET | ||
| .Column(s_Col_Note).AssignValue(maybeNote) // nullable: must use AssignValue in SET | ||
| .Where(s_Col_Id).Equals(rowId); // filter: Equals is correct here | ||
|
|
||
| // ✅ Correct: Equals(optional) in WHERE — emits "IS NULL" when empty | ||
| builder.Select(s_Col_Id).From(s_MyTable) | ||
| .Where(s_Col_Note).Equals(maybeNote); // → "WHERE note IS NULL" when empty | ||
| ``` | ||
|
|
||
| ### Execution | ||
|
|
||
| - `builder.Execute(connection)` — prepares, binds, and runs a statement that returns no rows. | ||
| - `builder.Prepare(connection)` — returns a `SQLite::Statement`; call `.Step()` to iterate, `.GetColumn<T>(index)` to read values. | ||
|
|
||
| ## Naming Conventions | ||
|
|
||
| - **Namespace structure**: `AppInstaller::<Area>[::<Subarea>]` | ||
| - `AppInstaller::CLI::Execution` - CLI execution context | ||
| - `AppInstaller::CLI::Workflow` - Workflow functions | ||
| - `AppInstaller::Repository` - Repository/source logic | ||
| - `AppInstaller::Manifest` - Manifest types | ||
| - `AppInstaller::Settings` - User/admin settings | ||
|
|
||
| - **Macros**: Prefixed with `AICLI_` for CLI, `WINGET_` for general | ||
| - **Data keys**: ExecutionContextData uses enum keys to type-safely store/retrieve data |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -87,4 +87,5 @@ namespace AppInstaller::CLI | |
| protected: | ||
| void ExecuteInternal(Execution::Context& context) const override; | ||
| }; | ||
|
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.