- Moved graph switches from search command to depend-info command.

- Added option to generate dgml graph.
This commit is contained in:
martin-s 2018-06-06 21:57:43 +02:00
parent 47d904608c
commit dfef4b8dd7
2 changed files with 115 additions and 51 deletions

View File

@ -9,20 +9,122 @@
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" },
} };
const CommandStructure COMMAND_STRUCTURE = {
Help::create_example_string(R"###(depend-info [pat])###"),
0,
1,
{},
{ DEPEND_SWITCHES,{} },
nullptr,
};
std::string replace_dashes_with_underscore(const std::string& input)
{
std::string output = input;
std::replace(output.begin(), output.end(), '-', '_');
return output;
}
std::string create_dot_as_string(
const std::vector<std::unique_ptr<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 auto& source_control_file : source_control_files)
{
const SourceParagraph& source_paragraph = *source_control_file->core_paragraph;
if (source_paragraph.depends.empty())
{
empty_node_count++;
continue;
}
const std::string name = replace_dashes_with_underscore(source_paragraph.name);
s.append(Strings::format("%s;", name));
for (const Dependency& d : source_paragraph.depends)
{
const std::string dependency_name = replace_dashes_with_underscore(d.name());
s.append(Strings::format("%s -> %s;", name, dependency_name));
}
}
s.append(Strings::format("empty [label=\"%d singletons...\"]; }", empty_node_count));
return s;
}
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\"?>");
s.append("<DirectedGraph xmlns=\"http://schemas.microsoft.com/vs/2009/dgml\">");
std::string nodes, links;
for (const auto& source_control_file : source_control_files)
{
const SourceParagraph& source_paragraph = *source_control_file->core_paragraph;
const std::string name = source_paragraph.name;
nodes.append(Strings::format("<Node Id=\"%s\" />", name));
// Iterate over dependencies.
for (const Dependency& d : source_paragraph.depends)
{
links.append(Strings::format("<Link Source=\"%s\" Target=\"%s\" />", name, d.name()));
}
// Iterate over feature dependencies.
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()));
}
}
}
s.append("<Nodes>");
s.append(nodes);
s.append("</Nodes>");
s.append("<Links>");
s.append(links);
s.append("</Links>");
s.append("</DirectedGraph>");
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)
{
if (Util::Sets::contains(switches, OPTION_DOT))
{
return create_dot_as_string(source_control_files);
}
else if (Util::Sets::contains(switches, OPTION_DGML))
{
return create_dgml_as_string(source_control_files);
}
return "";
}
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
Util::unused(args.parse_arguments(COMMAND_STRUCTURE));
const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
std::vector<std::unique_ptr<SourceControlFile>> source_control_files =
Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
auto source_control_files = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
if (args.command_arguments.size() == 1)
{
@ -49,6 +151,13 @@ namespace vcpkg::Commands::DependInfo
});
}
if (!options.switches.empty())
{
const std::string graph_as_string = create_graph_as_string(options.switches, source_control_files);
System::println(graph_as_string);
Checks::exit_success(VCPKG_LINE_INFO);
}
for (auto&& source_control_file : source_control_files)
{
const SourceParagraph& source_paragraph = *source_control_file->core_paragraph;

View File

@ -10,46 +10,9 @@
namespace vcpkg::Commands::Search
{
static constexpr StringLiteral OPTION_GRAPH = "--graph"; // TODO: This should find a better home, eventually
static constexpr StringLiteral OPTION_FULLDESC =
"--x-full-desc"; // TODO: This should find a better home, eventually
static std::string replace_dashes_with_underscore(const std::string& input)
{
std::string output = input;
std::replace(output.begin(), output.end(), '-', '_');
return output;
}
static std::string create_graph_as_string(
const std::vector<std::unique_ptr<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 auto& source_control_file : source_control_files)
{
const SourceParagraph& source_paragraph = *source_control_file->core_paragraph;
if (source_paragraph.depends.empty())
{
empty_node_count++;
continue;
}
const std::string name = replace_dashes_with_underscore(source_paragraph.name);
s.append(Strings::format("%s;", name));
for (const Dependency& d : source_paragraph.depends)
{
const std::string dependency_name = replace_dashes_with_underscore(d.name());
s.append(Strings::format("%s -> %s;", name, dependency_name));
}
}
s.append(Strings::format("empty [label=\"%d singletons...\"]; }", empty_node_count));
return s;
}
static void do_print(const SourceParagraph& source_paragraph, bool full_desc)
{
if (full_desc)
@ -80,8 +43,7 @@ namespace vcpkg::Commands::Search
}
}
static constexpr std::array<CommandSwitch, 2> SEARCH_SWITCHES = {{
{OPTION_GRAPH, "Open editor into the port-specific buildtree subfolder"},
static constexpr std::array<CommandSwitch, 1> SEARCH_SWITCHES = {{
{OPTION_FULLDESC, "Do not truncate long text"},
}};
@ -102,13 +64,6 @@ namespace vcpkg::Commands::Search
auto source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
if (Util::Sets::contains(options.switches, OPTION_GRAPH))
{
const std::string graph_as_string = create_graph_as_string(source_paragraphs);
System::println(graph_as_string);
Checks::exit_success(VCPKG_LINE_INFO);
}
if (args.command_arguments.empty())
{
for (const auto& source_control_file : source_paragraphs)