aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Karatarakis <alkarata@microsoft.com>2017-01-26 17:53:45 -0800
committerAlexander Karatarakis <alkarata@microsoft.com>2017-01-30 21:52:41 -0800
commit33b46b1fee70996a23a7860f853e95ef80ff3978 (patch)
tree985a5833c2c48cc9ccb9ec3e40139948e731ba03
parentcc81c3de6c74837dc146d7d3de73e4388cfc14dc (diff)
downloadvcpkg-33b46b1fee70996a23a7860f853e95ef80ff3978.tar.gz
vcpkg-33b46b1fee70996a23a7860f853e95ef80ff3978.zip
Create a remove plan. NOT used yet
-rw-r--r--toolsrc/include/vcpkg_Dependencies.h16
-rw-r--r--toolsrc/src/commands_remove.cpp8
-rw-r--r--toolsrc/src/vcpkg_Dependencies.cpp58
3 files changed, 79 insertions, 3 deletions
diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h
index 1c49ccafd..528abedfb 100644
--- a/toolsrc/include/vcpkg_Dependencies.h
+++ b/toolsrc/include/vcpkg_Dependencies.h
@@ -30,9 +30,23 @@ namespace vcpkg::Dependencies
{
NOT_INSTALLED,
DEPENDENCIES_NOT_SATISFIED,
- SHOULD_REMOVE
+ REMOVE,
+ REMOVE_USER_REQUESTED
};
+ struct remove_plan_action
+ {
+ remove_plan_type type;
+ std::unique_ptr<BinaryParagraph> bpgh;
+ };
+
+ struct package_spec_with_remove_plan
+ {
+ package_spec spec;
+ remove_plan_action plan;
+ };
std::vector<package_spec_with_install_plan> create_install_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db);
+
+ std::vector<package_spec_with_remove_plan> create_remove_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db);
}
diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp
index bf415d2c0..7b8286f9c 100644
--- a/toolsrc/src/commands_remove.cpp
+++ b/toolsrc/src/commands_remove.cpp
@@ -7,6 +7,7 @@
namespace vcpkg::Commands::Remove
{
+ using Dependencies::package_spec_with_remove_plan;
using Dependencies::remove_plan_type;
static const std::string OPTION_PURGE = "--purge";
@@ -57,7 +58,7 @@ namespace vcpkg::Commands::Remove
if (!dependencies_out.empty())
return remove_plan_type::DEPENDENCIES_NOT_SATISFIED;
- return remove_plan_type::SHOULD_REMOVE;
+ return remove_plan_type::REMOVE;
}
static void deinstall_package(const vcpkg_paths& paths, const package_spec& spec, StatusParagraphs& status_db)
@@ -85,7 +86,7 @@ namespace vcpkg::Commands::Remove
System::println(" %s depends on %s", dep->package.displayname(), pkg.package.displayname());
}
exit(EXIT_FAILURE);
- case remove_plan_type::SHOULD_REMOVE:
+ case remove_plan_type::REMOVE:
break;
default:
Checks::unreachable();
@@ -174,6 +175,9 @@ namespace vcpkg::Commands::Remove
Input::check_triplets(specs, paths);
bool alsoRemoveFolderFromPackages = options.find(OPTION_PURGE) != options.end();
+ const std::vector<package_spec_with_remove_plan> remove_plan = Dependencies::create_remove_plan(paths, specs, status_db);
+ Checks::check_exit(!remove_plan.empty(), "Remove plan cannot be empty");
+
for (const package_spec& spec : specs)
{
deinstall_package(paths, spec, status_db);
diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp
index 1daa6de02..4468930c4 100644
--- a/toolsrc/src/vcpkg_Dependencies.cpp
+++ b/toolsrc/src/vcpkg_Dependencies.cpp
@@ -5,6 +5,7 @@
#include "package_spec.h"
#include "StatusParagraphs.h"
#include <unordered_set>
+#include <unordered_map>
#include "vcpkg_Maps.h"
#include "vcpkg_Files.h"
#include "vcpkglib.h"
@@ -72,4 +73,61 @@ namespace vcpkg::Dependencies
}
return ret;
}
+
+ std::vector<package_spec_with_remove_plan> create_remove_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
+ {
+ std::unordered_set<package_spec> specs_as_set(specs.cbegin(), specs.cend());
+
+ std::unordered_map<package_spec, remove_plan_action> was_examined; // Examine = we have checked its immediate (non-recursive) dependencies
+ Graphs::Graph<package_spec> graph;
+ graph.add_vertices(specs);
+
+ std::vector<package_spec> examine_stack(specs);
+ while (!examine_stack.empty())
+ {
+ const package_spec spec = examine_stack.back();
+ examine_stack.pop_back();
+
+ if (was_examined.find(spec) != was_examined.end())
+ {
+ continue;
+ }
+
+ auto it = status_db.find(spec);
+ if (it == status_db.end() || (*it)->state == install_state_t::not_installed)
+ {
+ was_examined.emplace(spec, remove_plan_action{ remove_plan_type::NOT_INSTALLED, nullptr});
+ continue;
+ }
+
+ for (const std::unique_ptr<StatusParagraph>& an_installed_package : status_db)
+ {
+ if (an_installed_package->want != want_t::install)
+ continue;
+ if (an_installed_package->package.spec.target_triplet() != spec.target_triplet())
+ continue;
+
+ const std::vector<std::string>& deps = an_installed_package->package.depends;
+ if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end())
+ {
+ continue;
+ }
+
+ graph.add_edge(spec, an_installed_package.get()->package.spec);
+ examine_stack.push_back(an_installed_package.get()->package.spec);
+ }
+
+ const remove_plan_type type = specs_as_set.find(spec) != specs_as_set.end() ? remove_plan_type::REMOVE_USER_REQUESTED: remove_plan_type::REMOVE;
+ was_examined.emplace(spec, remove_plan_action{ type, std::make_unique<BinaryParagraph>(std::move((*it)->package))});
+ }
+
+ std::vector<package_spec_with_remove_plan> ret;
+
+ const std::vector<package_spec> pkgs = graph.find_topological_sort();
+ for (const package_spec& pkg : pkgs)
+ {
+ ret.push_back({ pkg, std::move(was_examined[pkg]) });
+ }
+ return ret;
+ }
}