mirror of
https://github.com/microsoft/vcpkg.git
synced 2025-06-07 13:32:50 +08:00
Generate dependeny tree graph (#5185)
* use dashed link for optional dependency * output full dependency tree * add warning if requested package does not exist * [vcpkg] Formatting * [vcpkg] Fix issue when parsing qualified dependencies Before this change, "harfbuzz[glib] (!x86)" would parse as "harfbuzz[glib]||!x86" instead of the desired "harfbuzz|glib|!x86" * [vcpkg] Improve depend-info handling of features and qualified dependencies.
This commit is contained in:
parent
2f875f461b
commit
cde34211a5
@ -12,16 +12,16 @@ namespace vcpkg::Commands::DependInfo
|
||||
constexpr StringLiteral OPTION_DOT = "--dot";
|
||||
constexpr StringLiteral OPTION_DGML = "--dgml";
|
||||
|
||||
constexpr std::array<CommandSwitch, 2> DEPEND_SWITCHES = { {
|
||||
{ OPTION_DOT, "Creates graph on basis of dot" },
|
||||
{ OPTION_DGML, "Creates graph on basis of dgml" },
|
||||
} };
|
||||
constexpr std::array<CommandSwitch, 2> DEPEND_SWITCHES = {{
|
||||
{OPTION_DOT, "Creates graph on basis of dot"},
|
||||
{OPTION_DGML, "Creates graph on basis of dgml"},
|
||||
}};
|
||||
|
||||
const CommandStructure COMMAND_STRUCTURE = {
|
||||
Help::create_example_string(R"###(depend-info [pat])###"),
|
||||
0,
|
||||
1,
|
||||
{ DEPEND_SWITCHES,{} },
|
||||
SIZE_MAX,
|
||||
{DEPEND_SWITCHES, {}},
|
||||
nullptr,
|
||||
};
|
||||
|
||||
@ -32,8 +32,7 @@ namespace vcpkg::Commands::DependInfo
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string create_dot_as_string(
|
||||
const std::vector<std::unique_ptr<SourceControlFile>>& source_control_files)
|
||||
std::string create_dot_as_string(const std::vector<std::unique_ptr<SourceControlFile>>& source_control_files)
|
||||
{
|
||||
int empty_node_count = 0;
|
||||
|
||||
@ -53,7 +52,7 @@ namespace vcpkg::Commands::DependInfo
|
||||
s.append(Strings::format("%s;", name));
|
||||
for (const Dependency& d : source_paragraph.depends)
|
||||
{
|
||||
const std::string dependency_name = replace_dashes_with_underscore(d.name());
|
||||
const std::string dependency_name = replace_dashes_with_underscore(d.depend.name);
|
||||
s.append(Strings::format("%s -> %s;", name, dependency_name));
|
||||
}
|
||||
}
|
||||
@ -62,8 +61,7 @@ namespace vcpkg::Commands::DependInfo
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string create_dgml_as_string(
|
||||
const std::vector<std::unique_ptr<SourceControlFile>>& source_control_files)
|
||||
std::string create_dgml_as_string(const std::vector<std::unique_ptr<SourceControlFile>>& source_control_files)
|
||||
{
|
||||
std::string s;
|
||||
s.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
|
||||
@ -79,16 +77,22 @@ namespace vcpkg::Commands::DependInfo
|
||||
// Iterate over dependencies.
|
||||
for (const Dependency& d : source_paragraph.depends)
|
||||
{
|
||||
links.append(Strings::format("<Link Source=\"%s\" Target=\"%s\" />", name, d.name()));
|
||||
if (d.qualifier.empty())
|
||||
links.append(Strings::format("<Link Source=\"%s\" Target=\"%s\" />", name, d.depend.name));
|
||||
else
|
||||
links.append(Strings::format(
|
||||
"<Link Source=\"%s\" Target=\"%s\" StrokeDashArray=\"4\" />", name, d.depend.name));
|
||||
}
|
||||
|
||||
// Iterate over feature dependencies.
|
||||
const std::vector<std::unique_ptr<FeatureParagraph>>& feature_paragraphs = source_control_file->feature_paragraphs;
|
||||
const std::vector<std::unique_ptr<FeatureParagraph>>& feature_paragraphs =
|
||||
source_control_file->feature_paragraphs;
|
||||
for (const auto& feature_paragraph : feature_paragraphs)
|
||||
{
|
||||
for (const Dependency& d : feature_paragraph->depends)
|
||||
{
|
||||
links.append(Strings::format("<Link Source=\"%s\" Target=\"%s\" />", name, d.name()));
|
||||
links.append(Strings::format(
|
||||
"<Link Source=\"%s\" Target=\"%s\" StrokeDashArray=\"4\" />", name, d.depend.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,9 +105,8 @@ namespace vcpkg::Commands::DependInfo
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string create_graph_as_string(
|
||||
const std::unordered_set<std::string>& switches,
|
||||
const std::vector<std::unique_ptr<SourceControlFile>>& source_control_files)
|
||||
std::string create_graph_as_string(const std::unordered_set<std::string>& switches,
|
||||
const std::vector<std::unique_ptr<SourceControlFile>>& source_control_files)
|
||||
{
|
||||
if (Util::Sets::contains(switches, OPTION_DOT))
|
||||
{
|
||||
@ -116,35 +119,50 @@ namespace vcpkg::Commands::DependInfo
|
||||
return "";
|
||||
}
|
||||
|
||||
void build_dependencies_list(std::set<std::string>& packages_to_keep,
|
||||
const std::string& requested_package,
|
||||
const std::vector<std::unique_ptr<SourceControlFile>>& source_control_files)
|
||||
{
|
||||
const auto source_control_file =
|
||||
Util::find_if(source_control_files, [&requested_package](const auto& source_control_file) {
|
||||
return source_control_file->core_paragraph->name == requested_package;
|
||||
});
|
||||
|
||||
if (source_control_file != source_control_files.end())
|
||||
{
|
||||
const auto new_package = packages_to_keep.insert(requested_package).second;
|
||||
|
||||
if (new_package)
|
||||
{
|
||||
for (const auto& dependency : (*source_control_file)->core_paragraph->depends)
|
||||
{
|
||||
build_dependencies_list(packages_to_keep, dependency.depend.name, source_control_files);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System::println(System::Color::warning, "package '%s' does not exist", requested_package);
|
||||
}
|
||||
}
|
||||
|
||||
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
|
||||
{
|
||||
const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
|
||||
|
||||
auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
|
||||
|
||||
if (args.command_arguments.size() == 1)
|
||||
if (args.command_arguments.size() >= 1)
|
||||
{
|
||||
const std::string filter = args.command_arguments.at(0);
|
||||
std::set<std::string> packages_to_keep;
|
||||
for (const auto& requested_package : args.command_arguments)
|
||||
{
|
||||
build_dependencies_list(packages_to_keep, requested_package, source_control_files);
|
||||
}
|
||||
|
||||
Util::erase_remove_if(source_control_files,
|
||||
[&](const std::unique_ptr<SourceControlFile>& source_control_file) {
|
||||
const SourceParagraph& source_paragraph = *source_control_file->core_paragraph;
|
||||
|
||||
if (Strings::case_insensitive_ascii_contains(source_paragraph.name, filter))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const Dependency& dependency : source_paragraph.depends)
|
||||
{
|
||||
if (Strings::case_insensitive_ascii_contains(dependency.name(), filter))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
Util::erase_remove_if(source_control_files, [&packages_to_keep](const auto& source_control_file) {
|
||||
return !Util::Sets::contains(packages_to_keep, source_control_file->core_paragraph->name);
|
||||
});
|
||||
}
|
||||
|
||||
if (!options.switches.empty())
|
||||
|
@ -194,16 +194,13 @@ namespace vcpkg
|
||||
auto pos = depend_string.find(' ');
|
||||
if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, "");
|
||||
// expect of the form "\w+ \[\w+\]"
|
||||
Dependency dep;
|
||||
|
||||
dep.depend.name = depend_string.substr(0, pos);
|
||||
if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')')
|
||||
{
|
||||
// Error, but for now just slurp the entire string.
|
||||
return Dependency::parse_dependency(depend_string, "");
|
||||
}
|
||||
dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3);
|
||||
return dep;
|
||||
return Dependency::parse_dependency(depend_string.substr(0, pos),
|
||||
depend_string.substr(pos + 2, depend_string.size() - pos - 3));
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user