Skip to content

Commit

Permalink
[command:depend-info] Add tree display (#74)
Browse files Browse the repository at this point in the history
* [command:depend-info] Add tree display

* change size_t to auto

* Update src/vcpkg/commands.dependinfo.cpp

Co-authored-by: ras0219 <533828+ras0219@users.noreply.github.com>

* Update src/vcpkg/commands.dependinfo.cpp

Co-authored-by: ras0219 <533828+ras0219@users.noreply.github.com>

* Update src/vcpkg/commands.dependinfo.cpp

Co-authored-by: ras0219 <533828+ras0219@users.noreply.github.com>

* Update src/vcpkg/commands.dependinfo.cpp

Co-authored-by: ras0219 <533828+ras0219@users.noreply.github.com>

* Update src/vcpkg/commands.dependinfo.cpp

Co-authored-by: ras0219 <533828+ras0219@users.noreply.github.com>

* Improve output, fix the connecting lines and spaces in front

* Delete the extra connecting line in front of the last element

* Fix multiple 'last' levels, reuse buffer, avoid combinatoricic explosion

Co-authored-by: ras0219 <533828+ras0219@users.noreply.github.com>
Co-authored-by: Robert Schumacher <roschuma@microsoft.com>
  • Loading branch information
3 people authored Nov 14, 2021
1 parent e185dfe commit 1aa8a5d
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 26 deletions.
1 change: 1 addition & 0 deletions include/vcpkg/commands.dependinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace vcpkg::Commands::DependInfo
{
extern const CommandStructure COMMAND_STRUCTURE;

void perform_and_exit(const VcpkgCmdArguments& args,
const VcpkgPaths& paths,
Triplet default_triplet,
Expand Down
134 changes: 108 additions & 26 deletions src/vcpkg/commands.dependinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,70 @@ namespace vcpkg::Commands::DependInfo
{
namespace
{
struct PackageDependInfo
{
std::string package;
int depth;
std::unordered_set<std::string> features;
std::vector<std::string> dependencies;
};

// invariant: prefix_buf is equivalent on exitv (but may have been reallocated)
void print_dep_tree(std::string& prefix_buf,
const std::string& currDepend,
const std::vector<PackageDependInfo>& allDepends,
std::set<std::string>& printed)
{
if (prefix_buf.size() > 400)
{
Checks::exit_with_message(VCPKG_LINE_INFO, "Recursion depth exceeded.");
}
auto currPos = std::find_if(
allDepends.begin(), allDepends.end(), [&currDepend](const auto& p) { return p.package == currDepend; });
Checks::check_exit(VCPKG_LINE_INFO, currPos != allDepends.end(), "internal vcpkg error");
if (currPos->dependencies.empty())
{
return;
}

const size_t original_size = prefix_buf.size();

if (Util::Sets::contains(printed, currDepend))
{
// If we've already printed the set of dependencies, print an elipsis instead
Strings::append(prefix_buf, "+- ...\n");
print2(prefix_buf);
prefix_buf.resize(original_size);
}
else
{
printed.insert(currDepend);

for (auto i = currPos->dependencies.begin(); i != currPos->dependencies.end() - 1; ++i)
{
// Print the current level
Strings::append(prefix_buf, "+-- ", *i, "\n");
print2(prefix_buf);
prefix_buf.resize(original_size);

// Recurse
prefix_buf.append("| ");
print_dep_tree(prefix_buf, *i, allDepends, printed);
prefix_buf.resize(original_size);
}

// Print the last of the current level
Strings::append(prefix_buf, "+-- ", currPos->dependencies.back(), "\n");
print2(prefix_buf);
prefix_buf.resize(original_size);

// Recurse
prefix_buf.append(" ");
print_dep_tree(prefix_buf, currPos->dependencies.back(), allDepends, printed);
prefix_buf.resize(original_size);
}
}

constexpr StringLiteral OPTION_DOT = "dot";
constexpr StringLiteral OPTION_DGML = "dgml";
constexpr StringLiteral OPTION_SHOW_DEPTH = "show-depth";
Expand All @@ -42,19 +106,12 @@ namespace vcpkg::Commands::DependInfo
"(default), "
"reverse"}}};

struct PackageDependInfo
{
std::string package;
int depth;
std::unordered_set<std::string> features;
std::vector<std::string> dependencies;
};

enum SortMode
{
Lexicographical = 0,
Topological,
ReverseTopological,
Treelogical,
Default = Topological
};

Expand Down Expand Up @@ -82,10 +139,12 @@ namespace vcpkg::Commands::DependInfo
constexpr StringLiteral OPTION_SORT_LEXICOGRAPHICAL = "lexicographical";
constexpr StringLiteral OPTION_SORT_TOPOLOGICAL = "topological";
constexpr StringLiteral OPTION_SORT_REVERSE = "reverse";
constexpr StringLiteral OPTION_SORT_TREE = "x-tree";

static const std::map<std::string, SortMode> sortModesMap{{OPTION_SORT_LEXICOGRAPHICAL, Lexicographical},
{OPTION_SORT_TOPOLOGICAL, Topological},
{OPTION_SORT_REVERSE, ReverseTopological}};
{OPTION_SORT_REVERSE, ReverseTopological},
{OPTION_SORT_TREE, Treelogical}};

auto iter = options.settings.find(OPTION_SORT);
if (iter != options.settings.end())
Expand Down Expand Up @@ -304,31 +363,54 @@ namespace vcpkg::Commands::DependInfo
{
case SortMode::Lexicographical: std::sort(std::begin(depend_info), std::end(depend_info), lex); break;
case SortMode::ReverseTopological:
std::sort(std::begin(depend_info), std::end(depend_info), reverse);
break;
case SortMode::Treelogical: std::sort(std::begin(depend_info), std::end(depend_info), reverse); break;
case SortMode::Topological: std::sort(std::begin(depend_info), std::end(depend_info), topo); break;
default: Checks::unreachable(VCPKG_LINE_INFO);
}

for (auto&& info : depend_info)
if (sort_mode == SortMode::Treelogical)
{
if (info.depth >= 0)
{
std::string features = Strings::join(", ", info.features);
const std::string dependencies = Strings::join(", ", info.dependencies);
auto first = depend_info.begin();
std::string features = Strings::join(", ", first->features);

if (show_depth)
{
print2(Color::error, "(", info.depth, ") ");
}
print2(Color::success, info.package);
if (!features.empty())
if (show_depth)
{
print2(Color::error, "(", first->depth, ") ");
}
print2(Color::success, first->package);
if (!features.empty())
{
print2("[");
print2(Color::warning, features);
print2("]");
}
print2("\n");
std::set<std::string> printed;
std::string prefix_buf;
print_dep_tree(prefix_buf, first->package, depend_info, printed);
}
else
{
for (auto&& info : depend_info)
{
if (info.depth >= 0)
{
print2("[");
print2(Color::warning, features);
print2("]");
const std::string features = Strings::join(", ", info.features);
const std::string dependencies = Strings::join(", ", info.dependencies);

if (show_depth)
{
print2(Color::error, "(", info.depth, ") ");
}
print2(Color::success, info.package);
if (!features.empty())
{
print2("[");
print2(Color::warning, features);
print2("]");
}
print2(": ", dependencies, "\n");
}
print2(": ", dependencies, "\n");
}
}
Checks::exit_success(VCPKG_LINE_INFO);
Expand Down

0 comments on commit 1aa8a5d

Please sign in to comment.