aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-02-22 21:13:28 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-02-22 21:13:28 +0000
commite52c3390245661351753cec5439635ce0e5b9385 (patch)
treeb967e636f5eb8476c1417208e10ec2cd22eb8f9b
parentab61bf146de0fafba0560241e0139bf3e2165044 (diff)
parente5c1faf7cfe38630d1e7d1bb430fe2d841af94a3 (diff)
downloadpaludis-e52c3390245661351753cec5439635ce0e5b9385.tar.gz
paludis-e52c3390245661351753cec5439635ce0e5b9385.tar.xz
Merge branch 'uninstall-as-part-of-install'
-rw-r--r--paludis/action.hh33
-rw-r--r--paludis/install_task.cc138
-rw-r--r--paludis/install_task.hh11
-rw-r--r--paludis/merger.cc6
-rw-r--r--paludis/repositories/accounts/accounts_id.cc37
-rw-r--r--paludis/repositories/e/e_installed_repository.hh3
-rw-r--r--paludis/repositories/e/e_installed_repository_id.cc3
-rw-r--r--paludis/repositories/e/e_repository_TEST.cc28
-rw-r--r--paludis/repositories/e/e_repository_TEST_ever.cc13
-rw-r--r--paludis/repositories/e/e_repository_TEST_exlibs.cc9
-rw-r--r--paludis/repositories/e/ebuild_entries.cc52
-rw-r--r--paludis/repositories/e/exndbam_repository.cc11
-rw-r--r--paludis/repositories/e/exndbam_repository.hh3
-rw-r--r--paludis/repositories/e/exndbam_repository_TEST.cc14
-rw-r--r--paludis/repositories/e/vdb_repository.cc15
-rw-r--r--paludis/repositories/e/vdb_repository.hh3
-rw-r--r--paludis/repositories/e/vdb_repository_TEST.cc33
-rw-r--r--paludis/repositories/unpackaged/installed_repository_TEST.cc23
-rw-r--r--paludis/repositories/unpackaged/unpackaged_id.cc43
-rw-r--r--paludis/repositories/unpackaged/unpackaged_repository_TEST.cc12
-rw-r--r--paludis/repository.hh12
-rw-r--r--paludis/uninstall_task.cc1
-rw-r--r--python/action.cc14
-rw-r--r--ruby/action.cc16
-rw-r--r--src/output/console_install_task.cc55
-rw-r--r--src/output/console_install_task.hh15
26 files changed, 354 insertions, 249 deletions
diff --git a/paludis/action.hh b/paludis/action.hh
index fd1f436..a8b1957 100644
--- a/paludis/action.hh
+++ b/paludis/action.hh
@@ -54,11 +54,13 @@ namespace paludis
struct failed_automatic_fetching;
struct failed_integrity_checks;
struct fetch_unneeded;
+ struct is_overwrite;
struct make_output_manager;
+ struct perform_uninstall;
+ struct replacing;
struct requires_manual_fetching;
struct safe_resume;
struct target_file;
- struct used_this_for_config_protect;
struct want_phase;
}
@@ -109,8 +111,27 @@ namespace paludis
*/
NamedValue<n::make_output_manager, std::tr1::function<std::tr1::shared_ptr<OutputManager> (
const InstallAction &)> > make_output_manager;
+ /**
+ * Callback to carry out an uninstall, for replacing.
+ *
+ * Won't necessarily be used. Some repositories have special code paths
+ * for reinstalls, and in some cases (e.g. accounts) an upgrade doesn't
+ * remove the old version at all.
+ *
+ * \since 0.36
+ */
+ NamedValue<n::perform_uninstall, std::tr1::function<void (
+ const std::tr1::shared_ptr<const PackageID> &,
+ const UninstallActionOptions &
+ )> > perform_uninstall;
+
+ /**
+ * We must replace these.
+ *
+ * \since 0.36
+ */
+ NamedValue<n::replacing, std::tr1::shared_ptr<const PackageIDSequence> > replacing;
- NamedValue<n::used_this_for_config_protect, std::tr1::function<void (const std::string &)> > used_this_for_config_protect;
NamedValue<n::want_phase, std::tr1::function<WantPhase (const std::string &)> > want_phase;
};
@@ -126,6 +147,14 @@ namespace paludis
NamedValue<n::config_protect, std::string> config_protect;
/**
+ * Some repositories need to do special handlings for direct overwrites
+ * (foo-1.2 replacing foo-1.2). Clients should set this to false.
+ *
+ * \since 0.36
+ */
+ NamedValue<n::is_overwrite, bool> is_overwrite;
+
+ /**
* This is a function to avoid chicken / egg problems when using
* Environment::create_output_manager.
*
diff --git a/paludis/install_task.cc b/paludis/install_task.cc
index bd48140..975717c 100644
--- a/paludis/install_task.cc
+++ b/paludis/install_task.cc
@@ -126,8 +126,6 @@ namespace paludis
Environment * const env;
DepList dep_list;
- std::string config_protect;
-
std::list<std::string> raw_targets;
std::tr1::shared_ptr<SetSpecTree> targets;
std::tr1::shared_ptr<std::string> add_to_world_spec;
@@ -158,7 +156,6 @@ namespace paludis
std::tr1::shared_ptr<const DestinationsSet> d) :
env(e),
dep_list(e, o),
- config_protect(""),
targets(new SetSpecTree(make_shared_ptr(new AllDepSpec))),
destinations(d),
pretend(false),
@@ -178,11 +175,6 @@ namespace paludis
had_resolution_failures(false)
{
}
-
- void assign_config_protect(const std::string & s)
- {
- config_protect = s;
- }
};
}
@@ -726,6 +718,39 @@ InstallTask::_pretend()
}
void
+InstallTask::_clean(
+ const DepList::Iterator dep,
+ const std::tr1::shared_ptr<const PackageID> & id,
+ const UninstallActionOptions & options,
+ const std::string & cpvr,
+ const int x, const int y, const int s, const int f)
+{
+ /* clean one item */
+ if (0 != perform_hook(Hook("clean_pre")("TARGET", stringify(*id))
+ ("X_OF_Y", stringify(x) + " of " + stringify(y))).max_exit_status())
+ throw InstallActionError("Clean of '" + cpvr + "' aborted by hook");
+ on_clean_pre(*dep, *id, x, y, s, f);
+
+ try
+ {
+ UninstallAction uninstall_action(options);
+ id->perform_action(uninstall_action);
+ }
+ catch (const UninstallActionError & e)
+ {
+ on_clean_fail(*dep, *id, x, y, s, f);
+ HookResult PALUDIS_ATTRIBUTE((unused)) dummy(perform_hook(Hook("clean_fail")
+ ("TARGET", stringify(*id))("MESSAGE", e.message())));
+ throw;
+ }
+
+ on_clean_post(*dep, *id, x, y, s, f);
+ if (0 != perform_hook(Hook("clean_post")("TARGET", stringify(*id))
+ ("X_OF_Y", stringify(x) + " of " + stringify(y))).max_exit_status())
+ throw InstallActionError("Clean of '" + cpvr + "' aborted by hook");
+}
+
+void
InstallTask::_one(const DepList::Iterator dep, const int x, const int y, const int s, const int f, const bool is_first, const bool is_last,
std::tr1::shared_ptr<OutputManagerFromEnvironment> & output_manager_holder)
{
@@ -780,12 +805,24 @@ InstallTask::_one(const DepList::Iterator dep, const int x, const int y, const i
{
output_manager_holder.reset(new OutputManagerFromEnvironment(_imp->env, dep->package_id(), oe_exclusive));
+ std::tr1::shared_ptr<PackageIDSequence> replacing;
+
+ // look for packages with the same name in the same slot in the destination repos
+ if (dep->destination())
+ replacing = (*_imp->env)[selection::AllVersionsSorted(
+ (generator::Package(dep->package_id()->name()) &
+ generator::InRepository(dep->destination()->name())) |
+ filter::SupportsAction<UninstallAction>() |
+ filter::SameSlot(dep->package_id()))];
+ else
+ replacing.reset(new PackageIDSequence);
+
InstallActionOptions install_options(make_named_values<InstallActionOptions>(
value_for<n::destination>(dep->destination()),
value_for<n::make_output_manager>(std::tr1::ref(*output_manager_holder)),
- value_for<n::used_this_for_config_protect>(std::tr1::bind(
- &Implementation<InstallTask>::assign_config_protect,
- _imp.get(), std::tr1::placeholders::_1)),
+ value_for<n::perform_uninstall>(std::tr1::bind(&InstallTask::_clean, this, dep,
+ std::tr1::placeholders::_1, std::tr1::placeholders::_2, cpvr, x, y, s, f)),
+ value_for<n::replacing>(replacing),
value_for<n::want_phase>(std::tr1::function<WantPhase (const std::string &)>())
));
@@ -847,90 +884,11 @@ InstallTask::_one(const DepList::Iterator dep, const int x, const int y, const i
if (_imp->fetch_only || ! live_destination)
return;
- /* figure out whether we need to unmerge (clean) anything */
- on_build_cleanlist_pre(*dep);
-
// manually invalidate repos, they're probably wrong now
for (PackageDatabase::RepositoryConstIterator r(_imp->env->package_database()->begin_repositories()),
r_end(_imp->env->package_database()->end_repositories()) ; r != r_end ; ++r)
(*r)->invalidate();
- // look for packages with the same name in the same slot in the destination repos
- std::tr1::shared_ptr<const PackageIDSequence> collision_list;
-
- if (dep->destination())
- collision_list = (*_imp->env)[selection::AllVersionsSorted(
- (generator::Package(dep->package_id()->name()) &
- generator::InRepository(dep->destination()->name())) |
- filter::SupportsAction<UninstallAction>() |
- filter::SameSlot(dep->package_id()))];
-
- // don't clean the thing we just installed
- PackageIDSequence clean_list;
- if (collision_list)
- for (PackageIDSequence::ConstIterator c(collision_list->begin()),
- c_end(collision_list->end()) ; c != c_end ; ++c)
- if (dep->package_id()->version() != (*c)->version())
- clean_list.push_back(*c);
- /* no need to sort clean_list here, although if the above is
- * changed then check that this still holds... */
-
- on_build_cleanlist_post(*dep);
-
- /* ok, we have the cleanlist. we're about to clean */
- if (clean_list.empty())
- on_no_clean_needed(*dep);
- else
- {
- if (0 != perform_hook(Hook("clean_all_pre")
- ("TARGETS", join(indirect_iterator(clean_list.begin()), indirect_iterator(clean_list.end()), " "))
- ).max_exit_status())
- throw InstallActionError("Clean aborted by hook");
- on_clean_all_pre(*dep, clean_list);
-
- for (PackageIDSequence::ConstIterator c(clean_list.begin()),
- c_end(clean_list.end()) ; c != c_end ; ++c)
- {
- /* clean one item */
- if (0 != perform_hook(Hook("clean_pre")("TARGET", stringify(**c))
- ("X_OF_Y", stringify(x) + " of " + stringify(y))).max_exit_status())
- throw InstallActionError("Clean of '" + cpvr + "' aborted by hook");
- on_clean_pre(*dep, **c, x, y, s, f);
-
- try
- {
- output_manager_holder.reset(new OutputManagerFromEnvironment(_imp->env, dep->package_id(), oe_exclusive));
- UninstallAction uninstall_action(
- make_named_values<UninstallActionOptions>(
- value_for<n::config_protect>(_imp->config_protect),
- value_for<n::make_output_manager>(std::tr1::ref(*output_manager_holder))
- ));
- (*c)->perform_action(uninstall_action);
- if (output_manager_holder->output_manager_if_constructed())
- output_manager_holder->output_manager_if_constructed()->succeeded();
- output_manager_holder.reset();
- }
- catch (const UninstallActionError & e)
- {
- on_clean_fail(*dep, **c, x, y, s, f);
- HookResult PALUDIS_ATTRIBUTE((unused)) dummy(perform_hook(Hook("clean_fail")
- ("TARGET", stringify(**c))("MESSAGE", e.message())));
- throw;
- }
-
- on_clean_post(*dep, **c, x, y, s, f);
- if (0 != perform_hook(Hook("clean_post")("TARGET", stringify(**c))
- ("X_OF_Y", stringify(x) + " of " + stringify(y))).max_exit_status())
- throw InstallActionError("Clean of '" + cpvr + "' aborted by hook");
- }
-
- /* we're done cleaning */
- if (0 != perform_hook(Hook("clean_all_post")("TARGETS", join(
- indirect_iterator(clean_list.begin()), indirect_iterator(clean_list.end()), " "))).max_exit_status())
- throw InstallActionError("Clean aborted by hook");
- on_clean_all_post(*dep, clean_list);
- }
-
dep->handled().reset(new DepListEntryHandledSuccess);
/* if we installed paludis and a re-exec is available, use it. */
diff --git a/paludis/install_task.hh b/paludis/install_task.hh
index e733324..f3a4f37 100644
--- a/paludis/install_task.hh
+++ b/paludis/install_task.hh
@@ -65,6 +65,9 @@ namespace paludis
void _main_actions();
void _one(const DepList::Iterator, const int, const int, const int, const int, const bool is_first, const bool is_last,
std::tr1::shared_ptr<OutputManagerFromEnvironment> &);
+ void _clean(const DepList::Iterator, const std::tr1::shared_ptr<const PackageID> & id,
+ const UninstallActionOptions &,
+ const std::string & cpvr, const int x, const int y, const int s, const int f);
void _display_failure_summary();
void _add_target(const std::string &);
@@ -136,9 +139,6 @@ namespace paludis
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;
@@ -175,9 +175,6 @@ namespace paludis
const int x, const int y, const int s, const int f) = 0;
virtual void on_skip_already_done(const DepListEntry &, const int, const int, const int, const int) = 0;
- virtual void on_no_clean_needed(const DepListEntry &) = 0;
- virtual void on_clean_all_pre(const DepListEntry &,
- const PackageIDSequence &) = 0;
virtual void on_clean_pre(const DepListEntry &,
const PackageID &,
const int x, const int y, const int s, const int f) = 0;
@@ -187,8 +184,6 @@ namespace paludis
virtual void on_clean_fail(const DepListEntry &,
const PackageID &,
const int x, const int y, const int s, const int f) = 0;
- virtual void on_clean_all_post(const DepListEntry &,
- const PackageIDSequence &) = 0;
virtual void on_update_world_pre() = 0;
virtual void on_update_world(const PackageDepSpec &) = 0;
diff --git a/paludis/merger.cc b/paludis/merger.cc
index 9ec76ac..0932b74 100644
--- a/paludis/merger.cc
+++ b/paludis/merger.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
* Copyright (c) 2008 Fernando J. Pereda
*
* This file is part of the Paludis package manager. Paludis is free software;
@@ -968,7 +968,9 @@ Merger::install_dir(const FSEntry & src, const FSEntry & dst_dir)
if ( !S_ISDIR(sb.st_mode))
throw MergerError("The directory that we just created is not a directory anymore");
if (! _imp->params.no_chown())
- ::fchown(dst_fd, src.owner(), src.group());
+ if (-1 == ::fchown(dst_fd, src.owner(), src.group()))
+ throw MergerError("Could not fchown the directory '" + stringify(dst) + "' that we just created: "
+ + stringify(::strerror(errno)));
/* pick up set*id bits */
::fchmod(dst_fd, mode);
try_to_copy_xattrs(src, dst_fd, result);
diff --git a/paludis/repositories/accounts/accounts_id.cc b/paludis/repositories/accounts/accounts_id.cc
index a306a69..a89cc84 100644
--- a/paludis/repositories/accounts/accounts_id.cc
+++ b/paludis/repositories/accounts/accounts_id.cc
@@ -421,6 +421,19 @@ AccountsID::supports_action(const SupportsActionTestBase & test) const
return simple_visitor_cast<const SupportsActionTest<InstallAction> >(test);
}
+namespace
+{
+ std::tr1::shared_ptr<OutputManager> this_output_manager(const std::tr1::shared_ptr<OutputManager> & o, const Action &)
+ {
+ return o;
+ }
+
+ void used_this_for_config_protect(std::string & s, const std::string & v)
+ {
+ s = v;
+ }
+}
+
void
AccountsID::perform_action(Action & action) const
{
@@ -436,6 +449,8 @@ AccountsID::perform_action(Action & action) const
std::tr1::shared_ptr<OutputManager> output_manager(install_action->options.make_output_manager()(
*install_action));
+ std::string used_config_protect;
+
switch (install_action->options.want_phase()("merge"))
{
case wp_yes:
@@ -447,7 +462,9 @@ AccountsID::perform_action(Action & action) const
value_for<n::options>(MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs),
value_for<n::output_manager>(output_manager),
value_for<n::package_id>(shared_from_this()),
- value_for<n::used_this_for_config_protect>(install_action->options.used_this_for_config_protect())
+ value_for<n::perform_uninstall>(install_action->options.perform_uninstall()),
+ value_for<n::used_this_for_config_protect>(std::tr1::bind(
+ &used_this_for_config_protect, std::tr1::ref(used_config_protect), std::tr1::placeholders::_1))
));
}
break;
@@ -462,6 +479,24 @@ AccountsID::perform_action(Action & action) const
throw InternalError(PALUDIS_HERE, "bad WantPhase");
}
+ for (PackageIDSequence::ConstIterator i(install_action->options.replacing()->begin()), i_end(install_action->options.replacing()->end()) ;
+ i != i_end ; ++i)
+ {
+ Context local_context("When cleaning '" + stringify(**i) + "':");
+ if ((*i)->repository()->format_key() && (*i)->repository()->format_key()->value() == "installed-accounts"
+ && (*i)->name() == name())
+ continue;
+ else
+ {
+ UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
+ value_for<n::config_protect>(used_config_protect),
+ value_for<n::is_overwrite>(false),
+ value_for<n::make_output_manager>(std::tr1::bind(&this_output_manager, output_manager, std::tr1::placeholders::_1))
+ ));
+ install_action->options.perform_uninstall()(*i, uo);
+ }
+ }
+
output_manager->succeeded();
}
diff --git a/paludis/repositories/e/e_installed_repository.hh b/paludis/repositories/e/e_installed_repository.hh
index 1368de1..ca1adba 100644
--- a/paludis/repositories/e/e_installed_repository.hh
+++ b/paludis/repositories/e/e_installed_repository.hh
@@ -99,8 +99,7 @@ namespace paludis
virtual void perform_uninstall(
const std::tr1::shared_ptr<const erepository::ERepositoryID> & id,
- const UninstallAction &,
- bool reinstalling) const = 0;
+ const UninstallAction &) const = 0;
virtual void perform_config(
const std::tr1::shared_ptr<const erepository::ERepositoryID> & id,
diff --git a/paludis/repositories/e/e_installed_repository_id.cc b/paludis/repositories/e/e_installed_repository_id.cc
index 5cac0e3..d7c8e3e 100644
--- a/paludis/repositories/e/e_installed_repository_id.cc
+++ b/paludis/repositories/e/e_installed_repository_id.cc
@@ -876,8 +876,7 @@ namespace
void visit(const UninstallAction & a)
{
- std::tr1::static_pointer_cast<const EInstalledRepository>(id->repository())->perform_uninstall(
- id, a, false);
+ std::tr1::static_pointer_cast<const EInstalledRepository>(id->repository())->perform_uninstall(id, a);
}
void visit(const InstalledAction &)
diff --git a/paludis/repositories/e/e_repository_TEST.cc b/paludis/repositories/e/e_repository_TEST.cc
index 2c152c5..4021075 100644
--- a/paludis/repositories/e/e_repository_TEST.cc
+++ b/paludis/repositories/e/e_repository_TEST.cc
@@ -58,6 +58,12 @@ using namespace paludis;
namespace
{
+ void cannot_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions &)
+ {
+ if (id)
+ throw InternalError(PALUDIS_HERE, "cannot uninstall");
+ }
+
std::tr1::shared_ptr<OutputManager> make_standard_output_manager(const Action &)
{
return make_shared_ptr(new StandardOutputManager);
@@ -73,10 +79,6 @@ namespace
return mm->second;
}
- void dummy_used_this_for_config_protect(const std::string &)
- {
- }
-
WantPhase want_all_phases(const std::string &)
{
return wp_yes;
@@ -1106,7 +1108,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
@@ -1362,7 +1365,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
@@ -1457,7 +1461,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
@@ -1582,7 +1587,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
@@ -1788,7 +1794,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
@@ -2371,7 +2378,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
diff --git a/paludis/repositories/e/e_repository_TEST_ever.cc b/paludis/repositories/e/e_repository_TEST_ever.cc
index 8dccca8..830cba8 100644
--- a/paludis/repositories/e/e_repository_TEST_ever.cc
+++ b/paludis/repositories/e/e_repository_TEST_ever.cc
@@ -58,6 +58,12 @@ using namespace paludis;
namespace
{
+ void cannot_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions &)
+ {
+ if (id)
+ throw InternalError(PALUDIS_HERE, "cannot uninstall");
+ }
+
std::tr1::shared_ptr<OutputManager> make_standard_output_manager(const Action &)
{
return make_shared_ptr(new StandardOutputManager);
@@ -73,10 +79,6 @@ namespace
return mm->second;
}
- void dummy_used_this_for_config_protect(const std::string &)
- {
- }
-
WantPhase want_all_phases(const std::string &)
{
return wp_yes;
@@ -146,7 +148,8 @@ namespace
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
diff --git a/paludis/repositories/e/e_repository_TEST_exlibs.cc b/paludis/repositories/e/e_repository_TEST_exlibs.cc
index 19e5396..1dbead3 100644
--- a/paludis/repositories/e/e_repository_TEST_exlibs.cc
+++ b/paludis/repositories/e/e_repository_TEST_exlibs.cc
@@ -58,6 +58,12 @@ using namespace paludis;
namespace
{
+ void cannot_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions &)
+ {
+ if (id)
+ throw InternalError(PALUDIS_HERE, "cannot uninstall");
+ }
+
std::tr1::shared_ptr<OutputManager> make_standard_output_manager(const Action &)
{
return make_shared_ptr(new StandardOutputManager);
@@ -136,7 +142,8 @@ namespace
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
diff --git a/paludis/repositories/e/ebuild_entries.cc b/paludis/repositories/e/ebuild_entries.cc
index 3f9f681..c8a0e23 100644
--- a/paludis/repositories/e/ebuild_entries.cc
+++ b/paludis/repositories/e/ebuild_entries.cc
@@ -524,13 +524,38 @@ EbuildEntries::pretend_fetch(const std::tr1::shared_ptr<const ERepositoryID> & i
}
}
+namespace
+{
+ bool slot_is_same(const std::tr1::shared_ptr<const PackageID> & a,
+ const std::tr1::shared_ptr<const PackageID> & b)
+ {
+ if (a->slot_key())
+ return b->slot_key() && a->slot_key()->value() == b->slot_key()->value();
+ else
+ return ! b->slot_key();
+ }
+
+ void used_this_for_config_protect(std::string & s, const std::string & v)
+ {
+ s = v;
+ }
+
+ std::tr1::shared_ptr<OutputManager> this_output_manager(const std::tr1::shared_ptr<OutputManager> & o, const Action &)
+ {
+ return o;
+ }
+}
+
void
EbuildEntries::install(const std::tr1::shared_ptr<const ERepositoryID> & id,
const InstallAction & install_action, const std::tr1::shared_ptr<const ERepositoryProfile> & p) const
{
using namespace std::tr1::placeholders;
- Context context("When installing '" + stringify(*id) + "':");
+ Context context("When installing '" + stringify(*id) + "'" +
+ (install_action.options.replacing()->empty() ? "" : " replacing { '"
+ + join(indirect_iterator(install_action.options.replacing()->begin()),
+ indirect_iterator(install_action.options.replacing()->end()), "', '") + "' }") + ":");
std::tr1::shared_ptr<OutputManager> output_manager(install_action.options.make_output_manager()(install_action));
@@ -624,6 +649,8 @@ EbuildEntries::install(const std::tr1::shared_ptr<const ERepositoryID> & id,
FSEntry package_builddir(_imp->params.builddir() / (stringify(id->name().category()) + "-" +
stringify(id->name().package()) + "-" + stringify(id->version())));
+ std::string used_config_protect;
+
EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_install());
for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
phase != phase_end ; ++phase)
@@ -673,7 +700,9 @@ EbuildEntries::install(const std::tr1::shared_ptr<const ERepositoryID> & id,
value_for<n::options>(id->eapi()->supported()->merger_options()),
value_for<n::output_manager>(output_manager),
value_for<n::package_id>(id),
- value_for<n::used_this_for_config_protect>(install_action.options.used_this_for_config_protect())
+ value_for<n::perform_uninstall>(install_action.options.perform_uninstall()),
+ value_for<n::used_this_for_config_protect>(std::tr1::bind(
+ &used_this_for_config_protect, std::tr1::ref(used_config_protect), std::tr1::placeholders::_1))
));
}
else if (phase->option("strip"))
@@ -776,6 +805,25 @@ EbuildEntries::install(const std::tr1::shared_ptr<const ERepositoryID> & id,
}
}
+ for (PackageIDSequence::ConstIterator i(install_action.options.replacing()->begin()), i_end(install_action.options.replacing()->end()) ;
+ i != i_end ; ++i)
+ {
+ Context local_context("When cleaning '" + stringify(**i) + "':");
+ if ((*i)->name() == id->name() && (*i)->version() == id->version())
+ continue;
+
+ if (id->eapi()->supported()->ebuild_phases()->ebuild_new_upgrade_phase_order())
+ if ((*i)->name() == id->name() && slot_is_same(*i, id))
+ continue;
+
+ UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
+ value_for<n::config_protect>(used_config_protect),
+ value_for<n::is_overwrite>(false),
+ value_for<n::make_output_manager>(std::tr1::bind(&this_output_manager, output_manager, std::tr1::placeholders::_1))
+ ));
+ install_action.options.perform_uninstall()(*i, uo);
+ }
+
output_manager->succeeded();
}
diff --git a/paludis/repositories/e/exndbam_repository.cc b/paludis/repositories/e/exndbam_repository.cc
index 67821f8..f50db36 100644
--- a/paludis/repositories/e/exndbam_repository.cc
+++ b/paludis/repositories/e/exndbam_repository.cc
@@ -412,9 +412,10 @@ ExndbamRepository::merge(const MergeParams & m)
{
UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(config_protect),
+ value_for<n::is_overwrite>(true),
value_for<n::make_output_manager>(std::tr1::bind(&this_output_manager, m.output_manager(), std::tr1::placeholders::_1))
));
- perform_uninstall(std::tr1::static_pointer_cast<const ERepositoryID>(if_overwritten_id), uo, true);
+ m.perform_uninstall()(if_overwritten_id, uo);
}
if (std::tr1::static_pointer_cast<const ERepositoryID>(m.package_id())
@@ -429,9 +430,10 @@ ExndbamRepository::merge(const MergeParams & m)
{
UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(config_protect),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(std::tr1::bind(&this_output_manager, m.output_manager(), std::tr1::placeholders::_1))
));
- perform_uninstall(candidate, uo, false);
+ m.perform_uninstall()(candidate, uo);
}
}
}
@@ -447,10 +449,9 @@ ExndbamRepository::merge(const MergeParams & m)
void
ExndbamRepository::perform_uninstall(
const std::tr1::shared_ptr<const ERepositoryID> & id,
- const UninstallAction & a,
- bool replace) const
+ const UninstallAction & a) const
{
- Context context("When uninstalling '" + stringify(*id) + (replace ? "' for a reinstall:" : "':"));
+ Context context("When uninstalling '" + stringify(*id) + (a.options.is_overwrite() ? "' for an overwrite:" : "':"));
if (! _imp->params.root().is_directory())
throw InstallActionError("Couldn't uninstall '" + stringify(*id) +
diff --git a/paludis/repositories/e/exndbam_repository.hh b/paludis/repositories/e/exndbam_repository.hh
index f5212ff..609f5ed 100644
--- a/paludis/repositories/e/exndbam_repository.hh
+++ b/paludis/repositories/e/exndbam_repository.hh
@@ -117,8 +117,7 @@ namespace paludis
void perform_uninstall(
const std::tr1::shared_ptr<const erepository::ERepositoryID> & id,
- const UninstallAction &,
- bool reinstalling) const;
+ const UninstallAction &) const;
///\}
diff --git a/paludis/repositories/e/exndbam_repository_TEST.cc b/paludis/repositories/e/exndbam_repository_TEST.cc
index 71c81dd..d03bd5f 100644
--- a/paludis/repositories/e/exndbam_repository_TEST.cc
+++ b/paludis/repositories/e/exndbam_repository_TEST.cc
@@ -40,6 +40,12 @@ using namespace paludis;
namespace
{
+ void do_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions & u)
+ {
+ UninstallAction a(u);
+ id->perform_action(a);
+ }
+
std::tr1::shared_ptr<OutputManager> make_standard_output_manager(const Action &)
{
return make_shared_ptr(new StandardOutputManager);
@@ -55,10 +61,6 @@ namespace
return mm->second;
}
- void dummy_used_this_for_config_protect(const std::string &)
- {
- }
-
WantPhase want_all_phases(const std::string &)
{
return wp_yes;
@@ -130,12 +132,14 @@ namespace test_cases
InstallAction install_action(make_named_values<InstallActionOptions>(
value_for<n::destination>(exndbam_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&do_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
UninstallAction uninstall_action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
diff --git a/paludis/repositories/e/vdb_repository.cc b/paludis/repositories/e/vdb_repository.cc
index 6a83bad..c0007b2 100644
--- a/paludis/repositories/e/vdb_repository.cc
+++ b/paludis/repositories/e/vdb_repository.cc
@@ -375,10 +375,9 @@ VDBRepositoryKeyReadError::VDBRepositoryKeyReadError(
void
VDBRepository::perform_uninstall(
const std::tr1::shared_ptr<const ERepositoryID> & id,
- const UninstallAction & a,
- bool reinstalling) const
+ const UninstallAction & a) const
{
- Context context("When uninstalling '" + stringify(*id) + (reinstalling ? "' for a reinstall:" : "':"));
+ Context context("When uninstalling '" + stringify(*id) + (a.options.is_overwrite() ? "' for an overwrite:" : "':"));
if (! _imp->params.root().is_directory())
throw InstallActionError("Couldn't uninstall '" + stringify(*id) +
@@ -386,7 +385,7 @@ VDBRepository::perform_uninstall(
std::tr1::shared_ptr<OutputManager> output_manager(a.options.make_output_manager()(a));
- std::string reinstalling_str(reinstalling ? "-reinstalling-" : "");
+ std::string reinstalling_str(a.options.is_overwrite() ? "-reinstalling-" : "");
std::tr1::shared_ptr<FSEntrySequence> eclassdirs(new FSEntrySequence);
eclassdirs->push_back(FSEntry(_imp->params.location() / stringify(id->name().category()) /
@@ -484,7 +483,7 @@ VDBRepository::perform_uninstall(
FSEntry(*d).unlink();
pkg_dir.rmdir();
- if (! reinstalling)
+ if (! a.options.is_overwrite())
{
std::tr1::shared_ptr<const PackageIDSequence> ids(package_ids(id->name()));
bool only(true);
@@ -918,9 +917,10 @@ VDBRepository::merge(const MergeParams & m)
{
UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(config_protect),
+ value_for<n::is_overwrite>(true),
value_for<n::make_output_manager>(std::tr1::bind(&this_output_manager, m.output_manager(), std::tr1::placeholders::_1))
));
- perform_uninstall(is_replace, uo, true);
+ m.perform_uninstall()(is_replace, uo);
}
if (std::tr1::static_pointer_cast<const ERepositoryID>(m.package_id())
@@ -935,9 +935,10 @@ VDBRepository::merge(const MergeParams & m)
{
UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(config_protect),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(std::tr1::bind(&this_output_manager, m.output_manager(), std::tr1::placeholders::_1))
));
- perform_uninstall(candidate, uo, false);
+ m.perform_uninstall()(candidate, uo);
}
}
}
diff --git a/paludis/repositories/e/vdb_repository.hh b/paludis/repositories/e/vdb_repository.hh
index f5f0421..971c59a 100644
--- a/paludis/repositories/e/vdb_repository.hh
+++ b/paludis/repositories/e/vdb_repository.hh
@@ -121,8 +121,7 @@ namespace paludis
virtual void perform_uninstall(
const std::tr1::shared_ptr<const erepository::ERepositoryID> & id,
- const UninstallAction &,
- bool reinstalling) const;
+ const UninstallAction &) const;
/* RepositoryProvidesInterface */
diff --git a/paludis/repositories/e/vdb_repository_TEST.cc b/paludis/repositories/e/vdb_repository_TEST.cc
index 3bbec00..d703fec 100644
--- a/paludis/repositories/e/vdb_repository_TEST.cc
+++ b/paludis/repositories/e/vdb_repository_TEST.cc
@@ -51,6 +51,12 @@ using namespace paludis;
namespace
{
+ void do_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions & u)
+ {
+ UninstallAction a(u);
+ id->perform_action(a);
+ }
+
std::tr1::shared_ptr<OutputManager> make_standard_output_manager(const Action &)
{
return make_shared_ptr(new StandardOutputManager);
@@ -66,10 +72,6 @@ namespace
return mm->second;
}
- void dummy_used_this_for_config_protect(const std::string &)
- {
- }
-
WantPhase want_all_phases(const std::string &)
{
return wp_yes;
@@ -344,12 +346,14 @@ namespace test_cases
InstallAction install_action(make_named_values<InstallActionOptions>(
value_for<n::destination>(vdb_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&do_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
UninstallAction uninstall_action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
@@ -470,12 +474,14 @@ namespace test_cases
InstallAction install_action(make_named_values<InstallActionOptions>(
value_for<n::destination>(vdb_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&do_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
UninstallAction uninstall_action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
@@ -596,12 +602,14 @@ namespace test_cases
InstallAction install_action(make_named_values<InstallActionOptions>(
value_for<n::destination>(vdb_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&do_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
UninstallAction uninstall_action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
@@ -994,12 +1002,14 @@ namespace test_cases
InstallAction install_action(make_named_values<InstallActionOptions>(
value_for<n::destination>(vdb_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&do_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
UninstallAction uninstall_action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
@@ -1233,7 +1243,8 @@ namespace test_cases
InstallAction install_action(make_named_values<InstallActionOptions>(
value_for<n::destination>(vdb_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&do_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
@@ -1325,12 +1336,14 @@ namespace test_cases
InstallAction install_action(make_named_values<InstallActionOptions>(
value_for<n::destination>(vdb_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&do_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
UninstallAction uninstall_action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
diff --git a/paludis/repositories/unpackaged/installed_repository_TEST.cc b/paludis/repositories/unpackaged/installed_repository_TEST.cc
index fdec71a..a677a0c 100644
--- a/paludis/repositories/unpackaged/installed_repository_TEST.cc
+++ b/paludis/repositories/unpackaged/installed_repository_TEST.cc
@@ -44,6 +44,12 @@ using namespace paludis;
namespace
{
+ void cannot_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions &)
+ {
+ if (id)
+ throw InternalError(PALUDIS_HERE, "cannot uninstall");
+ }
+
std::tr1::shared_ptr<OutputManager> make_standard_output_manager(const Action &)
{
return make_shared_ptr(new StandardOutputManager);
@@ -74,10 +80,6 @@ namespace
}
};
- void dummy_used_this_for_config_protect(const std::string &)
- {
- }
-
WantPhase want_all_phases(const std::string &)
{
return wp_yes;
@@ -260,6 +262,7 @@ namespace test_cases
UninstallAction action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
id->perform_action(action);
@@ -312,6 +315,7 @@ namespace test_cases
UninstallAction action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
id->perform_action(action);
@@ -397,7 +401,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
(*env[selection::RequireExactlyOne(generator::InRepository(RepositoryName("unpackaged")))]->begin())->perform_action(action);
@@ -453,7 +458,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
(*env[selection::RequireExactlyOne(generator::InRepository(RepositoryName("unpackaged")))]->begin())->perform_action(action);
@@ -512,7 +518,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
(*env[selection::RequireExactlyOne(generator::InRepository(RepositoryName("unpackaged")))]->begin())->perform_action(action);
@@ -554,6 +561,7 @@ namespace test_cases
UninstallAction action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
(*env[selection::RequireExactlyOne(generator::Matches(
@@ -597,6 +605,7 @@ namespace test_cases
UninstallAction action(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
(*env[selection::RequireExactlyOne(generator::Matches(
diff --git a/paludis/repositories/unpackaged/unpackaged_id.cc b/paludis/repositories/unpackaged/unpackaged_id.cc
index 64468b3..77c8f10 100644
--- a/paludis/repositories/unpackaged/unpackaged_id.cc
+++ b/paludis/repositories/unpackaged/unpackaged_id.cc
@@ -284,6 +284,28 @@ UnpackagedID::supports_action(const SupportsActionTestBase & test) const
return simple_visitor_cast<const SupportsActionTest<InstallAction> >(test);
}
+namespace
+{
+ bool slot_is_same(const std::tr1::shared_ptr<const PackageID> & a,
+ const PackageID * const b)
+ {
+ if (a->slot_key())
+ return b->slot_key() && a->slot_key()->value() == b->slot_key()->value();
+ else
+ return ! b->slot_key();
+ }
+
+ void used_this_for_config_protect(std::string & s, const std::string & v)
+ {
+ s = v;
+ }
+
+ std::tr1::shared_ptr<OutputManager> this_output_manager(const std::tr1::shared_ptr<OutputManager> & o, const Action &)
+ {
+ return o;
+ }
+}
+
void
UnpackagedID::perform_action(Action & action) const
{
@@ -315,6 +337,8 @@ UnpackagedID::perform_action(Action & action) const
std::tr1::shared_ptr<const ChoiceValue> split_choice(choices_key()->value()->find_by_name_with_prefix(
ELikeSplitChoiceValue::canonical_name_with_prefix()));
+ std::string used_config_protect;
+
switch (install_action->options.want_phase()("strip"))
{
case wp_yes:
@@ -353,7 +377,9 @@ UnpackagedID::perform_action(Action & action) const
value_for<n::options>(MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs),
value_for<n::output_manager>(output_manager),
value_for<n::package_id>(shared_from_this()),
- value_for<n::used_this_for_config_protect>(install_action->options.used_this_for_config_protect())
+ value_for<n::perform_uninstall>(install_action->options.perform_uninstall()),
+ value_for<n::used_this_for_config_protect>(std::tr1::bind(
+ &used_this_for_config_protect, std::tr1::ref(used_config_protect), std::tr1::placeholders::_1))
));
}
break;
@@ -368,6 +394,21 @@ UnpackagedID::perform_action(Action & action) const
throw InternalError(PALUDIS_HERE, "bad WantPhase");
}
+ for (PackageIDSequence::ConstIterator i(install_action->options.replacing()->begin()), i_end(install_action->options.replacing()->end()) ;
+ i != i_end ; ++i)
+ {
+ Context local_context("When cleaning '" + stringify(**i) + "':");
+ if ((*i)->name() == name() && (*i)->version() == version() && slot_is_same(*i, this))
+ continue;
+
+ UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
+ value_for<n::config_protect>(used_config_protect),
+ value_for<n::is_overwrite>(false),
+ value_for<n::make_output_manager>(std::tr1::bind(&this_output_manager, output_manager, std::tr1::placeholders::_1))
+ ));
+ install_action->options.perform_uninstall()(*i, uo);
+ }
+
output_manager->succeeded();
}
diff --git a/paludis/repositories/unpackaged/unpackaged_repository_TEST.cc b/paludis/repositories/unpackaged/unpackaged_repository_TEST.cc
index c5c02cd..f663d8d 100644
--- a/paludis/repositories/unpackaged/unpackaged_repository_TEST.cc
+++ b/paludis/repositories/unpackaged/unpackaged_repository_TEST.cc
@@ -42,6 +42,12 @@ using namespace paludis;
namespace
{
+ void cannot_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions &)
+ {
+ if (id)
+ throw InternalError(PALUDIS_HERE, "cannot uninstall");
+ }
+
std::tr1::shared_ptr<OutputManager> make_standard_output_manager(const Action &)
{
return make_shared_ptr(new StandardOutputManager);
@@ -237,7 +243,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
id->perform_action(action);
@@ -292,7 +299,8 @@ namespace test_cases
InstallAction action(make_named_values<InstallActionOptions>(
value_for<n::destination>(installed_repo),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
id->perform_action(action);
diff --git a/paludis/repository.hh b/paludis/repository.hh
index 9ccd40f..7068a74 100644
--- a/paludis/repository.hh
+++ b/paludis/repository.hh
@@ -69,6 +69,7 @@ namespace paludis
struct output_manager;
struct package_id;
struct path;
+ struct perform_uninstall;
struct profile;
struct provided_by;
struct provided_by_spec;
@@ -163,6 +164,17 @@ namespace paludis
NamedValue<n::options, MergerOptions> options;
NamedValue<n::output_manager, std::tr1::shared_ptr<OutputManager> > output_manager;
NamedValue<n::package_id, std::tr1::shared_ptr<const PackageID> > package_id;
+
+ /**
+ * Some merges need to do an uninstall mid-way through the merge process.
+ *
+ * \see InstallActionOptions::perform_uninstall
+ * \since 0.36
+ */
+ NamedValue<n::perform_uninstall, std::tr1::function<void (
+ const std::tr1::shared_ptr<const PackageID> &,
+ const UninstallActionOptions &)> > perform_uninstall;
+
NamedValue<n::used_this_for_config_protect, std::tr1::function<void (const std::string &)> > used_this_for_config_protect;
};
diff --git a/paludis/uninstall_task.cc b/paludis/uninstall_task.cc
index 7f9f3be..1cb4933 100644
--- a/paludis/uninstall_task.cc
+++ b/paludis/uninstall_task.cc
@@ -363,6 +363,7 @@ UninstallTask::execute()
UninstallAction uninstall_action(
make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(""),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(std::tr1::ref(output_manager_holder))
));
i->package_id()->perform_action(uninstall_action);
diff --git a/python/action.cc b/python/action.cc
index d84166a..9e54a2e 100644
--- a/python/action.cc
+++ b/python/action.cc
@@ -23,6 +23,7 @@
#include <paludis/action.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/sequence.hh>
#include <paludis/standard_output_manager.hh>
#include <paludis/repository.hh>
#include <tr1/memory>
@@ -51,10 +52,6 @@ class class_supports_action_test :
namespace
{
- void dummy_used_this_for_config_protect(const std::string &)
- {
- }
-
WantPhase want_all_phases(const std::string &)
{
return wp_yes;
@@ -65,13 +62,19 @@ namespace
return make_shared_ptr(new StandardOutputManager);
}
+ void cannot_perform_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions &)
+ {
+ throw InternalError(PALUDIS_HERE, "Can't uninstall '" + stringify(*id) + "'");
+ }
+
InstallActionOptions * make_install_action_options(
const std::tr1::shared_ptr<paludis::Repository> & r)
{
return new InstallActionOptions(make_named_values<InstallActionOptions>(
value_for<n::destination>(r),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_perform_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
}
@@ -81,6 +84,7 @@ namespace
{
return new UninstallActionOptions(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(c),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
}
diff --git a/ruby/action.cc b/ruby/action.cc
index f058ffb..f4705e4 100644
--- a/ruby/action.cc
+++ b/ruby/action.cc
@@ -30,13 +30,6 @@ using namespace paludis::ruby;
namespace
{
- void dummy_used_this_for_config_protect(const std::string &)
- {
- }
-}
-
-namespace
-{
static VALUE c_supports_action_test;
static VALUE c_action;
@@ -510,6 +503,11 @@ namespace
return wp_yes;
}
+ void cannot_perform_uninstall(const std::tr1::shared_ptr<const PackageID> & id, const UninstallActionOptions &)
+ {
+ throw InternalError(PALUDIS_HERE, "Can't uninstall '" + stringify(*id) + "'");
+ }
+
/*
* call-seq:
* InstallActionOptions.new(destination) -> InstallActionOptions
@@ -547,7 +545,8 @@ namespace
ptr = new InstallActionOptions(make_named_values<InstallActionOptions>(
value_for<n::destination>(v_destination),
value_for<n::make_output_manager>(&make_standard_output_manager),
- value_for<n::used_this_for_config_protect>(&dummy_used_this_for_config_protect),
+ value_for<n::perform_uninstall>(&cannot_perform_uninstall),
+ value_for<n::replacing>(make_shared_ptr(new PackageIDSequence)),
value_for<n::want_phase>(&want_all_phases)
));
@@ -632,6 +631,7 @@ namespace
ptr = new UninstallActionOptions(make_named_values<UninstallActionOptions>(
value_for<n::config_protect>(v_config_protect),
+ value_for<n::is_overwrite>(false),
value_for<n::make_output_manager>(&make_standard_output_manager)
));
diff --git a/src/output/console_install_task.cc b/src/output/console_install_task.cc
index d224b08..9fd1128 100644
--- a/src/output/console_install_task.cc
+++ b/src/output/console_install_task.cc
@@ -210,36 +210,6 @@ ConsoleInstallTask::on_build_deplist_post()
}
void
-ConsoleInstallTask::on_build_cleanlist_pre(const DepListEntry & d)
-{
- output_heading("Cleaning stale versions after installing " + stringify(*d.package_id()));
-}
-
-void
-ConsoleInstallTask::on_build_cleanlist_post(const DepListEntry &)
-{
-}
-
-void
-ConsoleInstallTask::on_clean_all_pre(const DepListEntry & d,
- const PackageIDSequence & c)
-{
- display_clean_all_pre_list_start(d, c);
-
- using namespace std::tr1::placeholders;
- std::for_each(indirect_iterator(c.begin()), indirect_iterator(c.end()),
- std::tr1::bind(std::tr1::mem_fn(&ConsoleInstallTask::display_one_clean_all_pre_list_entry), this, _1));
-
- display_clean_all_pre_list_end(d, c);
-}
-
-void
-ConsoleInstallTask::on_no_clean_needed(const DepListEntry &)
-{
- output_starred_item("No cleaning required");
-}
-
-void
ConsoleInstallTask::on_clean_pre(const DepListEntry &,
const PackageID & c, const int x, const int y, const int s, const int f)
{
@@ -262,12 +232,6 @@ ConsoleInstallTask::on_clean_fail(const DepListEntry &,
}
void
-ConsoleInstallTask::on_clean_all_post(const DepListEntry &,
- const PackageIDSequence &)
-{
-}
-
-void
ConsoleInstallTask::on_display_merge_list_pre()
{
output_heading("These packages will be installed:");
@@ -625,25 +589,6 @@ ConsoleInstallTask::on_preserve_world()
}
void
-ConsoleInstallTask::display_clean_all_pre_list_start(const DepListEntry &,
- const PackageIDSequence &)
-{
-}
-
-void
-ConsoleInstallTask::display_one_clean_all_pre_list_entry(
- const PackageID & c)
-{
- output_starred_item(render_as_package_name(stringify(c)));
-}
-
-void
-ConsoleInstallTask::display_clean_all_pre_list_end(const DepListEntry &,
- const PackageIDSequence &)
-{
-}
-
-void
ConsoleInstallTask::display_merge_list_post_counts()
{
std::ostringstream s;
diff --git a/src/output/console_install_task.hh b/src/output/console_install_task.hh
index 5262580..220c12a 100644
--- a/src/output/console_install_task.hh
+++ b/src/output/console_install_task.hh
@@ -126,9 +126,6 @@ namespace paludis
virtual void on_build_deplist_pre();
virtual void on_build_deplist_post();
- virtual void on_build_cleanlist_pre(const DepListEntry &);
- virtual void on_build_cleanlist_post(const DepListEntry &);
-
virtual void on_display_merge_list_pre();
virtual void on_display_merge_list_post();
virtual void on_not_continuing_due_to_errors();
@@ -156,17 +153,12 @@ namespace paludis
const int x, const int y, const int s, const int f);
virtual void on_skip_already_done(const DepListEntry &, const int, const int, const int, const int);
- virtual void on_no_clean_needed(const DepListEntry &);
- virtual void on_clean_all_pre(const DepListEntry &,
- const PackageIDSequence &);
virtual void on_clean_pre(const DepListEntry &,
const PackageID &, const int x, const int y, const int s, const int f);
virtual void on_clean_post(const DepListEntry &,
const PackageID &, const int x, const int y, const int s, const int f);
virtual void on_clean_fail(const DepListEntry &,
const PackageID &, const int x, const int y, const int s, const int f);
- virtual void on_clean_all_post(const DepListEntry &,
- const PackageIDSequence &);
virtual void on_update_world_pre();
virtual void on_update_world(const PackageDepSpec &);
@@ -204,13 +196,6 @@ namespace paludis
///\name More granular display routines
///\{
- virtual void display_clean_all_pre_list_start(const DepListEntry &,
- const PackageIDSequence &);
- virtual void display_one_clean_all_pre_list_entry(
- const PackageID &);
- virtual void display_clean_all_pre_list_end(const DepListEntry &,
- const PackageIDSequence &);
-
virtual void display_merge_list_post_counts();
virtual void display_merge_list_post_tags();
virtual void display_merge_list_post_use_descriptions();