diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2020-02-07 11:24:35 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-07 11:24:35 -0800 |
| commit | 8db6db5dac70c25b04cd4dd84392484dee822fbe (patch) | |
| tree | 4734de271f966ff4b9a913b15c1b7b537ecd1a8d | |
| parent | 2873f07823df192ba55693d200850669eabe332c (diff) | |
| download | vcpkg-8db6db5dac70c25b04cd4dd84392484dee822fbe.tar.gz vcpkg-8db6db5dac70c25b04cd4dd84392484dee822fbe.zip | |
[vcpkg] Further parser improvements (#9895)
* [vcpkg] Consolidate several internal parsers together (packagespecs + logicexpression + control) and enhance error messages
* [vcpkg] Migrate Build-Depends parsing to new framework
* [vcpkg] Fix tests. Re-enable underscores in feature names due to libwebp[vwebp_sdl] -- todo: rename this feature and remove underscores.
59 files changed, 958 insertions, 969 deletions
diff --git a/toolsrc/include/vcpkg-test/mockcmakevarprovider.h b/toolsrc/include/vcpkg-test/mockcmakevarprovider.h index 03defdcdd..21207c856 100644 --- a/toolsrc/include/vcpkg-test/mockcmakevarprovider.h +++ b/toolsrc/include/vcpkg-test/mockcmakevarprovider.h @@ -6,7 +6,7 @@ namespace vcpkg::Test {
struct MockCMakeVarProvider : CMakeVars::CMakeVarProvider
{
- void load_generic_triplet_vars(const Triplet& triplet) const override { generic_triplet_vars[triplet] = {}; }
+ void load_generic_triplet_vars(Triplet triplet) const override { generic_triplet_vars[triplet] = {}; }
void load_dep_info_vars(Span<const PackageSpec> specs) const override
{
@@ -23,7 +23,7 @@ namespace vcpkg::Test }
Optional<const std::unordered_map<std::string, std::string>&> get_generic_triplet_vars(
- const Triplet& triplet) const override;
+ Triplet triplet) const override;
Optional<const std::unordered_map<std::string, std::string>&> get_dep_info_vars(
const PackageSpec& spec) const override;
diff --git a/toolsrc/include/vcpkg-test/util.h b/toolsrc/include/vcpkg-test/util.h index 088a39b7d..d8ecc51ea 100644 --- a/toolsrc/include/vcpkg-test/util.h +++ b/toolsrc/include/vcpkg-test/util.h @@ -40,7 +40,7 @@ namespace vcpkg::Test { std::unordered_map<std::string, SourceControlFileLocation> map; Triplet triplet; - PackageSpecMap(const Triplet& t = Triplet::X86_WINDOWS) noexcept : triplet(t) {} + PackageSpecMap(Triplet t = Triplet::X86_WINDOWS) noexcept : triplet(t) {} PackageSpec emplace(const char* name, const char* depends = "", @@ -50,8 +50,6 @@ namespace vcpkg::Test PackageSpec emplace(vcpkg::SourceControlFileLocation&& scfl); }; - vcpkg::PackageSpec unsafe_pspec(std::string name, vcpkg::Triplet t = vcpkg::Triplet::X86_WINDOWS); - template<class T, class S> T&& unwrap(vcpkg::ExpectedT<T, S>&& p) { diff --git a/toolsrc/include/vcpkg/base/expected.h b/toolsrc/include/vcpkg/base/expected.h index c273d71e6..2b19bad2a 100644 --- a/toolsrc/include/vcpkg/base/expected.h +++ b/toolsrc/include/vcpkg/base/expected.h @@ -75,6 +75,30 @@ namespace vcpkg constexpr ExpectedLeftTag expected_left_tag; constexpr ExpectedRightTag expected_right_tag; + template<class T> + struct ExpectedHolder + { + ExpectedHolder() = default; + ExpectedHolder(const T& t) : t(t) {} + ExpectedHolder(T&& t) : t(std::move(t)) {} + using pointer = T*; + using const_pointer = const T*; + T* get() { return &t; } + const T* get() const { return &t; } + T t; + }; + template<class T> + struct ExpectedHolder<T&> + { + ExpectedHolder(T& t) : t(&t) {} + ExpectedHolder() : t(nullptr) {} + using pointer = T*; + using const_pointer = T*; + T* get() { return t; } + T* get() const { return t; } + T* t; + }; + template<class T, class S> class ExpectedT { @@ -87,7 +111,10 @@ namespace vcpkg ExpectedT(S&& s, ExpectedRightTag = {}) : m_s(std::move(s)) {} ExpectedT(const T& t, ExpectedLeftTag = {}) : m_t(t) {} - ExpectedT(T&& t, ExpectedLeftTag = {}) : m_t(std::move(t)) {} + template<class = std::enable_if<!std::is_reference_v<T>>> + ExpectedT(T&& t, ExpectedLeftTag = {}) : m_t(std::move(t)) + { + } ExpectedT(const ExpectedT&) = default; ExpectedT(ExpectedT&&) = default; @@ -100,35 +127,94 @@ namespace vcpkg T&& value_or_exit(const LineInfo& line_info) && { exit_if_error(line_info); - return std::move(this->m_t); + return std::move(*this->m_t.get()); } const T& value_or_exit(const LineInfo& line_info) const& { exit_if_error(line_info); - return this->m_t; + return *this->m_t.get(); } const S& error() const& { return this->m_s.error(); } S&& error() && { return std::move(this->m_s.error()); } - const T* get() const + typename ExpectedHolder<T>::const_pointer get() const { if (!this->has_value()) { return nullptr; } - return &this->m_t; + return this->m_t.get(); } - T* get() + typename ExpectedHolder<T>::pointer get() { if (!this->has_value()) { return nullptr; } - return &this->m_t; + return this->m_t.get(); + } + + template<class F> + using map_t = decltype(std::declval<F&>()(*std::declval<typename ExpectedHolder<T>::const_pointer>())); + + template<class F, class U = map_t<F>> + ExpectedT<U, S> map(F f) const& + { + if (has_value()) + { + return {f(*m_t.get()), expected_left_tag}; + } + else + { + return {error(), expected_right_tag}; + } + } + + template<class F> + using move_map_t = + decltype(std::declval<F&>()(std::move(*std::declval<typename ExpectedHolder<T>::pointer>()))); + + template<class F, class U = move_map_t<F>> + ExpectedT<U, S> map(F f) && + { + if (has_value()) + { + return {f(std::move(*m_t.get())), expected_left_tag}; + } + else + { + return {std::move(error()), expected_right_tag}; + } + } + + template<class F, class U = map_t<F>> + U then(F f) const& + { + if (has_value()) + { + return f(*m_t.get()); + } + else + { + return U{error(), expected_right_tag}; + } + } + + template<class F, class U = move_map_t<F>> + U then(F f) && + { + if (has_value()) + { + return f(std::move(*m_t.get())); + } + else + { + return U{std::move(error()), expected_right_tag}; + } } private: @@ -143,9 +229,12 @@ namespace vcpkg } ErrorHolder<S> m_s; - T m_t; + ExpectedHolder<T> m_t; }; template<class T> using Expected = ExpectedT<T, std::error_code>; + + template<class T> + using ExpectedS = ExpectedT<T, std::string>; } diff --git a/toolsrc/include/vcpkg/base/optional.h b/toolsrc/include/vcpkg/base/optional.h index 2d8c126c6..fc3733ead 100644 --- a/toolsrc/include/vcpkg/base/optional.h +++ b/toolsrc/include/vcpkg/base/optional.h @@ -228,12 +228,21 @@ namespace vcpkg return this->m_base.has_value() ? this->m_base.value() : static_cast<T>(std::forward<U>(default_value)); } + T value_or(T&& default_value) const& + { + return this->m_base.has_value() ? this->m_base.value() : static_cast<T&&>(default_value); + } + template<class U> T value_or(U&& default_value) && { return this->m_base.has_value() ? std::move(this->m_base.value()) : static_cast<T>(std::forward<U>(default_value)); } + T value_or(T&& default_value) && + { + return this->m_base.has_value() ? std::move(this->m_base.value()) : static_cast<T&&>(default_value); + } typename std::add_pointer<const T>::type get() const { @@ -242,6 +251,38 @@ namespace vcpkg typename std::add_pointer<T>::type get() { return this->m_base.has_value() ? &this->m_base.value() : nullptr; } + template<class F> + using map_t = decltype(std::declval<F&>()(std::declval<const T&>())); + + template<class F, class U = map_t<F>> + U then(F f) const& + { + if (has_value()) + { + return f(this->m_base.value()); + } + else + { + return nullopt; + } + } + + template<class F> + using move_map_t = decltype(std::declval<F&>()(std::declval<T&&>())); + + template<class F, class U = move_map_t<F>> + U then(F f) && + { + if (has_value()) + { + return f(std::move(this->m_base.value())); + } + else + { + return nullopt; + } + } + private: details::OptionalStorage<T> m_base; }; diff --git a/toolsrc/include/vcpkg/binaryparagraph.h b/toolsrc/include/vcpkg/binaryparagraph.h index 223a1fb86..05c42dee4 100644 --- a/toolsrc/include/vcpkg/binaryparagraph.h +++ b/toolsrc/include/vcpkg/binaryparagraph.h @@ -1,7 +1,7 @@ #pragma once #include <vcpkg/packagespec.h> -#include <vcpkg/parse.h> +#include <vcpkg/paragraphparser.h> #include <vcpkg/sourceparagraph.h> namespace vcpkg @@ -14,12 +14,12 @@ namespace vcpkg BinaryParagraph(); explicit BinaryParagraph(Parse::RawParagraph fields); BinaryParagraph(const SourceParagraph& spgh, - const Triplet& triplet, + Triplet triplet, const std::string& abi_tag, const std::vector<FeatureSpec>& deps); BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, - const Triplet& triplet, + Triplet triplet, const std::vector<FeatureSpec>& deps); std::string displayname() const; diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index b7b7475ef..9d555ae25 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -26,7 +26,7 @@ namespace vcpkg::Build const ParsedArguments& options, const VcpkgPaths& paths); - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } enum class UseHeadVersion @@ -140,7 +140,7 @@ namespace vcpkg::Build struct PreBuildInfo { PreBuildInfo(const VcpkgPaths& paths, - const Triplet& triplet, + Triplet triplet, const std::unordered_map<std::string, std::string>& cmakevars); std::string triplet_abi_tag; @@ -197,7 +197,7 @@ namespace vcpkg::Build struct BuildPackageConfig { BuildPackageConfig(const SourceControlFileLocation& scfl, - const Triplet& triplet, + Triplet triplet, const BuildPackageOptions& build_package_options, const CMakeVars::CMakeVarProvider& var_provider, const std::unordered_map<std::string, std::vector<FeatureSpec>>& feature_dependencies, @@ -217,7 +217,7 @@ namespace vcpkg::Build const SourceControlFileLocation& scfl; const SourceControlFile& scf; - const Triplet& triplet; + Triplet triplet; const fs::path& port_dir; const BuildPackageOptions& build_package_options; const CMakeVars::CMakeVarProvider& var_provider; diff --git a/toolsrc/include/vcpkg/cmakevars.h b/toolsrc/include/vcpkg/cmakevars.h index c634866d0..8d131d45e 100644 --- a/toolsrc/include/vcpkg/cmakevars.h +++ b/toolsrc/include/vcpkg/cmakevars.h @@ -11,7 +11,7 @@ namespace vcpkg::CMakeVars struct CMakeVarProvider { virtual Optional<const std::unordered_map<std::string, std::string>&> get_generic_triplet_vars( - const Triplet& triplet) const = 0; + Triplet triplet) const = 0; virtual Optional<const std::unordered_map<std::string, std::string>&> get_dep_info_vars( const PackageSpec& spec) const = 0; @@ -19,7 +19,7 @@ namespace vcpkg::CMakeVars virtual Optional<const std::unordered_map<std::string, std::string>&> get_tag_vars( const PackageSpec& spec) const = 0; - virtual void load_generic_triplet_vars(const Triplet& triplet) const = 0; + virtual void load_generic_triplet_vars(Triplet triplet) const = 0; virtual void load_dep_info_vars(Span<const PackageSpec> specs) const = 0; @@ -41,7 +41,7 @@ namespace vcpkg::CMakeVars public: explicit TripletCMakeVarProvider(const vcpkg::VcpkgPaths& paths) : paths(paths) {} - void load_generic_triplet_vars(const Triplet& triplet) const override; + void load_generic_triplet_vars(Triplet triplet) const override; void load_dep_info_vars(Span<const PackageSpec> specs) const override; @@ -49,7 +49,7 @@ namespace vcpkg::CMakeVars const PortFileProvider::PortFileProvider& port_provider) const override; Optional<const std::unordered_map<std::string, std::string>&> get_generic_triplet_vars( - const Triplet& triplet) const override; + Triplet triplet) const override; Optional<const std::unordered_map<std::string, std::string>&> get_dep_info_vars( const PackageSpec& spec) const override; diff --git a/toolsrc/include/vcpkg/commands.h b/toolsrc/include/vcpkg/commands.h index e73077e1d..9d2d0b6c6 100644 --- a/toolsrc/include/vcpkg/commands.h +++ b/toolsrc/include/vcpkg/commands.h @@ -12,27 +12,25 @@ namespace vcpkg::Commands { - using CommandTypeA = void (*)(const VcpkgCmdArguments& args, - const VcpkgPaths& paths, - const Triplet& default_triplet); + using CommandTypeA = void (*)(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); using CommandTypeB = void (*)(const VcpkgCmdArguments& args, const VcpkgPaths& paths); using CommandTypeC = void (*)(const VcpkgCmdArguments& args); namespace BuildExternal { - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace CI { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Env { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Create @@ -44,7 +42,7 @@ namespace vcpkg::Commands namespace Upgrade { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Edit @@ -56,7 +54,7 @@ namespace vcpkg::Commands namespace DependInfo { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Search diff --git a/toolsrc/include/vcpkg/dependencies.h b/toolsrc/include/vcpkg/dependencies.h index eb9d42b6d..1f92ee63c 100644 --- a/toolsrc/include/vcpkg/dependencies.h +++ b/toolsrc/include/vcpkg/dependencies.h @@ -121,7 +121,7 @@ namespace vcpkg::Dependencies RequestType request_type; Optional<const BinaryParagraph&> core_paragraph() const; - std::vector<PackageSpec> dependencies(const Triplet& triplet) const; + std::vector<PackageSpec> dependencies(Triplet triplet) const; private: Optional<InstalledPackageView> m_installed_package; diff --git a/toolsrc/include/vcpkg/export.h b/toolsrc/include/vcpkg/export.h index eb99b4fb1..3605081e3 100644 --- a/toolsrc/include/vcpkg/export.h +++ b/toolsrc/include/vcpkg/export.h @@ -6,7 +6,7 @@ namespace vcpkg::Export { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths); } diff --git a/toolsrc/include/vcpkg/input.h b/toolsrc/include/vcpkg/input.h index ef481bf52..917b5af10 100644 --- a/toolsrc/include/vcpkg/input.h +++ b/toolsrc/include/vcpkg/input.h @@ -5,11 +5,11 @@ namespace vcpkg::Input { PackageSpec check_and_get_package_spec(std::string&& spec_string, - const Triplet& default_triplet, + Triplet default_triplet, CStringView example_text); FullPackageSpec check_and_get_full_package_spec(std::string&& spec_string, - const Triplet& default_triplet, + Triplet default_triplet, CStringView example_text); - void check_triplet(const Triplet& t, const VcpkgPaths& paths); + void check_triplet(Triplet t, const VcpkgPaths& paths); } diff --git a/toolsrc/include/vcpkg/install.h b/toolsrc/include/vcpkg/install.h index e020c8653..1c42cc102 100644 --- a/toolsrc/include/vcpkg/install.h +++ b/toolsrc/include/vcpkg/install.h @@ -83,5 +83,5 @@ namespace vcpkg::Install extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } diff --git a/toolsrc/include/vcpkg/packagespec.h b/toolsrc/include/vcpkg/packagespec.h index 628352cdb..a37dc99b3 100644 --- a/toolsrc/include/vcpkg/packagespec.h +++ b/toolsrc/include/vcpkg/packagespec.h @@ -1,20 +1,16 @@ #pragma once #include <vcpkg/base/expected.h> -#include <vcpkg/packagespecparseresult.h> +#include <vcpkg/base/optional.h> #include <vcpkg/triplet.h> -namespace vcpkg +namespace vcpkg::Parse { - struct ParsedSpecifier - { - std::string name; - std::vector<std::string> features; - std::string triplet; - - static ExpectedT<ParsedSpecifier, PackageSpecParseResult> from_string(const std::string& input); - }; + struct ParserBase; +} +namespace vcpkg +{ /// /// <summary> /// Full specification of a package. Contains all information to reference @@ -26,14 +22,11 @@ namespace vcpkg PackageSpec() noexcept = default; PackageSpec(std::string name, Triplet triplet) : m_name(std::move(name)), m_triplet(triplet) {} - static ExpectedT<PackageSpec, PackageSpecParseResult> from_name_and_triplet(const std::string& name, - const Triplet& triplet); - - static std::vector<PackageSpec> to_package_specs(const std::vector<std::string>& ports, const Triplet& triplet); + static std::vector<PackageSpec> to_package_specs(const std::vector<std::string>& ports, Triplet triplet); const std::string& name() const; - const Triplet& triplet() const; + Triplet triplet() const; std::string dir() const; @@ -64,16 +57,13 @@ namespace vcpkg const std::string& name() const { return m_spec.name(); } const std::string& feature() const { return m_feature; } - const Triplet& triplet() const { return m_spec.triplet(); } + Triplet triplet() const { return m_spec.triplet(); } const PackageSpec& spec() const { return m_spec; } std::string to_string() const; void to_string(std::string& out) const; - static std::vector<FeatureSpec> from_strings_and_triplet(const std::vector<std::string>& depends, - const Triplet& t); - bool operator<(const FeatureSpec& other) const { if (name() < other.name()) return true; @@ -115,8 +105,7 @@ namespace vcpkg std::vector<FeatureSpec> to_feature_specs(const std::vector<std::string>& default_features, const std::vector<std::string>& all_features) const; - static ExpectedT<FullPackageSpec, PackageSpecParseResult> from_string(const std::string& spec_as_string, - const Triplet& default_triplet); + static ExpectedS<FullPackageSpec> from_string(const std::string& spec_as_string, Triplet default_triplet); }; /// @@ -129,9 +118,30 @@ namespace vcpkg std::string name; std::vector<std::string> features; - static ExpectedT<Features, PackageSpecParseResult> from_string(const std::string& input); + static ExpectedS<Features> from_string(const std::string& input); + }; + + struct Dependency + { + Features depend; + std::string qualifier; + + static ExpectedS<Dependency> from_string(const std::string& input); }; + struct ParsedQualifiedSpecifier + { + std::string name; + Optional<std::vector<std::string>> features; + Optional<std::string> triplet; + Optional<std::string> qualifier; + }; + + Optional<std::string> parse_feature_name(Parse::ParserBase& parser); + Optional<std::string> parse_package_name(Parse::ParserBase& parser); + ExpectedS<ParsedQualifiedSpecifier> parse_qualified_specifier(CStringView input); + Optional<ParsedQualifiedSpecifier> parse_qualified_specifier(Parse::ParserBase& parser); + bool operator==(const PackageSpec& left, const PackageSpec& right); bool operator!=(const PackageSpec& left, const PackageSpec& right); } diff --git a/toolsrc/include/vcpkg/packagespecparseresult.h b/toolsrc/include/vcpkg/packagespecparseresult.h deleted file mode 100644 index 4c99c84c7..000000000 --- a/toolsrc/include/vcpkg/packagespecparseresult.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <vcpkg/base/cstringview.h> -#include <vcpkg/base/expected.h> - -namespace vcpkg -{ - enum class PackageSpecParseResult - { - SUCCESS = 0, - TOO_MANY_COLONS, - INVALID_CHARACTERS - }; - - void to_string(std::string& out, ::vcpkg::PackageSpecParseResult p); - - CStringView to_string(PackageSpecParseResult ev) noexcept; - - template<> - struct ErrorHolder<PackageSpecParseResult> - { - ErrorHolder() noexcept : m_err(PackageSpecParseResult::SUCCESS) {} - ErrorHolder(PackageSpecParseResult err) : m_err(err) {} - - bool has_error() const { return m_err != PackageSpecParseResult::SUCCESS; } - - const PackageSpecParseResult& error() const { return m_err; } - PackageSpecParseResult& error() { return m_err; } - - CStringView to_string() const { return vcpkg::to_string(m_err); } - - private: - PackageSpecParseResult m_err; - }; -} diff --git a/toolsrc/include/vcpkg/paragraphparser.h b/toolsrc/include/vcpkg/paragraphparser.h new file mode 100644 index 000000000..86c3d0228 --- /dev/null +++ b/toolsrc/include/vcpkg/paragraphparser.h @@ -0,0 +1,45 @@ +#pragma once + +#include <vcpkg/base/expected.h> +#include <vcpkg/packagespec.h> + +#include <memory> +#include <string> +#include <unordered_map> +#include <vector> + +namespace vcpkg::Parse +{ + struct ParseControlErrorInfo + { + std::string name; + std::vector<std::string> missing_fields; + std::vector<std::string> extra_fields; + std::string error; + }; + + template<class P> + using ParseExpected = vcpkg::ExpectedT<std::unique_ptr<P>, std::unique_ptr<ParseControlErrorInfo>>; + + using RawParagraph = std::unordered_map<std::string, std::string>; + + struct ParagraphParser + { + ParagraphParser(RawParagraph&& fields) : fields(std::move(fields)) {} + + void required_field(const std::string& fieldname, std::string& out); + std::string optional_field(const std::string& fieldname) const; + std::unique_ptr<ParseControlErrorInfo> error_info(const std::string& name) const; + + private: + RawParagraph&& fields; + std::vector<std::string> missing_fields; + }; + + ExpectedS<std::vector<std::string>> parse_default_features_list(const std::string& str, + CStringView origin = "<unknown>"); + ExpectedS<std::vector<ParsedQualifiedSpecifier>> parse_qualified_specifier_list(const std::string& str, + CStringView origin = "<unknown>"); + ExpectedS<std::vector<Dependency>> parse_dependencies_list(const std::string& str, + CStringView origin = "<unknown>"); +} diff --git a/toolsrc/include/vcpkg/paragraphs.h b/toolsrc/include/vcpkg/paragraphs.h index 7e2410aef..cffe85af7 100644 --- a/toolsrc/include/vcpkg/paragraphs.h +++ b/toolsrc/include/vcpkg/paragraphs.h @@ -1,7 +1,7 @@ #pragma once #include <vcpkg/binaryparagraph.h> -#include <vcpkg/parse.h> +#include <vcpkg/paragraphparser.h> #include <vcpkg/vcpkgpaths.h> #include <vcpkg/base/expected.h> @@ -10,13 +10,13 @@ namespace vcpkg::Paragraphs { using RawParagraph = Parse::RawParagraph; - Expected<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path); - Expected<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path); - Expected<std::vector<RawParagraph>> parse_paragraphs(const std::string& str); + ExpectedS<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path); + ExpectedS<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path); + ExpectedS<std::vector<RawParagraph>> parse_paragraphs(const std::string& str, const std::string& origin); Parse::ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& control_path); - Expected<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); + ExpectedS<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); struct LoadResults { diff --git a/toolsrc/include/vcpkg/parse.h b/toolsrc/include/vcpkg/parse.h index 4b33e302e..3214305bf 100644 --- a/toolsrc/include/vcpkg/parse.h +++ b/toolsrc/include/vcpkg/parse.h @@ -1,38 +1,147 @@ #pragma once -#include <vcpkg/base/expected.h> +#include <vcpkg/base/cstringview.h> #include <vcpkg/base/optional.h> +#include <vcpkg/base/stringview.h> +#include <vcpkg/textrowcol.h> #include <memory> -#include <unordered_map> +#include <string> namespace vcpkg::Parse { - struct ParseControlErrorInfo + struct IParseError { - std::string name; - std::vector<std::string> missing_fields; - std::vector<std::string> extra_fields; - std::error_code error; + virtual ~IParseError() = default; + virtual std::string format() const = 0; }; - template<class P> - using ParseExpected = ExpectedT<std::unique_ptr<P>, std::unique_ptr<ParseControlErrorInfo>>; + struct ParseError : IParseError + { + ParseError(std::string origin, int row, int column, std::string line, std::string message) + : origin(std::move(origin)), row(row), column(column), line(std::move(line)), message(std::move(message)) + { + } + + const std::string origin; + const int row; + const int column; + const std::string line; + const std::string message; - using RawParagraph = std::unordered_map<std::string, std::string>; + virtual std::string format() const override; + }; - struct ParagraphParser + struct ParserBase { - ParagraphParser(RawParagraph&& fields) : fields(std::move(fields)) {} + struct SourceLoc + { + const char* it; + int row; + int column; + }; + + void init(CStringView text, CStringView origin, TextRowCol init_rowcol = {}) + { + m_text = text; + m_origin = origin; + m_it = text.c_str(); + row = init_rowcol.row ? init_rowcol.row : 1; + column = init_rowcol.column ? init_rowcol.column : 1; + } + + static constexpr bool is_whitespace(char ch) { return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; } + static constexpr bool is_lower_alpha(char ch) { return ch >= 'a' && ch <= 'z'; } + static constexpr bool is_upper_alpha(char ch) { return ch >= 'A' && ch <= 'Z'; } + static constexpr bool is_ascii_digit(char ch) { return ch >= '0' && ch <= '9'; } + static constexpr bool is_lineend(char ch) { return ch == '\r' || ch == '\n' || ch == '\0'; } + static constexpr bool is_alphanum(char ch) + { + return is_upper_alpha(ch) || is_lower_alpha(ch) || is_ascii_digit(ch); + } + static constexpr bool is_alphanumdash(char ch) { return is_alphanum(ch) || ch == '-'; } + + StringView skip_whitespace() { return match_zero_or_more(is_whitespace); } + StringView skip_tabs_spaces() + { + return match_zero_or_more([](char ch) { return ch == ' ' || ch == '\t'; }); + } + void skip_to_eof() + { + while (cur()) + ++m_it; + } + void skip_newline() + { + if (cur() == '\r') next(); + if (cur() == '\n') next(); + } + void skip_line() + { + match_until(is_lineend); + skip_newline(); + } - void required_field(const std::string& fieldname, std::string& out); - std::string optional_field(const std::string& fieldname) const; - std::unique_ptr<ParseControlErrorInfo> error_info(const std::string& name) const; + template<class Pred> + StringView match_zero_or_more(Pred p) + { + const char* start = m_it; + auto ch = cur(); + while (ch != '\0' && p(ch)) + ch = next(); + return {start, m_it}; + } + template<class Pred> + StringView match_until(Pred p) + { + const char* start = m_it; + auto ch = cur(); + while (ch != '\0' && !p(ch)) + ch = next(); + return {start, m_it}; + } + + CStringView text() const { return m_text; } + const char* it() const { return m_it; } + char cur() const { return *m_it; } + SourceLoc cur_loc() const { return {m_it, row, column}; } + char next() + { + char ch = *m_it; + // See https://www.gnu.org/prep/standards/standards.html#Errors + if (ch == '\t') + column = (column + 7) / 8 * 8 + 1; // round to next 8-width tab stop + else if (ch == '\n') + { + row++; + column = 1; + } + else if (ch == '\0') + { + return '\0'; + } + else + { + ++column; + } + return *++m_it; + } + bool at_eof() const { return *m_it == 0; } + + void add_error(std::string message) { add_error(std::move(message), cur_loc()); } + void add_error(std::string message, const SourceLoc& loc); + + const Parse::IParseError* get_error() const { return m_err.get(); } + std::unique_ptr<Parse::IParseError> extract_error() { return std::move(m_err); } private: - RawParagraph&& fields; - std::vector<std::string> missing_fields; - }; + const char* m_it; + int row; + int column; + + CStringView m_text; + CStringView m_origin; - std::vector<std::string> parse_comma_list(const std::string& str); + std::unique_ptr<IParseError> m_err; + }; } diff --git a/toolsrc/include/vcpkg/portfileprovider.h b/toolsrc/include/vcpkg/portfileprovider.h index 79f69d9ae..36cdba589 100644 --- a/toolsrc/include/vcpkg/portfileprovider.h +++ b/toolsrc/include/vcpkg/portfileprovider.h @@ -1,6 +1,6 @@ #pragma once -#include <vcpkg/base/optional.h> +#include <vcpkg/base/expected.h> #include <vcpkg/base/util.h> #include <vcpkg/sourceparagraph.h> #include <vcpkg/vcpkgpaths.h> @@ -9,14 +9,14 @@ namespace vcpkg::PortFileProvider { struct PortFileProvider { - virtual Optional<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const = 0; + virtual ExpectedS<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const = 0; virtual std::vector<const SourceControlFileLocation*> load_all_control_files() const = 0; }; struct MapPortFileProvider : Util::ResourceBase, PortFileProvider { explicit MapPortFileProvider(const std::unordered_map<std::string, SourceControlFileLocation>& map); - Optional<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override; + ExpectedS<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override; std::vector<const SourceControlFileLocation*> load_all_control_files() const override; private: @@ -27,7 +27,7 @@ namespace vcpkg::PortFileProvider { explicit PathsPortFileProvider(const vcpkg::VcpkgPaths& paths, const std::vector<std::string>* ports_dirs_paths); - Optional<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override; + ExpectedS<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override; std::vector<const SourceControlFileLocation*> load_all_control_files() const override; private: diff --git a/toolsrc/include/vcpkg/remove.h b/toolsrc/include/vcpkg/remove.h index 36aeda2ad..c43bc73c2 100644 --- a/toolsrc/include/vcpkg/remove.h +++ b/toolsrc/include/vcpkg/remove.h @@ -21,6 +21,6 @@ namespace vcpkg::Remove extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db); } diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h index 0574afe74..bdb75fc58 100644 --- a/toolsrc/include/vcpkg/sourceparagraph.h +++ b/toolsrc/include/vcpkg/sourceparagraph.h @@ -1,37 +1,20 @@ #pragma once -#include <vcpkg/packagespec.h> -#include <vcpkg/parse.h> - +#include <string> #include <vcpkg/base/expected.h> #include <vcpkg/base/span.h> #include <vcpkg/base/system.h> - #include <vcpkg/base/system.print.h> - -#include <string> +#include <vcpkg/packagespec.h> +#include <vcpkg/paragraphparser.h> #include <vector> namespace vcpkg { - struct Dependency - { - Features depend; - std::string qualifier; - - std::string name() const; - static Dependency parse_dependency(std::string name, std::string qualifier); - }; - std::vector<FullPackageSpec> filter_dependencies(const std::vector<Dependency>& deps, - const Triplet& t, + Triplet t, const std::unordered_map<std::string, std::string>& cmake_vars); - // zlib[uwp] becomes Dependency{"zlib", "uwp"} - std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends); - - std::string to_string(const Dependency& dep); - struct Type { enum diff --git a/toolsrc/include/vcpkg/statusparagraphs.h b/toolsrc/include/vcpkg/statusparagraphs.h index fa064de7e..7fcf0e916 100644 --- a/toolsrc/include/vcpkg/statusparagraphs.h +++ b/toolsrc/include/vcpkg/statusparagraphs.h @@ -35,10 +35,10 @@ namespace vcpkg /// <param name="triplet">Triplet</param> /// <param name="feature">Feature name</param> /// <returns>Iterator for found spec</returns> - iterator find(const std::string& name, const Triplet& triplet, const std::string& feature = ""); - const_iterator find(const std::string& name, const Triplet& triplet, const std::string& feature = "") const; + iterator find(const std::string& name, Triplet triplet, const std::string& feature = ""); + const_iterator find(const std::string& name, Triplet triplet, const std::string& feature = "") const; - std::vector<std::unique_ptr<StatusParagraph>*> find_all(const std::string& name, const Triplet& triplet); + std::vector<std::unique_ptr<StatusParagraph>*> find_all(const std::string& name, Triplet triplet); Optional<InstalledPackageView> find_all_installed(const PackageSpec& spec) const; diff --git a/toolsrc/include/vcpkg/textrowcol.h b/toolsrc/include/vcpkg/textrowcol.h new file mode 100644 index 000000000..5bbf6a899 --- /dev/null +++ b/toolsrc/include/vcpkg/textrowcol.h @@ -0,0 +1,12 @@ +#pragma once
+
+namespace vcpkg::Parse
+{
+ struct TextRowCol
+ {
+ /// '0' indicates uninitialized; '1' is the first row.
+ int row = 0;
+ /// '0' indicates uninitialized; '1' is the first column.
+ int column = 0;
+ };
+}
diff --git a/toolsrc/include/vcpkg/triplet.h b/toolsrc/include/vcpkg/triplet.h index f33f40fd5..8d8c3e879 100644 --- a/toolsrc/include/vcpkg/triplet.h +++ b/toolsrc/include/vcpkg/triplet.h @@ -27,8 +27,8 @@ namespace vcpkg void to_string(std::string& out) const; size_t hash_code() const; - bool operator==(const Triplet& other) const; - bool operator<(const Triplet& other) const { return canonical_name() < other.canonical_name(); } + bool operator==(Triplet other) const { return this->m_instance == other.m_instance; } + bool operator<(Triplet other) const { return canonical_name() < other.canonical_name(); } private: static const TripletInstance DEFAULT_INSTANCE; @@ -38,7 +38,7 @@ namespace vcpkg const TripletInstance* m_instance; }; - bool operator!=(const Triplet& left, const Triplet& right); + inline bool operator!=(Triplet left, Triplet right) { return !(left == right); } } namespace std @@ -46,6 +46,6 @@ namespace std template<> struct hash<vcpkg::Triplet> { - size_t operator()(const vcpkg::Triplet& t) const { return t.hash_code(); } + size_t operator()(vcpkg::Triplet t) const { return t.hash_code(); } }; } diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h index 52d77d283..63d19af2c 100644 --- a/toolsrc/include/vcpkg/vcpkgpaths.h +++ b/toolsrc/include/vcpkg/vcpkgpaths.h @@ -52,7 +52,7 @@ namespace vcpkg std::string name; fs::path location; - TripletFile(const std::string& name, const fs::path& location) : name(name), location(location){} + TripletFile(const std::string& name, const fs::path& location) : name(name), location(location) {} }; static Expected<VcpkgPaths> create(const fs::path& vcpkg_root_dir, @@ -64,10 +64,10 @@ namespace vcpkg fs::path build_info_file_path(const PackageSpec& spec) const; fs::path listfile_path(const BinaryParagraph& pgh) const; - bool is_valid_triplet(const Triplet& t) const; + bool is_valid_triplet(Triplet t) const; const std::vector<std::string> get_available_triplets_names() const; const std::vector<TripletFile>& get_available_triplets() const; - const fs::path get_triplet_file_path(const Triplet& triplet) const; + const fs::path get_triplet_file_path(Triplet triplet) const; fs::path root; fs::path packages; diff --git a/toolsrc/src/vcpkg-test/dependencies.cpp b/toolsrc/src/vcpkg-test/dependencies.cpp index 63e7cfee7..c9eb0df35 100644 --- a/toolsrc/src/vcpkg-test/dependencies.cpp +++ b/toolsrc/src/vcpkg-test/dependencies.cpp @@ -2,14 +2,17 @@ #include <vcpkg-test/mockcmakevarprovider.h> #include <vcpkg-test/util.h> #include <vcpkg/dependencies.h> +#include <vcpkg/paragraphparser.h> #include <vcpkg/sourceparagraph.h> using namespace vcpkg; -using Parse::parse_comma_list; +using namespace vcpkg::Parse; TEST_CASE ("parse depends", "[dependencies]") { - auto v = expand_qualified_dependencies(parse_comma_list("liba (windows)")); + auto w = parse_dependencies_list("liba (windows)"); + REQUIRE(w); + auto& v = *w.get(); REQUIRE(v.size() == 1); REQUIRE(v.at(0).depend.name == "liba"); REQUIRE(v.at(0).qualifier == "windows"); @@ -23,7 +26,9 @@ TEST_CASE ("filter depends", "[dependencies]") const std::unordered_map<std::string, std::string> arm_uwp_cmake_vars{{"VCPKG_TARGET_ARCHITECTURE", "arm"}, {"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}; - auto deps = expand_qualified_dependencies(parse_comma_list("liba (windows), libb, libc (uwp)")); + auto deps_ = parse_dependencies_list("liba (!uwp), libb, libc (uwp)"); + REQUIRE(deps_); + auto& deps = *deps_.get(); auto v = filter_dependencies(deps, Triplet::X64_WINDOWS, x64_win_cmake_vars); REQUIRE(v.size() == 2); REQUIRE(v.at(0).package_spec.name() == "liba"); @@ -37,10 +42,10 @@ TEST_CASE ("filter depends", "[dependencies]") TEST_CASE ("parse feature depends", "[dependencies]") { - auto u = parse_comma_list("libwebp[anim, gif2webp, img2webp, info, mux, nearlossless, " - "simd, cwebp, dwebp], libwebp[vwebp_sdl, extras] (!osx)"); - REQUIRE(u.at(1) == "libwebp[vwebp_sdl, extras] (!osx)"); - auto v = expand_qualified_dependencies(u); + auto u_ = parse_dependencies_list("libwebp[anim, gif2webp, img2webp, info, mux, nearlossless, " + "simd, cwebp, dwebp], libwebp[vwebp-sdl, extras] (!osx)"); + REQUIRE(u_); + auto& v = *u_.get(); REQUIRE(v.size() == 2); auto&& a0 = v.at(0); REQUIRE(a0.depend.name == "libwebp"); @@ -67,9 +72,7 @@ TEST_CASE ("qualified dependency", "[dependencies]") REQUIRE(plan.install_actions.size() == 2); REQUIRE(plan.install_actions.at(0).feature_list == std::vector<std::string>{"core"}); - FullPackageSpec linspec_a{PackageSpec::from_name_and_triplet("a", Triplet::from_canonical_name("x64-linux")) - .value_or_exit(VCPKG_LINE_INFO), - {}}; + FullPackageSpec linspec_a{{"a", Triplet::from_canonical_name("x64-linux")}, {}}; var_provider.dep_info_vars[linspec_a.package_spec].emplace("VCPKG_CMAKE_SYSTEM_NAME", "Linux"); auto plan2 = vcpkg::Dependencies::create_feature_install_plan(map_port, var_provider, {linspec_a}, {}); REQUIRE(plan2.install_actions.size() == 2); diff --git a/toolsrc/src/vcpkg-test/mockcmakevarsprovider.cpp b/toolsrc/src/vcpkg-test/mockcmakevarsprovider.cpp index eda1a7a64..655bc33b4 100644 --- a/toolsrc/src/vcpkg-test/mockcmakevarsprovider.cpp +++ b/toolsrc/src/vcpkg-test/mockcmakevarsprovider.cpp @@ -3,7 +3,7 @@ namespace vcpkg::Test
{
Optional<const std::unordered_map<std::string, std::string>&> MockCMakeVarProvider::get_generic_triplet_vars(
- const Triplet& triplet) const
+ Triplet triplet) const
{
auto it = generic_triplet_vars.find(triplet);
if (it == generic_triplet_vars.end()) return nullopt;
diff --git a/toolsrc/src/vcpkg-test/paragraph.cpp b/toolsrc/src/vcpkg-test/paragraph.cpp index 2ee4efe2f..21da80c5b 100644 --- a/toolsrc/src/vcpkg-test/paragraph.cpp +++ b/toolsrc/src/vcpkg-test/paragraph.cpp @@ -46,7 +46,7 @@ TEST_CASE ("SourceParagraph construct maximum", "[paragraph]") REQUIRE(pgh.core_paragraph->maintainer == "m"); REQUIRE(pgh.core_paragraph->description == "d"); REQUIRE(pgh.core_paragraph->depends.size() == 1); - REQUIRE(pgh.core_paragraph->depends[0].name() == "bd"); + REQUIRE(pgh.core_paragraph->depends[0].depend.name == "bd"); REQUIRE(pgh.core_paragraph->default_features.size() == 1); REQUIRE(pgh.core_paragraph->default_features[0] == "df"); } @@ -64,8 +64,8 @@ TEST_CASE ("SourceParagraph two depends", "[paragraph]") auto& pgh = **m_pgh.get(); REQUIRE(pgh.core_paragraph->depends.size() == 2); - REQUIRE(pgh.core_paragraph->depends[0].name() == "z"); - REQUIRE(pgh.core_paragraph->depends[1].name() == "openssl"); + REQUIRE(pgh.core_paragraph->depends[0].depend.name == "z"); + REQUIRE(pgh.core_paragraph->depends[1].depend.name == "openssl"); } TEST_CASE ("SourceParagraph three depends", "[paragraph]") @@ -81,9 +81,9 @@ TEST_CASE ("SourceParagraph three depends", "[paragraph]") auto& pgh = **m_pgh.get(); REQUIRE(pgh.core_paragraph->depends.size() == 3); - REQUIRE(pgh.core_paragraph->depends[0].name() == "z"); - REQUIRE(pgh.core_paragraph->depends[1].name() == "openssl"); - REQUIRE(pgh.core_paragraph->depends[2].name() == "xyz"); + REQUIRE(pgh.core_paragraph->depends[0].depend.name == "z"); + REQUIRE(pgh.core_paragraph->depends[1].depend.name == "openssl"); + REQUIRE(pgh.core_paragraph->depends[2].depend.name == "xyz"); } TEST_CASE ("SourceParagraph construct qualified depends", "[paragraph]") @@ -93,7 +93,7 @@ TEST_CASE ("SourceParagraph construct qualified depends", "[paragraph]") std::vector<std::unordered_map<std::string, std::string>>{{ {"Source", "zlib"}, {"Version", "1.2.8"}, - {"Build-Depends", "libA (windows), libB (uwp)"}, + {"Build-Depends", "liba (windows), libb (uwp)"}, }}); REQUIRE(m_pgh.has_value()); auto& pgh = **m_pgh.get(); @@ -103,9 +103,9 @@ TEST_CASE ("SourceParagraph construct qualified depends", "[paragraph]") REQUIRE(pgh.core_paragraph->maintainer == ""); REQUIRE(pgh.core_paragraph->description == ""); REQUIRE(pgh.core_paragraph->depends.size() == 2); - REQUIRE(pgh.core_paragraph->depends[0].name() == "libA"); + REQUIRE(pgh.core_paragraph->depends[0].depend.name == "liba"); REQUIRE(pgh.core_paragraph->depends[0].qualifier == "windows"); - REQUIRE(pgh.core_paragraph->depends[1].name() == "libB"); + REQUIRE(pgh.core_paragraph->depends[1].depend.name == "libb"); REQUIRE(pgh.core_paragraph->depends[1].qualifier == "uwp"); } @@ -210,14 +210,14 @@ TEST_CASE ("BinaryParagraph default features", "[paragraph]") TEST_CASE ("parse paragraphs empty", "[paragraph]") { const char* str = ""; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.empty()); } TEST_CASE ("parse paragraphs one field", "[paragraph]") { const char* str = "f1: v1"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0].size() == 1); REQUIRE(pghs[0]["f1"] == "v1"); @@ -227,7 +227,7 @@ TEST_CASE ("parse paragraphs one pgh", "[paragraph]") { const char* str = "f1: v1\n" "f2: v2"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0].size() == 2); REQUIRE(pghs[0]["f1"] == "v1"); @@ -241,7 +241,7 @@ TEST_CASE ("parse paragraphs two pgh", "[paragraph]") "\n" "f3: v3\n" "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 2); REQUIRE(pghs[0].size() == 2); @@ -259,7 +259,7 @@ TEST_CASE ("parse paragraphs field names", "[paragraph]") "F:\n" "0:\n" "F-2:\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0].size() == 5); @@ -273,7 +273,7 @@ TEST_CASE ("parse paragraphs multiple blank lines", "[paragraph]") "\n" "f3: v3\n" "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 2); } @@ -282,7 +282,7 @@ TEST_CASE ("parse paragraphs empty fields", "[paragraph]") { const char* str = "f1:\n" "f2: "; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0].size() == 2); @@ -298,7 +298,7 @@ TEST_CASE ("parse paragraphs multiline fields", "[paragraph]") "f2:\r\n" " f2\r\n" " continue\r\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0]["f1"] == "simple\n f1"); @@ -312,7 +312,7 @@ TEST_CASE ("parse paragraphs crlfs", "[paragraph]") "\r\n" "f3: v3\r\n" "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 2); REQUIRE(pghs[0].size() == 2); @@ -334,7 +334,7 @@ TEST_CASE ("parse paragraphs comment", "[paragraph]") "f3: v3\r\n" "#comment\r\n" "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 2); REQUIRE(pghs[0].size() == 2); @@ -349,7 +349,7 @@ TEST_CASE ("parse comment before single line feed", "[paragraph]") { const char* str = "f1: v1\r\n" "#comment\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs[0].size() == 1); REQUIRE(pghs[0]["f1"] == "v1"); } @@ -363,7 +363,7 @@ TEST_CASE ("BinaryParagraph serialize min", "[paragraph]") {"Multi-Arch", "same"}, }); std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0].size() == 5); @@ -386,7 +386,7 @@ TEST_CASE ("BinaryParagraph serialize max", "[paragraph]") {"Multi-Arch", "same"}, }); std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0].size() == 8); @@ -409,7 +409,7 @@ TEST_CASE ("BinaryParagraph serialize multiple deps", "[paragraph]") {"Depends", "a, b, c"}, }); std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0]["Depends"] == "a, b, c"); @@ -426,7 +426,7 @@ TEST_CASE ("BinaryParagraph serialize abi", "[paragraph]") {"Abi", "123abc"}, }); std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO); REQUIRE(pghs.size() == 1); REQUIRE(pghs[0]["Abi"] == "123abc"); diff --git a/toolsrc/src/vcpkg-test/plan.cpp b/toolsrc/src/vcpkg-test/plan.cpp index 594c9783b..d3d4310e9 100644 --- a/toolsrc/src/vcpkg-test/plan.cpp +++ b/toolsrc/src/vcpkg-test/plan.cpp @@ -19,7 +19,6 @@ using Test::make_status_feature_pgh; using Test::make_status_pgh; using Test::MockCMakeVarProvider; using Test::PackageSpecMap; -using Test::unsafe_pspec; /// <summary> /// Assert that the given action an install of given features from given package. @@ -27,7 +26,7 @@ using Test::unsafe_pspec; static void features_check(Dependencies::InstallPlanAction& plan, std::string pkg_name, std::vector<std::string> expected_features, - const Triplet& triplet = Triplet::X86_WINDOWS) + Triplet triplet = Triplet::X86_WINDOWS) { const auto& feature_list = plan.feature_list; @@ -53,7 +52,7 @@ static void features_check(Dependencies::InstallPlanAction& plan, /// </summary> static void remove_plan_check(Dependencies::RemovePlanAction& plan, std::string pkg_name, - const Triplet& triplet = Triplet::X86_WINDOWS) + Triplet triplet = Triplet::X86_WINDOWS) { REQUIRE(plan.spec.triplet().to_string() == triplet.to_string()); REQUIRE(pkg_name == plan.spec.name()); @@ -381,8 +380,7 @@ TEST_CASE ("basic feature test 8", "[plan]") std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; status_paragraphs.push_back(make_status_pgh("a")); status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + status_paragraphs.back()->package.spec = PackageSpec("a", Triplet::X64_WINDOWS); PackageSpecMap spec_map(Triplet::X64_WINDOWS); auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; @@ -464,8 +462,7 @@ TEST_CASE ("install default features test 2", "[plan]") { std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + status_paragraphs.back()->package.spec = PackageSpec("a", Triplet::X64_WINDOWS); // Add a port "a" of which "core" is already installed, but we will // install the default features "explicitly" @@ -610,8 +607,7 @@ TEST_CASE ("do not install default features of existing dependency", "[plan]") std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; // "b[core]" is already installed status_paragraphs.push_back(make_status_pgh("b")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + status_paragraphs.back()->package.spec = PackageSpec("b", Triplet::X64_WINDOWS); // Install "a" (without explicit feature specification) auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); @@ -632,8 +628,7 @@ TEST_CASE ("install default features of dependency test 3", "[plan]") { std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; status_paragraphs.push_back(make_status_pgh("b")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + status_paragraphs.back()->package.spec = PackageSpec("b", Triplet::X64_WINDOWS); // Add a port "a" which depends on the core of "b", which was already // installed explicitly @@ -945,7 +940,7 @@ TEST_CASE ("basic remove scheme", "[plan]") pghs.push_back(make_status_pgh("a")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); + auto remove_plan = Dependencies::create_remove_plan({{"a", Triplet::X86_WINDOWS}}, status_db); REQUIRE(remove_plan.size() == 1); REQUIRE(remove_plan.at(0).spec.name() == "a"); @@ -958,7 +953,7 @@ TEST_CASE ("recurse remove scheme", "[plan]") pghs.push_back(make_status_pgh("b", "a")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); + auto remove_plan = Dependencies::create_remove_plan({{"a", Triplet::X86_WINDOWS}}, status_db); REQUIRE(remove_plan.size() == 2); REQUIRE(remove_plan.at(0).spec.name() == "b"); @@ -973,7 +968,7 @@ TEST_CASE ("features depend remove scheme", "[plan]") pghs.push_back(make_status_feature_pgh("b", "0", "a")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); + auto remove_plan = Dependencies::create_remove_plan({{"a", Triplet::X86_WINDOWS}}, status_db); REQUIRE(remove_plan.size() == 2); REQUIRE(remove_plan.at(0).spec.name() == "b"); @@ -989,7 +984,7 @@ TEST_CASE ("features depend remove scheme once removed", "[plan]") pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("expat")}, status_db); + auto remove_plan = Dependencies::create_remove_plan({{"expat", Triplet::X86_WINDOWS}}, status_db); REQUIRE(remove_plan.size() == 3); REQUIRE(remove_plan.at(0).spec.name() == "opencv"); @@ -1006,8 +1001,7 @@ TEST_CASE ("features depend remove scheme once removed x64", "[plan]") pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk", "x64")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = - Dependencies::create_remove_plan({unsafe_pspec("expat", Triplet::from_canonical_name("x64"))}, status_db); + auto remove_plan = Dependencies::create_remove_plan({{"expat", Triplet::from_canonical_name("x64")}}, status_db); REQUIRE(remove_plan.size() == 3); REQUIRE(remove_plan.at(0).spec.name() == "opencv"); @@ -1022,8 +1016,7 @@ TEST_CASE ("features depend core remove scheme", "[plan]") pghs.push_back(make_status_pgh("cpr", "curl[core]", "", "x64")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = - Dependencies::create_remove_plan({unsafe_pspec("curl", Triplet::from_canonical_name("x64"))}, status_db); + auto remove_plan = Dependencies::create_remove_plan({{"curl", Triplet::from_canonical_name("x64")}}, status_db); REQUIRE(remove_plan.size() == 2); REQUIRE(remove_plan.at(0).spec.name() == "cpr"); @@ -1038,8 +1031,7 @@ TEST_CASE ("features depend core remove scheme 2", "[plan]") pghs.push_back(make_status_feature_pgh("curl", "b", "curl[a]", "x64")); StatusParagraphs status_db(std::move(pghs)); - auto remove_plan = - Dependencies::create_remove_plan({unsafe_pspec("curl", Triplet::from_canonical_name("x64"))}, status_db); + auto remove_plan = Dependencies::create_remove_plan({{"curl", Triplet::from_canonical_name("x64")}}, status_db); REQUIRE(remove_plan.size() == 1); REQUIRE(remove_plan.at(0).spec.name() == "curl"); diff --git a/toolsrc/src/vcpkg-test/specifier.cpp b/toolsrc/src/vcpkg-test/specifier.cpp index a0a3725e8..2a1398416 100644 --- a/toolsrc/src/vcpkg-test/specifier.cpp +++ b/toolsrc/src/vcpkg-test/specifier.cpp @@ -12,8 +12,8 @@ TEST_CASE ("specifier conversion", "[specifier]") { constexpr std::size_t SPEC_SIZE = 6; - auto a_spec = PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - auto b_spec = PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + PackageSpec a_spec("a", Triplet::X64_WINDOWS); + PackageSpec b_spec("b", Triplet::X64_WINDOWS); auto fspecs = FullPackageSpec{a_spec, {"0", "1"}}.to_feature_specs({}, {}); auto fspecs2 = FullPackageSpec{b_spec, {"2", "3"}}.to_feature_specs({}, {}); @@ -36,67 +36,59 @@ TEST_CASE ("specifier parsing", "[specifier]") { SECTION ("parsed specifier from string") { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); - REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + auto maybe_spec = vcpkg::parse_qualified_specifier("zlib"); + REQUIRE(maybe_spec.has_value()); auto& spec = *maybe_spec.get(); REQUIRE(spec.name == "zlib"); - REQUIRE(spec.features.size() == 0); - REQUIRE(spec.triplet == ""); + REQUIRE(!spec.features); + REQUIRE(!spec.triplet); } SECTION ("parsed specifier from string with triplet") { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); - REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + auto maybe_spec = vcpkg::parse_qualified_specifier("zlib:x64-uwp"); + REQUIRE(maybe_spec); auto& spec = *maybe_spec.get(); REQUIRE(spec.name == "zlib"); - REQUIRE(spec.triplet == "x64-uwp"); + REQUIRE(spec.triplet.value_or("") == "x64-uwp"); } SECTION ("parsed specifier from string with colons") { - auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); - REQUIRE(ec == vcpkg::PackageSpecParseResult::TOO_MANY_COLONS); + auto s = vcpkg::parse_qualified_specifier("zlib:x86-uwp:"); + REQUIRE(!s); } SECTION ("parsed specifier from string with feature") { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); - REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[feature]:x64-uwp"); + REQUIRE(maybe_spec); auto& spec = *maybe_spec.get(); REQUIRE(spec.name == "zlib"); - REQUIRE(spec.features.size() == 1); - REQUIRE(spec.features.at(0) == "feature"); - REQUIRE(spec.triplet == "x64-uwp"); + REQUIRE(spec.features.value_or(std::vector<std::string>{}) == std::vector<std::string>{"feature"}); + REQUIRE(spec.triplet.value_or("") == "x64-uwp"); } SECTION ("parsed specifier from string with many features") { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); - REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[0, 1,2]"); + REQUIRE(maybe_spec); auto& spec = *maybe_spec.get(); - REQUIRE(spec.name == "zlib"); - REQUIRE(spec.features.size() == 3); - REQUIRE(spec.features.at(0) == "0"); - REQUIRE(spec.features.at(1) == "1"); - REQUIRE(spec.features.at(2) == "2"); - REQUIRE(spec.triplet == ""); + REQUIRE(spec.features.value_or(std::vector<std::string>{}) == std::vector<std::string>{"0", "1", "2"}); } SECTION ("parsed specifier wildcard feature") { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[*]"); - REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[*]"); + System::print2(maybe_spec.error()); + REQUIRE(maybe_spec); auto& spec = *maybe_spec.get(); - REQUIRE(spec.name == "zlib"); - REQUIRE(spec.features.size() == 1); - REQUIRE(spec.features.at(0) == "*"); - REQUIRE(spec.triplet == ""); + REQUIRE(spec.features.value_or(std::vector<std::string>{}) == std::vector<std::string>{"*"}); } SECTION ("expand wildcards") @@ -109,17 +101,15 @@ TEST_CASE ("specifier parsing", "[specifier]") Util::Vectors::append(&specs, specs2); Util::sort(specs); - auto spectargets = FeatureSpec::from_strings_and_triplet( - { - "openssl", - "zlib", - "zlib[0]", - "zlib[1]", - }, - Triplet::X86_UWP); + std::vector<FeatureSpec> spectargets{ + {{"openssl", Triplet::X86_UWP}, "core"}, + {{"zlib", Triplet::X86_UWP}, "core"}, + {{"zlib", Triplet::X86_UWP}, "0"}, + {{"zlib", Triplet::X86_UWP}, "1"}, + }; Util::sort(spectargets); REQUIRE(specs.size() == spectargets.size()); - REQUIRE(Util::all_equal(specs, spectargets)); + REQUIRE(specs == spectargets); } #if defined(_WIN32) diff --git a/toolsrc/src/vcpkg-test/statusparagraphs.cpp b/toolsrc/src/vcpkg-test/statusparagraphs.cpp index 88b499118..c755948b5 100644 --- a/toolsrc/src/vcpkg-test/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg-test/statusparagraphs.cpp @@ -18,14 +18,15 @@ Architecture: x64-windows Multi-Arch: same Description: Status: install ok installed -)"); +)", + ""); REQUIRE(pghs); StatusParagraphs status_db( Util::fmap(*pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); - auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); + auto it = status_db.find_installed({"ffmpeg", Triplet::X64_WINDOWS}); REQUIRE(it != status_db.end()); } @@ -38,14 +39,15 @@ Architecture: x64-windows Multi-Arch: same Description: Status: purge ok not-installed -)"); +)", + ""); REQUIRE(pghs); StatusParagraphs status_db( Util::fmap(*pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); - auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); + auto it = status_db.find_installed({"ffmpeg", Triplet::X64_WINDOWS}); REQUIRE(it == status_db.end()); } @@ -66,18 +68,19 @@ Architecture: x64-windows Multi-Arch: same Description: Status: purge ok not-installed -)"); +)", + ""); REQUIRE(pghs); StatusParagraphs status_db( Util::fmap(*pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); - auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); + auto it = status_db.find_installed({"ffmpeg", Triplet::X64_WINDOWS}); REQUIRE(it != status_db.end()); // Feature "openssl" is not installed and should not be found - auto it1 = status_db.find_installed({unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS), "openssl"}); + auto it1 = status_db.find_installed({{"ffmpeg", Triplet::X64_WINDOWS}, "openssl"}); REQUIRE(it1 == status_db.end()); } @@ -98,13 +101,14 @@ Architecture: x64-windows Multi-Arch: same Description: Status: install ok installed -)"); +)", + ""); REQUIRE(pghs); StatusParagraphs status_db( Util::fmap(*pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); // Feature "openssl" is installed and should therefore be found - auto it = status_db.find_installed({unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS), "openssl"}); + auto it = status_db.find_installed({{"ffmpeg", Triplet::X64_WINDOWS}, "openssl"}); REQUIRE(it != status_db.end()); } diff --git a/toolsrc/src/vcpkg-test/util.cpp b/toolsrc/src/vcpkg-test/util.cpp index db310f7a0..ae02e3ab0 100644 --- a/toolsrc/src/vcpkg-test/util.cpp +++ b/toolsrc/src/vcpkg-test/util.cpp @@ -104,17 +104,8 @@ namespace vcpkg::Test PackageSpec PackageSpecMap::emplace(vcpkg::SourceControlFileLocation&& scfl) { - auto spec = PackageSpec::from_name_and_triplet(scfl.source_control_file->core_paragraph->name, triplet); - REQUIRE(spec.has_value()); map.emplace(scfl.source_control_file->core_paragraph->name, std::move(scfl)); - return PackageSpec{*spec.get()}; - } - - PackageSpec unsafe_pspec(std::string name, Triplet t) - { - auto m_ret = PackageSpec::from_name_and_triplet(name, t); - REQUIRE(m_ret.has_value()); - return m_ret.value_or_exit(VCPKG_LINE_INFO); + return {scfl.source_control_file->core_paragraph->name, triplet}; } static AllowSymlinks internal_can_create_symlinks() noexcept diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index 3404a6a48..e97400150 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -5,7 +5,7 @@ #include <vcpkg/base/util.h> #include <vcpkg/binaryparagraph.h> -#include <vcpkg/parse.h> +#include <vcpkg/paragraphparser.h> namespace vcpkg { @@ -41,8 +41,7 @@ namespace vcpkg parser.required_field(Fields::PACKAGE, name); std::string architecture; parser.required_field(Fields::ARCHITECTURE, architecture); - this->spec = PackageSpec::from_name_and_triplet(name, Triplet::from_canonical_name(std::move(architecture))) - .value_or_exit(VCPKG_LINE_INFO); + this->spec = PackageSpec(std::move(name), Triplet::from_canonical_name(std::move(architecture))); } // one or the other @@ -57,10 +56,16 @@ namespace vcpkg std::string multi_arch; parser.required_field(Fields::MULTI_ARCH, multi_arch); - this->depends = parse_comma_list(parser.optional_field(Fields::DEPENDS)); + this->depends = Util::fmap( + parse_qualified_specifier_list(parser.optional_field(Fields::DEPENDS)).value_or_exit(VCPKG_LINE_INFO), + [](const ParsedQualifiedSpecifier& dep) { + // for compatibility with previous vcpkg versions, we discard all irrelevant information + return dep.name; + }); if (this->feature.empty()) { - this->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); + this->default_features = parse_default_features_list(parser.optional_field(Fields::DEFAULTFEATURES)) + .value_or_exit(VCPKG_LINE_INFO); } this->type = Type::from_string(parser.optional_field(Fields::TYPE)); @@ -77,7 +82,7 @@ namespace vcpkg } BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, - const Triplet& triplet, + Triplet triplet, const std::string& abi_tag, const std::vector<FeatureSpec>& deps) : version(spgh.version) @@ -86,19 +91,19 @@ namespace vcpkg , abi(abi_tag) , type(spgh.type) { - this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->depends = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.to_string(); }); + this->spec = PackageSpec(spgh.name, triplet); + this->depends = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.spec().name(); }); Util::sort_unique_erase(this->depends); } BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, - const Triplet& triplet, + Triplet triplet, const std ::vector<FeatureSpec>& deps) : version(), description(fpgh.description), maintainer(), feature(fpgh.name), type(spgh.type) { - this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); - this->depends = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.to_string(); }); + this->spec = PackageSpec(spgh.name, triplet); + this->depends = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.spec().name(); }); Util::sort_unique_erase(this->depends); } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index c65cf9b77..01a22ba90 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -143,7 +143,7 @@ namespace vcpkg::Build::Command nullptr,
};
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
+ void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
{
// Build only takes a single package and all dependencies must already be installed
const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
@@ -307,7 +307,7 @@ namespace vcpkg::Build static std::unique_ptr<BinaryControlFile> create_binary_control_file(
const SourceParagraph& source_paragraph,
- const Triplet& triplet,
+ Triplet triplet,
const BuildInfo& build_info,
const std::string& abi_tag,
const std::vector<FeatureSpec>& core_dependencies)
@@ -353,7 +353,7 @@ namespace vcpkg::Build static std::vector<System::CMakeVariable> get_cmake_vars(const VcpkgPaths& paths,
const BuildPackageConfig& config,
- const Triplet& triplet,
+ Triplet triplet,
const Toolset& toolset)
{
#if !defined(_WIN32)
@@ -422,7 +422,7 @@ namespace vcpkg::Build static std::string make_build_cmd(const VcpkgPaths& paths,
const PreBuildInfo& pre_build_info,
const BuildPackageConfig& config,
- const Triplet& triplet)
+ Triplet triplet)
{
const Toolset& toolset = paths.get_toolset(pre_build_info);
const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE);
@@ -445,9 +445,7 @@ namespace vcpkg::Build return command;
}
- static std::string get_triplet_abi(const VcpkgPaths& paths,
- const PreBuildInfo& pre_build_info,
- const Triplet& triplet)
+ static std::string get_triplet_abi(const VcpkgPaths& paths, const PreBuildInfo& pre_build_info, Triplet triplet)
{
static std::map<fs::path, std::string> s_hash_cache;
@@ -516,7 +514,7 @@ namespace vcpkg::Build }
#endif
- const Triplet& triplet = spec.triplet();
+ Triplet triplet = spec.triplet();
const auto& triplet_file_path = paths.get_triplet_file_path(spec.triplet()).u8string();
if (Strings::case_insensitive_ascii_starts_with(triplet_file_path, paths.community_triplets.u8string()))
@@ -644,7 +642,7 @@ namespace vcpkg::Build Span<const AbiEntry> dependency_abis)
{
auto& fs = paths.get_filesystem();
- const Triplet& triplet = config.triplet;
+ Triplet triplet = config.triplet;
const std::string& name = config.scf.core_paragraph->name;
std::vector<AbiEntry> abi_tag_entries(dependency_abis.begin(), dependency_abis.end());
@@ -813,7 +811,7 @@ namespace vcpkg::Build const StatusParagraphs& status_db)
{
auto& fs = paths.get_filesystem();
- const Triplet& triplet = config.triplet;
+ Triplet triplet = config.triplet;
const std::string& name = config.scf.core_paragraph->name;
std::vector<FeatureSpec> missing_fspecs;
@@ -833,7 +831,7 @@ namespace vcpkg::Build return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(missing_fspecs)};
}
- const PackageSpec spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO);
+ const PackageSpec spec(name, triplet);
std::vector<AbiEntry> dependency_abis;
for (auto&& pspec : config.package_dependencies)
@@ -1075,13 +1073,14 @@ namespace vcpkg::Build BuildInfo read_build_info(const Files::Filesystem& fs, const fs::path& filepath)
{
- const Expected<Parse::RawParagraph> pghs = Paragraphs::get_single_paragraph(fs, filepath);
- Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package");
+ const ExpectedS<Parse::RawParagraph> pghs = Paragraphs::get_single_paragraph(fs, filepath);
+ Checks::check_exit(
+ VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package: %s", pghs.error());
return inner_create_buildinfo(*pghs.get());
}
PreBuildInfo::PreBuildInfo(const VcpkgPaths& paths,
- const Triplet& triplet,
+ Triplet triplet,
const std::unordered_map<std::string, std::string>& cmakevars)
{
for (auto&& kv : VCPKG_OPTIONS)
diff --git a/toolsrc/src/vcpkg/cmakevars.cpp b/toolsrc/src/vcpkg/cmakevars.cpp index 6059833e7..42bed5501 100644 --- a/toolsrc/src/vcpkg/cmakevars.cpp +++ b/toolsrc/src/vcpkg/cmakevars.cpp @@ -152,10 +152,11 @@ namespace vcpkg::CMakeVars } } - void TripletCMakeVarProvider::load_generic_triplet_vars(const Triplet& triplet) const + void TripletCMakeVarProvider::load_generic_triplet_vars(Triplet triplet) const { std::vector<std::vector<std::pair<std::string, std::string>>> vars(1); - FullPackageSpec full_spec = FullPackageSpec::from_string("", triplet).value_or_exit(VCPKG_LINE_INFO); + // Hack: PackageSpecs should never have .name=="" + FullPackageSpec full_spec({"", triplet}); const fs::path file_path = create_tag_extraction_file(std::array<std::pair<const FullPackageSpec*, std::string>, 1>{ std::pair<const FullPackageSpec*, std::string>{&full_spec, ""}}); @@ -222,7 +223,7 @@ namespace vcpkg::CMakeVars } Optional<const std::unordered_map<std::string, std::string>&> TripletCMakeVarProvider::get_generic_triplet_vars( - const Triplet& triplet) const + Triplet triplet) const { auto find_itr = generic_triplet_vars.find(triplet); if (find_itr != generic_triplet_vars.end()) diff --git a/toolsrc/src/vcpkg/commands.buildexternal.cpp b/toolsrc/src/vcpkg/commands.buildexternal.cpp index 135ef132b..4a69be879 100644 --- a/toolsrc/src/vcpkg/commands.buildexternal.cpp +++ b/toolsrc/src/vcpkg/commands.buildexternal.cpp @@ -16,7 +16,7 @@ namespace vcpkg::Commands::BuildExternal nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) { const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index 4c49db004..5fb9d15f4 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -14,8 +14,7 @@ namespace vcpkg::Commands::Cache std::vector<BinaryParagraph> output; for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.packages)) { - const Expected<Parse::RawParagraph> pghs = - Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL"); + const auto pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL"); if (const auto p = pghs.get()) { const BinaryParagraph binary_paragraph = BinaryParagraph(*p); diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index b8ac97563..301400b8b 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -387,7 +387,7 @@ namespace vcpkg::Commands::CI will_fail.emplace(p->spec); } else if (Util::any_of(p->package_dependencies, - [&](const PackageSpec& spec) { return Util::Sets::contains(will_fail, spec); })) + [&](const PackageSpec& spec) { return Util::Sets::contains(will_fail, spec); })) { state = "cascade"; ret->known.emplace(p->spec, BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES); @@ -426,7 +426,7 @@ namespace vcpkg::Commands::CI return ret; } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) { if (!GlobalState::g_binary_caching) { @@ -483,7 +483,7 @@ namespace vcpkg::Commands::CI }); std::vector<TripletAndSummary> results; auto timer = Chrono::ElapsedTimer::create_started(); - for (const Triplet& triplet : triplets) + for (Triplet triplet : triplets) { Input::check_triplet(triplet, paths); diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp index eecc45634..7023547da 100644 --- a/toolsrc/src/vcpkg/commands.dependinfo.cpp +++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp @@ -234,7 +234,7 @@ namespace vcpkg::Commands::DependInfo nullptr,
};
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
+ void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
{
const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
const int max_depth = get_max_depth(options);
diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index c54f73e76..b05c1f653 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -33,7 +33,7 @@ namespace vcpkg::Commands::Env }; // This command should probably optionally take a port - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet triplet) { const auto& fs = paths.get_filesystem(); diff --git a/toolsrc/src/vcpkg/commands.import.cpp b/toolsrc/src/vcpkg/commands.import.cpp index c18d788c5..521892e88 100644 --- a/toolsrc/src/vcpkg/commands.import.cpp +++ b/toolsrc/src/vcpkg/commands.import.cpp @@ -108,12 +108,13 @@ namespace vcpkg::Commands::Import const fs::path include_directory(args.command_arguments[1]); const fs::path project_directory(args.command_arguments[2]); - const Expected<Parse::RawParagraph> pghs = - Paragraphs::get_single_paragraph(paths.get_filesystem(), control_file_path); + const auto pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), control_file_path); Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid control file %s for package", - control_file_path.generic_u8string()); + control_file_path.generic_u8string(), + "\n", + pghs.error()); StatusParagraph spgh; spgh.package = BinaryParagraph(*pghs.get()); diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp index e8afabed5..960e9bbb3 100644 --- a/toolsrc/src/vcpkg/commands.upgrade.cpp +++ b/toolsrc/src/vcpkg/commands.upgrade.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands::Upgrade nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) { const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 5309501d9..beb92f4b0 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -115,7 +115,7 @@ namespace vcpkg::Dependencies for (auto&& fspec : fullspec_list) { // TODO: this is incorrect and does not handle default features nor "*" - Util::Vectors::append(&dep_list, fspec.to_feature_specs({"default"}, {})); + Util::Vectors::append(&dep_list, fspec.to_feature_specs({"default"}, {"default"})); } Util::sort_unique_erase(dep_list); @@ -130,10 +130,8 @@ namespace vcpkg::Dependencies { Util::Vectors::append( &dep_list, - FullPackageSpec(PackageSpec::from_name_and_triplet(dep.depend.name, m_spec.triplet()) - .value_or_exit(VCPKG_LINE_INFO), - dep.depend.features) - .to_feature_specs({"default"}, {})); + FullPackageSpec({dep.depend.name, m_spec.triplet()}, dep.depend.features) + .to_feature_specs({"default"}, {"default"})); } else { @@ -261,14 +259,15 @@ namespace vcpkg::Dependencies if (it == m_graph.end()) { - Optional<const SourceControlFileLocation&> maybe_scfl = + ExpectedS<const SourceControlFileLocation&> maybe_scfl = m_port_provider.get_control_file(ipv.spec().name()); if (!maybe_scfl) Checks::exit_with_message( VCPKG_LINE_INFO, - "We could not find a CONTROL file for '%s'. Please run \"vcpkg remove %s\" and re-attempt.", + "Error: while loading %s: %s.\nPlease run \"vcpkg remove %s\" and re-attempt.", ipv.spec().to_string(), + maybe_scfl.error(), ipv.spec().to_string()); return m_graph @@ -456,7 +455,7 @@ namespace vcpkg::Dependencies return nullopt; } - std::vector<PackageSpec> ExportPlanAction::dependencies(const Triplet&) const + std::vector<PackageSpec> ExportPlanAction::dependencies(Triplet) const { if (auto p_ip = m_installed_package.get()) return p_ip->dependencies(); diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 0094b712c..736ab6def 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -321,8 +321,7 @@ namespace vcpkg::Export nullptr, }; - static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args, - const Triplet& default_triplet) + static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args, Triplet default_triplet) { ExportArguments ret; @@ -513,7 +512,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console } } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) { const auto opts = handle_export_command_arguments(args, default_triplet); for (auto&& spec : opts.specs) diff --git a/toolsrc/src/vcpkg/input.cpp b/toolsrc/src/vcpkg/input.cpp index 42f81cbb9..0abe51823 100644 --- a/toolsrc/src/vcpkg/input.cpp +++ b/toolsrc/src/vcpkg/input.cpp @@ -10,7 +10,7 @@ namespace vcpkg { PackageSpec Input::check_and_get_package_spec(std::string&& spec_string, - const Triplet& default_triplet, + Triplet default_triplet, CStringView example_text) { const std::string as_lowercase = Strings::ascii_to_lowercase(std::move(spec_string)); @@ -21,12 +21,12 @@ namespace vcpkg } // Intentionally show the lowercased string - System::print2(System::Color::error, "Error: ", expected_spec.error(), ": ", as_lowercase, '\n'); + System::print2(System::Color::error, expected_spec.error()); System::print2(example_text); Checks::exit_fail(VCPKG_LINE_INFO); } - void Input::check_triplet(const Triplet& t, const VcpkgPaths& paths) + void Input::check_triplet(Triplet t, const VcpkgPaths& paths) { if (!paths.is_valid_triplet(t)) { @@ -38,7 +38,7 @@ namespace vcpkg } FullPackageSpec Input::check_and_get_full_package_spec(std::string&& full_package_spec_as_string, - const Triplet& default_triplet, + Triplet default_triplet, CStringView example_text) { const std::string as_lowercase = Strings::ascii_to_lowercase(std::move(full_package_spec_as_string)); @@ -49,7 +49,7 @@ namespace vcpkg } // Intentionally show the lowercased string - System::print2(System::Color::error, "Error: ", expected_spec.error(), ": ", as_lowercase, '\n'); + System::print2(System::Color::error, expected_spec.error()); System::print2(example_text); Checks::exit_fail(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 0af9a33a1..fc76aa765 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -146,7 +146,7 @@ namespace vcpkg::Install static std::vector<file_pack> extract_files_in_triplet( const std::vector<StatusParagraphAndAssociatedFiles>& pgh_and_files, - const Triplet& triplet, + Triplet triplet, const size_t remove_chars = 0) { std::vector<file_pack> output; @@ -184,7 +184,7 @@ namespace vcpkg::Install } static SortedVector<file_pack> build_list_of_installed_files( - const std::vector<StatusParagraphAndAssociatedFiles>& pgh_and_files, const Triplet& triplet) + const std::vector<StatusParagraphAndAssociatedFiles>& pgh_and_files, Triplet triplet) { const size_t installed_remove_char_count = triplet.canonical_name().size() + 1; // +1 for the slash std::vector<file_pack> installed_files = @@ -196,7 +196,7 @@ namespace vcpkg::Install InstallResult install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db) { const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec); - const Triplet& triplet = bcf.core_paragraph.spec.triplet(); + Triplet triplet = bcf.core_paragraph.spec.triplet(); const std::vector<StatusParagraphAndAssociatedFiles> pgh_and_files = get_installed_files(paths, *status_db); const SortedVector<std::string> package_files = @@ -639,7 +639,7 @@ namespace vcpkg::Install /// Run "install" command. /// </summary> /// - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) { // input sanitization const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); diff --git a/toolsrc/src/vcpkg/logicexpression.cpp b/toolsrc/src/vcpkg/logicexpression.cpp index 2f646e80a..e91c57310 100644 --- a/toolsrc/src/vcpkg/logicexpression.cpp +++ b/toolsrc/src/vcpkg/logicexpression.cpp @@ -3,33 +3,14 @@ #include <vcpkg/base/strings.h> #include <vcpkg/base/system.print.h> #include <vcpkg/logicexpression.h> +#include <vcpkg/parse.h> #include <string> #include <vector> namespace vcpkg { - struct ParseError - { - ParseError(int column, std::string line, std::string message) : column(column), line(line), message(message) {} - - const int column; - const std::string line; - const std::string message; - - std::string format_error() const - { - return Strings::concat("Error: ", - message, - "\n" - " on expression: \"", - line, - "\"\n", - " ", - std::string(column, ' '), - "^\n"); - } - }; + using vcpkg::Parse::ParseError; enum class Identifier { @@ -64,15 +45,12 @@ namespace vcpkg // // | and & have equal precidence and cannot be used together at the same nesting level // for example a|b&c is not allowd but (a|b)&c and a|(b&c) are allowed. - class ExpressionParser + class ExpressionParser : public Parse::ParserBase { public: - ExpressionParser(const std::string& str, const ExpressionContext& context) - : raw_text(str) - , evaluation_context(context) - , current_iter(raw_text.begin()) - , current_char(get_current_char()) + ExpressionParser(const std::string& str, const ExpressionContext& context) : evaluation_context(context) { + this->init(str, "CONTROL"); { auto override_vars = evaluation_context.cmake_context.find("VCPKG_DEP_INFO_OVERRIDE_VARS"); if (override_vars != evaluation_context.cmake_context.end()) @@ -98,81 +76,23 @@ namespace vcpkg final_result = logic_expression(); - if (current_iter != raw_text.end()) + if (!at_eof()) { - add_error("Invalid logic expression"); + add_error("invalid logic expression, unexpected character"); } } bool get_result() const { return final_result; } - const ParseError* get_error() const { return err.get(); } - private: - const std::string& raw_text; - const ExpressionContext& evaluation_context; std::map<std::string, bool> context_override; - std::string::const_iterator current_iter; - char current_char; - bool final_result; - std::unique_ptr<ParseError> err; - - char get_current_char() const { return (current_iter != raw_text.end() ? *current_iter : '\0'); } - - void add_error(std::string message, int column = -1) - { - // avoid castcading errors by only saving the first - if (!err) - { - if (column < 0) - { - column = current_column(); - } - err = std::make_unique<ParseError>(column, raw_text, message); - } - - // Avoid error loops by skipping to the end - skip_to_end(); - } - - int current_column() const { return static_cast<int>(current_iter - raw_text.begin()); } - - void skip_to_end() + static bool is_identifier_char(char ch) { - current_iter = raw_text.end(); - current_char = '\0'; - } - char current() const { return current_char; } - char next() - { - if (current_char != '\0') - { - current_iter++; - current_char = get_current_char(); - } - return current(); - } - void skip_whitespace() - { - while (current_char == ' ' || current_char == '\t') - { - current_char = next(); - } - } - char next_skip_whitespace() - { - next(); - skip_whitespace(); - return current_char; - } - - static bool is_alphanum(char ch) - { - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '-'); + return is_upper_alpha(ch) || is_lower_alpha(ch) || is_ascii_digit(ch) || ch == '-'; } // Legacy evaluation only searches for substrings. Use this only for diagnostic purposes. @@ -219,7 +139,7 @@ namespace vcpkg // If an identifier is on the explicit override list, return the override value // Otherwise fall back to the built in logic to evaluate // All unrecognized identifiers are an error - bool evaluate_identifier_cmake(const std::string name, int column) + bool evaluate_identifier_cmake(const std::string name, const SourceLoc& loc) { auto id = string2identifier(name); @@ -229,7 +149,7 @@ namespace vcpkg // Point out in the diagnostic that they should add to the override list because that is what // most users should do, however it is also valid to update the built in identifiers to recognize // the name. - add_error("Unrecognized identifer name. Add to override list in triplet file.", column); + add_error("Unrecognized identifer name. Add to override list in triplet file.", loc); break; case Identifier::x64: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "x64"); @@ -251,7 +171,7 @@ namespace vcpkg return evaluation_context.legacy_context.find(name) != std::string::npos; } - bool evaluate_identifier(const std::string name, int column) + bool evaluate_identifier(const std::string name, const SourceLoc& loc) { if (!context_override.empty()) { @@ -264,15 +184,14 @@ namespace vcpkg } bool legacy = evaluate_identifier_legacy(name); - bool cmake = evaluate_identifier_cmake(name, column); + bool cmake = evaluate_identifier_cmake(name, loc); if (legacy != cmake) { // Legacy evaluation only used the name of the triplet, now we use the actual // cmake variables. This has the potential to break custom triplets. // For now just print a message, this will need to change once we start introducing // new variables that did not exist previously (such as host-*) - System::print2( - "Warning: Identifier logic evaluation does not match legacy evaluation:\n ", name, '\n'); + System::print2("Warning: qualifier has changed meaning recently:\n ", name, '\n'); } return cmake; } @@ -281,22 +200,16 @@ namespace vcpkg // alpha-numeric string of characters bool identifier_expression() { - auto curr = current(); - std::string name; - auto starting_column = current_column(); - - for (curr = current(); is_alphanum(curr); curr = next()) - { - name += curr; - } + auto start_loc = cur_loc(); + std::string name = match_zero_or_more(is_identifier_char).to_string(); if (name.empty()) { - add_error("Invalid logic expression, unexpected character"); + add_error("unexpected character in logic expression"); return false; } - bool result = evaluate_identifier(name, starting_column); + bool result = evaluate_identifier(name, start_loc); skip_whitespace(); return result; } @@ -306,9 +219,10 @@ namespace vcpkg // primary-expression bool not_expression() { - if (current() == '!') + if (cur() == '!') { - next_skip_whitespace(); + next(); + skip_whitespace(); return !primary_expression(); } @@ -327,11 +241,11 @@ namespace vcpkg skip_whitespace(); seed = operation(not_expression(), seed); - } while (current() == oper); + } while (cur() == oper); - if (current() == other) + if (cur() == other) { - add_error("Mixing & and | is not allowed, Use () to specify order of operations."); + add_error("mixing & and | is not allowed, use () to specify order of operations"); } skip_whitespace(); @@ -348,7 +262,7 @@ namespace vcpkg { auto result = not_expression(); - switch (current()) + switch (cur()) { case '|': { @@ -367,16 +281,18 @@ namespace vcpkg // identifier bool primary_expression() { - if (current() == '(') + if (cur() == '(') { - next_skip_whitespace(); + next(); + skip_whitespace(); bool result = logic_expression(); - if (current() != ')') + if (cur() != ')') { add_error("missing closing )"); return result; } - next_skip_whitespace(); + next(); + skip_whitespace(); return result; } @@ -390,7 +306,7 @@ namespace vcpkg if (auto err = parser.get_error()) { - return err->format_error(); + return err->format(); } return parser.get_result(); diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp index ea25f57e1..702f7aad3 100644 --- a/toolsrc/src/vcpkg/packagespec.cpp +++ b/toolsrc/src/vcpkg/packagespec.cpp @@ -3,18 +3,11 @@ #include <vcpkg/base/checks.h> #include <vcpkg/base/util.h> #include <vcpkg/packagespec.h> -#include <vcpkg/packagespecparseresult.h> +#include <vcpkg/paragraphparser.h> #include <vcpkg/parse.h> -using vcpkg::Parse::parse_comma_list; - namespace vcpkg { - static bool is_valid_package_spec_char(char c) - { - return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); - } - std::string FeatureSpec::to_string() const { std::string ret; @@ -27,38 +20,6 @@ namespace vcpkg Strings::append(out, name(), '[', feature(), "]:", triplet()); } - std::vector<FeatureSpec> FeatureSpec::from_strings_and_triplet(const std::vector<std::string>& depends, - const Triplet& triplet) - { - std::vector<FeatureSpec> f_specs; - for (auto&& depend : depends) - { - auto maybe_spec = ParsedSpecifier::from_string(depend); - if (auto spec = maybe_spec.get()) - { - Checks::check_exit(VCPKG_LINE_INFO, - spec->triplet.empty(), - "error: triplets cannot currently be specified in this context: %s", - depend); - PackageSpec pspec = - PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO); - - for (auto&& feature : spec->features) - f_specs.push_back(FeatureSpec{pspec, feature}); - - if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, "core"}); - } - else - { - Checks::exit_with_message(VCPKG_LINE_INFO, - "error while parsing feature list: %s: %s", - vcpkg::to_string(maybe_spec.error()), - depend); - } - } - return f_specs; - } - std::vector<FeatureSpec> FullPackageSpec::to_feature_specs(const std::vector<std::string>& default_features, const std::vector<std::string>& all_features) const { @@ -99,57 +60,26 @@ namespace vcpkg return feature_specs; } - ExpectedT<FullPackageSpec, PackageSpecParseResult> FullPackageSpec::from_string(const std::string& spec_as_string, - const Triplet& default_triplet) - { - auto res = ParsedSpecifier::from_string(spec_as_string); - if (auto p = res.get()) - { - FullPackageSpec fspec; - Triplet t = p->triplet.empty() ? default_triplet : Triplet::from_canonical_name(std::move(p->triplet)); - fspec.package_spec = PackageSpec::from_name_and_triplet(p->name, t).value_or_exit(VCPKG_LINE_INFO); - fspec.features = std::move(p->features); - return fspec; - } - return res.error(); - } - - ExpectedT<PackageSpec, PackageSpecParseResult> PackageSpec::from_name_and_triplet(const std::string& name, - const Triplet& triplet) + ExpectedS<FullPackageSpec> FullPackageSpec::from_string(const std::string& spec_as_string, Triplet default_triplet) { - if (Util::find_if_not(name, is_valid_package_spec_char) != name.end()) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - - PackageSpec p; - p.m_name = name; - p.m_triplet = triplet; - return p; + return parse_qualified_specifier(spec_as_string) + .then([&](ParsedQualifiedSpecifier&& p) -> ExpectedS<FullPackageSpec> { + if (p.qualifier) return "Error: qualifier not allowed in this context: " + spec_as_string + "\n"; + auto triplet = p.triplet ? Triplet::from_canonical_name(std::move(*p.triplet.get())) : default_triplet; + return FullPackageSpec({p.name, triplet}, p.features.value_or({})); + }); } - std::vector<PackageSpec> PackageSpec::to_package_specs(const std::vector<std::string>& ports, - const Triplet& triplet) + std::vector<PackageSpec> PackageSpec::to_package_specs(const std::vector<std::string>& ports, Triplet triplet) { return Util::fmap(ports, [&](const std::string& spec_as_string) -> PackageSpec { - auto maybe_spec = PackageSpec::from_name_and_triplet(spec_as_string, triplet); - if (auto spec = maybe_spec.get()) - { - return std::move(*spec); - } - - const PackageSpecParseResult error_type = maybe_spec.error(); - Checks::exit_with_message(VCPKG_LINE_INFO, - "Invalid package: %s\n" - "%s", - spec_as_string, - vcpkg::to_string(error_type)); + return {spec_as_string, triplet}; }); } const std::string& PackageSpec::name() const { return this->m_name; } - const Triplet& PackageSpec::triplet() const { return this->m_triplet; } + Triplet PackageSpec::triplet() const { return this->m_triplet; } std::string PackageSpec::dir() const { return Strings::format("%s_%s", this->m_name, this->m_triplet); } @@ -163,69 +93,155 @@ namespace vcpkg bool operator!=(const PackageSpec& left, const PackageSpec& right) { return !(left == right); } - ExpectedT<ParsedSpecifier, PackageSpecParseResult> ParsedSpecifier::from_string(const std::string& input) + ExpectedS<Features> Features::from_string(const std::string& name) + { + return parse_qualified_specifier(name).then([&](ParsedQualifiedSpecifier&& pqs) -> ExpectedS<Features> { + if (pqs.triplet) return "Error: triplet not allowed in this context: " + name + "\n"; + if (pqs.qualifier) return "Error: qualifier not allowed in this context: " + name + "\n"; + return Features{pqs.name, pqs.features.value_or({})}; + }); + } + + static bool is_package_name_char(char ch) { - auto pos = input.find(':'); - auto pos_l_bracket = input.find('['); - auto pos_r_bracket = input.find(']'); + return Parse::ParserBase::is_lower_alpha(ch) || Parse::ParserBase::is_ascii_digit(ch) || ch == '-'; + } + + static bool is_feature_name_char(char ch) { + // TODO: we do not intend underscores to be valid, however there is currently a feature using them (libwebp[vwebp_sdl]). + // TODO: we need to rename this feature, then remove underscores from this list. + return is_package_name_char(ch) || ch == '_'; + } + + ExpectedS<ParsedQualifiedSpecifier> parse_qualified_specifier(CStringView input) + { + Parse::ParserBase parser; + parser.init(input, "<unknown>"); + auto maybe_pqs = parse_qualified_specifier(parser); + if (!parser.at_eof()) parser.add_error("expected eof"); + if (auto e = parser.get_error()) return e->format(); + return std::move(maybe_pqs).value_or_exit(VCPKG_LINE_INFO); + } - ParsedSpecifier f; - if (pos == std::string::npos && pos_l_bracket == std::string::npos) + Optional<std::string> parse_feature_name(Parse::ParserBase& parser) + { + using Parse::ParserBase; + auto ret = parser.match_zero_or_more(is_feature_name_char).to_string(); + auto ch = parser.cur(); + if (ParserBase::is_upper_alpha(ch) || ch == '_') { - f.name = input; - return f; + parser.add_error("invalid character in feature name (must be lowercase, digits, '-')"); + return nullopt; } - else if (pos == std::string::npos) + if (ret.empty()) { - if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) - { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - const std::string name = input.substr(0, pos_l_bracket); - f.name = name; - f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); - return f; + parser.add_error("expected feature name (must be lowercase, digits, '-')"); + return nullopt; } - else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) + return ret; + } + Optional<std::string> parse_package_name(Parse::ParserBase& parser) + { + using Parse::ParserBase; + auto ret = parser.match_zero_or_more(is_package_name_char).to_string(); + auto ch = parser.cur(); + if (ParserBase::is_upper_alpha(ch) || ch == '_') + { + parser.add_error("invalid character in package name (must be lowercase, digits, '-')"); + return nullopt; + } + if (ret.empty()) { - const std::string name = input.substr(0, pos); - f.triplet = input.substr(pos + 1); - f.name = name; + parser.add_error("expected package name (must be lowercase, digits, '-')"); + return nullopt; } + return ret; + } + + Optional<ParsedQualifiedSpecifier> parse_qualified_specifier(Parse::ParserBase& parser) + { + using Parse::ParserBase; + ParsedQualifiedSpecifier ret; + auto name = parse_package_name(parser); + if (auto n = name.get()) + ret.name = std::move(*n); else + return nullopt; + auto ch = parser.cur(); + if (ch == '[') { - if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + std::vector<std::string> features; + do { - return PackageSpecParseResult::INVALID_CHARACTERS; - } - const std::string name = input.substr(0, pos_l_bracket); - f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); - f.triplet = input.substr(pos + 1); - f.name = name; + parser.next(); + parser.skip_tabs_spaces(); + if (parser.cur() == '*') + { + features.push_back("*"); + parser.next(); + } + else + { + auto feature = parse_feature_name(parser); + if (auto f = feature.get()) + features.push_back(std::move(*f)); + else + return nullopt; + } + auto skipped_space = parser.skip_tabs_spaces(); + ch = parser.cur(); + if (ch == ']') + { + ch = parser.next(); + break; + } + else if (ch == ',') + { + continue; + } + else + { + if (skipped_space.size() > 0 || Parse::ParserBase::is_lineend(parser.cur())) + parser.add_error("expected ',' or ']' in feature list"); + else + parser.add_error("invalid character in feature name (must be lowercase, digits, '-', or '*')"); + return nullopt; + } + } while (true); + ret.features = std::move(features); } - - auto pos2 = input.find(':', pos + 1); - if (pos2 != std::string::npos) + if (ch == ':') { - return PackageSpecParseResult::TOO_MANY_COLONS; + parser.next(); + ret.triplet = parser.match_zero_or_more(is_package_name_char).to_string(); + if (ret.triplet.get()->empty()) + { + parser.add_error("expected triplet name (must be lowercase, digits, '-')"); + return nullopt; + } } - return f; - } - - ExpectedT<Features, PackageSpecParseResult> Features::from_string(const std::string& name) - { - auto maybe_spec = ParsedSpecifier::from_string(name); - if (auto spec = maybe_spec.get()) + parser.skip_tabs_spaces(); + ch = parser.cur(); + if (ch == '(') { - Checks::check_exit( - VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name); - - Features f; - f.name = spec->name; - f.features = spec->features; - return f; + auto loc = parser.cur_loc(); + int depth = 1; + while (depth > 0 && (ch = parser.next()) != 0) + { + if (ch == '(') ++depth; + if (ch == ')') --depth; + } + if (depth > 0) + { + parser.add_error("unmatched open braces in qualifier", loc); + return nullopt; + } + ret.qualifier = StringView(loc.it + 1, parser.it()).to_string(); + parser.next(); } - - return maybe_spec.error(); + // This makes the behavior of the parser more consistent -- otherwise, it will skip tabs and spaces only if + // there isn't a qualifier. + parser.skip_tabs_spaces(); + return ret; } } diff --git a/toolsrc/src/vcpkg/packagespecparseresult.cpp b/toolsrc/src/vcpkg/packagespecparseresult.cpp deleted file mode 100644 index ef078ea28..000000000 --- a/toolsrc/src/vcpkg/packagespecparseresult.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "pch.h" - -#include <vcpkg/packagespecparseresult.h> - -#include <vcpkg/base/checks.h> - -namespace vcpkg -{ - CStringView to_string(PackageSpecParseResult ev) noexcept - { - switch (ev) - { - case PackageSpecParseResult::SUCCESS: return "OK"; - case PackageSpecParseResult::TOO_MANY_COLONS: return "Too many colons"; - case PackageSpecParseResult::INVALID_CHARACTERS: - return "Contains invalid characters. Only alphanumeric lowercase ASCII characters and dashes are " - "allowed"; - default: Checks::unreachable(VCPKG_LINE_INFO); - } - } - - void to_string(std::string& out, PackageSpecParseResult p) { out.append(vcpkg::to_string(p).c_str()); } -} diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index 797d681cd..8f1b72172 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -4,209 +4,136 @@ #include <vcpkg/base/system.debug.h> #include <vcpkg/base/system.print.h> #include <vcpkg/base/util.h> +#include <vcpkg/binaryparagraph.h> #include <vcpkg/paragraphparseresult.h> #include <vcpkg/paragraphs.h> +#include <vcpkg/parse.h> using namespace vcpkg::Parse; +using namespace vcpkg; namespace vcpkg::Paragraphs { - struct Parser + struct PghParser : private Parse::ParserBase { - Parser(const char* c, const char* e) : cur(c), end(e) {} - private: - const char* cur; - const char* const end; - - void peek(char& ch) const - { - if (cur == end) - ch = 0; - else - ch = *cur; - } - - void next(char& ch) - { - if (cur == end) - ch = 0; - else - { - ++cur; - peek(ch); - } - } - - void skip_comment(char& ch) - { - while (ch != '\r' && ch != '\n' && ch != '\0') - next(ch); - if (ch == '\r') next(ch); - if (ch == '\n') next(ch); - } - - void skip_spaces(char& ch) - { - while (ch == ' ' || ch == '\t') - next(ch); - } - - static bool is_alphanum(char ch) - { - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'); - } - - static bool is_comment(char ch) { return (ch == '#'); } - - static bool is_lineend(char ch) { return ch == '\r' || ch == '\n' || ch == 0; } - - void get_fieldvalue(char& ch, std::string& fieldvalue) + void get_fieldvalue(std::string& fieldvalue) { fieldvalue.clear(); - auto beginning_of_line = cur; do { // scan to end of current line (it is part of the field value) - while (!is_lineend(ch)) - next(ch); - - fieldvalue.append(beginning_of_line, cur); - - if (ch == '\r') next(ch); - if (ch == '\n') next(ch); - - if (is_alphanum(ch) || is_comment(ch)) - { - // Line begins a new field. - return; - } - - beginning_of_line = cur; - - // Line may continue the current field with data or terminate the paragraph, - // depending on first nonspace character. - skip_spaces(ch); - - if (is_lineend(ch)) - { - // Line was whitespace or empty. - // This terminates the field and the paragraph. - // We leave the blank line's whitespace consumed, because it doesn't matter. - return; - } + Strings::append(fieldvalue, match_until(is_lineend)); + skip_newline(); - // First nonspace is not a newline. This continues the current field value. - // We forcibly convert all newlines into single '\n' for ease of text handling later on. - fieldvalue.push_back('\n'); + if (cur() != ' ') return; + auto spacing = skip_tabs_spaces(); + if (is_lineend(cur())) return add_error("unexpected end of line, to span a blank line use \" .\""); + Strings::append(fieldvalue, "\n", spacing); } while (true); } - void get_fieldname(char& ch, std::string& fieldname) + void get_fieldname(std::string& fieldname) { - auto begin_fieldname = cur; - while (is_alphanum(ch) || ch == '-') - next(ch); - Checks::check_exit(VCPKG_LINE_INFO, ch == ':', "Expected ':'"); - fieldname = std::string(begin_fieldname, cur); - - // skip ': ' - next(ch); - skip_spaces(ch); + fieldname = match_zero_or_more(is_alphanumdash).to_string(); + if (fieldname.empty()) return add_error("expected fieldname"); } - void get_paragraph(char& ch, RawParagraph& fields) + void get_paragraph(RawParagraph& fields) { fields.clear(); std::string fieldname; std::string fieldvalue; do { - if (is_comment(ch)) + if (cur() == '#') { - skip_comment(ch); + skip_line(); continue; } - get_fieldname(ch, fieldname); - - auto it = fields.find(fieldname); - Checks::check_exit(VCPKG_LINE_INFO, it == fields.end(), "Duplicate field"); + auto loc = cur_loc(); + get_fieldname(fieldname); + if (cur() != ':') return add_error("expected ':' after field name"); + if (Util::Sets::contains(fields, fieldname)) return add_error("duplicate field", loc); + next(); + skip_tabs_spaces(); - get_fieldvalue(ch, fieldvalue); + get_fieldvalue(fieldvalue); fields.emplace(fieldname, fieldvalue); - } while (!is_lineend(ch)); + } while (!is_lineend(cur())); } public: - std::vector<RawParagraph> get_paragraphs() + ExpectedS<std::vector<RawParagraph>> get_paragraphs(CStringView text, CStringView origin) { std::vector<RawParagraph> paragraphs; - char ch; - peek(ch); + init(text, origin); - while (ch != 0) + skip_whitespace(); + while (!at_eof()) { - if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') - { - next(ch); - continue; - } - paragraphs.emplace_back(); - get_paragraph(ch, paragraphs.back()); + get_paragraph(paragraphs.back()); + match_zero_or_more(is_lineend); } + if (get_error()) return get_error()->format(); return paragraphs; } }; - static Expected<RawParagraph> parse_single_paragraph(const std::string& str) + static ExpectedS<RawParagraph> parse_single_paragraph(const std::string& str, const std::string& origin) { - const std::vector<RawParagraph> p = Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); + PghParser parser; + auto pghs = parser.get_paragraphs(str, origin); - if (p.size() == 1) + if (auto p = pghs.get()) { - return p.at(0); + if (p->size() != 1) return std::error_code(ParagraphParseResult::EXPECTED_ONE_PARAGRAPH).message(); + return std::move(p->front()); + } + else + { + return pghs.error(); } - - return std::error_code(ParagraphParseResult::EXPECTED_ONE_PARAGRAPH); } - Expected<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path) + ExpectedS<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path) { const Expected<std::string> contents = fs.read_contents(control_path); if (auto spgh = contents.get()) { - return parse_single_paragraph(*spgh); + return parse_single_paragraph(*spgh, control_path.u8string()); } - return contents.error(); + return contents.error().message(); } - Expected<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path) + ExpectedS<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path) { const Expected<std::string> contents = fs.read_contents(control_path); if (auto spgh = contents.get()) { - return parse_paragraphs(*spgh); + return parse_paragraphs(*spgh, control_path.u8string()); } - return contents.error(); + return contents.error().message(); } - Expected<std::vector<RawParagraph>> parse_paragraphs(const std::string& str) + ExpectedS<std::vector<RawParagraph>> parse_paragraphs(const std::string& str, const std::string& origin) { - return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); + PghParser parser; + return parser.get_paragraphs(str, origin); } ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& path) { const auto path_to_control = path / "CONTROL"; - Expected<std::vector<RawParagraph>> pghs = get_paragraphs(fs, path_to_control); + ExpectedS<std::vector<RawParagraph>> pghs = get_paragraphs(fs, path_to_control); if (auto vector_pghs = pghs.get()) { return SourceControlFile::parse_control_file(path_to_control, std::move(*vector_pghs)); @@ -217,9 +144,9 @@ namespace vcpkg::Paragraphs return error_info; } - Expected<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) + ExpectedS<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) { - Expected<std::vector<RawParagraph>> pghs = + ExpectedS<std::vector<RawParagraph>> pghs = get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); if (auto p = pghs.get()) diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index 6015d9927..0bc748794 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -1,12 +1,60 @@ #include "pch.h" -#include <vcpkg/parse.h> - +#include <utility> #include <vcpkg/base/system.print.h> #include <vcpkg/base/util.h> +#include <vcpkg/packagespec.h> +#include <vcpkg/paragraphparser.h> +#include <vcpkg/parse.h> + +using namespace vcpkg; namespace vcpkg::Parse { + std::string ParseError::format() const + { + return Strings::concat("Error: ", + origin, + ":", + row, + ":", + column, + ": ", + message, + "\n" + " on expression: \"", + line, + "\"\n", + " ", + std::string(column - 1, ' '), + "^\n"); + } + + void ParserBase::add_error(std::string message, const ParserBase::SourceLoc& loc) + { + // avoid cascading errors by only saving the first + if (!m_err) + { + // find beginning of line + auto linestart = loc.it; + while (linestart != m_text.c_str()) + { + if (linestart[-1] == '\n') break; + --linestart; + } + + // find end of line + auto lineend = loc.it; + while (*lineend != '\n' && *lineend != '\r' && *lineend != '\0') + ++lineend; + m_err.reset( + new ParseError(m_origin.c_str(), loc.row, loc.column, {linestart, lineend}, std::move(message))); + } + + // Avoid error loops by skipping to the end + skip_to_eof(); + } + static Optional<std::string> remove_field(RawParagraph* fields, const std::string& fieldname) { auto it = fields->find(fieldname); @@ -45,105 +93,65 @@ namespace vcpkg::Parse return nullptr; } - static bool is_whitespace(char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } - - std::vector<std::string> parse_comma_list(const std::string& str) + template<class T, class F> + static Optional<std::vector<T>> parse_list_until_eof(StringLiteral plural_item_name, Parse::ParserBase& parser, F f) { - if (str.empty()) - { - return {}; - } - - std::vector<std::string> out; - - auto iter = str.cbegin(); - + std::vector<T> ret; + parser.skip_whitespace(); + if (parser.at_eof()) return std::vector<T>{}; do { - // Trim leading whitespace of each element - while (iter != str.cend() && is_whitespace(*iter)) - { - ++iter; - } - - // Allow commas inside of []. - bool bracket_nesting = false; - - auto element_begin = iter; - auto element_end = iter; - while (iter != str.cend() && (*iter != ',' || bracket_nesting)) - { - char value = *iter; - - // do not support nested [] - if (value == '[') - { - if (bracket_nesting) - { - Checks::exit_with_message(VCPKG_LINE_INFO, - "Lists do not support nested brackets, Did you forget a ']'?\n" - "> '%s'\n" - "> %s^\n", - str, - std::string(static_cast<int>(iter - str.cbegin()), ' ')); - } - bracket_nesting = true; - } - else if (value == ']') - { - if (!bracket_nesting) - { - Checks::exit_with_message(VCPKG_LINE_INFO, - "Found unmatched ']'. Did you forget a '['?\n" - "> '%s'\n" - "> %s^\n", - str, - std::string(static_cast<int>(iter - str.cbegin()), ' ')); - } - bracket_nesting = false; - } - - ++iter; - - // Trim ending whitespace - if (!is_whitespace(value)) - { - // Update element_end after iter is incremented so it will be one past. - element_end = iter; - } - } - - if (element_begin == element_end) + auto item = f(parser); + if (!item) return nullopt; + ret.push_back(std::move(item).value_or_exit(VCPKG_LINE_INFO)); + parser.skip_whitespace(); + if (parser.at_eof()) return {std::move(ret)}; + if (parser.cur() != ',') { - Checks::exit_with_message(VCPKG_LINE_INFO, - "Empty element in list\n" - "> '%s'\n" - "> %s^\n", - str, - std::string(static_cast<int>(element_begin - str.cbegin()), ' ')); + parser.add_error(Strings::concat("expected ',' or end of text in ", plural_item_name, " list")); + return nullopt; } - out.push_back({element_begin, element_end}); - - if (iter != str.cend()) - { - Checks::check_exit(VCPKG_LINE_INFO, *iter == ',', "Internal parsing error - expected comma"); + parser.next(); + parser.skip_whitespace(); + } while (true); + } - // Not at the end, must be at a comma that needs to be stepped over - ++iter; + ExpectedS<std::vector<std::string>> parse_default_features_list(const std::string& str, CStringView origin) + { + Parse::ParserBase parser; + parser.init(str, origin); + auto opt = parse_list_until_eof<std::string>("default features", parser, &parse_feature_name); + if (!opt) return {parser.get_error()->format(), expected_right_tag}; + return {std::move(opt).value_or_exit(VCPKG_LINE_INFO), expected_left_tag}; + } + ExpectedS<std::vector<ParsedQualifiedSpecifier>> parse_qualified_specifier_list(const std::string& str, + CStringView origin) + { + Parse::ParserBase parser; + parser.init(str, origin); + auto opt = parse_list_until_eof<ParsedQualifiedSpecifier>( + "dependencies", parser, [](ParserBase& parser) { return parse_qualified_specifier(parser); }); + if (!opt) return {parser.get_error()->format(), expected_right_tag}; - if (iter == str.end()) + return {std::move(opt).value_or_exit(VCPKG_LINE_INFO), expected_left_tag}; + } + ExpectedS<std::vector<Dependency>> parse_dependencies_list(const std::string& str, CStringView origin) + { + Parse::ParserBase parser; + parser.init(str, origin); + auto opt = parse_list_until_eof<Dependency>("dependencies", parser, [](ParserBase& parser) { + auto loc = parser.cur_loc(); + return parse_qualified_specifier(parser).then([&](ParsedQualifiedSpecifier&& pqs) -> Optional<Dependency> { + if (pqs.triplet) { - Checks::exit_with_message(VCPKG_LINE_INFO, - "Empty element in list\n" - "> '%s'\n" - "> %s^\n", - str, - std::string(str.length(), ' ')); + parser.add_error("triplet specifier not allowed in this context", loc); + return nullopt; } - } - - } while (iter != str.cend()); + return Dependency{{pqs.name, pqs.features.value_or({})}, pqs.qualifier.value_or({})}; + }); + }); + if (!opt) return {parser.get_error()->format(), expected_right_tag}; - return out; + return {std::move(opt).value_or_exit(VCPKG_LINE_INFO), expected_left_tag}; } } diff --git a/toolsrc/src/vcpkg/portfileprovider.cpp b/toolsrc/src/vcpkg/portfileprovider.cpp index 04ab918df..e43fa862a 100644 --- a/toolsrc/src/vcpkg/portfileprovider.cpp +++ b/toolsrc/src/vcpkg/portfileprovider.cpp @@ -11,10 +11,10 @@ namespace vcpkg::PortFileProvider { } - Optional<const SourceControlFileLocation&> MapPortFileProvider::get_control_file(const std::string& spec) const + ExpectedS<const SourceControlFileLocation&> MapPortFileProvider::get_control_file(const std::string& spec) const { auto scf = ports.find(spec); - if (scf == ports.end()) return nullopt; + if (scf == ports.end()) return std::string("does not exist in map"); return scf->second; } @@ -53,7 +53,7 @@ namespace vcpkg::PortFileProvider ports_dirs.emplace_back(paths.ports); } - Optional<const SourceControlFileLocation&> PathsPortFileProvider::get_control_file(const std::string& spec) const + ExpectedS<const SourceControlFileLocation&> PathsPortFileProvider::get_control_file(const std::string& spec) const { auto cache_it = cache.find(spec); if (cache_it != cache.end()) @@ -84,8 +84,7 @@ namespace vcpkg::PortFileProvider VCPKG_LINE_INFO, "Error: Failed to load port from %s", spec, ports_dir.u8string()); } } - - if (filesystem.exists(ports_dir / spec / "CONTROL")) + else if (filesystem.exists(ports_dir / spec / "CONTROL")) { auto found_scf = Paragraphs::try_load_port(filesystem, ports_dir / spec); if (auto scf = found_scf.get()) @@ -112,7 +111,7 @@ namespace vcpkg::PortFileProvider } } - return nullopt; + return std::string("Port definition not found"); } std::vector<const SourceControlFileLocation*> PathsPortFileProvider::load_all_control_files() const diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 1bcfe58a0..e1a03b808 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -214,7 +214,7 @@ namespace vcpkg::Remove &valid_arguments, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) { const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp index 26681e107..e4d9ffc63 100644 --- a/toolsrc/src/vcpkg/sourceparagraph.cpp +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -52,14 +52,10 @@ namespace vcpkg for (auto&& error_info : error_info_list) { Checks::check_exit(VCPKG_LINE_INFO, error_info != nullptr); - if (error_info->error) + if (!error_info->error.empty()) { - System::print2(System::Color::error, - "Error: while loading ", - error_info->name, - ": ", - error_info->error.message(), - '\n'); + System::print2( + System::Color::error, "Error: while loading ", error_info->name, ":\n", error_info->error, '\n'); } } @@ -131,9 +127,11 @@ namespace vcpkg spgh->description = parser.optional_field(SourceParagraphFields::DESCRIPTION); spgh->maintainer = parser.optional_field(SourceParagraphFields::MAINTAINER); spgh->homepage = parser.optional_field(SourceParagraphFields::HOMEPAGE); - spgh->depends = expand_qualified_dependencies( - parse_comma_list(parser.optional_field(SourceParagraphFields::BUILD_DEPENDS))); - spgh->default_features = parse_comma_list(parser.optional_field(SourceParagraphFields::DEFAULTFEATURES)); + spgh->depends = parse_dependencies_list(parser.optional_field(SourceParagraphFields::BUILD_DEPENDS)) + .value_or_exit(VCPKG_LINE_INFO); + spgh->default_features = + parse_default_features_list(parser.optional_field(SourceParagraphFields::DEFAULTFEATURES)) + .value_or_exit(VCPKG_LINE_INFO); spgh->supports_expression = parser.optional_field(SourceParagraphFields::SUPPORTS); spgh->type = Type::from_string(parser.optional_field(SourceParagraphFields::TYPE)); auto err = parser.error_info(spgh->name.empty() ? path_to_control.u8string() : spgh->name); @@ -153,8 +151,8 @@ namespace vcpkg parser.required_field(SourceParagraphFields::FEATURE, fpgh->name); parser.required_field(SourceParagraphFields::DESCRIPTION, fpgh->description); - fpgh->depends = expand_qualified_dependencies( - parse_comma_list(parser.optional_field(SourceParagraphFields::BUILD_DEPENDS))); + fpgh->depends = parse_dependencies_list(parser.optional_field(SourceParagraphFields::BUILD_DEPENDS)) + .value_or_exit(VCPKG_LINE_INFO); auto err = parser.error_info(fpgh->name.empty() ? path_to_control.u8string() : fpgh->name); if (err) @@ -217,69 +215,8 @@ namespace vcpkg return nullopt; } - Dependency Dependency::parse_dependency(std::string name, std::string qualifier) - { - Dependency dep; - dep.qualifier = qualifier; - if (auto maybe_features = Features::from_string(name)) - dep.depend = *maybe_features.get(); - else - Checks::exit_with_message( - VCPKG_LINE_INFO, "error while parsing dependency: %s: %s", to_string(maybe_features.error()), name); - return dep; - } - - std::string Dependency::name() const - { - if (this->depend.features.empty()) return this->depend.name; - - const std::string features = Strings::join(",", this->depend.features); - return Strings::format("%s[%s]", this->depend.name, features); - } - - std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends) - { - return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { - // First, try to find beginning and end of features list - auto end_of_features = depend_string.find(']'); - if (end_of_features != std::string::npos) - { - ++end_of_features; - } - else - { - end_of_features = depend_string.find(' '); - if (end_of_features == std::string::npos) end_of_features = depend_string.size(); - } - - auto begin_of_qualifier = depend_string.find('(', end_of_features); - if (begin_of_qualifier == std::string::npos) - { - return Dependency::parse_dependency(depend_string.substr(0, end_of_features), ""); - } - else - { - int depth = 1; - auto i = begin_of_qualifier + 1; - for (; i != depend_string.size(); ++i) - { - auto ch = depend_string[i]; - if (ch == '(') - ++depth; - else if (ch == ')') - --depth; - - if (depth == 0) break; - } - return Dependency::parse_dependency( - depend_string.substr(0, end_of_features), - depend_string.substr(begin_of_qualifier + 1, i - begin_of_qualifier - 1)); - } - }); - } - std::vector<FullPackageSpec> filter_dependencies(const std::vector<vcpkg::Dependency>& deps, - const Triplet& t, + Triplet t, const std::unordered_map<std::string, std::string>& cmake_vars) { std::vector<FullPackageSpec> ret; @@ -289,13 +226,9 @@ namespace vcpkg if (qualifier.empty() || evaluate_expression(qualifier, {cmake_vars, t.canonical_name()}).value_or_exit(VCPKG_LINE_INFO)) { - ret.emplace_back(FullPackageSpec( - PackageSpec::from_name_and_triplet(dep.depend.name, t).value_or_exit(VCPKG_LINE_INFO), - dep.depend.features)); + ret.emplace_back(FullPackageSpec({dep.depend.name, t}, dep.depend.features)); } } return ret; } - - std::string to_string(const Dependency& dep) { return dep.name(); } } diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp index c0ecca3a0..144d079ec 100644 --- a/toolsrc/src/vcpkg/statusparagraph.cpp +++ b/toolsrc/src/vcpkg/statusparagraph.cpp @@ -88,27 +88,14 @@ namespace vcpkg std::unordered_map<std::string, std::vector<FeatureSpec>> InstalledPackageView::feature_dependencies() const { - auto extract_deps = [&](const std::string& dep) { - FullPackageSpec dependency = - FullPackageSpec::from_string(dep, spec().triplet()).value_or_exit(VCPKG_LINE_INFO); - std::vector<FeatureSpec> fspecs; - - for (std::string& feature : dependency.features) - { - fspecs.emplace_back(dependency.package_spec, std::move(feature)); - } - - return fspecs; - }; + auto extract_deps = [&](const std::string& name) { return FeatureSpec{{name, spec().triplet()}, "core"}; }; std::unordered_map<std::string, std::vector<FeatureSpec>> deps; - for (const StatusParagraph* const& feature : features) - { - deps.emplace(feature->package.feature, Util::fmap_flatten(feature->package.depends, extract_deps)); - } + deps.emplace("core", Util::fmap(core->package.depends, extract_deps)); - deps.emplace("core", Util::fmap_flatten(core->package.depends, extract_deps)); + for (const StatusParagraph* const& feature : features) + deps.emplace(feature->package.feature, Util::fmap(feature->package.depends, extract_deps)); return deps; } @@ -117,40 +104,18 @@ namespace vcpkg { // accumulate all features in installed dependencies // Todo: make this unneeded by collapsing all package dependencies into the core package - auto deps = Util::fmap_flatten(features, [](const StatusParagraph* pgh) -> std::vector<std::string> const& { - return pgh->package.depends; - }); + std::vector<std::string> deps; + for (auto&& feature : features) + for (auto&& dep : feature->package.depends) + deps.push_back(dep); // Add the core paragraph dependencies to the list - deps.insert(deps.end(), core->package.depends.begin(), core->package.depends.end()); - - auto&& l_spec = spec(); + for (auto&& dep : core->package.depends) + deps.push_back(dep); - // <hack> - // This is a hack to work around existing installations that put featurespecs into binary packages - // (example: curl[core]) - for (auto&& dep : deps) - { - dep.erase(std::find(dep.begin(), dep.end(), '['), dep.end()); - } - Util::erase_remove_if(deps, [&](auto&& e) { return e == l_spec.name(); }); - // </hack> + Util::erase_remove_if(deps, [&](const std::string& pspec) { return pspec == spec().name(); }); Util::sort_unique_erase(deps); - return Util::fmap(deps, [&](const std::string& dep) -> PackageSpec { - auto maybe_dependency_spec = PackageSpec::from_name_and_triplet(dep, l_spec.triplet()); - if (auto dependency_spec = maybe_dependency_spec.get()) - { - return std::move(*dependency_spec); - } - - const PackageSpecParseResult error_type = maybe_dependency_spec.error(); - Checks::exit_with_message(VCPKG_LINE_INFO, - "Invalid dependency [%s] in package [%s]\n" - "%s", - dep, - l_spec.name(), - vcpkg::to_string(error_type)); - }); + return PackageSpec::to_package_specs(deps, spec().triplet()); } } diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index 2fa9df7df..2621c43e3 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -11,8 +11,7 @@ namespace vcpkg { } - std::vector<std::unique_ptr<StatusParagraph>*> StatusParagraphs::find_all(const std::string& name, - const Triplet& triplet) + std::vector<std::unique_ptr<StatusParagraph>*> StatusParagraphs::find_all(const std::string& name, Triplet triplet) { std::vector<std::unique_ptr<StatusParagraph>*> spghs; for (auto&& p : *this) @@ -52,7 +51,7 @@ namespace vcpkg } StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, - const Triplet& triplet, + Triplet triplet, const std::string& feature) { if (feature == "core") @@ -67,7 +66,7 @@ namespace vcpkg } StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name, - const Triplet& triplet, + Triplet triplet, const std::string& feature) const { if (feature == "core") diff --git a/toolsrc/src/vcpkg/triplet.cpp b/toolsrc/src/vcpkg/triplet.cpp index 1abfa0b39..4bc684d0b 100644 --- a/toolsrc/src/vcpkg/triplet.cpp +++ b/toolsrc/src/vcpkg/triplet.cpp @@ -39,10 +39,6 @@ namespace vcpkg const Triplet Triplet::ARM_WINDOWS = from_canonical_name("arm-windows"); const Triplet Triplet::ARM64_WINDOWS = from_canonical_name("arm64-windows"); - bool Triplet::operator==(const Triplet& other) const { return this->m_instance == other.m_instance; } - - bool operator!=(const Triplet& left, const Triplet& right) { return !(left == right); } - Triplet Triplet::from_canonical_name(std::string&& triplet_as_string) { std::string s(Strings::ascii_to_lowercase(std::move(triplet_as_string))); diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 692cf1634..98be491e3 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -129,7 +129,7 @@ namespace vcpkg return this->vcpkg_dir_info / (pgh.fullstem() + ".list"); } - bool VcpkgPaths::is_valid_triplet(const Triplet& t) const + bool VcpkgPaths::is_valid_triplet(Triplet t) const { const auto it = Util::find_if(this->get_available_triplets(), [&](auto&& available_triplet) { return t.canonical_name() == available_triplet.name; @@ -162,7 +162,7 @@ namespace vcpkg }); } - const fs::path VcpkgPaths::get_triplet_file_path(const Triplet& triplet) const + const fs::path VcpkgPaths::get_triplet_file_path(Triplet triplet) const { return m_triplets_cache.get_lazy( triplet, [&]() -> auto { diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj b/toolsrc/vcpkglib/vcpkglib.vcxproj index 5119c5833..e033625a0 100644 --- a/toolsrc/vcpkglib/vcpkglib.vcxproj +++ b/toolsrc/vcpkglib/vcpkglib.vcxproj @@ -171,26 +171,32 @@ <ClInclude Include="..\include\vcpkg\base\zstringview.h" />
<ClInclude Include="..\include\vcpkg\binaryparagraph.h" />
<ClInclude Include="..\include\vcpkg\build.h" />
+ <ClInclude Include="..\include\vcpkg\cmakevars.h" />
<ClInclude Include="..\include\vcpkg\commands.h" />
<ClInclude Include="..\include\vcpkg\dependencies.h" />
+ <ClInclude Include="..\include\vcpkg\export.chocolatey.h" />
<ClInclude Include="..\include\vcpkg\export.h" />
<ClInclude Include="..\include\vcpkg\export.ifw.h" />
<ClInclude Include="..\include\vcpkg\globalstate.h" />
<ClInclude Include="..\include\vcpkg\help.h" />
<ClInclude Include="..\include\vcpkg\input.h" />
<ClInclude Include="..\include\vcpkg\install.h" />
+ <ClInclude Include="..\include\vcpkg\logicexpression.h" />
<ClInclude Include="..\include\vcpkg\metrics.h" />
<ClInclude Include="..\include\vcpkg\packagespec.h" />
- <ClInclude Include="..\include\vcpkg\packagespecparseresult.h" />
+ <ClInclude Include="..\include\vcpkg\paragraphparser.h" />
<ClInclude Include="..\include\vcpkg\paragraphparseresult.h" />
<ClInclude Include="..\include\vcpkg\paragraphs.h" />
<ClInclude Include="..\include\vcpkg\parse.h" />
+ <ClInclude Include="..\include\vcpkg\portfileprovider.h" />
<ClInclude Include="..\include\vcpkg\postbuildlint.h" />
<ClInclude Include="..\include\vcpkg\postbuildlint.buildtype.h" />
+ <ClInclude Include="..\include\vcpkg\pragmas.h" />
<ClInclude Include="..\include\vcpkg\remove.h" />
<ClInclude Include="..\include\vcpkg\sourceparagraph.h" />
<ClInclude Include="..\include\vcpkg\statusparagraph.h" />
<ClInclude Include="..\include\vcpkg\statusparagraphs.h" />
+ <ClInclude Include="..\include\vcpkg\textrowcol.h" />
<ClInclude Include="..\include\vcpkg\tools.h" />
<ClInclude Include="..\include\vcpkg\triplet.h" />
<ClInclude Include="..\include\vcpkg\update.h" />
@@ -255,7 +261,6 @@ <ClCompile Include="..\src\vcpkg\logicexpression.cpp" />
<ClCompile Include="..\src\vcpkg\metrics.cpp" />
<ClCompile Include="..\src\vcpkg\packagespec.cpp" />
- <ClCompile Include="..\src\vcpkg\packagespecparseresult.cpp" />
<ClCompile Include="..\src\vcpkg\paragraphparseresult.cpp" />
<ClCompile Include="..\src\vcpkg\paragraphs.cpp" />
<ClCompile Include="..\src\vcpkg\parse.cpp" />
diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters index 043a9a22f..d7adfcdfd 100644 --- a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters +++ b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters @@ -120,9 +120,6 @@ <ClCompile Include="..\src\vcpkg\packagespec.cpp">
<Filter>Source Files\vcpkg</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg\packagespecparseresult.cpp">
- <Filter>Source Files\vcpkg</Filter>
- </ClCompile>
<ClCompile Include="..\src\vcpkg\paragraphparseresult.cpp">
<Filter>Source Files\vcpkg</Filter>
</ClCompile>
@@ -226,10 +223,10 @@ <Filter>Source Files\vcpkg</Filter>
</ClCompile>
<ClCompile Include="..\src\vcpkg\cmakevars.cpp">
- <Filter>Source Files</Filter>
+ <Filter>Source Files\vcpkg</Filter>
</ClCompile>
<ClCompile Include="..\src\vcpkg\portfileprovider.cpp">
- <Filter>Source Files</Filter>
+ <Filter>Source Files\vcpkg</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -320,9 +317,6 @@ <ClInclude Include="..\include\vcpkg\packagespec.h">
<Filter>Header Files\vcpkg</Filter>
</ClInclude>
- <ClInclude Include="..\include\vcpkg\packagespecparseresult.h">
- <Filter>Header Files\vcpkg</Filter>
- </ClInclude>
<ClInclude Include="..\include\vcpkg\paragraphparseresult.h">
<Filter>Header Files\vcpkg</Filter>
</ClInclude>
@@ -416,5 +410,26 @@ <ClInclude Include="..\include\vcpkg\base\zstringview.h">
<Filter>Header Files\vcpkg\base</Filter>
</ClInclude>
+ <ClInclude Include="..\include\vcpkg\cmakevars.h">
+ <Filter>Header Files\vcpkg</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg\export.chocolatey.h">
+ <Filter>Header Files\vcpkg</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg\logicexpression.h">
+ <Filter>Header Files\vcpkg</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg\paragraphparser.h">
+ <Filter>Header Files\vcpkg</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg\portfileprovider.h">
+ <Filter>Header Files\vcpkg</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg\pragmas.h">
+ <Filter>Header Files\vcpkg</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg\textrowcol.h">
+ <Filter>Header Files\vcpkg</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file |
