winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

ShowFlow.cpp (14535B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 
      4 #include "pch.h"
      5 #include "ShowFlow.h"
      6 #include <winget/ManifestComparator.h>
      7 #include "TableOutput.h"
      8 
      9 using namespace AppInstaller::Repository;
     10 using namespace AppInstaller::CLI;
     11 using namespace AppInstaller::Utility;
     12 using namespace AppInstaller::Utility::literals;
     13 
     14 namespace {
     15 
     16     template <typename String>
     17     void ShowSingleLineField(Execution::OutputStream outputStream, AppInstaller::StringResource::StringId label, const String& value, bool indent = false)
     18     {
     19         if (value.empty())
     20         {
     21             return;
     22         }
     23         if (indent)
     24         {
     25             outputStream << "  "_liv;
     26         }
     27         outputStream << Execution::ManifestInfoEmphasis << label << ' ' << value << std::endl;
     28     }
     29 
     30     template <typename String>
     31     void ShowMultiLineField(Execution::OutputStream outputStream, AppInstaller::StringResource::StringId label, const String& value)
     32     {
     33         if (value.empty())
     34         {
     35             return;
     36         }
     37         /*
     38             We need to be able to find and replace within the string.However, we don't want to own the original string
     39             Therefore, a copy is created here so we can manipulate it. The memory should be freed again once this method
     40             returns and the string is no longer in scope.
     41         */
     42         std::string shownValue = value;
     43         bool isMultiLine = FindAndReplace(shownValue, "\n", "\n  ");
     44         outputStream << Execution::ManifestInfoEmphasis << label;
     45         if (isMultiLine)
     46         {
     47             outputStream << std::endl << "  "_liv << shownValue << std::endl;
     48         }
     49         else
     50         {
     51             outputStream << ' ' << shownValue << std::endl;
     52         }
     53     }
     54 
     55     template <typename Enumerable>
     56     void ShowMultiValueField(Execution::OutputStream outputStream, AppInstaller::StringResource::StringId label, const Enumerable& values)
     57     {
     58         if (values.empty())
     59         {
     60             return;
     61         }
     62         outputStream << Execution::ManifestInfoEmphasis << label << std::endl;
     63         for (const auto& value : values)
     64         {
     65             outputStream << "  "_liv << value << std::endl;
     66         }
     67     }
     68 
     69     void ShowAgreements(Execution::OutputStream outputStream, const std::vector<AppInstaller::Manifest::Agreement>& agreements) {
     70 
     71         if (agreements.empty()) {
     72             return;
     73         }
     74 
     75         outputStream << Execution::ManifestInfoEmphasis << Resource::String::ShowLabelAgreements << std::endl;
     76         for (const auto& agreement : agreements) {
     77 
     78             if (!agreement.Label.empty())
     79             {
     80                 outputStream << "  "_liv << Execution::ManifestInfoEmphasis << agreement.Label << ": "_liv;
     81             }
     82 
     83             if (!agreement.AgreementText.empty())
     84             {
     85                 outputStream << agreement.AgreementText << std::endl;
     86             }
     87 
     88             if (!agreement.AgreementUrl.empty())
     89             {
     90                 outputStream << agreement.AgreementUrl << std::endl;
     91             }
     92         }
     93     }
     94 }
     95 
     96 namespace AppInstaller::CLI::Workflow
     97 {
     98     void ShowAgreementsInfo(Execution::Context& context)
     99     {
    100         const auto& manifest = context.Get<Execution::Data::Manifest>();
    101         auto info = context.Reporter.Info();
    102 
    103         ShowSingleLineField(info, Resource::String::ShowLabelVersion, manifest.Version);
    104         ShowSingleLineField(info, Resource::String::ShowLabelPublisher, manifest.CurrentLocalization.Get<Manifest::Localization::Publisher>());
    105         ShowSingleLineField(info, Resource::String::ShowLabelPublisherUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PublisherUrl>());
    106         ShowSingleLineField(info, Resource::String::ShowLabelPublisherSupportUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PublisherSupportUrl>());
    107         ShowSingleLineField(info, Resource::String::ShowLabelAuthor, manifest.CurrentLocalization.Get<Manifest::Localization::Author>());
    108         ShowSingleLineField(info, Resource::String::ShowLabelPackageUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PackageUrl>());
    109         ShowSingleLineField(info, Resource::String::ShowLabelLicense, manifest.CurrentLocalization.Get<Manifest::Localization::License>());
    110         ShowSingleLineField(info, Resource::String::ShowLabelLicenseUrl, manifest.CurrentLocalization.Get<Manifest::Localization::LicenseUrl>());
    111         ShowSingleLineField(info, Resource::String::ShowLabelPrivacyUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PrivacyUrl>());
    112         ShowSingleLineField(info, Resource::String::ShowLabelCopyright, manifest.CurrentLocalization.Get<Manifest::Localization::Copyright>());
    113         ShowSingleLineField(info, Resource::String::ShowLabelCopyrightUrl, manifest.CurrentLocalization.Get<Manifest::Localization::CopyrightUrl>());
    114         ShowSingleLineField(info, Resource::String::ShowLabelPurchaseUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PurchaseUrl>());
    115         ShowAgreements(info, manifest.CurrentLocalization.Get<Manifest::Localization::Agreements>());
    116         
    117     }
    118 
    119     void ShowManifestInfo(Execution::Context& context)
    120     {
    121         context << ShowPackageInfo << ShowInstallerInfo;
    122     }
    123 
    124     void ShowPackageInfo(Execution::Context& context)
    125     {
    126         const auto& manifest = context.Get<Execution::Data::Manifest>();
    127         auto info = context.Reporter.Info();
    128         // Get description from manifest so we can see if it is empty later
    129         auto description = manifest.CurrentLocalization.Get<Manifest::Localization::Description>();
    130 
    131         // TODO: Come up with a prettier format
    132         ShowSingleLineField(info, Resource::String::ShowLabelVersion, manifest.Version);
    133         ShowSingleLineField(info, Resource::String::ShowLabelPublisher, manifest.CurrentLocalization.Get<Manifest::Localization::Publisher>());
    134         ShowSingleLineField(info, Resource::String::ShowLabelPublisherUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PublisherUrl>());
    135         ShowSingleLineField(info, Resource::String::ShowLabelPublisherSupportUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PublisherSupportUrl>());
    136         ShowSingleLineField(info, Resource::String::ShowLabelAuthor, manifest.CurrentLocalization.Get<Manifest::Localization::Author>());
    137         ShowSingleLineField(info, Resource::String::ShowLabelMoniker, manifest.Moniker);
    138         ShowMultiLineField(info,  Resource::String::ShowLabelDescription, description.empty() ? manifest.CurrentLocalization.Get<Manifest::Localization::ShortDescription>() : description);
    139         ShowSingleLineField(info, Resource::String::ShowLabelPackageUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PackageUrl>());
    140         ShowSingleLineField(info, Resource::String::ShowLabelLicense, manifest.CurrentLocalization.Get<Manifest::Localization::License>());
    141         ShowSingleLineField(info, Resource::String::ShowLabelLicenseUrl, manifest.CurrentLocalization.Get<Manifest::Localization::LicenseUrl>());
    142         ShowSingleLineField(info, Resource::String::ShowLabelPrivacyUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PrivacyUrl>());
    143         ShowSingleLineField(info, Resource::String::ShowLabelCopyright, manifest.CurrentLocalization.Get<Manifest::Localization::Copyright>());
    144         ShowSingleLineField(info, Resource::String::ShowLabelCopyrightUrl, manifest.CurrentLocalization.Get<Manifest::Localization::CopyrightUrl>());
    145         ShowMultiLineField(info,  Resource::String::ShowLabelReleaseNotes, manifest.CurrentLocalization.Get<Manifest::Localization::ReleaseNotes>());
    146         ShowSingleLineField(info, Resource::String::ShowLabelReleaseNotesUrl, manifest.CurrentLocalization.Get<Manifest::Localization::ReleaseNotesUrl>());
    147         ShowSingleLineField(info, Resource::String::ShowLabelPurchaseUrl, manifest.CurrentLocalization.Get<Manifest::Localization::PurchaseUrl>());
    148         ShowMultiLineField(info, Resource::String::ShowLabelInstallationNotes, manifest.CurrentLocalization.Get<Manifest::Localization::InstallationNotes>());
    149         const auto& documentations = manifest.CurrentLocalization.Get<Manifest::Localization::Documentations>();
    150         if (!documentations.empty())
    151         {
    152             context.Reporter.Info() << Execution::ManifestInfoEmphasis << Resource::String::ShowLabelDocumentation << std::endl;
    153             for (const auto& documentation : documentations)
    154             {
    155                 if (!documentation.DocumentUrl.empty())
    156                 {
    157                     info << "  "_liv;
    158                     if (!documentation.DocumentLabel.empty())
    159                     {
    160                         info << Execution::ManifestInfoEmphasis << documentation.DocumentLabel << ": "_liv;
    161                     }
    162 
    163                     info << documentation.DocumentUrl << std::endl;
    164                 }
    165             }
    166         }
    167         ShowMultiValueField(info, Resource::String::ShowLabelTags, manifest.CurrentLocalization.Get<Manifest::Localization::Tags>());
    168         ShowAgreements(info, manifest.CurrentLocalization.Get<Manifest::Localization::Agreements>());
    169     }
    170 
    171     void ShowInstallerInfo(Execution::Context& context)
    172     {
    173         const auto& installer = context.Get<Execution::Data::Installer>();
    174         auto info = context.Reporter.Info();
    175 
    176         info << Execution::ManifestInfoEmphasis << Resource::String::ShowLabelInstaller << std::endl;
    177         if (installer)
    178         {
    179             Manifest::InstallerTypeEnum effectiveInstallerType = installer->EffectiveInstallerType();
    180             Manifest::InstallerTypeEnum baseInstallerType = installer->BaseInstallerType;
    181             std::string shownInstallerType;
    182             shownInstallerType = Manifest::InstallerTypeToString(effectiveInstallerType);
    183             if (effectiveInstallerType != baseInstallerType)
    184             {
    185                 shownInstallerType += " ("_liv;
    186                 shownInstallerType += Manifest::InstallerTypeToString(baseInstallerType);
    187                 shownInstallerType += ')';
    188             }
    189             ShowSingleLineField(info, Resource::String::ShowLabelInstallerType, shownInstallerType, true);
    190             ShowSingleLineField(info, Resource::String::ShowLabelInstallerLocale, installer->Locale, true);
    191             ShowSingleLineField(info, Resource::String::ShowLabelInstallerUrl, installer->Url, true);
    192             ShowSingleLineField(info, Resource::String::ShowLabelInstallerSha256, (installer->Sha256.empty()) ? "" : Utility::SHA256::ConvertToString(installer->Sha256), true);
    193             ShowSingleLineField(info, Resource::String::ShowLabelInstallerProductId, installer->ProductId, true);
    194             ShowSingleLineField(info, Resource::String::ShowLabelInstallerReleaseDate, installer->ReleaseDate, true);
    195             ShowSingleLineField(info, Resource::String::ShowLabelInstallerOfflineDistributionSupported, Utility::ConvertBoolToString(!installer->DownloadCommandProhibited), true);
    196 
    197             const auto& dependencies = installer->Dependencies;
    198 
    199             if (dependencies.HasAny())
    200             {
    201                 info << Execution::ManifestInfoEmphasis << "  "_liv << Resource::String::ShowLabelDependencies << ' ' << std::endl;
    202 
    203                 if (dependencies.HasAnyOf(Manifest::DependencyType::WindowsFeature))
    204                 {
    205                     info << "    - "_liv << Resource::String::ShowLabelWindowsFeaturesDependencies << ' ' << std::endl;
    206                     dependencies.ApplyToType(Manifest::DependencyType::WindowsFeature, [&info](Manifest::Dependency dependency) {info << "        "_liv << dependency.Id() << std::endl; });
    207                 }
    208 
    209                 if (dependencies.HasAnyOf(Manifest::DependencyType::WindowsLibrary))
    210                 {
    211                     info << "    - "_liv << Resource::String::ShowLabelWindowsLibrariesDependencies << ' ' << std::endl;
    212                     dependencies.ApplyToType(Manifest::DependencyType::WindowsLibrary, [&info](Manifest::Dependency dependency) {info << "        "_liv << dependency.Id() << std::endl; });
    213                 }
    214 
    215                 if (dependencies.HasAnyOf(Manifest::DependencyType::Package))
    216                 {
    217                     info << "    - "_liv << Resource::String::ShowLabelPackageDependencies << ' ' << std::endl;
    218                     dependencies.ApplyToType(Manifest::DependencyType::Package, [&info](Manifest::Dependency dependency)
    219                         {
    220                             info << "        "_liv << dependency.Id();
    221                             if (dependency.MinVersion)
    222                             {
    223                                 info << " [>= " << dependency.MinVersion.value().ToString() << "]";
    224                             }
    225                             info << std::endl;
    226                         });
    227                 }
    228 
    229                 if (dependencies.HasAnyOf(Manifest::DependencyType::External))
    230                 {
    231                     info << "    - "_liv << Resource::String::ShowLabelExternalDependencies << ' ' << std::endl;
    232                     dependencies.ApplyToType(Manifest::DependencyType::External, [&info](Manifest::Dependency dependency) {info << "        "_liv << dependency.Id() << std::endl; });
    233                 }
    234             }
    235         }
    236         else
    237         {
    238             context.Reporter.Warn() << "  "_liv << Resource::String::NoApplicableInstallers << std::endl;
    239         }
    240     }
    241 
    242     void ShowManifestVersion(Execution::Context& context)
    243     {
    244         const auto& manifest = context.Get<Execution::Data::Manifest>();
    245         Execution::TableOutput<2> table(context.Reporter, { Resource::String::ShowVersion, Resource::String::ShowChannel });
    246         table.OutputLine({ manifest.Version, manifest.Channel });
    247         table.Complete();
    248     }
    249 
    250     void GetManifest::operator()(Execution::Context& context) const
    251     {
    252         if (context.Args.Contains(Execution::Args::Type::Manifest))
    253         {
    254             context <<
    255                 GetManifestFromArg;
    256         }
    257         else
    258         {
    259             context <<
    260                 OpenSource() <<
    261                 SearchSourceForSingle <<
    262                 HandleSearchResultFailures <<
    263                 EnsureOneMatchFromSearchResult(OperationType::Show) <<
    264                 GetManifestFromPackage(m_considerPins);
    265         }
    266     }
    267 }