aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-07-22 01:16:40 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-07-22 01:16:40 +0000
commitae884592e33072e0f4203f85ba358655277085dd (patch)
tree573ed7d3b8c50c31a990b37effa9b75e7f79dd5a
parent91ec7668948d960a94aed3238c4c286d63559ed3 (diff)
downloadpaludis-ae884592e33072e0f4203f85ba358655277085dd.tar.gz
paludis-ae884592e33072e0f4203f85ba358655277085dd.tar.xz
Switch install action over to a tasks interface. More to follow.
-rw-r--r--configure.ac1
-rw-r--r--paludis/Makefile.am.m42
-rw-r--r--paludis/environment.cc45
-rw-r--r--paludis/environment.hh33
-rw-r--r--paludis/tasks/Makefile.am28
-rw-r--r--paludis/tasks/install_task.cc384
-rw-r--r--paludis/tasks/install_task.hh131
-rw-r--r--src/paludis/Makefile.am1
-rw-r--r--src/paludis/install.cc812
-rw-r--r--src/paludis/uninstall.cc13
10 files changed, 1004 insertions, 446 deletions
diff --git a/configure.ac b/configure.ac
index 9dd4ce6..a553738 100644
--- a/configure.ac
+++ b/configure.ac
@@ -461,6 +461,7 @@ AC_OUTPUT(
paludis/repositories/portage/Makefile
paludis/repositories/vdb/Makefile
paludis/selinux/Makefile
+ paludis/tasks/Makefile
paludis/util/Makefile
src/Makefile
src/paludis/Makefile
diff --git a/paludis/Makefile.am.m4 b/paludis/Makefile.am.m4
index 0981cc7..1674e16 100644
--- a/paludis/Makefile.am.m4
+++ b/paludis/Makefile.am.m4
@@ -45,7 +45,7 @@ DEFS= \
-DDATADIR=\"$(datadir)\"
EXTRA_DIST = about.hh.in Makefile.am.m4 paludis.hh.m4 files.m4 \
hashed_containers.hh.in testscriptlist
-SUBDIRS = digests util . repositories args qa selinux
+SUBDIRS = digests util . repositories args qa selinux tasks
libpaludis_la_SOURCES = filelist
libpaludis_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
diff --git a/paludis/environment.cc b/paludis/environment.cc
index 8f46327..f190ba7 100644
--- a/paludis/environment.cc
+++ b/paludis/environment.cc
@@ -306,11 +306,8 @@ namespace
/// Matches
std::list<const PackageDepAtom *> items;
- /// Callback for adding world file entries, may be 0.
- void (* add_callback)(const PackageDepAtom *);
-
- /// Callback for skipping world file adds, may be 0.
- void (* skip_callback)(const PackageDepAtom *, const std::string & why);
+ /// Callback object pointer, may be 0.
+ Environment::WorldCallbacks * const w;
/// Are we inside a || ( ) group?
bool inside_any;
@@ -319,10 +316,8 @@ namespace
bool inside_use;
/// Constructor.
- WorldTargetFinder(void (* a)(const PackageDepAtom *),
- void (* s)(const PackageDepAtom *, const std::string &)) :
- add_callback(a),
- skip_callback(s),
+ WorldTargetFinder(Environment::WorldCallbacks * const ww) :
+ w(ww),
inside_any(false),
inside_use(false)
{
@@ -355,29 +350,29 @@ namespace
{
if (inside_any)
{
- if (skip_callback)
- (*skip_callback)(a, "inside || ( ) block");
+ if (w)
+ w->skip_callback(a, "inside || ( ) block");
}
else if (inside_use)
{
- if (skip_callback)
- (*skip_callback)(a, "inside use? ( ) block");
+ if (w)
+ w->skip_callback(a, "inside use? ( ) block");
}
else if (a->slot_ptr())
{
- if (skip_callback)
- (*skip_callback)(a, ":slot restrictions");
+ if (w)
+ w->skip_callback(a, ":slot restrictions");
}
else if (a->version_spec_ptr())
{
- if (skip_callback)
- (*skip_callback)(a, "version restrictions");
+ if (w)
+ w->skip_callback(a, "version restrictions");
}
else
{
items.push_back(a);
- if (add_callback)
- (*add_callback)(a);
+ if (w)
+ w->add_callback(a);
}
}
@@ -391,10 +386,9 @@ namespace
void
Environment::add_appropriate_to_world(DepAtom::ConstPointer a,
- void (* add_callback)(const PackageDepAtom *),
- void (* skip_callback)(const PackageDepAtom *, const std::string & why)) const
+ Environment::WorldCallbacks * const ww) const
{
- WorldTargetFinder w(add_callback, skip_callback);
+ WorldTargetFinder w(ww);
a->accept(&w);
for (std::list<const PackageDepAtom *>::const_iterator i(w.items.begin()),
i_end(w.items.end()) ; i != i_end ; ++i)
@@ -409,9 +403,9 @@ Environment::add_appropriate_to_world(DepAtom::ConstPointer a,
void
Environment::remove_appropriate_from_world(DepAtom::ConstPointer a,
- void (* remove_callback)(const PackageDepAtom *)) const
+ Environment::WorldCallbacks * const ww) const
{
- WorldTargetFinder w(0, 0);
+ WorldTargetFinder w(ww);
a->accept(&w);
for (std::list<const PackageDepAtom *>::const_iterator i(w.items.begin()),
i_end(w.items.end()) ; i != i_end ; ++i)
@@ -422,8 +416,7 @@ Environment::remove_appropriate_from_world(DepAtom::ConstPointer a,
if ((*r)->get_interface<repo_world>())
(*r)->get_interface<repo_world>()->remove_from_world((*i)->package());
- if (remove_callback)
- (*remove_callback)(*i);
+ ww->remove_callback(*i);
}
}
diff --git a/paludis/environment.hh b/paludis/environment.hh
index 95bf844..82ab219 100644
--- a/paludis/environment.hh
+++ b/paludis/environment.hh
@@ -215,20 +215,43 @@ namespace paludis
DepAtom::Pointer package_set(const std::string &,
const PackageSetOptions & = PackageSetOptions(false)) const;
+ class WorldCallbacks
+ {
+ protected:
+ WorldCallbacks()
+ {
+ }
+
+ public:
+ virtual ~WorldCallbacks()
+ {
+ }
+
+ virtual void add_callback(const PackageDepAtom *)
+ {
+ }
+
+ virtual void skip_callback(const PackageDepAtom *,
+ const std::string &)
+ {
+ }
+
+ virtual void remove_callback(const PackageDepAtom *)
+ {
+ }
+ };
+
/**
* Add packages to world, if they are not there already, and if they are
* not a restricted atom.
*/
void
- add_appropriate_to_world(DepAtom::ConstPointer a,
- void (* add_callback)(const PackageDepAtom *) = 0,
- void (* skip_callback)(const PackageDepAtom *, const std::string &) = 0) const;
+ add_appropriate_to_world(DepAtom::ConstPointer a, WorldCallbacks * const) const;
/**
* Remove packages from world, if they are there.
*/
- void remove_appropriate_from_world(DepAtom::ConstPointer,
- void (* remove_callback)(const PackageDepAtom *) = 0) const;
+ void remove_appropriate_from_world(DepAtom::ConstPointer, WorldCallbacks * const) const;
/**
* Perform a hook.
diff --git a/paludis/tasks/Makefile.am b/paludis/tasks/Makefile.am
new file mode 100644
index 0000000..bfd5442
--- /dev/null
+++ b/paludis/tasks/Makefile.am
@@ -0,0 +1,28 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+MAINTAINERCLEANFILES = Makefile.in Makefile.am
+AM_CXXFLAGS = -I$(top_srcdir)
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\"
+SUBDIRS = .
+
+TESTS =
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="$(top_srcdir)/ebuild/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ bash $(top_srcdir)/test/run_test.sh
+
+check_PROGRAMS = $(TESTS)
+check_SCRIPTS =
+
+lib_LIBRARIES = libpaludistasks.a
+paludis_tasks_includedir = $(includedir)/paludis/tasks
+paludis_tasks_include_HEADERS = \
+ install_task.hh
+
+libpaludistasks_a_SOURCES = $(paludis_tasks_include_HEADERS) \
+ install_task.cc
+
diff --git a/paludis/tasks/install_task.cc b/paludis/tasks/install_task.cc
new file mode 100644
index 0000000..323c0d1
--- /dev/null
+++ b/paludis/tasks/install_task.cc
@@ -0,0 +1,384 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "install_task.hh"
+#include <paludis/dep_atom.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <list>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<InstallTask> :
+ InternalCounted<Implementation<InstallTask> >
+ {
+ Environment * const env;
+ DepList dep_list;
+ InstallOptions install_options;
+
+ std::list<std::string> raw_targets;
+ AllDepAtom::Pointer targets;
+
+ bool pretend;
+ bool preserve_world;
+
+ bool had_set_targets;
+ bool had_package_targets;
+
+ Implementation<InstallTask>(Environment * const e) :
+ env(e),
+ dep_list(e),
+ install_options(false, false),
+ targets(new AllDepAtom),
+ pretend(false),
+ preserve_world(false),
+ had_set_targets(false),
+ had_package_targets(false)
+ {
+ }
+ };
+}
+
+MultipleSetTargetsSpecified::MultipleSetTargetsSpecified() throw () :
+ Exception("More than one set target was specified")
+{
+}
+
+HadBothPackageAndSetTargets::HadBothPackageAndSetTargets() throw () :
+ Exception("Both package and set targets were specified")
+{
+}
+
+InstallTask::InstallTask(Environment * const env) :
+ PrivateImplementationPattern<InstallTask>(new Implementation<InstallTask>(env))
+{
+}
+
+InstallTask::~InstallTask()
+{
+}
+
+void
+InstallTask::set_rdepend_post(const DepListRdependOption value)
+{
+ _imp->dep_list.set_rdepend_post(value);
+}
+
+void
+InstallTask::set_drop_self_circular(const bool value)
+{
+ _imp->dep_list.set_drop_self_circular(value);
+}
+
+void
+InstallTask::set_drop_circular(const bool value)
+{
+ _imp->dep_list.set_drop_circular(value);
+}
+
+void
+InstallTask::set_drop_all(const bool value)
+{
+ _imp->dep_list.set_drop_all(value);
+}
+
+void
+InstallTask::set_ignore_installed(const bool value)
+{
+ _imp->dep_list.set_ignore_installed(value);
+}
+
+void
+InstallTask::set_recursive_deps(const bool value)
+{
+ _imp->dep_list.set_recursive_deps(value);
+}
+
+void
+InstallTask::set_max_stack_depth(const int value)
+{
+ _imp->dep_list.set_max_stack_depth(value);
+}
+
+void
+InstallTask::set_no_unnecessary_upgrades(const bool value)
+{
+ _imp->dep_list.set_no_unnecessary_upgrades(value);
+}
+
+void
+InstallTask::set_no_config_protect(const bool value)
+{
+ _imp->install_options.set<io_noconfigprotect>(value);
+}
+
+void
+InstallTask::set_fetch_only(const bool value)
+{
+ _imp->install_options.set<io_fetchonly>(value);
+}
+
+void
+InstallTask::set_pretend(const bool value)
+{
+ _imp->pretend = value;
+}
+
+void
+InstallTask::set_preserve_world(const bool value)
+{
+ _imp->preserve_world = value;
+}
+
+void
+InstallTask::add_target(const std::string & target)
+{
+ Context context("When adding install target '" + target + "':");
+
+ DepAtom::Pointer s(0);
+
+ if (s = ((_imp->env->package_set(target))))
+ {
+ if (_imp->had_set_targets)
+ throw MultipleSetTargetsSpecified();
+
+ if (_imp->had_package_targets)
+ throw HadBothPackageAndSetTargets();
+
+ _imp->had_set_targets = true;
+ _imp->dep_list.set_reinstall(false);
+ _imp->targets->add_child(s);
+ }
+ else
+ {
+ if (_imp->had_set_targets)
+ throw HadBothPackageAndSetTargets();
+
+ _imp->had_package_targets = true;
+
+ if (std::string::npos != target.find('/'))
+ _imp->targets->add_child(PortageDepParser::parse(target));
+ else
+ _imp->targets->add_child(DepAtom::Pointer(new PackageDepAtom(
+ _imp->env->package_database()->fetch_unique_qualified_package_name(
+ PackageNamePart(target)))));
+ }
+
+ _imp->raw_targets.push_back(target);
+}
+
+namespace
+{
+ struct WorldCallbacks :
+ public Environment::WorldCallbacks
+ {
+ InstallTask * const t;
+
+ WorldCallbacks(InstallTask * const tt) :
+ t(tt)
+ {
+ }
+
+ virtual void add_callback(const PackageDepAtom * a)
+ {
+ t->on_update_world(*a);
+ }
+
+ virtual void skip_callback(const PackageDepAtom * a,
+ const std::string & s)
+ {
+ t->on_update_world_skip(*a, s);
+ }
+ };
+}
+
+void
+InstallTask::execute()
+{
+ Context context("When executing install task:");
+
+ /* build up our dep list */
+ on_build_deplist_pre();
+ _imp->dep_list.add(_imp->targets);
+ on_build_deplist_post();
+
+ /* we're about to display our task list */
+ if (_imp->pretend)
+ _imp->env->perform_hook(Hook("install_pretend_pre")("TARGETS", join(_imp->raw_targets.begin(),
+ _imp->raw_targets.end(), " ")));
+
+ on_display_merge_list_pre();
+
+ /* display our task list */
+ for (DepList::Iterator dep(_imp->dep_list.begin()), dep_end(_imp->dep_list.end()) ;
+ dep != dep_end ; ++dep)
+ on_display_merge_list_entry(*dep);
+
+ /* we're done displaying our task list */
+ on_display_merge_list_post();
+
+ if (_imp->pretend)
+ {
+ _imp->env->perform_hook(Hook("install_pretend_post")("TARGETS", join(
+ _imp->raw_targets.begin(), _imp->raw_targets.end(), " ")));
+ return;
+ }
+
+ /* we're about to fetch / install the entire list */
+ if (_imp->install_options.get<io_fetchonly>())
+ {
+ _imp->env->perform_hook(Hook("fetch_all_pre")("TARGETS", join(
+ _imp->raw_targets.begin(), _imp->raw_targets.end(), " ")));
+ on_fetch_all_pre();
+ }
+ else
+ {
+ _imp->env->perform_hook(Hook("install_all_pre")("TARGETS", join(
+ _imp->raw_targets.begin(), _imp->raw_targets.end(), " ")));
+ on_install_all_pre();
+ }
+
+ /* fetch / install our entire list */
+ for (DepList::Iterator dep(_imp->dep_list.begin()), dep_end(_imp->dep_list.end()) ;
+ dep != dep_end ; ++dep)
+ {
+ std::string cpvr(stringify(dep->get<dle_name>()) + "-" +
+ stringify(dep->get<dle_version>()) + "::" +
+ stringify(dep->get<dle_repository>()));
+
+ /* we're about to fetch / install one item */
+ if (_imp->install_options.get<io_fetchonly>())
+ {
+ _imp->env->perform_hook(Hook("fetch_pre")("TARGET", cpvr));
+ on_fetch_pre(*dep);
+ }
+ else
+ {
+ _imp->env->perform_hook(Hook("install_pre")("TARGET", cpvr));
+ on_install_pre(*dep);
+ }
+
+ /* fetch / install one item */
+ const Repository::InstallableInterface * const installable_interface(
+ _imp->env->package_database()->fetch_repository(dep->get<dle_repository>())->
+ get_interface<repo_installable>());
+ if (! installable_interface)
+ throw InternalError(PALUDIS_HERE, "Trying to install from a non-installable repository");
+
+ installable_interface->install(dep->get<dle_name>(), dep->get<dle_version>(), _imp->install_options);
+
+ /* we've fetched / installed one item */
+ if (_imp->install_options.get<io_fetchonly>())
+ {
+ on_fetch_post(*dep);
+ _imp->env->perform_hook(Hook("fetch_post")("TARGET", cpvr));
+ }
+ else
+ {
+ on_install_post(*dep);
+ _imp->env->perform_hook(Hook("install_post")("TARGET", cpvr));
+ }
+
+ if (_imp->install_options.get<io_fetchonly>())
+ continue;
+
+ /* figure out whether we need to unmerge (clean) anything */
+ on_build_cleanlist_pre(*dep);
+
+ // manually invalidate any installed repos, they're probably
+ // wrong now
+ for (PackageDatabase::RepositoryIterator r(_imp->env->package_database()->begin_repositories()),
+ r_end(_imp->env->package_database()->end_repositories()) ; r != r_end ; ++r)
+ if ((*r)->get_interface<repo_installed>())
+ (*r)->invalidate();
+
+ // look for packages with the same name in the same slot
+ PackageDatabaseEntryCollection::Pointer collision_list(_imp->env->package_database()->query(
+ PackageDepAtom::Pointer(new PackageDepAtom(
+ stringify(dep->get<dle_name>()) + ":" +
+ stringify(dep->get<dle_metadata>()->get<vm_slot>()))),
+ is_installed_only));
+
+ // don't clean the thing we just installed
+ PackageDatabaseEntryCollection::Concrete clean_list;
+ for (PackageDatabaseEntryCollection::Iterator c(collision_list->begin()),
+ c_end(collision_list->end()) ; c != c_end ; ++c)
+ if (dep->get<dle_version>() != c->get<pde_version>())
+ clean_list.insert(*c);
+
+ on_build_cleanlist_post(*dep);
+
+ /* ok, we have the cleanlist. we're about to clean */
+ _imp->env->perform_hook(Hook("uninstall_all_pre")("TARGETS", join(
+ clean_list.begin(), clean_list.end(), " ")));
+ on_clean_all_pre(*dep, clean_list);
+
+ for (PackageDatabaseEntryCollection::Iterator c(clean_list.begin()),
+ c_end(clean_list.end()) ; c != c_end ; ++c)
+ {
+ /* clean one item */
+ _imp->env->perform_hook(Hook("uninstall_pre")("TARGET", stringify(*c)));
+ on_clean_pre(*dep, *c);
+
+ const Repository::UninstallableInterface * const uninstall_interface(
+ _imp->env->package_database()->fetch_repository(c->get<pde_repository>())->
+ get_interface<repo_uninstallable>());
+ if (! uninstall_interface)
+ throw InternalError(PALUDIS_HERE, "Trying to uninstall from a non-uninstallable repo");
+ uninstall_interface->uninstall(c->get<pde_name>(), c->get<pde_version>(), _imp->install_options);
+
+ on_clean_post(*dep, *c);
+ _imp->env->perform_hook(Hook("uninstall_post")("TARGET", stringify(*c)));
+ }
+
+ /* we're done cleaning */
+ _imp->env->perform_hook(Hook("uninstall_all_post")("TARGETS", join(
+ clean_list.begin(), clean_list.end(), " ")));
+ on_clean_all_post(*dep, clean_list);
+ }
+
+ /* update world */
+ if (! _imp->preserve_world)
+ {
+ on_update_world_pre();
+ WorldCallbacks w(this);
+ _imp->env->add_appropriate_to_world(_imp->targets, &w);
+ on_update_world_post();
+ }
+ else
+ on_preserve_world();
+
+ /* we've fetched / installed the entire list */
+ if (_imp->install_options.get<io_fetchonly>())
+ {
+ on_fetch_all_post();
+ _imp->env->perform_hook(Hook("fetch_all_post")("TARGETS", join(
+ _imp->raw_targets.begin(), _imp->raw_targets.end(), " ")));
+ }
+ else
+ {
+ on_install_all_post();
+ _imp->env->perform_hook(Hook("install_all_post")("TARGETS", join(
+ _imp->raw_targets.begin(), _imp->raw_targets.end(), " ")));
+ }
+}
+
diff --git a/paludis/tasks/install_task.hh b/paludis/tasks/install_task.hh
new file mode 100644
index 0000000..5aef57d
--- /dev/null
+++ b/paludis/tasks/install_task.hh
@@ -0,0 +1,131 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_TASKS_INSTALL_TASK_HH
+#define PALUDIS_GUARD_PALUDIS_TASKS_INSTALL_TASK_HH 1
+
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/dep_list.hh>
+
+namespace paludis
+{
+ class Environment;
+
+ class MultipleSetTargetsSpecified :
+ public Exception
+ {
+ public:
+ MultipleSetTargetsSpecified() throw ();
+ };
+
+ class HadBothPackageAndSetTargets :
+ public Exception
+ {
+ public:
+ HadBothPackageAndSetTargets() throw ();
+ };
+
+ class InstallTask :
+ PrivateImplementationPattern<InstallTask>,
+ InstantiationPolicy<InstallTask, instantiation_method::NonCopyableTag>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ InstallTask(Environment * const env);
+ virtual ~InstallTask();
+
+ ///\}
+
+ ///\name DepList and Install behaviour options
+ ///\{
+
+ void set_rdepend_post(const DepListRdependOption value);
+ void set_drop_self_circular(const bool value);
+ void set_drop_circular(const bool value);
+ void set_drop_all(const bool value);
+ void set_ignore_installed(const bool value);
+ void set_recursive_deps(const bool value);
+ void set_max_stack_depth(const int value);
+ void set_no_unnecessary_upgrades(const bool value);
+
+ void set_no_config_protect(const bool value);
+ void set_fetch_only(const bool value);
+ void set_pretend(const bool value);
+ void set_preserve_world(const bool value);
+
+ ///\}
+
+ ///\name Add targets
+ ///\{
+
+ void add_target(const std::string &);
+
+ ///\}
+
+ ///\name Event callbacks
+ ///\{
+
+ virtual void on_build_deplist_pre() = 0;
+ virtual void on_build_deplist_post() = 0;
+
+ virtual void on_build_cleanlist_pre(const DepListEntry &) = 0;
+ virtual void on_build_cleanlist_post(const DepListEntry &) = 0;
+
+ virtual void on_display_merge_list_pre() = 0;
+ virtual void on_display_merge_list_post() = 0;
+ virtual void on_display_merge_list_entry(const DepListEntry &) = 0;
+
+ virtual void on_fetch_all_pre() = 0;
+ virtual void on_fetch_pre(const DepListEntry &) = 0;
+ virtual void on_fetch_post(const DepListEntry &) = 0;
+ virtual void on_fetch_all_post() = 0;
+
+ virtual void on_install_all_pre() = 0;
+ virtual void on_install_pre(const DepListEntry &) = 0;
+ virtual void on_install_post(const DepListEntry &) = 0;
+ virtual void on_install_all_post() = 0;
+
+ virtual void on_clean_all_pre(const DepListEntry &,
+ const PackageDatabaseEntryCollection &) = 0;
+ virtual void on_clean_pre(const DepListEntry &,
+ const PackageDatabaseEntry &) = 0;
+ virtual void on_clean_post(const DepListEntry &,
+ const PackageDatabaseEntry &) = 0;
+ virtual void on_clean_all_post(const DepListEntry &,
+ const PackageDatabaseEntryCollection &) = 0;
+
+ virtual void on_update_world_pre() = 0;
+ virtual void on_update_world(const PackageDepAtom &) = 0;
+ virtual void on_update_world_skip(const PackageDepAtom &, const std::string &) = 0;
+ virtual void on_update_world_post() = 0;
+ virtual void on_preserve_world() = 0;
+
+ ///\}
+
+ /**
+ * Run the task.
+ */
+ void execute();
+ };
+}
+
+#endif
diff --git a/src/paludis/Makefile.am b/src/paludis/Makefile.am
index af1e3eb..1106f39 100644
--- a/src/paludis/Makefile.am
+++ b/src/paludis/Makefile.am
@@ -25,6 +25,7 @@ paludis_LDADD = \
$(top_builddir)/paludis/repositories/nothing/libpaludisnothingrepository.la \
$(top_builddir)/paludis/repositories/portage/libpaludisportagerepository.la \
$(top_builddir)/paludis/repositories/vdb/libpaludisvdbrepository.la \
+ $(top_builddir)/paludis/tasks/libpaludistasks.a \
$(top_builddir)/paludis/libpaludis.la \
$(top_builddir)/paludis/args/libpaludisargs.la \
$(top_builddir)/paludis/util/libpaludisutil.la
diff --git a/src/paludis/install.cc b/src/paludis/install.cc
index 2a22140..edccb49 100644
--- a/src/paludis/install.cc
+++ b/src/paludis/install.cc
@@ -20,18 +20,19 @@
#include "colour.hh"
#include "install.hh"
#include "licence.hh"
+
#include <iostream>
-#include <paludis/paludis.hh>
-#include <paludis/util/iterator.hh>
-#include <paludis/util/tokeniser.hh>
+#include <set>
+
+#include <paludis/tasks/install_task.hh>
#include <paludis/util/log.hh>
-#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/tokeniser.hh>
/** \file
* Handle the --install action for the main paludis program.
*/
-namespace p = paludis;
+using namespace paludis;
using std::cerr;
using std::cout;
@@ -40,15 +41,15 @@ using std::endl;
namespace
{
struct TagDisplayer :
- p::DepTagVisitorTypes::ConstVisitor
+ DepTagVisitorTypes::ConstVisitor
{
- void visit(const p::GLSADepTag * const tag)
+ void visit(const GLSADepTag * const tag)
{
cout << "* " << colour(cl_tag, tag->short_text()) << ": "
<< tag->glsa_title() << endl;
}
- void visit(const p::GeneralSetDepTag * const tag)
+ void visit(const GeneralSetDepTag * const tag)
{
cout << "* " << colour(cl_tag, tag->short_text());
if (tag->short_text() == "world")
@@ -62,344 +63,245 @@ namespace
};
void
- world_add_callback(const p::PackageDepAtom * const p)
+ world_add_callback(const PackageDepAtom * const p)
{
cout << "* adding " << colour(cl_package_name, stringify(*p)) << endl;
}
void
- world_skip_callback(const p::PackageDepAtom * const p, const std::string & why)
+ world_skip_callback(const PackageDepAtom * const p, const std::string & why)
{
cout << "* skipping " << colour(cl_package_name, stringify(*p))
<< " (" << why << ")" << endl;
}
-}
-
-int
-do_install()
-{
- int return_code(0);
-
- p::Context context("When performing install action from command line:");
- p::Environment * const env(p::DefaultEnvironment::get_instance());
-
- cout << colour(cl_heading, "These packages will be installed:") << endl << endl;
-
- p::CompositeDepAtom::Pointer targets(new p::AllDepAtom);
- p::DepList dep_list(env);
-
- dep_list.set_drop_self_circular(CommandLine::get_instance()->a_dl_drop_self_circular.specified());
- dep_list.set_drop_circular(CommandLine::get_instance()->a_dl_drop_circular.specified());
- dep_list.set_drop_all(CommandLine::get_instance()->a_dl_drop_all.specified());
- dep_list.set_ignore_installed(CommandLine::get_instance()->a_dl_ignore_installed.specified());
- dep_list.set_recursive_deps(! CommandLine::get_instance()->a_dl_no_recursive_deps.specified());
- dep_list.set_max_stack_depth(CommandLine::get_instance()->a_dl_max_stack_depth.argument());
- dep_list.set_no_unnecessary_upgrades(CommandLine::get_instance()->a_dl_no_unnecessary_upgrades.specified());
-
- if (CommandLine::get_instance()->a_dl_rdepend_post.argument() == "always")
- dep_list.set_rdepend_post(p::dlro_always);
- else if (CommandLine::get_instance()->a_dl_rdepend_post.argument() == "never")
- dep_list.set_rdepend_post(p::dlro_never);
- else
- dep_list.set_rdepend_post(p::dlro_as_needed);
-
- p::InstallOptions opts(false, false);
- if (CommandLine::get_instance()->a_no_config_protection.specified())
- opts.set<p::io_noconfigprotect>(true);
- if (CommandLine::get_instance()->a_fetch.specified())
- opts.set<p::io_fetchonly>(true);
-
- bool had_set_targets(false), had_pkg_targets(false);
- try
+ class OurInstallTask :
+ public InstallTask
{
- CommandLine::ParametersIterator q(CommandLine::get_instance()->begin_parameters()),
- q_end(CommandLine::get_instance()->end_parameters());
-
- for ( ; q != q_end ; ++q)
- {
- p::DepAtom::Pointer s(0);
- if (s = ((env->package_set(*q))))
+ private:
+ int _current_count, _max_count, _new_count, _upgrade_count,
+ _downgrade_count, _new_slot_count, _rebuild_count;
+
+ std::set<DepTag::ConstPointer, DepTag::Comparator> _all_tags;
+
+ public:
+ OurInstallTask() :
+ InstallTask(DefaultEnvironment::get_instance()),
+ _current_count(0),
+ _max_count(0),
+ _new_count(0),
+ _upgrade_count(0),
+ _downgrade_count(0),
+ _new_slot_count(0),
+ _rebuild_count(0)
{
- if (had_set_targets)
- throw DoHelp("You should not specify more than one set target.");
-
- had_set_targets = true;
- targets->add_child(s);
}
- else
- {
- had_pkg_targets = true;
- /* we might have a dep atom, but we might just have a simple package name
- * without a category. either should work. also allow full atoms, to make
- * it easy to test things like '|| ( foo/bar foo/baz )'. */
- if (std::string::npos != q->find('/'))
- targets->add_child(p::PortageDepParser::parse(*q));
- else
- targets->add_child(p::DepAtom::Pointer(new p::PackageDepAtom(
- env->package_database()->fetch_unique_qualified_package_name(
- p::PackageNamePart(*q)))));
+ void on_build_deplist_pre()
+ {
+ cout << "Building dependency list... " << std::flush;
}
- }
- if (had_set_targets && had_pkg_targets)
- throw DoHelp("You should not specify set and package targets at the same time.");
+ virtual void on_build_deplist_post()
+ {
+ cout << "done" << endl;
+ }
- if (had_set_targets)
- dep_list.set_reinstall(false);
- }
- catch (const p::AmbiguousPackageNameError & e)
- {
- cout << endl;
- cerr << "Query error:" << endl;
- cerr << " * " << e.backtrace("\n * ");
- cerr << "Ambiguous package name '" << e.name() << "'. Did you mean:" << endl;
- for (p::AmbiguousPackageNameError::OptionsIterator o(e.begin_options()),
- o_end(e.end_options()) ; o != o_end ; ++o)
- cerr << " * " << colour(cl_package_name, *o) << endl;
- cerr << endl;
- return 1;
- }
+ virtual void on_build_cleanlist_pre(const DepListEntry & d)
+ {
+ cout << endl << colour(cl_heading, "Cleaning stale versions after installing " +
+ stringify(d.get<dle_name>()) + "-" + stringify(d.get<dle_version>()) +
+ "::" + stringify(d.get<dle_repository>())) << endl << endl;
+ }
- try
- {
- dep_list.add(targets);
+ virtual void on_build_cleanlist_post(const DepListEntry &)
+ {
+ }
- int current_count(0), max_count(0), new_count(0), upgrade_count(0),
- downgrade_count(0), new_slot_count(0), rebuild_count(0);
+ virtual void on_clean_all_pre(const DepListEntry &,
+ const PackageDatabaseEntryCollection & c)
+ {
+ if (c.empty())
+ cout << "* No cleaning required" << endl;
+ else
+ {
+ for (PackageDatabaseEntryCollection::Iterator cc(c.begin()),
+ cc_end(c.end()) ; cc != cc_end ; ++cc)
+ cout << "* " << colour(cl_package_name, *cc) << endl;
+ }
+ cout << endl;
+ }
- if (CommandLine::get_instance()->a_pretend.specified())
- env->perform_hook(p::Hook("install_pretend_pre")("TARGETS", p::join(
- CommandLine::get_instance()->begin_parameters(),
- CommandLine::get_instance()->end_parameters(), " ")));
+ virtual void on_clean_pre(const DepListEntry &,
+ const PackageDatabaseEntry & c)
+ {
+ cout << colour(cl_heading, "Cleaning " + stringify(c)) << endl << endl;
- std::set<p::DepTag::ConstPointer, p::DepTag::Comparator> all_tags;
+ cerr << xterm_title("(" + stringify(_current_count) + " of " +
+ stringify(_max_count) + ") Cleaning " + stringify(c));
+ }
- for (p::DepList::Iterator dep(dep_list.begin()), dep_end(dep_list.end()) ;
- dep != dep_end ; ++dep)
- {
- p::Context loop_context("When displaying DepList entry '" + stringify(*dep) + "':");
+ virtual void on_clean_post(const DepListEntry &,
+ const PackageDatabaseEntry &)
+ {
+ }
- /* display name */
- cout << "* " << colour(cl_package_name, dep->get<p::dle_name>());
+ virtual void on_clean_all_post(const DepListEntry &,
+ const PackageDatabaseEntryCollection &)
+ {
+ }
- /* display version, unless it's 0 and our category is "virtual" */
- if ((p::VersionSpec("0") != dep->get<p::dle_version>()) ||
- p::CategoryNamePart("virtual") != dep->get<p::dle_name>().get<p::qpn_category>())
- cout << "-" << dep->get<p::dle_version>();
+ virtual void on_display_merge_list_pre()
+ {
+ cout << endl << colour(cl_heading, "These packages will be installed:")
+ << endl << endl;
+ }
- /* display repository, unless it's our main repository */
- if (env->package_database()->favourite_repository() != dep->get<p::dle_repository>())
- cout << "::" << dep->get<p::dle_repository>();
+ virtual void on_display_merge_list_post();
+ virtual void on_display_merge_list_entry(const DepListEntry &);
- /* display slot name, unless it's 0 */
- if (p::SlotName("0") != dep->get<p::dle_metadata>()->get<p::vm_slot>())
- cout << colour(cl_slot, " {:" + p::stringify(
- dep->get<p::dle_metadata>()->get<p::vm_slot>()) + "}");
+ virtual void on_fetch_all_pre()
+ {
+ }
- /* indicate [U], [S] or [N]. display existing version, if we're
- * already installed */
- p::PackageDatabaseEntryCollection::Pointer existing(env->package_database()->
- query(p::PackageDepAtom::Pointer(new p::PackageDepAtom(p::stringify(
- dep->get<p::dle_name>()))), p::is_installed_only));
+ virtual void on_fetch_pre(const DepListEntry & d)
+ {
+ cout << colour(cl_heading, "Fetching " +
+ stringify(d.get<dle_name>()) + "-" + stringify(d.get<dle_version>()) +
+ "::" + stringify(d.get<dle_repository>())) << endl << endl;
+
+ cerr << xterm_title("(" + stringify(++_current_count) + " of " +
+ stringify(_max_count) + ") Fetching " +
+ stringify(d.get<dle_name>()) + "-" + stringify(d.get<dle_version>()) +
+ "::" + stringify(d.get<dle_repository>()));
+ }
- if (existing->empty())
+ virtual void on_fetch_post(const DepListEntry &)
{
- cout << colour(cl_updatemode, " [N]");
- ++new_count;
- ++max_count;
}
- else
+
+ virtual void on_fetch_all_post()
{
- existing = env->package_database()->query(p::PackageDepAtom::Pointer(
- new p::PackageDepAtom(p::stringify(dep->get<p::dle_name>()) + ":" +
- stringify(dep->get<p::dle_metadata>()->get<p::vm_slot>()))),
- p::is_installed_only);
- if (existing->empty())
- {
- cout << colour(cl_updatemode, " [S]");
- ++new_slot_count;
- ++max_count;
- }
- else if (existing->last()->get<p::pde_version>() < dep->get<p::dle_version>())
- {
- cout << colour(cl_updatemode, " [U " + p::stringify(
- existing->last()->get<p::pde_version>()) + "]");
- ++upgrade_count;
- ++max_count;
- }
- else if (existing->last()->get<p::pde_version>() > dep->get<p::dle_version>())
- {
- cout << colour(cl_updatemode, " [D " + p::stringify(
- existing->last()->get<p::pde_version>()) + "]");
- ++downgrade_count;
- ++max_count;
- }
- else
- {
- cout << colour(cl_updatemode, " [R]");
- ++rebuild_count;
- ++max_count;
- }
}
- /* fetch db entry */
- p::PackageDatabaseEntry p(p::PackageDatabaseEntry(dep->get<p::dle_name>(),
- dep->get<p::dle_version>(), dep->get<p::dle_repository>()));
+ virtual void on_install_all_pre()
+ {
+ }
- /* display USE flags */
- if (dep->get<p::dle_metadata>()->get_ebuild_interface())
+ virtual void on_install_pre(const DepListEntry & d)
{
- const p::Repository::UseInterface * const use_interface(
- env->package_database()->fetch_repository(dep->get<p::dle_repository>())->
- get_interface<p::repo_use>());
- std::set<p::UseFlagName> iuse;
- p::WhitespaceTokeniser::get_instance()->tokenise(
- dep->get<p::dle_metadata>()->get_ebuild_interface()->get<p::evm_iuse>(),
- p::create_inserter<p::UseFlagName>(std::inserter(iuse, iuse.end())));
+ cout << endl << colour(cl_heading, "Installing " +
+ stringify(d.get<dle_name>()) + "-" + stringify(d.get<dle_version>()) +
+ "::" + stringify(d.get<dle_repository>())) << endl << endl;
+
+ cerr << xterm_title("(" + stringify(++_current_count) + " of " +
+ stringify(_max_count) + ") Installing " +
+ stringify(d.get<dle_name>()) + "-" + stringify(d.get<dle_version>()) +
+ "::" + stringify(d.get<dle_repository>()));
+ }
+ virtual void on_install_post(const DepListEntry &)
+ {
+ }
- /* display normal use flags first */
- for (std::set<p::UseFlagName>::const_iterator i(iuse.begin()), i_end(iuse.end()) ;
- i != i_end ; ++i)
- {
- if (use_interface->is_expand_flag(*i))
- continue;
+ virtual void on_install_all_post()
+ {
+ }
- if (env->query_use(*i, &p))
- {
- if (use_interface && use_interface->query_use_force(*i, &p))
- cout << " " << colour(cl_flag_on, "(" + p::stringify(*i) + ")");
- else
- cout << " " << colour(cl_flag_on, *i);
- }
- else
- {
- if (use_interface && use_interface->query_use_mask(*i, &p))
- cout << " " << colour(cl_flag_off, "(-" + p::stringify(*i) + ")");
- else
- cout << " " << colour(cl_flag_off, "-" + p::stringify(*i));
- }
- }
+ virtual void on_update_world_pre()
+ {
+ cout << endl << colour(cl_heading, "Updating world file") << endl << endl;
+ }
- /* now display expand flags */
- p::UseFlagName old_expand_name("OFTEN_NOT_BEEN_ON_BOATS");
- for (std::set<p::UseFlagName>::const_iterator i(iuse.begin()), i_end(iuse.end()) ;
- i != i_end ; ++i)
- {
- if ((! use_interface->is_expand_flag(*i)) ||
- (use_interface->is_expand_hidden_flag(*i)))
- continue;
+ virtual void on_update_world(const PackageDepAtom & a)
+ {
+ cout << "* adding " << colour(cl_package_name, a.package()) << endl;
+ }
- p::UseFlagName expand_name(use_interface->expand_flag_name(*i)),
- expand_value(use_interface->expand_flag_value(*i));
-
- if (expand_name != old_expand_name)
- {
- cout << " " << expand_name << ":";
- old_expand_name = expand_name;
- }
-
- if (env->query_use(*i, &p))
- {
- if (use_interface && use_interface->query_use_force(*i, &p))
- cout << " " << colour(cl_flag_on, "(" + p::stringify(expand_value) + ")");
- else
- cout << " " << colour(cl_flag_on, expand_value);
- }
- else
- {
- if (use_interface && use_interface->query_use_mask(*i, &p))
- cout << " " << colour(cl_flag_off, "(-" + p::stringify(expand_value) + ")");
- else
- cout << " " << colour(cl_flag_off, "-" + p::stringify(expand_value));
- }
- }
+ virtual void on_update_world_skip(const PackageDepAtom & a, const std::string & s)
+ {
+ cout << "* skipping " << colour(cl_package_name, a.package()) << " ("
+ << s << ")" << endl;
}
- /* display tag, add tag to our post display list */
- if (! dep->get<p::dle_tag>()->empty())
+ virtual void on_update_world_post()
{
- std::string tag_titles;
- for (p::SortedCollection<p::DepTag::ConstPointer, p::DepTag::Comparator>::Iterator
- tag(dep->get<p::dle_tag>()->begin()),
- tag_end(dep->get<p::dle_tag>()->end()) ;
- tag != tag_end ; ++tag)
- {
- all_tags.insert(*tag);
- tag_titles.append((*tag)->short_text());
- tag_titles.append(",");
- }
- tag_titles.erase(tag_titles.length() - 1);
- cout << " " << colour(cl_tag, "<" + tag_titles + ">");
+ cout << endl;
}
- cout << endl;
- }
+ virtual void on_preserve_world()
+ {
+ cout << endl << colour(cl_heading, "Updating world file") << endl << endl;
+ cout << "* --preserve-world was specified, skipping world changes" << endl;
+ cout << endl;
+ }
+ };
- if (max_count != new_count + upgrade_count + downgrade_count + new_slot_count +
- rebuild_count)
- p::Log::get_instance()->message(p::ll_warning, p::lc_no_context,
+ void
+ OurInstallTask::on_display_merge_list_post()
+ {
+ if (_max_count != _new_count + _upgrade_count + _downgrade_count + _new_slot_count +
+ _rebuild_count)
+ Log::get_instance()->message(ll_warning, lc_no_context,
"Max count doesn't add up. This is a bug!");
- cout << endl << "Total: " << max_count << (max_count == 1 ? " package" : " packages");
- if (max_count)
+ cout << endl << "Total: " << _max_count << (_max_count == 1 ? " package" : " packages");
+ if (_max_count)
{
bool need_comma(false);
cout << " (";
- if (new_count)
+ if (_new_count)
{
- cout << new_count << " new";
+ cout << _new_count << " new";
need_comma = true;
}
- if (upgrade_count)
+ if (_upgrade_count)
{
if (need_comma)
cout << ", ";
- cout << upgrade_count << (upgrade_count == 1 ? " upgrade" : " upgrades");
+ cout << _upgrade_count << (_upgrade_count == 1 ? " upgrade" : " upgrades");
need_comma = true;
}
- if (downgrade_count)
+ if (_downgrade_count)
{
if (need_comma)
cout << ", ";
- cout << downgrade_count << (downgrade_count == 1 ? " downgrade" : " downgrades");
+ cout << _downgrade_count << (_downgrade_count == 1 ? " downgrade" : " downgrades");
need_comma = true;
}
- if (new_slot_count)
+ if (_new_slot_count)
{
if (need_comma)
cout << ", ";
- cout << new_slot_count << (new_slot_count == 1 ? " in new slot" : " in new slots");
+ cout << _new_slot_count << (_new_slot_count == 1 ? " in new slot" : " in new slots");
need_comma = true;
}
- if (rebuild_count)
+ if (_rebuild_count)
{
if (need_comma)
cout << ", ";
- cout << rebuild_count << (rebuild_count == 1 ? " rebuild" : " rebuilds");
+ cout << _rebuild_count << (_rebuild_count == 1 ? " rebuild" : " rebuilds");
need_comma = true;
}
cout << ")";
}
cout << endl << endl;
- if (CommandLine::get_instance()->a_pretend.specified() && ! all_tags.empty())
+ if (CommandLine::get_instance()->a_pretend.specified() && ! _all_tags.empty())
{
TagDisplayer tag_displayer;
std::set<std::string> tag_categories;
std::transform(
- p::indirect_iterator<const p::DepTag>(all_tags.begin()),
- p::indirect_iterator<const p::DepTag>(all_tags.end()),
+ indirect_iterator<const DepTag>(_all_tags.begin()),
+ indirect_iterator<const DepTag>(_all_tags.end()),
std::inserter(tag_categories, tag_categories.begin()),
- std::mem_fun_ref(&p::DepTag::category));
+ std::mem_fun_ref(&DepTag::category));
for (std::set<std::string>::iterator cat(tag_categories.begin()),
cat_end(tag_categories.end()) ; cat != cat_end ; ++cat)
{
- p::DepTagCategory::ConstPointer c(p::DepTagCategoryMaker::get_instance()->
+ DepTagCategory::ConstPointer c(DepTagCategoryMaker::get_instance()->
find_maker(*cat)());
if (! c->title().empty())
@@ -407,8 +309,8 @@ do_install()
if (! c->pre_text().empty())
cout << c->pre_text() << endl << endl;
- for (std::set<p::DepTag::ConstPointer, p::DepTag::Comparator>::const_iterator
- t(all_tags.begin()), t_end(all_tags.end()) ;
+ for (std::set<DepTag::ConstPointer, DepTag::Comparator>::const_iterator
+ t(_all_tags.begin()), t_end(_all_tags.end()) ;
t != t_end ; ++t)
{
if ((*t)->category() != *cat)
@@ -421,156 +323,223 @@ do_install()
cout << c->post_text() << endl << endl;
}
}
+ }
- if (CommandLine::get_instance()->a_pretend.specified())
+ void
+ OurInstallTask::on_display_merge_list_entry(const DepListEntry & d)
+ {
+ Context context("When displaying entry '" + stringify(d) + "':");
+
+ cout << "* " << colour(cl_package_name, d.get<dle_name>());
+
+ /* display version, unless it's 0 and our category is "virtual" */
+ if ((VersionSpec("0") != d.get<dle_version>()) ||
+ CategoryNamePart("virtual") != d.get<dle_name>().get<qpn_category>())
+ cout << "-" << d.get<dle_version>();
+
+ /* display repository, unless it's our main repository */
+ if (DefaultEnvironment::get_instance()->package_database()->favourite_repository() != d.get<dle_repository>())
+ cout << "::" << d.get<dle_repository>();
+
+ /* display slot name, unless it's 0 */
+ if (SlotName("0") != d.get<dle_metadata>()->get<vm_slot>())
+ cout << colour(cl_slot, " {:" + stringify(
+ d.get<dle_metadata>()->get<vm_slot>()) + "}");
+
+ /* indicate [U], [S] or [N]. display existing version, if we're
+ * already installed */
+ PackageDatabaseEntryCollection::Pointer existing(DefaultEnvironment::get_instance()->package_database()->
+ query(PackageDepAtom::Pointer(new PackageDepAtom(stringify(
+ d.get<dle_name>()))), is_installed_only));
+
+ if (existing->empty())
{
- env->perform_hook(p::Hook("install_pretend_post")("TARGETS", p::join(
- CommandLine::get_instance()->begin_parameters(),
- CommandLine::get_instance()->end_parameters(), " ")));
- return return_code;
+ cout << colour(cl_updatemode, " [N]");
+ ++_new_count;
+ ++_max_count;
}
-
- if (opts.get<p::io_fetchonly>())
- env->perform_hook(p::Hook("fetch_all_pre")("TARGETS", p::join(
- CommandLine::get_instance()->begin_parameters(),
- CommandLine::get_instance()->end_parameters(), " ")));
else
- env->perform_hook(p::Hook("install_all_pre")("TARGETS", p::join(
- CommandLine::get_instance()->begin_parameters(),
- CommandLine::get_instance()->end_parameters(), " ")));
-
- for (p::DepList::Iterator dep(dep_list.begin()), dep_end(dep_list.end()) ;
- dep != dep_end ; ++dep)
{
- std::string cpvr = p::stringify(dep->get<p::dle_name>()) + "-" +
- p::stringify(dep->get<p::dle_version>()) + "::" +
- p::stringify(dep->get<p::dle_repository>());
-
- if (opts.get<p::io_fetchonly>())
+ existing = DefaultEnvironment::get_instance()->package_database()->query(PackageDepAtom::Pointer(
+ new PackageDepAtom(stringify(d.get<dle_name>()) + ":" +
+ stringify(d.get<dle_metadata>()->get<vm_slot>()))),
+ is_installed_only);
+ if (existing->empty())
{
- cout << endl << colour(cl_heading, "Fetching " + cpvr) << endl << endl;
-
- // TODO: some way to reset this properly would be nice.
- cerr << xterm_title("(" + p::stringify(++current_count) + " of " +
- p::stringify(max_count) + ") Fetching " + cpvr);
-
+ cout << colour(cl_updatemode, " [S]");
+ ++_new_slot_count;
+ ++_max_count;
+ }
+ else if (existing->last()->get<pde_version>() < d.get<dle_version>())
+ {
+ cout << colour(cl_updatemode, " [U " + stringify(
+ existing->last()->get<pde_version>()) + "]");
+ ++_upgrade_count;
+ ++_max_count;
+ }
+ else if (existing->last()->get<pde_version>() > d.get<dle_version>())
+ {
+ cout << colour(cl_updatemode, " [D " + stringify(
+ existing->last()->get<pde_version>()) + "]");
+ ++_downgrade_count;
+ ++_max_count;
}
else
{
- cout << endl << colour(cl_heading,
- "Installing " + cpvr) << endl << endl;
+ cout << colour(cl_updatemode, " [R]");
+ ++_rebuild_count;
+ ++_max_count;
+ }
+ }
+
+ /* fetch db entry */
+ PackageDatabaseEntry p(PackageDatabaseEntry(d.get<dle_name>(),
+ d.get<dle_version>(), d.get<dle_repository>()));
+
+ /* display USE flags */
+ if (d.get<dle_metadata>()->get_ebuild_interface())
+ {
+ const Repository::UseInterface * const use_interface(
+ DefaultEnvironment::get_instance()->package_database()->fetch_repository(d.get<dle_repository>())->
+ get_interface<repo_use>());
+ std::set<UseFlagName> iuse;
+ WhitespaceTokeniser::get_instance()->tokenise(
+ d.get<dle_metadata>()->get_ebuild_interface()->get<evm_iuse>(),
+ create_inserter<UseFlagName>(std::inserter(iuse, iuse.end())));
+
+
+ /* display normal use flags first */
+ for (std::set<UseFlagName>::const_iterator i(iuse.begin()), i_end(iuse.end()) ;
+ i != i_end ; ++i)
+ {
+ if (use_interface->is_expand_flag(*i))
+ continue;
- // TODO: some way to reset this properly would be nice.
- cerr << xterm_title("(" + p::stringify(++current_count) + " of " +
- p::stringify(max_count) + ") Installing " + cpvr);
+ if (DefaultEnvironment::get_instance()->query_use(*i, &p))
+ {
+ if (use_interface && use_interface->query_use_force(*i, &p))
+ cout << " " << colour(cl_flag_on, "(" + stringify(*i) + ")");
+ else
+ cout << " " << colour(cl_flag_on, *i);
+ }
+ else
+ {
+ if (use_interface && use_interface->query_use_mask(*i, &p))
+ cout << " " << colour(cl_flag_off, "(-" + stringify(*i) + ")");
+ else
+ cout << " " << colour(cl_flag_off, "-" + stringify(*i));
+ }
}
- if (opts.get<p::io_fetchonly>())
- env->perform_hook(p::Hook("fetch_pre")("TARGET", cpvr));
- else
- env->perform_hook(p::Hook("install_pre")("TARGET", cpvr));
+ /* now display expand flags */
+ UseFlagName old_expand_name("OFTEN_NOT_BEEN_ON_BOATS");
+ for (std::set<UseFlagName>::const_iterator i(iuse.begin()), i_end(iuse.end()) ;
+ i != i_end ; ++i)
+ {
+ if ((! use_interface->is_expand_flag(*i)) ||
+ (use_interface->is_expand_hidden_flag(*i)))
+ continue;
- const p::Repository::InstallableInterface * const installable_interface(
- env->package_database()->fetch_repository(dep->get<p::dle_repository>())->
- get_interface<p::repo_installable>());
- if (! installable_interface)
- throw p::InternalError(PALUDIS_HERE, "Trying to install from a non-installable repository");
- installable_interface->install(dep->get<p::dle_name>(), dep->get<p::dle_version>(), opts);
+ UseFlagName expand_name(use_interface->expand_flag_name(*i)),
+ expand_value(use_interface->expand_flag_value(*i));
- if (opts.get<p::io_fetchonly>())
- env->perform_hook(p::Hook("fetch_post")("TARGET", cpvr));
- else
- env->perform_hook(p::Hook("install_post")("TARGET", cpvr));
-
- if (! opts.get<p::io_fetchonly>())
- {
- // figure out if we need to unmerge anything
- cout << endl << colour(cl_heading,
- "Cleaning stale versions after installing " + cpvr) << endl << endl;
-
- // manually invalidate any installed repos, they're probably
- // wrong now
- for (p::PackageDatabase::RepositoryIterator r(env->package_database()->begin_repositories()),
- r_end(env->package_database()->end_repositories()) ; r != r_end ; ++r)
- if ((*r)->get_interface<p::repo_installed>())
- (*r)->invalidate();
-
- // look for packages with the same name in the same slot
- p::PackageDatabaseEntryCollection::Pointer collision_list(env->package_database()->query(
- p::PackageDepAtom::Pointer(new p::PackageDepAtom(
- p::stringify(dep->get<p::dle_name>()) + ":" +
- p::stringify(dep->get<p::dle_metadata>()->get<p::vm_slot>()))),
- p::is_installed_only));
-
- // don't clean the thing we just installed
- p::PackageDatabaseEntryCollection::Concrete clean_list;
- for (p::PackageDatabaseEntryCollection::Iterator c(collision_list->begin()),
- c_end(collision_list->end()) ; c != c_end ; ++c)
- if (dep->get<p::dle_version>() != c->get<p::pde_version>())
- clean_list.insert(*c);
-
- if (clean_list.empty())
+ if (expand_name != old_expand_name)
{
- cout << "* No cleaning required" << endl;
+ cout << " " << expand_name << ":";
+ old_expand_name = expand_name;
+ }
+
+ if (DefaultEnvironment::get_instance()->query_use(*i, &p))
+ {
+ if (use_interface && use_interface->query_use_force(*i, &p))
+ cout << " " << colour(cl_flag_on, "(" + stringify(expand_value) + ")");
+ else
+ cout << " " << colour(cl_flag_on, expand_value);
}
else
{
- for (p::PackageDatabaseEntryCollection::Iterator c(clean_list.begin()),
- c_end(clean_list.end()) ; c != c_end ; ++c)
- cout << "* " << colour(cl_package_name, *c) << endl;
- cout << endl;
-
- p::PackageDatabaseEntryCollection::Iterator c(clean_list.begin()),
- c_end(clean_list.end());
- env->perform_hook(p::Hook("uninstall_all_pre")("TARGETS", p::join(c, c_end, " ")));
- for ( ; c != c_end ; ++c)
- {
- cout << endl << colour(cl_heading, "Cleaning " + p::stringify(*c)) << endl << endl;
-
- // TODO: some way to reset this properly would be nice.
- cerr << xterm_title("(" + p::stringify(current_count) + " of " +
- p::stringify(max_count) + ") Cleaning " + cpvr + ": " + stringify(*c));
-
- env->perform_hook(p::Hook("uninstall_pre")("TARGET", stringify(*c)));
-
- const p::Repository::UninstallableInterface * const uninstall_interface(
- env->package_database()->fetch_repository(c->get<p::pde_repository>())->
- get_interface<p::repo_uninstallable>());
- if (! uninstall_interface)
- throw p::InternalError(PALUDIS_HERE, "Trying to uninstall from a non-uninstallable repo");
- uninstall_interface->uninstall(c->get<p::pde_name>(), c->get<p::pde_version>(), opts);
- env->perform_hook(p::Hook("uninstall_post")("TARGET", stringify(*c)));
- }
- env->perform_hook(p::Hook("uninstall_all_pre")("TARGETS", p::join(c, c_end, " ")));
+ if (use_interface && use_interface->query_use_mask(*i, &p))
+ cout << " " << colour(cl_flag_off, "(-" + stringify(expand_value) + ")");
+ else
+ cout << " " << colour(cl_flag_off, "-" + stringify(expand_value));
}
}
}
- if ((! had_set_targets) &&
- (! CommandLine::get_instance()->a_pretend.specified()) &&
- (! opts.get<p::io_fetchonly>()))
+ /* display tag, add tag to our post display list */
+ if (! d.get<dle_tag>()->empty())
{
- cout << endl << colour(cl_heading, "Updating world file") << endl << endl;
- if (! CommandLine::get_instance()->a_preserve_world.specified())
- env->add_appropriate_to_world(targets, &world_add_callback,
- &world_skip_callback);
- else
- cout << "* --preserve-world was specified, skipping world adds" << endl;
+ std::string tag_titles;
+ for (SortedCollection<DepTag::ConstPointer, DepTag::Comparator>::Iterator
+ tag(d.get<dle_tag>()->begin()),
+ tag_end(d.get<dle_tag>()->end()) ;
+ tag != tag_end ; ++tag)
+ {
+ _all_tags.insert(*tag);
+ tag_titles.append((*tag)->short_text());
+ tag_titles.append(",");
+ }
+ tag_titles.erase(tag_titles.length() - 1);
+ cout << " " << colour(cl_tag, "<" + tag_titles + ">");
}
+ cout << endl;
+ }
+}
- if (opts.get<p::io_fetchonly>())
- env->perform_hook(p::Hook("fetch_all_post")("TARGETS", p::join(
- CommandLine::get_instance()->begin_parameters(),
- CommandLine::get_instance()->end_parameters(), " ")));
- else
- env->perform_hook(p::Hook("install_all_post")("TARGETS", p::join(
- CommandLine::get_instance()->begin_parameters(),
- CommandLine::get_instance()->end_parameters(), " ")));
+int
+do_install()
+{
+ int return_code(0);
+
+ Context context("When performing install action from command line:");
+
+ OurInstallTask task;
+
+ task.set_drop_self_circular(CommandLine::get_instance()->a_dl_drop_self_circular.specified());
+ task.set_drop_circular(CommandLine::get_instance()->a_dl_drop_circular.specified());
+ task.set_drop_all(CommandLine::get_instance()->a_dl_drop_all.specified());
+ task.set_ignore_installed(CommandLine::get_instance()->a_dl_ignore_installed.specified());
+ task.set_recursive_deps(! CommandLine::get_instance()->a_dl_no_recursive_deps.specified());
+ task.set_max_stack_depth(CommandLine::get_instance()->a_dl_max_stack_depth.argument());
+ task.set_no_unnecessary_upgrades(CommandLine::get_instance()->a_dl_no_unnecessary_upgrades.specified());
+
+ if (CommandLine::get_instance()->a_dl_rdepend_post.argument() == "always")
+ task.set_rdepend_post(dlro_always);
+ else if (CommandLine::get_instance()->a_dl_rdepend_post.argument() == "never")
+ task.set_rdepend_post(dlro_never);
+ else
+ task.set_rdepend_post(dlro_as_needed);
+
+ task.set_no_config_protect(CommandLine::get_instance()->a_no_config_protection.specified());
+ task.set_fetch_only(CommandLine::get_instance()->a_fetch.specified());
+ task.set_pretend(CommandLine::get_instance()->a_pretend.specified());
+ task.set_preserve_world(CommandLine::get_instance()->a_preserve_world.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 AmbiguousPackageNameError & e)
+ {
cout << endl;
+ cerr << "Query error:" << endl;
+ cerr << " * " << e.backtrace("\n * ");
+ cerr << "Ambiguous package name '" << e.name() << "'. Did you mean:" << endl;
+ for (AmbiguousPackageNameError::OptionsIterator o(e.begin_options()),
+ o_end(e.end_options()) ; o != o_end ; ++o)
+ cerr << " * " << colour(cl_package_name, *o) << endl;
+ cerr << endl;
+ return 1;
}
- catch (const p::PackageInstallActionError & e)
+ catch (const PackageInstallActionError & e)
{
cout << endl;
cerr << "Install error:" << endl;
@@ -579,7 +548,7 @@ do_install()
return_code |= 1;
}
- catch (const p::NoSuchPackageError & e)
+ catch (const NoSuchPackageError & e)
{
cout << endl;
cerr << "Query error:" << endl;
@@ -587,13 +556,14 @@ do_install()
cerr << "No such package '" << e.name() << "'" << endl;
return 1;
}
- catch (const p::AllMaskedError & e)
+ catch (const AllMaskedError & e)
{
try
{
- p::PackageDatabaseEntryCollection::ConstPointer p(env->package_database()->query(
- p::PackageDepAtom::ConstPointer(new p::PackageDepAtom(e.query())),
- p::is_uninstalled_only));
+ PackageDatabaseEntryCollection::ConstPointer p(
+ DefaultEnvironment::get_instance()->package_database()->query(
+ PackageDepAtom::ConstPointer(new PackageDepAtom(e.query())),
+ is_uninstalled_only));
if (p->empty())
{
cout << endl;
@@ -607,52 +577,54 @@ do_install()
cerr << "Query error:" << endl;
cerr << " * " << e.backtrace("\n * ");
cerr << "All versions of '" << e.query() << "' are masked. Candidates are:" << endl;
- for (p::PackageDatabaseEntryCollection::Iterator pp(p->begin()), pp_end(p->end()) ;
+ for (PackageDatabaseEntryCollection::Iterator pp(p->begin()), pp_end(p->end()) ;
pp != pp_end ; ++pp)
{
cerr << " * " << colour(cl_package_name, *pp) << ": Masked by ";
bool need_comma(false);
- p::MaskReasons m(env->mask_reasons(*pp));
+ MaskReasons m(DefaultEnvironment::get_instance()->mask_reasons(*pp));
for (unsigned mm = 0 ; mm < m.size() ; ++mm)
if (m[mm])
{
if (need_comma)
cerr << ", ";
- cerr << p::MaskReason(mm);
+ cerr << MaskReason(mm);
- if (p::mr_eapi == mm)
+ if (mr_eapi == mm)
{
- std::string eapi_str(env->package_database()->fetch_repository(
- pp->get<p::pde_repository>())->version_metadata(
- pp->get<p::pde_name>(), pp->get<p::pde_version>())->get<p::vm_eapi>());
+ std::string eapi_str(DefaultEnvironment::get_instance()->
+ package_database()->fetch_repository(
+ pp->get<pde_repository>())->version_metadata(
+ pp->get<pde_name>(), pp->get<pde_version>())->get<vm_eapi>());
cerr << " ( " << colour(cl_masked, eapi_str) << " )";
}
- else if (p::mr_license == mm)
+ else if (mr_license == mm)
{
cerr << " ";
- LicenceDisplayer ld(cerr, env, &*pp);
- env->package_database()->fetch_repository(
- pp->get<p::pde_repository>())->version_metadata(
- pp->get<p::pde_name>(), pp->get<p::pde_version>())->license()->
+ LicenceDisplayer ld(cerr, DefaultEnvironment::get_instance(), &*pp);
+ DefaultEnvironment::get_instance()->package_database()->fetch_repository(
+ pp->get<pde_repository>())->version_metadata(
+ pp->get<pde_name>(), pp->get<pde_version>())->license()->
accept(&ld);
}
- else if (p::mr_keyword == mm)
+ else if (mr_keyword == mm)
{
- p::VersionMetadata::ConstPointer m(env->package_database()->fetch_repository(
- pp->get<p::pde_repository>())->version_metadata(
- pp->get<p::pde_name>(), pp->get<p::pde_version>()));
+ VersionMetadata::ConstPointer m(DefaultEnvironment::get_instance()->
+ package_database()->fetch_repository(
+ pp->get<pde_repository>())->version_metadata(
+ pp->get<pde_name>(), pp->get<pde_version>()));
if (m->get_ebuild_interface())
{
- std::set<p::KeywordName> keywords;
- p::WhitespaceTokeniser::get_instance()->tokenise(
- m->get_ebuild_interface()->get<p::evm_keywords>(),
- p::create_inserter<p::KeywordName>(
+ std::set<KeywordName> keywords;
+ WhitespaceTokeniser::get_instance()->tokenise(
+ m->get_ebuild_interface()->get<evm_keywords>(),
+ create_inserter<KeywordName>(
std::inserter(keywords, keywords.end())));
- cerr << " ( " << colour(cl_masked, p::join(keywords.begin(),
+ cerr << " ( " << colour(cl_masked, join(keywords.begin(),
keywords.end(), " ")) << " )";
}
}
@@ -670,7 +642,7 @@ do_install()
return 1;
}
- catch (const p::UseRequirementsNotMetError & e)
+ catch (const UseRequirementsNotMetError & e)
{
cout << endl;
cerr << "DepList USE requirements not met error:" << endl;
@@ -684,7 +656,7 @@ do_install()
return_code |= 1;
}
- catch (const p::DepListStackTooDeepError & e)
+ catch (const DepListStackTooDeepError & e)
{
cout << endl;
cerr << "DepList stack too deep error:" << endl;
@@ -696,7 +668,7 @@ do_install()
return_code |= 1;
}
- catch (const p::DepListError & e)
+ catch (const DepListError & e)
{
cout << endl;
cerr << "Dependency error:" << endl;
@@ -706,6 +678,26 @@ do_install()
return_code |= 1;
}
+ catch (const HadBothPackageAndSetTargets &)
+ {
+ cout << endl;
+ cerr << "Error: both package sets and packages were specified." << endl;
+ cerr << endl;
+ cerr << "Package sets (like 'system' and 'world') cannot be installed at the same time" << endl;
+ cerr << "as ordinary packages." << endl;
+
+ return_code |= 1;
+ }
+ catch (const MultipleSetTargetsSpecified &)
+ {
+ cout << endl;
+ cerr << "Error: multiple package sets were specified." << endl;
+ cerr << endl;
+ cerr << "Package sets (like 'system' and 'world') must be installed individually," << endl;
+ cerr << "without any other sets or packages." << endl;
+
+ return_code |= 1;
+ }
return return_code;
}
diff --git a/src/paludis/uninstall.cc b/src/paludis/uninstall.cc
index bf24ebd..fc2205d 100644
--- a/src/paludis/uninstall.cc
+++ b/src/paludis/uninstall.cc
@@ -35,10 +35,14 @@ using std::endl;
namespace
{
- void world_remove_callback(const p::PackageDepAtom * const p)
+ struct WorldCallbacks :
+ public p::Environment::WorldCallbacks
{
- cout << "* removing " << colour(cl_package_name, stringify(*p)) << endl;
- }
+ void remove_callback(const p::PackageDepAtom * const p)
+ {
+ cout << "* removing " << colour(cl_package_name, stringify(*p)) << endl;
+ }
+ };
}
int
@@ -114,7 +118,8 @@ do_uninstall()
t_end(targets.end()) ; t != t_end ; ++t)
all->add_child(*t);
- env->remove_appropriate_from_world(all, &world_remove_callback);
+ WorldCallbacks w;
+ env->remove_appropriate_from_world(all, &w);
}
else
cout << "* --preserve-world was specified, skipping world removes" << endl;