vcpkg-tool/include/vcpkg/vcpkgcmdarguments.h

340 строки
11 KiB
C++

#pragma once
#include <vcpkg/base/fwd/system.process.h>
#include <vcpkg/fwd/vcpkgcmdarguments.h>
#include <vcpkg/fwd/vcpkgpaths.h>
#include <vcpkg/base/cmd-parser.h>
#include <vcpkg/base/messages.h>
#include <vcpkg/base/optional.h>
#include <vcpkg/base/span.h>
#include <vcpkg/base/stringview.h>
#include <assert.h>
#include <map>
#include <memory>
#include <set>
#include <vector>
namespace vcpkg
{
struct ParsedArguments
{
std::set<StringLiteral, std::less<>> switches;
std::map<StringLiteral, std::string, std::less<>> settings;
std::map<StringLiteral, std::vector<std::string>, std::less<>> multisettings;
const std::string* read_setting(StringLiteral setting) const noexcept;
std::vector<std::string> command_arguments;
};
struct MetadataMessage
{
constexpr MetadataMessage() noexcept : kind(MetadataMessageKind::Unused), literal{} { }
/*implicit*/ constexpr MetadataMessage(const msg::MessageT<>& message) noexcept
: kind(MetadataMessageKind::Message), message(&message)
{
}
template<int N>
/*implicit*/ constexpr MetadataMessage(const char (&literal)[N]) noexcept
: kind(MetadataMessageKind::Literal), literal(literal)
{
}
template<class Callback,
std::enable_if_t<std::is_convertible_v<const Callback&, LocalizedString (*)()>, int> = 0>
/*implicit*/ constexpr MetadataMessage(const Callback& callback) noexcept
: kind(MetadataMessageKind::Callback), callback(callback)
{
}
constexpr MetadataMessage(std::nullptr_t) = delete;
MetadataMessage(const MetadataMessage&) = delete;
MetadataMessage& operator=(const MetadataMessage&) = delete;
LocalizedString to_string() const;
void to_string(LocalizedString& target) const;
explicit operator bool() const noexcept;
private:
enum class MetadataMessageKind
{
Unused,
Message,
Literal,
Callback
};
MetadataMessageKind kind;
union
{
const msg::MessageT<>* message;
const char* literal; // not StringLiteral so this union is sizeof(void*)
LocalizedString (*callback)();
};
};
inline constexpr bool constexpr_contains(const char* haystack, const char* needle) noexcept
{
for (;; ++haystack)
{
for (std::size_t offset = 0;; ++offset)
{
if (!needle[offset])
{
return true;
}
if (!haystack[offset])
{
return false;
}
if (needle[offset] != haystack[offset])
{
break;
}
}
}
}
static_assert(constexpr_contains("", ""), "boom");
static_assert(constexpr_contains("hay", ""), "boom");
static_assert(!constexpr_contains("", "needle"), "boom");
static_assert(constexpr_contains("needle", "nee"), "boom");
struct LearnWebsiteLinkLiteralUndocumentedCookie
{
};
constexpr LearnWebsiteLinkLiteralUndocumentedCookie Undocumented;
struct LearnWebsiteLinkLiteral
{
/*implicit*/ constexpr LearnWebsiteLinkLiteral(LearnWebsiteLinkLiteralUndocumentedCookie) noexcept : literal{}
{
}
template<int N>
/*implicit*/ constexpr LearnWebsiteLinkLiteral(const char (&literal)[N]) noexcept : literal(literal)
{
assert(!constexpr_contains(literal, "en-us") &&
"If you get a build error here, remove the en-us from the learn uri so that the correct locale is "
"chosen for the user");
}
LocalizedString to_string() const;
void to_string(LocalizedString& target) const;
explicit operator bool() const noexcept;
private:
const char* literal; // not StringLiteral to be nullable
};
struct CommandSwitch
{
StringLiteral name;
MetadataMessage helpmsg;
};
struct CommandSetting
{
StringLiteral name;
MetadataMessage helpmsg;
};
struct CommandMultiSetting
{
StringLiteral name;
MetadataMessage helpmsg;
};
struct CommandOptionsStructure
{
View<CommandSwitch> switches;
View<CommandSetting> settings;
View<CommandMultiSetting> multisettings;
};
struct CommandMetadata
{
StringLiteral name;
MetadataMessage synopsis;
static constexpr std::size_t example_max_size = 4;
MetadataMessage examples[example_max_size];
LearnWebsiteLinkLiteral website_link;
AutocompletePriority autocomplete_priority;
size_t minimum_arity;
size_t maximum_arity;
CommandOptionsStructure options;
std::vector<std::string> (*valid_arguments)(const VcpkgPaths& paths);
LocalizedString get_example_text() const;
};
LocalizedString usage_for_command(const CommandMetadata& command_metadata);
struct FeatureFlagSettings
{
bool registries;
bool compiler_tracking;
bool binary_caching;
bool versions;
bool dependency_graph;
};
struct PortApplicableSetting
{
std::string value;
PortApplicableSetting(StringView setting);
bool is_port_affected(StringView port_name) const noexcept;
private:
std::vector<std::string> affected_ports;
};
struct VcpkgCmdArguments
{
static VcpkgCmdArguments create_from_command_line(const ILineReader& fs,
const int argc,
const CommandLineCharType* const* const argv);
static VcpkgCmdArguments create_from_arg_sequence(const std::string* arg_begin, const std::string* arg_end);
Optional<std::string> vcpkg_root_dir_arg;
Optional<std::string> vcpkg_root_dir_env;
Optional<std::string> manifest_root_dir;
Optional<std::string> buildtrees_root_dir;
Optional<std::string> downloads_root_dir;
Optional<std::string> install_root_dir;
Optional<std::string> packages_root_dir;
Optional<std::string> scripts_root_dir;
Optional<std::string> builtin_ports_root_dir;
Optional<std::string> builtin_registry_versions_dir;
Optional<std::string> registries_cache_dir;
Optional<std::string> default_visual_studio_path;
Optional<std::string> triplet;
Optional<std::string> host_triplet;
std::vector<std::string> cli_overlay_ports;
std::vector<std::string> env_overlay_ports;
std::vector<std::string> cli_overlay_triplets;
std::vector<std::string> env_overlay_triplets;
std::vector<std::string> cli_binary_sources;
Optional<std::string> env_binary_sources;
Optional<std::string> actions_cache_url;
Optional<std::string> actions_runtime_token;
Optional<std::string> nuget_id_prefix;
Optional<bool> use_nuget_cache;
Optional<std::string> vcpkg_nuget_repository;
Optional<std::string> github_repository;
Optional<std::string> github_server_url;
Optional<std::string> github_ref;
Optional<std::string> github_sha;
Optional<std::string> ci_repository_id;
Optional<std::string> ci_repository_owner_id;
Optional<PortApplicableSetting> cmake_debug;
Optional<PortApplicableSetting> cmake_configure_debug;
std::vector<std::string> cmake_args;
Optional<bool> exact_abi_tools_versions;
Optional<bool> debug = nullopt;
Optional<bool> debug_env = nullopt;
Optional<bool> send_metrics = nullopt;
// fully disable metrics -- both printing and sending
Optional<bool> disable_metrics = nullopt;
Optional<bool> print_metrics = nullopt;
Optional<bool> wait_for_lock = nullopt;
Optional<bool> ignore_lock_failures = nullopt;
bool do_not_take_lock = false;
Optional<std::string> github_run_id;
Optional<std::string> github_token;
Optional<std::string> github_job;
Optional<std::string> github_workflow;
// feature flags
Optional<bool> dependency_graph_feature = nullopt;
Optional<bool> feature_packages = nullopt;
Optional<bool> binary_caching = nullopt;
Optional<bool> compiler_tracking = nullopt;
Optional<bool> registries_feature = nullopt;
Optional<bool> versions_feature = nullopt;
bool dependency_graph_enabled() const { return dependency_graph_feature.value_or(false); }
bool binary_caching_enabled() const { return binary_caching.value_or(true); }
bool compiler_tracking_enabled() const { return compiler_tracking.value_or(true); }
bool registries_enabled() const { return registries_feature.value_or(true); }
bool versions_enabled() const { return versions_feature.value_or(true); }
FeatureFlagSettings feature_flag_settings() const
{
FeatureFlagSettings f;
f.binary_caching = binary_caching_enabled();
f.compiler_tracking = compiler_tracking_enabled();
f.registries = registries_enabled();
f.versions = versions_enabled();
f.dependency_graph = dependency_graph_enabled();
return f;
}
const Optional<StringLiteral>& detected_ci_environment() const { return m_detected_ci_environment; }
const std::string& get_command() const noexcept { return command; }
std::vector<std::string> forwardable_arguments;
ParsedArguments parse_arguments(const CommandMetadata& command_metadata) const;
void imbue_from_environment();
void imbue_from_fake_environment(const std::map<StringLiteral, std::string, std::less<>>& env);
// Applies recursive settings from the environment or sets a global environment variable
// to be consumed by subprocesses; may only be called once per process.
static void imbue_or_apply_process_recursion(VcpkgCmdArguments& args);
void check_feature_flag_consistency() const;
void debug_print_feature_flags() const;
void track_feature_flag_metrics() const;
void track_environment_metrics() const;
Optional<std::string> asset_sources_template() const;
const std::vector<std::string>& get_forwardable_arguments() const noexcept;
private:
VcpkgCmdArguments(CmdParser&& parser);
void imbue_from_environment_impl(std::function<Optional<std::string>(ZStringView)> get_env);
Optional<std::string> asset_sources_template_env; // for EnvironmentVariableXVcpkgAssetSources
Optional<std::string> asset_sources_template_arg; // for SwitchAssetSources
std::string command;
Optional<StringLiteral> m_detected_ci_environment;
friend LocalizedString usage_for_command(const CommandMetadata& command_metadata);
CmdParser parser;
};
}