@@ -44,32 +44,41 @@ namespace AppInstaller::CLI::Workflow
44
44
bool updateFound = false ;
45
45
bool installedTypeInapplicable = false ;
46
46
47
- if (! installedVersion.IsUnknown () || context.Args .Contains (Execution::Args::Type::IncludeUnknown))
47
+ if (installedVersion.IsUnknown () && ! context.Args .Contains (Execution::Args::Type::IncludeUnknown))
48
48
{
49
- // The version keys should have already been sorted by version
50
- const auto & versionKeys = package->GetAvailableVersionKeys ();
51
- for (const auto & key : versionKeys)
49
+ // the package has an unknown version and the user did not request to upgrade it anyway.
50
+ if (m_reportUpdateNotFound)
52
51
{
53
- // Check Update Version
54
- if (IsUpdateVersionApplicable (installedVersion, Utility::Version (key.Version )))
55
- {
56
- auto packageVersion = package->GetAvailableVersion (key);
57
- auto manifest = packageVersion->GetManifest ();
52
+ context.Reporter .Info () << Resource::String::UpgradeUnknownVersionExplanation << std::endl;
53
+ }
54
+
55
+ AICLI_TERMINATE_CONTEXT (APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE);
56
+ }
57
+
58
+ // The version keys should have already been sorted by version
59
+ const auto & versionKeys = package->GetAvailableVersionKeys ();
60
+ for (const auto & key : versionKeys)
61
+ {
62
+ // Check Update Version
63
+ if (IsUpdateVersionApplicable (installedVersion, Utility::Version (key.Version )))
64
+ {
65
+ auto packageVersion = package->GetAvailableVersion (key);
66
+ auto manifest = packageVersion->GetManifest ();
58
67
59
- // Check applicable Installer
60
- auto [installer, inapplicabilities] = manifestComparator.GetPreferredInstaller (manifest);
61
- if (!installer.has_value ())
68
+ // Check applicable Installer
69
+ auto [installer, inapplicabilities] = manifestComparator.GetPreferredInstaller (manifest);
70
+ if (!installer.has_value ())
71
+ {
72
+ // If there is at least one installer whose only reason is InstalledType.
73
+ auto onlyInstalledType = std::find (inapplicabilities.begin (), inapplicabilities.end (), InapplicabilityFlags::InstalledType);
74
+ if (onlyInstalledType != inapplicabilities.end ())
62
75
{
63
- // If there is at least one installer whose only reason is InstalledType.
64
- auto onlyInstalledType = std::find (inapplicabilities.begin (), inapplicabilities.end (), InapplicabilityFlags::InstalledType);
65
- if (onlyInstalledType != inapplicabilities.end ())
66
- {
67
- installedTypeInapplicable = true ;
68
- }
69
-
70
- continue ;
76
+ installedTypeInapplicable = true ;
71
77
}
72
78
79
+ continue ;
80
+ }
81
+
73
82
Logging::Telemetry ().LogSelectedInstaller (
74
83
static_cast <int >(installer->Arch ),
75
84
installer->Url ,
@@ -88,25 +97,16 @@ namespace AppInstaller::CLI::Workflow
88
97
context.Add <Execution::Data::PackageVersion>(std::move (packageVersion));
89
98
context.Add <Execution::Data::Installer>(std::move (installer));
90
99
91
- updateFound = true ;
92
- break ;
93
- }
94
- else
95
- {
96
- // Any following versions are not applicable
97
- break ;
98
- }
100
+ updateFound = true ;
101
+ break ;
99
102
}
100
- }
101
- else
102
- {
103
- // the package has an unknown version and the user did not request to upgrade it anyway.
104
- if (m_reportUpdateNotFound)
103
+ else
105
104
{
106
- context.Reporter .Info () << Resource::String::UpgradeUnknownVersionExplanation << std::endl;
105
+ // Any following versions are not applicable
106
+ break ;
107
107
}
108
- AICLI_TERMINATE_CONTEXT (APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE);
109
108
}
109
+
110
110
if (!updateFound)
111
111
{
112
112
if (m_reportUpdateNotFound)
@@ -143,7 +143,8 @@ namespace AppInstaller::CLI::Workflow
143
143
const auto & matches = context.Get <Execution::Data::SearchResult>().Matches ;
144
144
std::vector<std::unique_ptr<Execution::Context>> packagesToInstall;
145
145
bool updateAllFoundUpdate = false ;
146
- int unknownPackagesCount = 0 ;
146
+ int packagesWithUnknownVersionSkipped = 0 ;
147
+ int packagesThatRequireExplicitSkipped = 0 ;
147
148
148
149
for (const auto & match : matches)
149
150
{
@@ -154,15 +155,17 @@ namespace AppInstaller::CLI::Workflow
154
155
auto installedVersion = match.Package ->GetInstalledVersion ();
155
156
156
157
updateContext.Add <Execution::Data::Package>(match.Package );
157
-
158
+
159
+ // Filter out packages with unknown installed versions
158
160
if (context.Args .Contains (Execution::Args::Type::IncludeUnknown))
159
161
{
160
162
updateContext.Args .AddArg (Execution::Args::Type::IncludeUnknown);
161
163
}
162
164
else if (Utility::Version (installedVersion->GetProperty (PackageVersionProperty::Version)).IsUnknown ())
163
165
{
164
166
// we don't know what the package's version is and the user didn't ask to upgrade it anyway.
165
- unknownPackagesCount++;
167
+ AICLI_LOG (CLI, Info, << " Skipping " << match.Package ->GetProperty (PackageProperty::Id) << " as it has unknown installed version" );
168
+ ++packagesWithUnknownVersionSkipped;
166
169
continue ;
167
170
}
168
171
@@ -176,6 +179,24 @@ namespace AppInstaller::CLI::Workflow
176
179
continue ;
177
180
}
178
181
182
+ // Filter out packages that require explicit upgrades.
183
+ // We require explicit upgrades only if the installed version is pinned,
184
+ // either because it was manually pinned or because the manifest indicated
185
+ // RequireExplicitUpgrade.
186
+ // Note that this does not consider whether the update to be installed has
187
+ // RequireExplicitUpgrade. While this has the downside of not working with
188
+ // packages installed from another source, it ensures consistency with the
189
+ // list of available updates (there we don't have the selected installer)
190
+ // and at most we will update each package like this once.
191
+ auto installedMetadata = updateContext.Get <Execution::Data::InstalledPackageVersion>()->GetMetadata ();
192
+ auto pinnedState = ConvertToPackagePinnedStateEnum (installedMetadata[PackageVersionMetadata::PinnedState]);
193
+ if (pinnedState != PackagePinnedState::NotPinned)
194
+ {
195
+ AICLI_LOG (CLI, Info, << " Skipping " << match.Package ->GetProperty (PackageProperty::Id) << " as it requires explicit upgrade" );
196
+ ++packagesThatRequireExplicitSkipped;
197
+ continue ;
198
+ }
199
+
179
200
updateAllFoundUpdate = true ;
180
201
181
202
AddToPackagesToInstallIfNotPresent (packagesToInstall, std::move (updateContextPtr));
@@ -191,5 +212,17 @@ namespace AppInstaller::CLI::Workflow
191
212
APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE,
192
213
{ APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE });
193
214
}
215
+
216
+ if (packagesWithUnknownVersionSkipped > 0 )
217
+ {
218
+ AICLI_LOG (CLI, Info, << packagesWithUnknownVersionSkipped << " package(s) skipped due to unknown installed version" );
219
+ context.Reporter .Info () << packagesWithUnknownVersionSkipped << " " << Resource::String::UpgradeUnknownVersionCount << std::endl;
220
+ }
221
+
222
+ if (packagesThatRequireExplicitSkipped > 0 )
223
+ {
224
+ AICLI_LOG (CLI, Info, << packagesThatRequireExplicitSkipped << " package(s) skipped due to requiring explicit upgrade" );
225
+ context.Reporter .Info () << packagesThatRequireExplicitSkipped << " " << Resource::String::UpgradeRequireExplicitCount << std::endl;
226
+ }
194
227
}
195
228
}
0 commit comments