Skip to content

Commit

Permalink
Added argument to control whether to upgrade packages if they have "u…
Browse files Browse the repository at this point in the history
…nknown" versions (#1765)

* Added --include-unknown command to `upgrade`.

* Added documentation of new arg, and moved if.

* Fixed grammar for comment.

* Added messaging/loop suggestions from code review.

* Apply suggestions from code review (localization)

Co-authored-by: Chacón <[email protected]>

* Added count of unknown packages.

* Added count to upgrade --all too.

* Attempted to fix comments/phrasing for localization.

* Undid change to AppInstallerCLICore project -- sorry!

* Removed unnecessary if statement for ShouldListUpgrade.

Co-authored-by: Chacón <[email protected]>
  • Loading branch information
jedieaston and Chacón authored Dec 9, 2021
1 parent df9e5e7 commit 4968df4
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 44 deletions.
10 changes: 1 addition & 9 deletions doc/windows/package-manager/winget/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ The **upgrade** command requires that you specify the exact string to upgrade. I

![upgrade command](images/upgrade.png)

## Arguments

The following arguments are available.

| Argument | Description |
|-------------|-------------|
| **-q,--query** | The query used to search for an app. |
| **-?, --help** | Get additional help on this command. |

## Options

The options allow you to customize the upgrade experience to meet your needs.
Expand All @@ -47,6 +38,7 @@ The options allow you to customize the upgrade experience to meet your needs.
| **-l, --location** | Location to upgrade to (if supported). |
| **--force** | When a hash mismatch is discovered will ignore the error and attempt to install the package. |
| **--all** | Updates all available packages to the latest application. |
| **--include-unknown** | Attempt to upgrade a package even if the package's current version is unknown. |
### Example queries

The following example upgrades a specific version of an application.
Expand Down
11 changes: 9 additions & 2 deletions src/AppInstallerCLICore/Commands/UpgradeCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@ namespace AppInstaller::CLI
{
bool ShouldListUpgrade(Context& context)
{
return context.Args.Empty() ||
(context.Args.GetArgsCount() == 1 && context.Args.Contains(Execution::Args::Type::Source));
for (Execution::Args::Type type : context.Args.GetTypes())
{
if (type != Execution::Args::Type::Source && type != Execution::Args::Type::IncludeUnknown)
{
return false;
}
}
return true;
}
}

Expand All @@ -46,6 +52,7 @@ namespace AppInstaller::CLI
Argument::ForType(Args::Type::AcceptSourceAgreements),
Argument::ForType(Execution::Args::Type::CustomHeader),
Argument{ "all", Argument::NoAlias, Args::Type::All, Resource::String::UpdateAllArgumentDescription, ArgumentType::Flag },
Argument{ "include-unknown", Argument::NoAlias, Args::Type::IncludeUnknown, Resource::String::IncludeUnknownArgumentDescription, ArgumentType::Flag }
};
}

Expand Down
13 changes: 13 additions & 0 deletions src/AppInstallerCLICore/ExecutionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ namespace AppInstaller::CLI::Execution
DependencySource, // Index source to be queried against for finding dependencies
CustomHeader, // Optional Rest source header
AcceptSourceAgreements, // Accept all source agreements
IncludeUnknown, // Used in Upgrade command to allow upgrades of packages with unknown versions

// Used for demonstration purposes
ExperimentalArg,
Expand Down Expand Up @@ -141,6 +142,18 @@ namespace AppInstaller::CLI::Execution
return m_parsedArgs.size();
}

std::vector<Type> GetTypes()
{
std::vector<Type> types;

for (auto const& i : m_parsedArgs)
{
types.emplace_back(i.first);
}

return types;
}

private:
std::map<Type, std::vector<std::string>> m_parsedArgs;
};
Expand Down
4 changes: 4 additions & 0 deletions src/AppInstallerCLICore/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ImportPackageAlreadyInstalled);
WINGET_DEFINE_RESOURCE_STRINGID(ImportSearchFailed);
WINGET_DEFINE_RESOURCE_STRINGID(ImportSourceNotInstalled);
WINGET_DEFINE_RESOURCE_STRINGID(IncludeUnknownArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(InstallAndUpgradeCommandsReportDependencies);
WINGET_DEFINE_RESOURCE_STRINGID(InstallArchitectureArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(InstallationAbandoned);
Expand Down Expand Up @@ -340,6 +341,9 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeDifferentInstallTechnology);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeDifferentInstallTechnologyInNewerVersions);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeUnknownCount);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeUnknownCountSingle);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeUnknownVersionExplanation);
WINGET_DEFINE_RESOURCE_STRINGID(Usage);
WINGET_DEFINE_RESOURCE_STRINGID(ValidateCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ValidateCommandReportDependencies);
Expand Down
95 changes: 62 additions & 33 deletions src/AppInstallerCLICore/Workflows/UpdateFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,32 @@ namespace AppInstaller::CLI::Workflow
bool updateFound = false;
bool installedTypeInapplicable = false;

