aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Schumacher <roschuma@microsoft.com>2017-06-19 15:09:54 -0700
committerRobert Schumacher <roschuma@microsoft.com>2017-06-19 15:09:54 -0700
commit34c08e2b15777c86c5aaacfee5f04eed986c62da (patch)
tree5a65eed065343bcb2f999da6937d423fff00c93e
parent8d955c83b53d42983ebd9a046a0a0a5ade08537f (diff)
parentbca0988023a8c7bfc896d0f5787eb02e74c6fb59 (diff)
downloadvcpkg-34c08e2b15777c86c5aaacfee5f04eed986c62da.tar.gz
vcpkg-34c08e2b15777c86c5aaacfee5f04eed986c62da.zip
Merge branch 'feature_package_implementation'
-rw-r--r--toolsrc/include/PackageSpec.h6
-rw-r--r--toolsrc/include/Paragraphs.h8
-rw-r--r--toolsrc/include/SourceParagraph.h27
-rw-r--r--toolsrc/include/vcpkg_Commands.h2
-rw-r--r--toolsrc/include/vcpkg_Input.h3
-rw-r--r--toolsrc/include/vcpkg_Strings.h2
-rw-r--r--toolsrc/src/Paragraphs.cpp21
-rw-r--r--toolsrc/src/SourceParagraph.cpp62
-rw-r--r--toolsrc/src/VcpkgCmdArguments.cpp5
-rw-r--r--toolsrc/src/commands_build.cpp32
-rw-r--r--toolsrc/src/commands_build_external.cpp6
-rw-r--r--toolsrc/src/commands_ci.cpp6
-rw-r--r--toolsrc/src/commands_depends.cpp5
-rw-r--r--toolsrc/src/commands_portsdiff.cpp4
-rw-r--r--toolsrc/src/commands_search.cpp61
-rw-r--r--toolsrc/src/commands_update.cpp4
-rw-r--r--toolsrc/src/tests_paragraph.cpp116
-rw-r--r--toolsrc/src/vcpkg_Dependencies.cpp16
-rw-r--r--toolsrc/src/vcpkg_Input.cpp34
-rw-r--r--toolsrc/src/vcpkg_Strings.cpp5
20 files changed, 300 insertions, 125 deletions
diff --git a/toolsrc/include/PackageSpec.h b/toolsrc/include/PackageSpec.h
index 58edb8274..62b6fc9de 100644
--- a/toolsrc/include/PackageSpec.h
+++ b/toolsrc/include/PackageSpec.h
@@ -26,6 +26,12 @@ namespace vcpkg
Triplet m_triplet;
};
+ struct FullPackageSpec
+ {
+ PackageSpec package_spec;
+ std::vector<std::string> features;
+ };
+
bool operator==(const PackageSpec& left, const PackageSpec& right);
bool operator!=(const PackageSpec& left, const PackageSpec& right);
}
diff --git a/toolsrc/include/Paragraphs.h b/toolsrc/include/Paragraphs.h
index 04f9fb879..83a32b2af 100644
--- a/toolsrc/include/Paragraphs.h
+++ b/toolsrc/include/Paragraphs.h
@@ -16,20 +16,20 @@ namespace vcpkg::Paragraphs
Expected<ParagraphDataMap> parse_single_paragraph(const std::string& str);
Expected<std::vector<ParagraphDataMap>> parse_paragraphs(const std::string& str);
- ExpectedT<SourceParagraph, ParseControlErrorInfo> try_load_port(const Files::Filesystem& fs,
- const fs::path& control_path);
+ ExpectedT<SourceControlFile, ParseControlErrorInfo> try_load_port(const Files::Filesystem& fs,
+ const fs::path& control_path);
Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec);
struct LoadResults
{
- std::vector<SourceParagraph> paragraphs;
+ std::vector<SourceControlFile> paragraphs;
std::vector<ParseControlErrorInfo> errors;
};
LoadResults try_load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir);
- std::vector<SourceParagraph> load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir);
+ std::vector<SourceControlFile> load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir);
std::map<std::string, VersionT> extract_port_names_and_versions(
const std::vector<SourceParagraph>& source_paragraphs);
diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h
index 2f30e338e..31c9560cc 100644
--- a/toolsrc/include/SourceParagraph.h
+++ b/toolsrc/include/SourceParagraph.h
@@ -10,6 +10,8 @@
namespace vcpkg
{
+ extern bool g_feature_packages;
+
struct Triplet;
struct Dependency
@@ -27,23 +29,38 @@ namespace vcpkg
std::error_code error;
};
+ struct FeatureParagraph
+ {
+ std::string name;
+ std::string description;
+ std::vector<Dependency> depends;
+ };
+
/// <summary>
/// Port metadata (CONTROL file)
/// </summary>
struct SourceParagraph
{
- static ExpectedT<SourceParagraph, ParseControlErrorInfo> parse_control_file(
- std::unordered_map<std::string, std::string> fields);
-
- SourceParagraph() = default;
-
std::string name;
std::string version;
std::string description;
std::string maintainer;
std::vector<std::string> supports;
std::vector<Dependency> depends;
+ std::string default_features;
};
+ struct SourceControlFile
+ {
+ static ExpectedT<SourceControlFile, ParseControlErrorInfo> parse_control_file(
+ std::vector<std::unordered_map<std::string, std::string>>&& control_paragraphs);
+
+ SourceParagraph core_paragraph;
+ std::vector<std::unique_ptr<FeatureParagraph>> feature_paragraphs;
+
+ std::vector<ParseControlErrorInfo> errors;
+ };
+
+ std::vector<SourceParagraph> getSourceParagraphs(const std::vector<SourceControlFile>& control_files);
void print_error_message(span<const ParseControlErrorInfo> error_info_list);
inline void print_error_message(const ParseControlErrorInfo& error_info_list)
diff --git a/toolsrc/include/vcpkg_Commands.h b/toolsrc/include/vcpkg_Commands.h
index 006971e47..67319f240 100644
--- a/toolsrc/include/vcpkg_Commands.h
+++ b/toolsrc/include/vcpkg_Commands.h
@@ -18,7 +18,7 @@ namespace vcpkg::Commands
namespace BuildCommand
{
- void perform_and_exit(const PackageSpec& spec,
+ void perform_and_exit(const FullPackageSpec& full_spec,
const fs::path& port_dir,
const std::unordered_set<std::string>& options,
const VcpkgPaths& paths);
diff --git a/toolsrc/include/vcpkg_Input.h b/toolsrc/include/vcpkg_Input.h
index 77f7ecfb5..fa568207a 100644
--- a/toolsrc/include/vcpkg_Input.h
+++ b/toolsrc/include/vcpkg_Input.h
@@ -6,6 +6,9 @@ namespace vcpkg::Input
PackageSpec check_and_get_package_spec(const std::string& package_spec_as_string,
const Triplet& default_triplet,
CStringView example_text);
+ FullPackageSpec check_and_get_full_package_spec(const std::string& full_package_spec_as_string,
+ const Triplet& default_triplet,
+ CStringView example_text);
void check_triplet(const Triplet& t, const VcpkgPaths& paths);
}
diff --git a/toolsrc/include/vcpkg_Strings.h b/toolsrc/include/vcpkg_Strings.h
index e95a0601a..325a2cb4c 100644
--- a/toolsrc/include/vcpkg_Strings.h
+++ b/toolsrc/include/vcpkg_Strings.h
@@ -54,6 +54,8 @@ namespace vcpkg::Strings
std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern);
+ bool case_insensitive_ascii_contains(const std::string& s, const std::string& pattern);
+
int case_insensitive_ascii_compare(const CStringView left, const CStringView right);
std::string ascii_to_lowercase(const std::string& input);
diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp
index 31e8f1da3..440d04ce4 100644
--- a/toolsrc/src/Paragraphs.cpp
+++ b/toolsrc/src/Paragraphs.cpp
@@ -201,13 +201,22 @@ namespace vcpkg::Paragraphs
return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs();
}
- ExpectedT<SourceParagraph, ParseControlErrorInfo> try_load_port(const Files::Filesystem& fs, const fs::path& path)
+ ExpectedT<SourceControlFile, ParseControlErrorInfo> try_load_port(const Files::Filesystem& fs, const fs::path& path)
{
ParseControlErrorInfo error_info;
- Expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(fs, path / "CONTROL");
- if (auto p = pghs.get())
+ Expected<std::vector<std::unordered_map<std::string, std::string>>> pghs = get_paragraphs(fs, path / "CONTROL");
+ if (auto vector_pghs = pghs.get())
{
- return SourceParagraph::parse_control_file(*p);
+ auto csf = SourceControlFile::parse_control_file(std::move(*vector_pghs));
+ if (!g_feature_packages)
+ {
+ if (auto ptr = csf.get())
+ {
+ ptr->core_paragraph.default_features.clear();
+ ptr->feature_paragraphs.clear();
+ }
+ }
+ return csf;
}
error_info.name = path.filename().generic_u8string();
error_info.error = pghs.error();
@@ -232,7 +241,7 @@ namespace vcpkg::Paragraphs
LoadResults ret;
for (auto&& path : fs.get_files_non_recursive(ports_dir))
{
- ExpectedT<SourceParagraph, ParseControlErrorInfo> source_paragraph = try_load_port(fs, path);
+ ExpectedT<SourceControlFile, ParseControlErrorInfo> source_paragraph = try_load_port(fs, path);
if (auto srcpgh = source_paragraph.get())
{
ret.paragraphs.emplace_back(std::move(*srcpgh));
@@ -245,7 +254,7 @@ namespace vcpkg::Paragraphs
return ret;
}
- std::vector<SourceParagraph> load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir)
+ std::vector<SourceControlFile> load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir)
{
auto results = try_load_all_ports(fs, ports_dir);
if (!results.errors.empty())
diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp
index 3b770a4b4..a938feb99 100644
--- a/toolsrc/src/SourceParagraph.cpp
+++ b/toolsrc/src/SourceParagraph.cpp
@@ -12,7 +12,7 @@
namespace vcpkg
{
- //
+ bool g_feature_packages = false;
namespace SourceParagraphRequiredField
{
static const std::string SOURCE = "Source";
@@ -25,6 +25,7 @@ namespace vcpkg
static const std::string MAINTAINER = "Maintainer";
static const std::string BUILD_DEPENDS = "Build-Depends";
static const std::string SUPPORTS = "Supports";
+ static const std::string DEFAULTFEATURES = "Default-Features";
}
static span<const std::string> get_list_of_valid_fields()
@@ -40,6 +41,17 @@ namespace vcpkg
return valid_fields;
}
+ namespace FeatureParagraphRequiredField
+ {
+ static const std::string FEATURE = "Feature";
+ }
+
+ namespace FeatureParagraphOptionalField
+ {
+ static const std::string DESCRIPTION = "Description";
+ static const std::string BUILD_DEPENDS = "Build-Depends";
+ }
+
void print_error_message(span<const ParseControlErrorInfo> error_info_list)
{
Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0);
@@ -74,11 +86,22 @@ namespace vcpkg
System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n");
}
}
+ std::vector<SourceParagraph> getSourceParagraphs(const std::vector<SourceControlFile>& control_files)
+ {
+ return Util::fmap(control_files, [](const SourceControlFile& x) { return x.core_paragraph; });
+ }
- ExpectedT<SourceParagraph, ParseControlErrorInfo> SourceParagraph::parse_control_file(
- std::unordered_map<std::string, std::string> fields)
+ ExpectedT<SourceControlFile, ParseControlErrorInfo> SourceControlFile::parse_control_file(
+ std::vector<std::unordered_map<std::string, std::string>>&& control_paragraphs)
{
- SourceParagraph sparagraph;
+ if (control_paragraphs.size() == 0)
+ {
+ return ExpectedT<SourceControlFile, ParseControlErrorInfo>();
+ }
+ auto&& fields = control_paragraphs.front();
+
+ SourceControlFile control_file;
+ SourceParagraph& sparagraph = control_file.core_paragraph;
sparagraph.name = details::remove_required_field(&fields, SourceParagraphRequiredField::SOURCE);
sparagraph.version = details::remove_required_field(&fields, SourceParagraphRequiredField::VERSION);
sparagraph.description = details::remove_optional_field(&fields, SourceParagraphOptionalField::DESCRIPTION);
@@ -90,6 +113,9 @@ namespace vcpkg
std::string sups = details::remove_optional_field(&fields, SourceParagraphOptionalField::SUPPORTS);
sparagraph.supports = parse_comma_list(sups);
+ sparagraph.default_features =
+ details::remove_optional_field(&fields, SourceParagraphOptionalField::DEFAULTFEATURES);
+
if (!fields.empty())
{
const std::vector<std::string> remaining_fields = Maps::extract_keys(fields);
@@ -98,7 +124,33 @@ namespace vcpkg
return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string};
}
- return sparagraph;
+
+ control_paragraphs.erase(control_paragraphs.begin());
+
+ for (auto&& feature_pgh : control_paragraphs)
+ {
+ control_file.feature_paragraphs.emplace_back(std::make_unique<FeatureParagraph>());
+
+ FeatureParagraph& fparagraph = *control_file.feature_paragraphs.back();
+
+ fparagraph.name = details::remove_required_field(&feature_pgh, FeatureParagraphRequiredField::FEATURE);
+ fparagraph.description =
+ details::remove_required_field(&feature_pgh, FeatureParagraphOptionalField::DESCRIPTION);
+ std::string feature_deps =
+ details::remove_optional_field(&feature_pgh, FeatureParagraphOptionalField::BUILD_DEPENDS);
+ fparagraph.depends = expand_qualified_dependencies(parse_comma_list(feature_deps));
+
+ if (!feature_pgh.empty())
+ {
+ const std::vector<std::string> remaining_fields = Maps::extract_keys(feature_pgh);
+
+ const std::string remaining_fields_as_string = Strings::join("\n ", remaining_fields);
+
+ return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string};
+ }
+ }
+
+ return control_file;
}
std::vector<Dependency> vcpkg::expand_qualified_dependencies(const std::vector<std::string>& depends)
diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp
index 733308cb0..62e0b114c 100644
--- a/toolsrc/src/VcpkgCmdArguments.cpp
+++ b/toolsrc/src/VcpkgCmdArguments.cpp
@@ -117,6 +117,11 @@ namespace vcpkg
parse_switch(false, "printmetrics", args.printmetrics);
continue;
}
+ if (arg == "--featurepackages")
+ {
+ g_feature_packages = true;
+ continue;
+ }
args.optional_command_arguments.insert(arg);
continue;
diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp
index 5a5cd462e..a9e4f574e 100644
--- a/toolsrc/src/commands_build.cpp
+++ b/toolsrc/src/commands_build.cpp
@@ -19,11 +19,12 @@ namespace vcpkg::Commands::BuildCommand
static const std::string OPTION_CHECKS_ONLY = "--checks-only";
- void perform_and_exit(const PackageSpec& spec,
+ void perform_and_exit(const FullPackageSpec& full_spec,
const fs::path& port_dir,
const std::unordered_set<std::string>& options,
const VcpkgPaths& paths)
{
+ const PackageSpec& spec = full_spec.package_spec;
if (options.find(OPTION_CHECKS_ONLY) != options.end())
{
auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet());
@@ -33,25 +34,32 @@ namespace vcpkg::Commands::BuildCommand
Checks::exit_success(VCPKG_LINE_INFO);
}
- const ExpectedT<SourceParagraph, ParseControlErrorInfo> maybe_spgh =
+ const ExpectedT<SourceControlFile, ParseControlErrorInfo> source_control_file =
Paragraphs::try_load_port(paths.get_filesystem(), port_dir);
- if (!maybe_spgh)
+ if (!source_control_file.has_value())
{
- print_error_message(maybe_spgh.error());
+ print_error_message(source_control_file.error());
Checks::exit_fail(VCPKG_LINE_INFO);
}
- const SourceParagraph& spgh = maybe_spgh.value_or_exit(VCPKG_LINE_INFO);
+ for (std::string str : full_spec.features)
+ {
+ System::println("%s \n", str);
+ }
+ const SourceControlFile& scf = source_control_file.value_or_exit(VCPKG_LINE_INFO);
Checks::check_exit(VCPKG_LINE_INFO,
- spec.name() == spgh.name,
+ spec.name() == scf.core_paragraph.name,
"The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'",
- spgh.name,
+ scf.core_paragraph.name,
spec.name());
StatusParagraphs status_db = database_load_check(paths);
Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES};
- const Build::BuildPackageConfig build_config{spgh, spec.triplet(), paths.port_dir(spec), build_package_options};
+
+ const Build::BuildPackageConfig build_config{
+ scf.core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options};
+
const auto result = Build::build_package(paths, build_config, status_db);
if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES)
{
@@ -82,11 +90,11 @@ namespace vcpkg::Commands::BuildCommand
static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows");
args.check_exact_arg_count(
1, example); // Build only takes a single package and all dependencies must already be installed
- const PackageSpec spec =
- Input::check_and_get_package_spec(args.command_arguments.at(0), default_triplet, example);
- Input::check_triplet(spec.triplet(), paths);
+ std::string command_argument = args.command_arguments.at(0);
+ const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, example);
+ Input::check_triplet(spec.package_spec.triplet(), paths);
const std::unordered_set<std::string> options =
args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY});
- perform_and_exit(spec, paths.port_dir(spec), options, paths);
+ perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths);
}
}
diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp
index 2712ba0cf..ff70e9cf2 100644
--- a/toolsrc/src/commands_build_external.cpp
+++ b/toolsrc/src/commands_build_external.cpp
@@ -11,9 +11,9 @@ namespace vcpkg::Commands::BuildExternal
static const std::string example =
Commands::Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)");
args.check_exact_arg_count(2, example);
- const PackageSpec spec =
- Input::check_and_get_package_spec(args.command_arguments.at(0), default_triplet, example);
- Input::check_triplet(spec.triplet(), paths);
+ const FullPackageSpec spec =
+ Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, example);
+ Input::check_triplet(spec.package_spec.triplet(), paths);
const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({});
const fs::path port_dir = args.command_arguments.at(1);
diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp
index 7e724f3ee..65e44e847 100644
--- a/toolsrc/src/commands_ci.cpp
+++ b/toolsrc/src/commands_ci.cpp
@@ -20,11 +20,11 @@ namespace vcpkg::Commands::CI
const fs::path& ports_directory,
const Triplet& triplet)
{
- auto sources = Paragraphs::load_all_ports(fs, ports_directory);
-
+ auto ports = Paragraphs::load_all_ports(fs, ports_directory);
std::vector<PackageSpec> specs;
- for (const SourceParagraph& p : sources)
+ for (const SourceControlFile& control_file : ports)
{
+ const SourceParagraph& p = control_file.core_paragraph;
specs.push_back(PackageSpec::from_name_and_triplet(p.name, triplet).value_or_exit(VCPKG_LINE_INFO));
}
diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp
index 9db4b7bb1..468bf5d72 100644
--- a/toolsrc/src/commands_depends.cpp
+++ b/toolsrc/src/commands_depends.cpp
@@ -13,10 +13,11 @@ namespace vcpkg::Commands::DependInfo
args.check_exact_arg_count(0, example);
args.check_and_get_optional_command_arguments({});
- auto sources = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
+ const auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
- for (const SourceParagraph& source_paragraph : sources)
+ for (const SourceControlFile& source_control_file : source_control_files)
{
+ const SourceParagraph& source_paragraph = source_control_file.core_paragraph;
auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; });
System::println("%s: %s", source_paragraph.name, s);
}
diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp
index a614d654e..e872c394d 100644
--- a/toolsrc/src/commands_portsdiff.cpp
+++ b/toolsrc/src/commands_portsdiff.cpp
@@ -97,10 +97,10 @@ namespace vcpkg::Commands::PortsDiff
L".vcpkg-root",
git_exe.native());
System::cmd_execute_clean(cmd);
- const std::vector<SourceParagraph> source_paragraphs =
+ const std::vector<SourceControlFile> source_control_files =
Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string);
const std::map<std::string, VersionT> names_and_versions =
- Paragraphs::extract_port_names_and_versions(source_paragraphs);
+ Paragraphs::extract_port_names_and_versions(getSourceParagraphs(source_control_files));
fs.remove_all(temp_checkout_path, ec);
return names_and_versions;
}
diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp
index 0f8ebbb3b..b39d21887 100644
--- a/toolsrc/src/commands_search.cpp
+++ b/toolsrc/src/commands_search.cpp
@@ -19,15 +19,16 @@ namespace vcpkg::Commands::Search
return output;
}
- static std::string create_graph_as_string(const std::vector<SourceParagraph>& source_paragraphs)
+ static std::string create_graph_as_string(const std::vector<SourceControlFile>& source_control_files)
{
int empty_node_count = 0;
std::string s;
s.append("digraph G{ rankdir=LR; edge [minlen=3]; overlap=false;");
- for (const SourceParagraph& source_paragraph : source_paragraphs)
+ for (const SourceControlFile& source_control_file : source_control_files)
{
+ const SourceParagraph& source_paragraph = source_control_file.core_paragraph;
if (source_paragraph.depends.empty())
{
empty_node_count++;
@@ -46,10 +47,9 @@ namespace vcpkg::Commands::Search
s.append(Strings::format("empty [label=\"%d singletons...\"]; }", empty_node_count));
return s;
}
-
- static void do_print(const SourceParagraph& source_paragraph, bool FullDesc)
+ static void do_print(const SourceParagraph& source_paragraph, bool full_desc)
{
- if (FullDesc)
+ if (full_desc)
{
System::println(
"%-20s %-16s %s", source_paragraph.name, source_paragraph.version, source_paragraph.description);
@@ -63,6 +63,20 @@ namespace vcpkg::Commands::Search
}
}
+ static void do_print(const std::string& name, const FeatureParagraph& feature_paragraph, bool full_desc)
+ {
+ if (full_desc)
+ {
+ System::println("%-37s %s", name + "[" + feature_paragraph.name + "]", feature_paragraph.description);
+ }
+ else
+ {
+ System::println("%-37s %s",
+ name + "[" + feature_paragraph.name + "]",
+ details::shorten_description(feature_paragraph.description));
+ }
+ }
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
static const std::string example = Strings::format(
@@ -85,7 +99,7 @@ namespace vcpkg::Commands::Search
for (auto&& error : sources_and_errors.errors)
{
System::println(
- System::Color::warning, "Warning: an error occurred while parsing '%s'\n", error.name);
+ System::Color::warning, "Warning: an error occurred while parsing '%s'", error.name);
}
System::println(System::Color::warning,
"Use '--debug' to get more information about the parse failures.\n");
@@ -93,7 +107,6 @@ namespace vcpkg::Commands::Search
}
auto& source_paragraphs = sources_and_errors.paragraphs;
-
if (options.find(OPTION_GRAPH) != options.cend())
{
const std::string graph_as_string = create_graph_as_string(source_paragraphs);
@@ -103,27 +116,41 @@ namespace vcpkg::Commands::Search
if (args.command_arguments.empty())
{
- for (const SourceParagraph& source_paragraph : source_paragraphs)
+ for (const SourceControlFile& source_control_file : source_paragraphs)
{
- do_print(source_paragraph, options.find(OPTION_FULLDESC) != options.cend());
+ do_print(source_control_file.core_paragraph, options.find(OPTION_FULLDESC) != options.cend());
+ for (auto&& feature_paragraph : source_control_file.feature_paragraphs)
+ {
+ do_print(source_control_file.core_paragraph.name,
+ *feature_paragraph,
+ options.find(OPTION_FULLDESC) != options.cend());
+ }
}
}
else
{
+ const auto& icontains = Strings::case_insensitive_ascii_contains;
+
// At this point there is 1 argument
- for (const SourceParagraph& source_paragraph : source_paragraphs)
+ auto&& args_zero = args.command_arguments[0];
+ for (const SourceControlFile& source_control_file : source_paragraphs)
{
- if (Strings::case_insensitive_ascii_find(source_paragraph.name, args.command_arguments[0]) ==
- source_paragraph.name.end())
+ auto&& sp = source_control_file.core_paragraph;
+
+ bool contains_name = icontains(sp.name, args_zero);
+ if (contains_name || icontains(sp.description, args_zero))
{
- if (Strings::case_insensitive_ascii_find(source_paragraph.description, args.command_arguments[0]) ==
- source_paragraph.description.end())
+ do_print(sp, options.find(OPTION_FULLDESC) != options.cend());
+ }
+
+ for (auto&& feature_paragraph : source_control_file.feature_paragraphs)
+ {
+ if (contains_name || icontains(feature_paragraph->name, args_zero) ||
+ icontains(feature_paragraph->description, args_zero))
{
- continue;
+ do_print(sp.name, *feature_paragraph, options.find(OPTION_FULLDESC) != options.cend());
}
}
-
- do_print(source_paragraph, options.find(OPTION_FULLDESC) != options.cend());
}
}
diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp
index f87ccfb06..f00a89da4 100644
--- a/toolsrc/src/commands_update.cpp
+++ b/toolsrc/src/commands_update.cpp
@@ -15,8 +15,8 @@ namespace vcpkg::Commands::Update
std::vector<OutdatedPackage> find_outdated_packages(const VcpkgPaths& paths, const StatusParagraphs& status_db)
{
- const std::vector<SourceParagraph> source_paragraphs =
- Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
+ auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
+ const std::vector<SourceParagraph> source_paragraphs = getSourceParagraphs(source_control_files);
const std::map<std::string, VersionT> src_names_to_versions =
Paragraphs::extract_port_names_and_versions(source_paragraphs);
const std::vector<StatusParagraph*> installed_packages = get_installed_ports(status_db);
diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp
index 374e4ddd1..8dff520fb 100644
--- a/toolsrc/src/tests_paragraph.cpp
+++ b/toolsrc/src/tests_paragraph.cpp
@@ -25,99 +25,107 @@ namespace UnitTest1
{
TEST_METHOD(SourceParagraph_Construct_Minimum)
{
- auto m_pgh = vcpkg::SourceParagraph::parse_control_file({{"Source", "zlib"}, {"Version", "1.2.8"}});
+ auto m_pgh =
+ vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
+ {"Source", "zlib"}, {"Version", "1.2.8"},
+ }});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
- Assert::AreEqual("zlib", pgh.name.c_str());
- Assert::AreEqual("1.2.8", pgh.version.c_str());
- Assert::AreEqual("", pgh.maintainer.c_str());
- Assert::AreEqual("", pgh.description.c_str());
- Assert::AreEqual(size_t(0), pgh.depends.size());
+ Assert::AreEqual("zlib", pgh.core_paragraph.name.c_str());
+ Assert::AreEqual("1.2.8", pgh.core_paragraph.version.c_str());
+ Assert::AreEqual("", pgh.core_paragraph.maintainer.c_str());
+ Assert::AreEqual("", pgh.core_paragraph.description.c_str());
+ Assert::AreEqual(size_t(0), pgh.core_paragraph.depends.size());
}
TEST_METHOD(SourceParagraph_Construct_Maximum)
{
- auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
- {"Source", "s"},
- {"Version", "v"},
- {"Maintainer", "m"},
- {"Description", "d"},
- {"Build-Depends", "bd"},
- {"Supports", "x64"},
- });
+ auto m_pgh =
+ vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
+ {"Source", "s"},
+ {"Version", "v"},
+ {"Maintainer", "m"},
+ {"Description", "d"},
+ {"Build-Depends", "bd"},
+ {"Supports", "x64"},
+ }});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
- Assert::AreEqual("s", pgh.name.c_str());
- Assert::AreEqual("v", pgh.version.c_str());
- Assert::AreEqual("m", pgh.maintainer.c_str());
- Assert::AreEqual("d", pgh.description.c_str());
- Assert::AreEqual(size_t(1), pgh.depends.size());
- Assert::AreEqual("bd", pgh.depends[0].name.c_str());
- Assert::AreEqual(size_t(1), pgh.supports.size());
- Assert::AreEqual("x64", pgh.supports[0].c_str());
+ Assert::AreEqual("s", pgh.core_paragraph.name.c_str());
+ Assert::AreEqual("v", pgh.core_paragraph.version.c_str());
+ Assert::AreEqual("m", pgh.core_paragraph.maintainer.c_str());
+ Assert::AreEqual("d", pgh.core_paragraph.description.c_str());
+ Assert::AreEqual(size_t(1), pgh.core_paragraph.depends.size());
+ Assert::AreEqual("bd", pgh.core_paragraph.depends[0].name.c_str());
+ Assert::AreEqual(size_t(1), pgh.core_paragraph.supports.size());
+ Assert::AreEqual("x64", pgh.core_paragraph.supports[0].c_str());
}
TEST_METHOD(SourceParagraph_Two_Depends)
{
- auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
- {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"},
- });
+ auto m_pgh =
+ vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
+ {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"},
+ }});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
- Assert::AreEqual(size_t(2), pgh.depends.size());
- Assert::AreEqual("z", pgh.depends[0].name.c_str());
- Assert::AreEqual("openssl", pgh.depends[1].name.c_str());
+ Assert::AreEqual(size_t(2), pgh.core_paragraph.depends.size());
+ Assert::AreEqual("z", pgh.core_paragraph.depends[0].name.c_str());
+ Assert::AreEqual("openssl", pgh.core_paragraph.depends[1].name.c_str());
}
TEST_METHOD(SourceParagraph_Three_Depends)
{
- auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
- {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"},
- });
+ auto m_pgh =
+ vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
+ {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"},
+ }});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
- Assert::AreEqual(size_t(3), pgh.depends.size());
- Assert::AreEqual("z", pgh.depends[0].name.c_str());
- Assert::AreEqual("openssl", pgh.depends[1].name.c_str());
- Assert::AreEqual("xyz", pgh.depends[2].name.c_str());
+ Assert::AreEqual(size_t(3), pgh.core_paragraph.depends.size());
+ Assert::AreEqual("z", pgh.core_paragraph.depends[0].name.c_str());
+ Assert::AreEqual("openssl", pgh.core_paragraph.depends[1].name.c_str());
+ Assert::AreEqual("xyz", pgh.core_paragraph.depends[2].name.c_str());
}
TEST_METHOD(SourceParagraph_Three_Supports)
{
- auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
- {"Source", "zlib"}, {"Version", "1.2.8"}, {"Supports", "x64, windows, uwp"},
- });
+ auto m_pgh =
+ vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
+ {"Source", "zlib"}, {"Version", "1.2.8"}, {"Supports", "x64, windows, uwp"},
+ }});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
- Assert::AreEqual(size_t(3), pgh.supports.size());
- Assert::AreEqual("x64", pgh.supports[0].c_str());
- Assert::AreEqual("windows", pgh.supports[1].c_str());
- Assert::AreEqual("uwp", pgh.supports[2].c_str());
+ Assert::AreEqual(size_t(3), pgh.core_paragraph.supports.size());
+ Assert::AreEqual("x64", pgh.core_paragraph.supports[0].c_str());
+ Assert::AreEqual("windows", pgh.core_paragraph.supports[1].c_str());
+ Assert::AreEqual("uwp", pgh.core_paragraph.supports[2].c_str());
}
TEST_METHOD(SourceParagraph_Construct_Qualified_Depends)
{
- auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
- {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"},
- });
+ auto m_pgh =
+ vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
+ {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"},
+ }});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
- Assert::AreEqual("zlib", pgh.name.c_str());
- Assert::AreEqual("1.2.8", pgh.version.c_str());
- Assert::AreEqual("", pgh.maintainer.c_str());
- Assert::AreEqual("", pgh.description.c_str());
- Assert::AreEqual(size_t(2), pgh.depends.size());
- Assert::AreEqual("libA", pgh.depends[0].name.c_str());
- Assert::AreEqual("windows", pgh.depends[0].qualifier.c_str());
- Assert::AreEqual("libB", pgh.depends[1].name.c_str());
- Assert::AreEqual("uwp", pgh.depends[1].qualifier.c_str());
+ Assert::AreEqual("zlib", pgh.core_paragraph.name.c_str());
+ Assert::AreEqual("1.2.8", pgh.core_paragraph.version.c_str());
+ Assert::AreEqual("", pgh.core_paragraph.maintainer.c_str());
+ Assert::AreEqual("", pgh.core_paragraph.description.c_str());
+ Assert::AreEqual(size_t(2), pgh.core_paragraph.depends.size());
+ Assert::AreEqual("libA", pgh.core_paragraph.depends[0].name.c_str());
+ Assert::AreEqual("windows", pgh.core_paragraph.depends[0].qualifier.c_str());
+ Assert::AreEqual("libB", pgh.core_paragraph.depends[1].name.c_str());
+ Assert::AreEqual("uwp", pgh.core_paragraph.depends[1].qualifier.c_str());
}
TEST_METHOD(BinaryParagraph_Construct_Minimum)
diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp
index f32d92f4c..add8acb4d 100644
--- a/toolsrc/src/vcpkg_Dependencies.cpp
+++ b/toolsrc/src/vcpkg_Dependencies.cpp
@@ -174,12 +174,12 @@ namespace vcpkg::Dependencies
if (auto bpgh = maybe_bpgh.get())
return InstallPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type};
- ExpectedT<SourceParagraph, ParseControlErrorInfo> maybe_spgh =
+ ExpectedT<SourceControlFile, ParseControlErrorInfo> source_control_file =
Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec));
- if (auto spgh = maybe_spgh.get())
- return InstallPlanAction{spec, {nullopt, nullopt, *spgh}, request_type};
+ if (auto scf = source_control_file.get())
+ return InstallPlanAction{spec, {nullopt, nullopt, (*scf).core_paragraph}, request_type};
- print_error_message(maybe_spgh.error());
+ print_error_message(source_control_file.error());
Checks::exit_fail(VCPKG_LINE_INFO);
}
};
@@ -284,13 +284,13 @@ namespace vcpkg::Dependencies
if (auto bpgh = maybe_bpgh.get())
return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type};
- ExpectedT<SourceParagraph, ParseControlErrorInfo> maybe_spgh =
+ ExpectedT<SourceControlFile, ParseControlErrorInfo> source_control_file =
Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec));
- if (auto spgh = maybe_spgh.get())
- return ExportPlanAction{spec, {nullopt, nullopt, *spgh}, request_type};
+ if (auto scf = source_control_file.get())
+ return ExportPlanAction{spec, {nullopt, nullopt, (*scf).core_paragraph}, request_type};
else
- print_error_message(maybe_spgh.error());
+ print_error_message(source_control_file.error());
Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec);
}
diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp
index df738315b..fdedd5507 100644
--- a/toolsrc/src/vcpkg_Input.cpp
+++ b/toolsrc/src/vcpkg_Input.cpp
@@ -15,7 +15,7 @@ namespace vcpkg::Input
auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet);
if (auto spec = expected_spec.get())
{
- return *spec;
+ return PackageSpec{*spec};
}
// Intentionally show the lowercased string
@@ -34,4 +34,36 @@ namespace vcpkg::Input
Checks::exit_fail(VCPKG_LINE_INFO);
}
}
+
+ FullPackageSpec check_and_get_full_package_spec(const std::string& full_package_spec_as_string,
+ const Triplet& default_triplet,
+ CStringView example_text)
+ {
+ int left_pos = (int)full_package_spec_as_string.find('[');
+ if (left_pos == std::string::npos)
+ {
+ return FullPackageSpec{
+ check_and_get_package_spec(full_package_spec_as_string, default_triplet, example_text)};
+ }
+ int right_pos = (int)full_package_spec_as_string.find(']');
+ if (left_pos >= right_pos)
+ {
+ System::println(System::Color::error, "Error: Argument is not formatted correctly \"%s\"");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+
+ std::string package_spec_as_string = full_package_spec_as_string.substr(0, left_pos);
+ const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string);
+ auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet);
+ if (auto&& spec = expected_spec.get())
+ {
+ return {*spec,
+ parse_comma_list(full_package_spec_as_string.substr(left_pos + 1, right_pos - left_pos - 1))};
+ }
+
+ // Intentionally show the lowercased string
+ System::println(System::Color::error, "Error: %s: %s", vcpkg::to_string(expected_spec.error()), as_lowercase);
+ System::print(example_text);
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
}
diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp
index 9ba9eb700..aafed5fd3 100644
--- a/toolsrc/src/vcpkg_Strings.cpp
+++ b/toolsrc/src/vcpkg_Strings.cpp
@@ -68,6 +68,11 @@ namespace vcpkg::Strings
[](const char a, const char b) { return details::tolower_char(a) == b; });
}
+ bool case_insensitive_ascii_contains(const std::string& s, const std::string& pattern)
+ {
+ return case_insensitive_ascii_find(s, pattern) != s.end();
+ }
+
int case_insensitive_ascii_compare(const CStringView left, const CStringView right)
{
return _stricmp(left, right);