Refactor dependency related code to vcpkg::Dependencies

This commit is contained in:
Alexander Karatarakis 2016-09-22 23:28:50 -07:00
Родитель 7428d6cc3a
Коммит 4970dff5ca
7 изменённых файлов: 97 добавлений и 48 удалений

Просмотреть файл

@ -0,0 +1,13 @@
#pragma once
#include <vector>
#include "package_spec.h"
#include "StatusParagraphs.h"
#include <unordered_set>
#include "vcpkg_paths.h"
namespace vcpkg {namespace Dependencies
{
std::vector<package_spec> create_dependency_ordered_install_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db);
std::unordered_set<package_spec> find_unmet_dependencies(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db);
}}

Просмотреть файл

@ -28,7 +28,6 @@ namespace vcpkg
void check_max_args(size_t arg_count, const char* example_text = nullptr) const;
std::vector<package_spec> parse_all_arguments_as_package_specs(const triplet& default_target_triplet, const char* example_text = nullptr) const;
std::vector<package_spec> extract_package_specs_with_unmet_dependencies(const vcpkg_paths& paths, const triplet& default_target_triplet, const StatusParagraphs& status_db) const;
private:
std::unordered_set<std::string> optional_command_arguments;

Просмотреть файл

@ -6,6 +6,7 @@
#include "vcpkg_Files.h"
#include "post_build_lint.h"
#include "vcpkg_System.h"
#include "vcpkg_Dependencies.h"
namespace vcpkg
{
@ -59,18 +60,19 @@ namespace vcpkg
{
StatusParagraphs status_db = database_load_check(paths);
std::vector<package_spec> specs = args.extract_package_specs_with_unmet_dependencies(paths, default_target_triplet, status_db);
Checks::check_exit(!specs.empty(), "Specs cannot be empty");
std::string specs_string = to_string(specs[0]);
for (size_t i = 1; i < specs.size(); ++i)
std::vector<package_spec> specs = args.parse_all_arguments_as_package_specs(default_target_triplet);
std::vector<package_spec> install_plan = Dependencies::create_dependency_ordered_install_plan(paths, specs, status_db);
Checks::check_exit(!install_plan.empty(), "Install plan cannot be empty");
std::string specs_string = to_string(install_plan[0]);
for (size_t i = 1; i < install_plan.size(); ++i)
{
specs_string.push_back(',');
specs_string.append(to_string(specs[i]));
specs_string.append(to_string(install_plan[i]));
}
TrackProperty("installplan", specs_string);
Environment::ensure_utilities_on_path(paths);
for (const package_spec& spec : specs)
for (const package_spec& spec : install_plan)
{
if (status_db.find_installed(spec.name, spec.target_triplet) != status_db.end())
{

Просмотреть файл

@ -0,0 +1,68 @@
#include "vcpkg_Dependencies.h"
#include <vector>
#include "vcpkg_Graphs.h"
#include "vcpkg_paths.h"
#include "package_spec.h"
#include "StatusParagraphs.h"
#include <unordered_set>
#include "vcpkg.h"
#include "vcpkg_Maps.h"
#include "vcpkg_Sets.h"
namespace vcpkg { namespace Dependencies
{
static Graphs::Graph<package_spec> build_dependency_graph(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
{
std::vector<package_spec> examine_stack(specs);
std::unordered_set<package_spec> was_examined; // Examine = we have checked its immediate (non-recursive) dependencies
Graphs::Graph<package_spec> graph;
graph.add_vertices(examine_stack);
while (!examine_stack.empty())
{
package_spec spec = examine_stack.back();
examine_stack.pop_back();
if (was_examined.find(spec) != was_examined.end())
{
continue;
}
std::vector<std::string> dependencies_as_string = get_unmet_package_dependencies(paths, spec, status_db);
for (const std::string& dep_as_string : dependencies_as_string)
{
package_spec current_dep = {dep_as_string, spec.target_triplet};
auto it = status_db.find(current_dep.name, current_dep.target_triplet);
if (it != status_db.end() && (*it)->want == want_t::install)
{
continue;
}
graph.add_edge(spec, current_dep);
if (was_examined.find(current_dep) == was_examined.end())
{
examine_stack.push_back(std::move(current_dep));
}
}
was_examined.insert(spec);
}
return graph;
}
std::vector<package_spec> create_dependency_ordered_install_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
{
return build_dependency_graph(paths, specs, status_db).find_topological_sort();
}
std::unordered_set<package_spec> find_unmet_dependencies(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
{
const Graphs::Graph<package_spec> dependency_graph = build_dependency_graph(paths, specs, status_db);
std::unordered_set<package_spec> key_set = Maps::extract_key_set(dependency_graph.adjacency_list());
Sets::remove_all(&key_set, specs);
return key_set;
}
}}

Просмотреть файл

@ -179,47 +179,6 @@ namespace vcpkg
}
}
std::vector<package_spec> vcpkg_cmd_arguments::extract_package_specs_with_unmet_dependencies(const vcpkg_paths& paths, const triplet& default_target_triplet, const StatusParagraphs& status_db) const
{
std::vector<package_spec> specs = parse_all_arguments_as_package_specs(default_target_triplet);
std::unordered_set<package_spec> had_its_immediate_dependencies_added;
Graphs::Graph<package_spec> graph;
graph.add_vertices(specs);
while (!specs.empty())
{
package_spec spec = specs.back();
specs.pop_back();
if (had_its_immediate_dependencies_added.find(spec) != had_its_immediate_dependencies_added.end())
{
continue;
}
std::vector<std::string> dependencies_as_string = get_unmet_package_dependencies(paths, spec, status_db);
for (const std::string& dep_as_string : dependencies_as_string)
{
package_spec current_dep = {dep_as_string, spec.target_triplet};
auto it = status_db.find(current_dep.name, current_dep.target_triplet);
if (it != status_db.end() && (*it)->want == want_t::install)
{
continue;
}
graph.add_edge(spec, current_dep);
if (had_its_immediate_dependencies_added.find(current_dep) == had_its_immediate_dependencies_added.end())
{
specs.push_back(std::move(current_dep));
}
}
had_its_immediate_dependencies_added.insert(spec);
}
return graph.find_topological_sort();
}
std::vector<package_spec> vcpkg_cmd_arguments::parse_all_arguments_as_package_specs(const triplet& default_target_triplet, const char* example_text) const
{
size_t arg_count = command_arguments.size();

Просмотреть файл

@ -139,6 +139,7 @@
<ClCompile Include="..\src\commands_update.cpp" />
<ClCompile Include="..\src\vcpkg_cmd_arguments.cpp" />
<ClCompile Include="..\src\commands_other.cpp" />
<ClCompile Include="..\src\vcpkg_Dependencies.cpp" />
<ClCompile Include="..\src\vcpkg_Environment.cpp" />
<ClCompile Include="..\src\commands_installation.cpp" />
<ClCompile Include="..\src\commands_integration.cpp" />
@ -149,6 +150,7 @@
<ItemGroup>
<ClInclude Include="..\include\vcpkg_cmd_arguments.h" />
<ClInclude Include="..\include\vcpkg_Commands.h" />
<ClInclude Include="..\include\vcpkg_Dependencies.h" />
<ClInclude Include="..\include\vcpkg_Environment.h" />
<ClInclude Include="..\include\post_build_lint.h" />
</ItemGroup>

Просмотреть файл

@ -66,6 +66,9 @@
<ClCompile Include="..\src\commands_import.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\vcpkg_Dependencies.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\post_build_lint.h">
@ -80,5 +83,8 @@
<ClInclude Include="..\include\vcpkg_Environment.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\vcpkg_Dependencies.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>