// The version keys should have already been sorted by version
const auto& versionKeys = package->GetAvailableVersionKeys();
for (const auto& key : versionKeys)
if (!installedVersion.IsUnknown() || context.Args.Contains(Execution::Args::Type::IncludeUnknown))
{
// Check Update Version
if (IsUpdateVersionApplicable(installedVersion, Utility::Version(key.Version)))
// The version keys should have already been sorted by version
const auto& versionKeys = package->GetAvailableVersionKeys();
for (const auto& key : versionKeys)
{
auto packageVersion = package->GetAvailableVersion(key);
auto manifest = packageVersion->GetManifest();

// Check applicable Installer
auto [installer, inapplicabilities] = manifestComparator.GetPreferredInstaller(manifest);
if (!installer.has_value())
// Check Update Version
if (IsUpdateVersionApplicable(installedVersion, Utility::Version(key.Version)))
{
// If there is at least one installer whose only reason is InstalledType.
auto onlyInstalledType = std::find(inapplicabilities.begin(), inapplicabilities.end(), InapplicabilityFlags::InstalledType);
if (onlyInstalledType != inapplicabilities.end())
auto packageVersion = package->GetAvailableVersion(key);
auto manifest = packageVersion->GetManifest();

// Check applicable Installer
auto [installer, inapplicabilities] = manifestComparator.GetPreferredInstaller(manifest);
if (!installer.has_value())
{
installedTypeInapplicable = true;
// If there is at least one installer whose only reason is InstalledType.
auto onlyInstalledType = std::find(inapplicabilities.begin(), inapplicabilities.end(), InapplicabilityFlags::InstalledType);
if (onlyInstalledType != inapplicabilities.end())
{
installedTypeInapplicable = true;
}

continue;
}

continue;
}

Logging::Telemetry().LogSelectedInstaller(
static_cast<int>(installer->Arch),
installer->Url,
Expand All @@ -86,16 +88,25 @@ namespace AppInstaller::CLI::Workflow
context.Add<Execution::Data::PackageVersion>(std::move(packageVersion));
context.Add<Execution::Data::Installer>(std::move(installer));

updateFound = true;
break;
updateFound = true;
break;
}
else
{
// Any following versions are not applicable
break;
}
}
else
}
else
{
// the package has an unknown version and the user did not request to upgrade it anyway.
if (m_reportUpdateNotFound)
{
// Any following versions are not applicable
break;
context.Reporter.Info() << Resource::String::UpgradeUnknownVersionExplanation << std::endl;
}
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE);
}

