winget-cli

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

Argument.h (15011B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 #include "ExecutionContext.h"
      5 #include "Resources.h"
      6 #include <winget/UserSettings.h>
      7 #include <winget/ExperimentalFeature.h>
      8 #include <winget/GroupPolicy.h>
      9 #include <winget/AdminSettings.h>
     10 #include <winget/LocIndependent.h>
     11 
     12 #include <string>
     13 #include <string_view>
     14 
     15 
     16 #define APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR       '-'
     17 #define APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_STRING     "-"
     18 #define APPINSTALLER_CLI_ARGUMENT_SPLIT_CHAR            '='
     19 #define APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_CHAR        '?'
     20 #define APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_STRING      "?"
     21 #define APPINSTALLER_CLI_HELP_ARGUMENT                  APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_STRING APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_STRING
     22 
     23 namespace AppInstaller::CLI
     24 {
     25     using namespace AppInstaller::Utility::literals;
     26 
     27     // The type of argument.
     28     enum class ArgumentType
     29     {
     30         // Argument requires specifying the name before the value.
     31         Standard,
     32         // Argument value can be specified alone; position indicates argument name.
     33         Positional,
     34         // Only argument name can be specified and indicates a bool value.
     35         Flag,
     36     };
     37 
     38     // Categories an arg type can belong to.
     39     // Used to reason about the arguments present without having to repeat the same
     40     // lists every time.
     41     enum class ArgTypeCategory
     42     {
     43         None = 0,
     44         // The --manifest argument.
     45         Manifest = 0x1,
     46         // Arguments for querying or selecting a package.
     47         // E.g.: --query
     48         PackageQuery = 0x2,
     49         // Arguments for querying or selecting a package, which do not work for multiple packages.
     50         // E.g.: --version
     51         SinglePackageQuery = 0x4,
     52         // Arguments for installer or uninstaller selection.
     53         // E.g.: --scope
     54         InstallerSelection = 0x8,
     55         // Arguments for installer or uninstaller behavior.
     56         // E.g.: --interactive
     57         InstallerBehavior = 0x10,
     58         // Arguments for installer or uninstaller behavior, which do not work for multiple packages.
     59         // E.g.: --override
     60         SingleInstallerBehavior = 0x20,
     61         // Arguments for selecting or interacting with the source used for initial querying
     62         // E.g.: --header
     63         QuerySource = 0x40,
     64         // Arguments that only make sense when talking about multiple packages
     65         MultiplePackages = 0x80,
     66         // Flag arguments that should be copied over when creating a sub-context
     67         CopyFlagToSubContext = 0x100,
     68         // Arguments with associated values that should be copied over when creating a sub-context
     69         CopyValueToSubContext = 0x200,
     70         // Arguments for selecting or interacting with dependencies or setting specific source behaviors
     71         // E.g.: --dependency-source
     72         // E.g.: --accept-source-agreements
     73         ExtendedSource = 0x400,
     74         // Arguments for selecting a configuration set (file or history).
     75         ConfigurationSetChoice = 0x800,
     76     };
     77 
     78     DEFINE_ENUM_FLAG_OPERATORS(ArgTypeCategory);
     79 
     80     // Exclusive sets an argument can belong to.
     81     // Only one argument from each exclusive set is allowed at a time.
     82     enum class ArgTypeExclusiveSet : uint32_t
     83     {
     84         None = 0x0,
     85         ProgressBarOption = 0x1,
     86         EnableDisable = 0x2,
     87         PurgePreserve = 0x4,
     88         PinType = 0x8,
     89         StubType = 0x10,
     90         Proxy = 0x20,
     91         AllAndTargetVersion = 0x40,
     92         ConfigurationSetChoice = 0x80,
     93         DscResourceFunction = 0x100,
     94 
     95         // This must always be at the end
     96         Max
     97     };
     98 
     99     DEFINE_ENUM_FLAG_OPERATORS(ArgTypeExclusiveSet);
    100 
    101     // An argument to a command; containing only data that is common to all its uses.
    102     // Argument extends this by adding command-specific values, like help strings.
    103     struct ArgumentCommon
    104     {
    105         // Defines an argument with no alias.
    106         constexpr static char NoAlias = '\0';
    107 
    108         ArgumentCommon(Execution::Args::Type execArgType, Utility::LocIndView name, char alias, Utility::LocIndView alternateName, ArgTypeCategory typeCategory = ArgTypeCategory::None, ArgTypeExclusiveSet exclusiveSet = ArgTypeExclusiveSet::None)
    109             : Type(execArgType), Name(name), Alias(alias), AlternateName(alternateName), TypeCategory(typeCategory), ExclusiveSet(exclusiveSet) {}
    110 
    111         ArgumentCommon(Execution::Args::Type execArgType, Utility::LocIndView name, char alias, ArgTypeCategory typeCategory = ArgTypeCategory::None, ArgTypeExclusiveSet exclusiveSet = ArgTypeExclusiveSet::None)
    112             : Type(execArgType), Name(name), Alias(alias), TypeCategory(typeCategory), ExclusiveSet(exclusiveSet) {}
    113 
    114         ArgumentCommon(Execution::Args::Type execArgType, Utility::LocIndView name, Utility::LocIndView alternateName, ArgTypeCategory typeCategory = ArgTypeCategory::None, ArgTypeExclusiveSet exclusiveSet = ArgTypeExclusiveSet::None)
    115             : Type(execArgType), Name(name), Alias(NoAlias), AlternateName(alternateName), TypeCategory(typeCategory), ExclusiveSet(exclusiveSet) {}
    116 
    117         ArgumentCommon(Execution::Args::Type execArgType, Utility::LocIndView name, ArgTypeCategory typeCategory = ArgTypeCategory::None, ArgTypeExclusiveSet exclusiveSet = ArgTypeExclusiveSet::None)
    118             : Type(execArgType), Name(name), Alias(NoAlias), TypeCategory(typeCategory), ExclusiveSet(exclusiveSet) {}
    119 
    120         // Gets the argument for the given type.
    121         static ArgumentCommon ForType(Execution::Args::Type execArgType);
    122 
    123         static std::vector<ArgumentCommon> GetFromExecArgs(const Execution::Args& execArgs);
    124 
    125         Execution::Args::Type Type;
    126         Utility::LocIndView Name;
    127         char Alias;
    128         Utility::LocIndView AlternateName;
    129         ArgTypeCategory TypeCategory;
    130         ArgTypeExclusiveSet ExclusiveSet;
    131     };
    132 
    133     // An argument to a command.
    134     struct Argument
    135     {
    136         // Controls the visibility of the field.
    137         enum class Visibility
    138         {
    139             // Shown in the example.
    140             Example,
    141             // Shown only in the table below the example.
    142             Help,
    143             // Not shown in help.
    144             Hidden,
    145         };
    146 
    147         // Defines an argument with no alternate name
    148         constexpr static std::string_view NoAlternateName = "";
    149 
    150         Argument(Execution::Args::Type execArgType, Resource::StringId desc) :
    151             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)) {}
    152 
    153         Argument(Execution::Args::Type execArgType, Resource::StringId desc, bool required) :
    154             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_required(required) {}
    155 
    156         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type) :
    157             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type) {}
    158 
    159         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility) :
    160             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility) {}
    161 
    162         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, bool required) :
    163             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_required(required) {}
    164 
    165         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, bool required) :
    166             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_required(required) {}
    167 
    168 #ifndef AICLI_DISABLE_TEST_HOOKS
    169         // Constructors for arguments with custom names and aliases to use in tests
    170         Argument(std::string_view name, char alias, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type) :
    171             m_argCommon(execArgType, Utility::LocIndView{ name }, alias), m_desc(std::move(desc)), m_type(type) {}
    172 
    173         Argument(std::string_view name, char alias, std::string_view alternateName, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type) :
    174             m_argCommon(execArgType, Utility::LocIndView{ name }, alias, Utility::LocIndView{ alternateName }), m_desc(std::move(desc)), m_type(type) {}
    175 #endif
    176 
    177         ~Argument() = default;
    178 
    179         Argument(const Argument&) = default;
    180         Argument& operator=(const Argument&) = default;
    181 
    182         Argument(Argument&&) = default;
    183         Argument& operator=(Argument&&) = default;
    184 
    185         // Gets the argument for the given type.
    186         static Argument ForType(Execution::Args::Type type);
    187 
    188         // Gets the common arguments for all commands.
    189         static void GetCommon(std::vector<Argument>& args);
    190 
    191         // Static argument validation helpers; throw CommandException when validation fails.
    192 
    193         // Requires that at most one argument from the list is present.
    194         static void ValidateExclusiveArguments(const Execution::Args& args);
    195 
    196         // Requires that if an argument depends on another one, it is not present without the dependency.
    197         static void ValidateArgumentDependency(const Execution::Args& args, Execution::Args::Type type, Execution::Args::Type dependencyArgType);
    198 
    199         static ArgTypeCategory GetCategoriesPresent(const Execution::Args& arg);
    200 
    201         // Requires that arguments meet common requirements
    202         static ArgTypeCategory GetCategoriesAndValidateCommonArguments(const Execution::Args& args, bool requirePackageSelectionArg = true);
    203         static void ValidateCommonArguments(const Execution::Args& args, bool requirePackageSelectionArg = true) { std::ignore = GetCategoriesAndValidateCommonArguments(args, requirePackageSelectionArg); }
    204 
    205         // Gets the argument usage string in the format of "-alias,--name".
    206         std::string GetUsageString() const;
    207 
    208         // Arguments are not localized at this time.
    209         Utility::LocIndView Name() const { return m_argCommon.Name; }
    210         char Alias() const { return m_argCommon.Alias; }
    211         std::string_view AlternateName() const { return m_argCommon.AlternateName; }
    212         Execution::Args::Type ExecArgType() const { return m_argCommon.Type; }
    213         const Resource::StringId& Description() const { return m_desc; }
    214         bool Required() const { return m_required; }
    215         ArgumentType Type() const { return m_type; }
    216         size_t Limit() const { return m_countLimit; }
    217         Argument::Visibility GetVisibility() const;
    218         Settings::ExperimentalFeature::Feature Feature() const { return m_feature; }
    219         Settings::TogglePolicy::Policy GroupPolicy() const { return m_groupPolicy; }
    220         Settings::BoolAdminSetting AdminSetting() const { return m_adminSetting; }
    221 
    222         Argument& SetRequired(bool required) { m_required = required; return *this; }
    223         Argument& SetCountLimit(size_t countLimit) { m_countLimit = countLimit; return *this; }
    224 
    225     private:
    226         // Constructors that set a Feature or Policy are private to force callers to go through the ForType() function.
    227         // This helps keep it all in one place to reduce chances of missing it somewhere.
    228         Argument(Execution::Args::Type execArgType, Resource::StringId desc, Settings::ExperimentalFeature::Feature feature) :
    229             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_feature(feature) {}
    230 
    231         Argument(Execution::Args::Type execArgType, Resource::StringId desc, bool required, Settings::ExperimentalFeature::Feature feature) :
    232             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_required(required), m_feature(feature) {}
    233 
    234         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::ExperimentalFeature::Feature feature) :
    235             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_feature(feature) {}
    236 
    237         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::ExperimentalFeature::Feature feature) :
    238             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_feature(feature) {}
    239 
    240         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, bool required, Settings::ExperimentalFeature::Feature feature) :
    241             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_required(required), m_feature(feature) {}
    242 
    243         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, bool required, Settings::ExperimentalFeature::Feature feature) :
    244             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_required(required), m_feature(feature) {}
    245 
    246         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
    247             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
    248 
    249         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
    250             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
    251 
    252         Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::ExperimentalFeature::Feature feature, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
    253             m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_feature(feature), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
    254 
    255         ArgumentCommon m_argCommon;
    256         Resource::StringId m_desc;
    257         bool m_required = false;
    258         ArgumentType m_type = ArgumentType::Standard;
    259         Argument::Visibility m_visibility = Argument::Visibility::Example;
    260         size_t m_countLimit = 1;
    261         Settings::ExperimentalFeature::Feature m_feature = Settings::ExperimentalFeature::Feature::None;
    262         Settings::TogglePolicy::Policy m_groupPolicy = Settings::TogglePolicy::Policy::None;
    263         Settings::BoolAdminSetting m_adminSetting = Settings::BoolAdminSetting::Unknown;
    264     };
    265 }