aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-11-21 10:13:54 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-11-21 10:13:54 +0000
commitb3aa89002259a774b767e6bc267f126a8acd0e45 (patch)
treeba3da6b61b0a0c179dbbc2bf380ca1d2d654c96c
parentf399011a936517fa3c88a8672124a39e747c1fd6 (diff)
downloadpaludis-b3aa89002259a774b767e6bc267f126a8acd0e45.tar.gz
paludis-b3aa89002259a774b767e6bc267f126a8acd0e45.tar.xz
Add a rather crude paludis --uninstall-unused.
-rw-r--r--paludis/tasks/uninstall_task.cc48
-rw-r--r--paludis/tasks/uninstall_task.hh1
-rw-r--r--paludis/uninstall_list.cc130
-rw-r--r--paludis/uninstall_list.hh2
-rw-r--r--src/paludis/command_line.cc3
-rw-r--r--src/paludis/command_line.hh3
-rw-r--r--src/paludis/paludis.cc9
-rw-r--r--src/paludis/uninstall.cc120
-rw-r--r--src/paludis/uninstall.hh3
9 files changed, 251 insertions, 68 deletions
diff --git a/paludis/tasks/uninstall_task.cc b/paludis/tasks/uninstall_task.cc
index d9ff100..4871022 100644
--- a/paludis/tasks/uninstall_task.cc
+++ b/paludis/tasks/uninstall_task.cc
@@ -41,6 +41,7 @@ namespace paludis
bool preserve_world;
bool with_unused_dependencies;
bool with_dependencies;
+ bool unused;
Implementation<UninstallTask>(Environment * const e) :
env(e),
@@ -48,7 +49,8 @@ namespace paludis
pretend(false),
preserve_world(false),
with_unused_dependencies(false),
- with_dependencies(false)
+ with_dependencies(false),
+ unused(false)
{
}
};
@@ -96,6 +98,19 @@ UninstallTask::add_target(const std::string & target)
PackageNamePart(target)))));
_imp->raw_targets.push_back(target);
+
+ if (_imp->unused)
+ throw InternalError(PALUDIS_HERE, "Trying to mix unused and normal targets?");
+}
+
+void
+UninstallTask::add_unused()
+{
+ Context context("When adding unused packages:");
+ _imp->unused = true;
+
+ if (! _imp->raw_targets.empty())
+ throw InternalError(PALUDIS_HERE, "Trying to mix unused and normal targets?");
}
namespace
@@ -128,20 +143,23 @@ UninstallTask::execute()
.with_dependencies(_imp->with_dependencies)
.with_unused_dependencies(_imp->with_unused_dependencies));
- for (std::list<PackageDepAtom::Pointer>::const_iterator t(_imp->targets.begin()),
- t_end(_imp->targets.end()) ; t != t_end ; ++t)
- {
- Context local_context("When looking for target '" + stringify(**t) + "':");
-
- PackageDatabaseEntryCollection::ConstPointer r(_imp->env->package_database()->query(
- *t, is_installed_only));
- if (r->empty())
- throw NoSuchPackageError(stringify(**t));
- else if (r->size() > 1)
- throw AmbiguousUnmergeTargetError(stringify(**t), r);
- else
- list.add(*r->begin());
- }
+ if (_imp->unused)
+ list.add_unused();
+ else
+ for (std::list<PackageDepAtom::Pointer>::const_iterator t(_imp->targets.begin()),
+ t_end(_imp->targets.end()) ; t != t_end ; ++t)
+ {
+ Context local_context("When looking for target '" + stringify(**t) + "':");
+
+ PackageDatabaseEntryCollection::ConstPointer r(_imp->env->package_database()->query(
+ *t, is_installed_only));
+ if (r->empty())
+ throw NoSuchPackageError(stringify(**t));
+ else if (r->size() > 1)
+ throw AmbiguousUnmergeTargetError(stringify(**t), r);
+ else
+ list.add(*r->begin());
+ }
on_build_unmergelist_post();
diff --git a/paludis/tasks/uninstall_task.hh b/paludis/tasks/uninstall_task.hh
index 339295c..aa8244c 100644
--- a/paludis/tasks/uninstall_task.hh
+++ b/paludis/tasks/uninstall_task.hh
@@ -112,6 +112,7 @@ namespace paludis
///\{
void add_target(const std::string &);
+ void add_unused();
///\}
diff --git a/paludis/uninstall_list.cc b/paludis/uninstall_list.cc
index 0b39e2c..022554e 100644
--- a/paludis/uninstall_list.cc
+++ b/paludis/uninstall_list.cc
@@ -27,6 +27,7 @@ using namespace paludis;
#include <paludis/util/join.hh>
#include <paludis/util/log.hh>
#include <paludis/hashed_containers.hh>
+#include <paludis/match_package.hh>
#include <list>
#include <algorithm>
@@ -112,6 +113,37 @@ UninstallList::add(const PackageDatabaseEntry & e)
add_unused_dependencies();
}
+void
+UninstallList::add_unused()
+{
+ Context context("When finding unused packages:");
+
+ PackageDatabaseEntryCollection::ConstPointer world(collect_world()),
+ everything(collect_all_installed());
+
+ PackageDatabaseEntryCollection::Pointer
+ world_plus_deps(new PackageDatabaseEntryCollection::Concrete),
+ unused(new PackageDatabaseEntryCollection::Concrete);
+
+ world_plus_deps->insert(world->begin(), world->end());
+
+ std::size_t old_size(0);
+ while (old_size != world_plus_deps->size())
+ {
+ old_size = world_plus_deps->size();
+ PackageDatabaseEntryCollection::ConstPointer new_world_deps(
+ collect_depped_upon(world_plus_deps));
+ world_plus_deps->insert(new_world_deps->begin(), new_world_deps->end());
+ }
+
+ std::set_difference(everything->begin(), everything->end(),
+ world_plus_deps->begin(), world_plus_deps->end(), unused->inserter());
+
+ for (PackageDatabaseEntryCollection::Iterator i(unused->begin()),
+ i_end(unused->end()) ; i != i_end ; ++i)
+ add_package(*i);
+}
+
UninstallList::Iterator
UninstallList::begin() const
{
@@ -365,3 +397,101 @@ UninstallList::add_dependencies(const PackageDatabaseEntry & e)
}
}
+namespace
+{
+ struct IsWorldMatcher :
+ DepAtomVisitorTypes::ConstVisitor
+ {
+ bool matched;
+
+ IsWorldMatcher() :
+ matched(false)
+ {
+ }
+ };
+
+ struct IsWorld :
+ DepAtomVisitorTypes::ConstVisitor,
+ std::unary_function<PackageDatabaseEntry, bool>
+ {
+ const Environment * const env;
+ DepAtom::ConstPointer world;
+ const PackageDatabaseEntry * dbe;
+ bool matched;
+
+ IsWorld(const Environment * const e) :
+ env(e),
+ world(e->package_set(SetName("world"))),
+ matched(false)
+ {
+ }
+
+ bool operator() (const PackageDatabaseEntry & e)
+ {
+ dbe = &e;
+ matched = false;
+ world->accept(this);
+ return matched;
+ }
+
+ void visit(const AllDepAtom * const a)
+ {
+ if (matched)
+ return;
+
+ std::for_each(a->begin(), a->end(), accept_visitor(this));
+ }
+
+ void visit(const PackageDepAtom * const a)
+ {
+ if (matched)
+ return;
+
+ if (match_package(env, a, *dbe))
+ matched = true;
+ }
+
+ void visit(const UseDepAtom * const u)
+ {
+ if (matched)
+ return;
+
+ std::for_each(u->begin(), u->end(), accept_visitor(this));
+ }
+
+ void visit(const AnyDepAtom * const a)
+ {
+ if (matched)
+ return;
+
+ std::for_each(a->begin(), a->end(), accept_visitor(this));
+ }
+
+ void visit(const BlockDepAtom * const)
+ {
+ }
+
+ void visit(const PlainTextDepAtom * const) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw InternalError(PALUDIS_HERE, "Got PlainTextDepAtom?");
+ }
+ };
+}
+
+PackageDatabaseEntryCollection::ConstPointer
+UninstallList::collect_world() const
+{
+ Context local_context("When collecting world packages:");
+
+ PackageDatabaseEntryCollection::Pointer result(new PackageDatabaseEntryCollection::Concrete);
+ PackageDatabaseEntryCollection::ConstPointer everything(collect_all_installed());
+
+ IsWorld w(_imp->env);
+ for (PackageDatabaseEntryCollection::Iterator i(everything->begin()),
+ i_end(everything->end()) ; i != i_end ; ++i)
+ if (w(*i))
+ result->insert(*i);
+
+ return result;
+}
+
diff --git a/paludis/uninstall_list.hh b/paludis/uninstall_list.hh
index 2c486a9..b99649e 100644
--- a/paludis/uninstall_list.hh
+++ b/paludis/uninstall_list.hh
@@ -45,6 +45,7 @@ namespace paludis
PackageDatabaseEntryCollection::ConstPointer collect_depped_upon(
const PackageDatabaseEntryCollection::ConstPointer targets) const;
PackageDatabaseEntryCollection::ConstPointer collect_all_installed() const;
+ PackageDatabaseEntryCollection::ConstPointer collect_world() const;
public:
UninstallList(const Environment * const, const UninstallListOptions &);
@@ -53,6 +54,7 @@ namespace paludis
UninstallListOptions & options;
void add(const PackageDatabaseEntry &);
+ void add_unused();
typedef libwrapiter::ForwardIterator<UninstallList, const UninstallListEntry> Iterator;
Iterator begin() const;
diff --git a/src/paludis/command_line.cc b/src/paludis/command_line.cc
index 1d6a748..4cd6d57 100644
--- a/src/paludis/command_line.cc
+++ b/src/paludis/command_line.cc
@@ -28,6 +28,7 @@ CommandLine::CommandLine() :
a_query(&action_args, "query", 'q', "Query for package information"),
a_install(&action_args, "install", 'i', "Install one or more packages"),
a_uninstall(&action_args, "uninstall", 'u', "Uninstall one or more packages"),
+ a_uninstall_unused(&action_args, "uninstall-unused", '\0', "Uninstall unused packages"),
a_sync(&action_args, "sync", 's', "Sync all or specified repositories"),
a_contents(&action_args, "contents", 'k', "Display contents of a package"),
a_owner(&action_args, "owner", 'o', "Display the owner of a file"),
@@ -71,7 +72,7 @@ CommandLine::CommandLine() :
a_show_metadata(&query_args, "show-metadata", 'M', "Show raw metadata"),
install_args(this, "Install, Uninstall options",
- "Options which are relevant for --install or --uninstall."),
+ "Options which are relevant for --install, --uninstall or --uninstall-unused."),
a_pretend(&install_args, "pretend", 'p', "Pretend only"),
a_preserve_world(&install_args, "preserve-world", '1', "Don't modify the world file"),
a_no_config_protection(&install_args, "no-config-protection", '\0', "Disable config file protection (dangerous)"),
diff --git a/src/paludis/command_line.hh b/src/paludis/command_line.hh
index 8f5a3b1..363b16f 100644
--- a/src/paludis/command_line.hh
+++ b/src/paludis/command_line.hh
@@ -68,6 +68,9 @@ class CommandLine :
/// --uninstall
paludis::args::SwitchArg a_uninstall;
+ /// --uninstall-unused
+ paludis::args::SwitchArg a_uninstall_unused;
+
/// --sync
paludis::args::SwitchArg a_sync;
diff --git a/src/paludis/paludis.cc b/src/paludis/paludis.cc
index fd9c4fa..788eb14 100644
--- a/src/paludis/paludis.cc
+++ b/src/paludis/paludis.cc
@@ -192,6 +192,7 @@ main(int argc, char *argv[])
CommandLine::get_instance()->a_version.specified() +
CommandLine::get_instance()->a_install.specified() +
CommandLine::get_instance()->a_uninstall.specified() +
+ CommandLine::get_instance()->a_uninstall_unused.specified() +
CommandLine::get_instance()->a_sync.specified() +
CommandLine::get_instance()->a_list_repositories.specified() +
CommandLine::get_instance()->a_list_categories.specified() +
@@ -315,6 +316,14 @@ main(int argc, char *argv[])
return do_uninstall();
}
+ if (CommandLine::get_instance()->a_uninstall_unused.specified())
+ {
+ if (! CommandLine::get_instance()->empty())
+ throw DoHelp("uninstall-unused action takes no parameters");
+
+ return do_uninstall_unused();
+ }
+
if (CommandLine::get_instance()->a_sync.specified())
{
return do_sync();
diff --git a/src/paludis/uninstall.cc b/src/paludis/uninstall.cc
index 856030e..742d0d1 100644
--- a/src/paludis/uninstall.cc
+++ b/src/paludis/uninstall.cc
@@ -126,63 +126,79 @@ namespace
cout << endl;
}
};
+
+ int real_uninstall(bool unused)
+ {
+ int return_code(0);
+
+ Context context(unused ?
+ "When performing uninstall-unused action from command line:" :
+ "When performing uninstall action from command line:");
+
+ OurUninstallTask task;
+
+ task.set_pretend(CommandLine::get_instance()->a_pretend.specified());
+ task.set_no_config_protect(CommandLine::get_instance()->a_no_config_protection.specified());
+ task.set_preserve_world(CommandLine::get_instance()->a_preserve_world.specified());
+ task.set_with_unused_dependencies(CommandLine::get_instance()->a_with_unused_dependencies.specified());
+ task.set_with_dependencies(CommandLine::get_instance()->a_with_dependencies.specified());
+
+ try
+ {
+ if (unused)
+ task.add_unused();
+ else
+ for (CommandLine::ParametersIterator q(CommandLine::get_instance()->begin_parameters()),
+ q_end(CommandLine::get_instance()->end_parameters()) ; q != q_end ; ++q)
+ task.add_target(*q);
+
+ task.execute();
+
+ cout << endl;
+ }
+ catch (const AmbiguousUnmergeTargetError & e)
+ {
+ cout << endl;
+ cerr << "Query error:" << endl;
+ cerr << " * " << e.backtrace("\n * ");
+ cerr << "Ambiguous unmerge target '" << e.target() << "'. Did you mean:" << endl;
+ for (AmbiguousUnmergeTargetError::Iterator o(e.begin()),
+ o_end(e.end()) ; o != o_end ; ++o)
+ cerr << " * =" << colour(cl_package_name, *o) << endl;
+ cerr << endl;
+ return 1;
+ }
+ catch (const PackageUninstallActionError & e)
+ {
+ cout << endl;
+ cerr << "Uninstall error:" << endl;
+ cerr << " * " << e.backtrace("\n * ");
+ cerr << e.message() << endl;
+
+ return_code |= 1;
+ }
+ catch (const NoSuchPackageError & e)
+ {
+ cout << endl;
+ cerr << "Query error:" << endl;
+ cerr << " * " << e.backtrace("\n * ");
+ cerr << "No such package '" << e.name() << "'" << endl;
+ return 1;
+ }
+
+ return return_code;
+ }
}
int
do_uninstall()
{
- int return_code(0);
-
- Context context("When performing uninstall action from command line:");
-
- OurUninstallTask task;
-
- task.set_pretend(CommandLine::get_instance()->a_pretend.specified());
- task.set_no_config_protect(CommandLine::get_instance()->a_no_config_protection.specified());
- task.set_preserve_world(CommandLine::get_instance()->a_preserve_world.specified());
- task.set_with_unused_dependencies(CommandLine::get_instance()->a_with_unused_dependencies.specified());
- task.set_with_dependencies(CommandLine::get_instance()->a_with_dependencies.specified());
-
- try
- {
- for (CommandLine::ParametersIterator q(CommandLine::get_instance()->begin_parameters()),
- q_end(CommandLine::get_instance()->end_parameters()) ; q != q_end ; ++q)
- task.add_target(*q);
-
- task.execute();
-
- cout << endl;
- }
- catch (const AmbiguousUnmergeTargetError & e)
- {
- cout << endl;
- cerr << "Query error:" << endl;
- cerr << " * " << e.backtrace("\n * ");
- cerr << "Ambiguous unmerge target '" << e.target() << "'. Did you mean:" << endl;
- for (AmbiguousUnmergeTargetError::Iterator o(e.begin()),
- o_end(e.end()) ; o != o_end ; ++o)
- cerr << " * =" << colour(cl_package_name, *o) << endl;
- cerr << endl;
- return 1;
- }
- catch (const PackageUninstallActionError & e)
- {
- cout << endl;
- cerr << "Uninstall error:" << endl;
- cerr << " * " << e.backtrace("\n * ");
- cerr << e.message() << endl;
-
- return_code |= 1;
- }
- catch (const NoSuchPackageError & e)
- {
- cout << endl;
- cerr << "Query error:" << endl;
- cerr << " * " << e.backtrace("\n * ");
- cerr << "No such package '" << e.name() << "'" << endl;
- return 1;
- }
+ return real_uninstall(false);
+}
- return return_code;
+int
+do_uninstall_unused()
+{
+ return real_uninstall(true);
}
diff --git a/src/paludis/uninstall.hh b/src/paludis/uninstall.hh
index a2a49ff..55686db 100644
--- a/src/paludis/uninstall.hh
+++ b/src/paludis/uninstall.hh
@@ -29,5 +29,8 @@
/// Handle --uninstall.
int do_uninstall();
+/// Handle --uninstall-unused.
+int do_uninstall_unused();
+
#endif