if (!updateFound)
{
if (m_reportUpdateNotFound)
Expand Down Expand Up @@ -132,15 +143,28 @@ namespace AppInstaller::CLI::Workflow
const auto& matches = context.Get<Execution::Data::SearchResult>().Matches;
std::vector<std::unique_ptr<Execution::Context>> packagesToInstall;
bool updateAllFoundUpdate = false;
int unknownPackagesCount = 0;

for (const auto& match : matches)
{
// We want to do best effort to update all applicable updates regardless on previous update failure
auto updateContextPtr = context.CreateSubContext();
Execution::Context& updateContext = *updateContextPtr;
auto previousThreadGlobals = updateContext.SetForCurrentThread();
auto installedVersion = match.Package->GetInstalledVersion();

updateContext.Add<Execution::Data::Package>(match.Package);

if (context.Args.Contains(Execution::Args::Type::IncludeUnknown))
{
updateContext.Args.AddArg(Execution::Args::Type::IncludeUnknown);
}
else if (Utility::Version(installedVersion->GetProperty(PackageVersionProperty::Version)).IsUnknown())
{
// we don't know what the package's version is and the user didn't ask to upgrade it anyway.
unknownPackagesCount++;
continue;
}

updateContext <<
Workflow::GetInstalledPackageVersion <<
Expand All @@ -160,14 +184,19 @@ namespace AppInstaller::CLI::Workflow
if (!updateAllFoundUpdate)
{
context.Reporter.Info() << Resource::String::UpdateNotApplicable << std::endl;
return;
}

context.Add<Execution::Data::PackagesToInstall>(std::move(packagesToInstall));
context <<
InstallMultiplePackages(
Resource::String::InstallAndUpgradeCommandsReportDependencies,
APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE,
{ APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE });
else
{
context.Add<Execution::Data::PackagesToInstall>(std::move(packagesToInstall));
context <<
InstallMultiplePackages(
Resource::String::InstallAndUpgradeCommandsReportDependencies,
APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE,
{ APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE });
}
if (unknownPackagesCount > 0 && !context.Args.Contains(Execution::Args::Type::IncludeUnknown))
{
context.Reporter.Info() << unknownPackagesCount << " " << (unknownPackagesCount == 1 ? Resource::String::UpgradeUnknownCountSingle : Resource::String::UpgradeUnknownCount) << std::endl;
}
}
}
}
12 changes: 12 additions & 0 deletions src/AppInstallerCLICore/Workflows/WorkflowBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ namespace AppInstaller::CLI::Workflow
});

int availableUpgradesCount = 0;
int unknownPackagesCount = 0;
auto &source = context.Get<Execution::Data::Source>();
bool shouldShowSource = source.IsComposite() && source.GetAvailableSources().size() > 1;

Expand All @@ -720,6 +721,13 @@ namespace AppInstaller::CLI::Workflow
auto latestVersion = match.Package->GetLatestAvailableVersion();
bool updateAvailable = match.Package->IsUpdateAvailable();

if (m_onlyShowUpgrades && !context.Args.Contains(Execution::Args::Type::IncludeUnknown) && Utility::Version(installedVersion->GetProperty(PackageVersionProperty::Version)).IsUnknown())
{
// We are only showing upgrades, and the user did not request to include packages with unknown versions.
unknownPackagesCount++;
continue;
}

// The only time we don't want to output a line is when filtering and no update is available.
if (updateAvailable || !m_onlyShowUpgrades)
{
Expand Down Expand Up @@ -766,6 +774,10 @@ namespace AppInstaller::CLI::Workflow
context.Reporter.Info() << availableUpgradesCount << ' ' << Resource::String::AvailableUpgrades << std::endl;
}
}
if (m_onlyShowUpgrades && unknownPackagesCount > 0 && !context.Args.Contains(Execution::Args::Type::IncludeUnknown))
{
context.Reporter.Info() << unknownPackagesCount << " " << (unknownPackagesCount == 1 ? Resource::String::UpgradeUnknownCountSingle : Resource::String::UpgradeUnknownCount) << std::endl;
}

}

Expand Down
15 changes: 15 additions & 0 deletions src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
Original file line number Diff line number Diff line change
Expand Up @@ -1250,4 +1250,19 @@ Please specify one of them using the `--source` option to proceed.</value>
<data name="InstallArchitectureArgumentDescription" xml:space="preserve">
<value>Select the architecture to install</value>
</data>
<data name="IncludeUnknownArgumentDescription" xml:space="preserve">
<value>Upgrade packages even if their current version cannot be determined</value>
</data>
<data name="UpgradeUnknownVersionExplanation" xml:space="preserve">
<value>This package's version number cannot be determined. To upgrade it anyway, add the argument --include-unknown to your previous command.</value>
<comment>{Locked="--include-unknown"}</comment>
</data>
<data name="UpgradeUnknownCount" xml:space="preserve">
<value>packages have version numbers that cannot be determined. Use "--include-unknown" to see all results.</value>
<comment>{Locked="--include-unknown"} This string is preceded by a (integer) number of packages that do not have notated versions. </comment>
</data>
<data name="UpgradeUnknownCountSingle" xml:space="preserve">
<value>package has a version number that cannot be determined. Use "--include-unknown" to see all results.</value>
<comment>{Locked="--include-unknown"} This string is preceded by a (integer) number of packages that do not have notated versions.</comment>
</data>
</root>

0 comments on commit 4968df4

Please sign in to comment.