aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-12-15 21:26:15 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-12-15 21:26:15 +0000
commit6b36e86d003321a4f644d8e83ae2bd6428c1b07e (patch)
tree745d8e22c081e74b4d6f732dcc99965b928fb56b
parentf85fd9b7a6df192119efe1abb89d72ba1e47e9ef (diff)
downloadpaludis-6b36e86d003321a4f644d8e83ae2bd6428c1b07e.tar.gz
paludis-6b36e86d003321a4f644d8e83ae2bd6428c1b07e.tar.xz
cave import
-rw-r--r--src/clients/cave/Makefile.am4
-rw-r--r--src/clients/cave/cmd_display_resolution.cc6
-rw-r--r--src/clients/cave/cmd_execute_resolution.cc30
-rw-r--r--src/clients/cave/cmd_import.cc242
-rw-r--r--src/clients/cave/cmd_import.hh43
-rw-r--r--src/clients/cave/cmd_perform.cc9
-rw-r--r--src/clients/cave/cmd_resolve.cc1157
-rw-r--r--src/clients/cave/cmd_resolve_cmdline.cc115
-rw-r--r--src/clients/cave/cmd_resolve_cmdline.hh16
-rw-r--r--src/clients/cave/cmd_resolve_dump.cc8
-rw-r--r--src/clients/cave/cmd_resolve_dump.hh2
-rw-r--r--src/clients/cave/command_factory.cc2
-rw-r--r--src/clients/cave/resolve_common.cc1164
-rw-r--r--src/clients/cave/resolve_common.hh45
14 files changed, 1686 insertions, 1157 deletions
diff --git a/src/clients/cave/Makefile.am b/src/clients/cave/Makefile.am
index b53d3c2..044b87e 100644
--- a/src/clients/cave/Makefile.am
+++ b/src/clients/cave/Makefile.am
@@ -84,6 +84,7 @@ libcave_a_SOURCES = \
cmd_display_resolution.cc cmd_display_resolution.hh \
cmd_execute_resolution.cc cmd_execute_resolution.hh \
cmd_help.cc cmd_help.hh \
+ cmd_import.cc cmd_import.hh \
cmd_perform.cc cmd_perform.hh \
cmd_print_categories.cc cmd_print_categories.hh \
cmd_print_commands.cc cmd_print_commands.hh \
@@ -112,7 +113,8 @@ libcave_a_SOURCES = \
format_string.cc format_string.hh \
formats.cc formats.hh \
select_format_for_spec.cc select_format_for_spec.hh \
- match_qpns.cc match_qpns.hh
+ match_qpns.cc match_qpns.hh \
+ resolve_common.cc resolve_common.hh
# cmd_config.cc \
# cmd_contents.cc \
diff --git a/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc
index 0d2b9ac..a5a63f8 100644
--- a/src/clients/cave/cmd_display_resolution.cc
+++ b/src/clients/cave/cmd_display_resolution.cc
@@ -86,9 +86,11 @@ namespace
CaveCommandCommandLine
{
ResolveCommandLineDisplayOptions display_options;
+ ResolveCommandLineImportOptions import_options;
DisplayResolutionCommandLine() :
- display_options(this)
+ display_options(this),
+ import_options(this)
{
add_environment_variable("PALUDIS_SERIALISED_RESOLUTION_FD",
"The file descriptor on which the serialised resolution can be found.");
@@ -902,6 +904,8 @@ DisplayResolutionCommand::run(
if (getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", "").empty())
throw args::DoHelp("PALUDIS_SERIALISED_RESOLUTION_FD must be provided");
+ cmdline.import_options.apply(env);
+
int fd(destringify<int>(getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", "")));
SafeIFStream deser_stream(fd);
const std::string deser_str((std::istreambuf_iterator<char>(deser_stream)), std::istreambuf_iterator<char>());
diff --git a/src/clients/cave/cmd_execute_resolution.cc b/src/clients/cave/cmd_execute_resolution.cc
index c5525bd..8071e70 100644
--- a/src/clients/cave/cmd_execute_resolution.cc
+++ b/src/clients/cave/cmd_execute_resolution.cc
@@ -83,13 +83,15 @@ namespace
ResolveCommandLineExecutionOptions execution_options;
ResolveCommandLineProgramOptions program_options;
+ ResolveCommandLineImportOptions import_options;
ExecuteResolutionCommandLine() :
g_general_options(main_options_section(), "General Options", "General options."),
a_pretend(&g_general_options, "pretend", '\0', "Only carry out the pretend action", false),
a_set(&g_general_options, "set", '\0', "Our target is a set rather than package specs", false),
execution_options(this),
- program_options(this)
+ program_options(this),
+ import_options(this)
{
add_environment_variable("PALUDIS_SERIALISED_RESOLUTION_FD",
"The file descriptor on which the serialised resolution can be found.");
@@ -132,6 +134,14 @@ namespace
command.append(stringify(decision.origin_id()->uniquely_identifying_spec()));
command.append(" --x-of-y '" + stringify(x) + " of " + stringify(y) + "'");
+ if (cmdline.import_options.a_unpackaged_repository_params.specified())
+ {
+ for (args::StringSetArg::ConstIterator p(cmdline.import_options.a_unpackaged_repository_params.begin_args()),
+ p_end(cmdline.import_options.a_unpackaged_repository_params.end_args()) ;
+ p != p_end ; ++p)
+ command.append(" --" + cmdline.import_options.a_unpackaged_repository_params.long_name() + " '" + *p + "'");
+ }
+
paludis::Command cmd(command);
return run_command(cmd);
}
@@ -184,6 +194,14 @@ namespace
if (normal_only)
command.append(" --regulars-only");
+ if (cmdline.import_options.a_unpackaged_repository_params.specified())
+ {
+ for (args::StringSetArg::ConstIterator p(cmdline.import_options.a_unpackaged_repository_params.begin_args()),
+ p_end(cmdline.import_options.a_unpackaged_repository_params.end_args()) ;
+ p != p_end ; ++p)
+ command.append(" --" + cmdline.import_options.a_unpackaged_repository_params.long_name() + " '" + *p + "'");
+ }
+
paludis::Command cmd(command);
int retcode(run_command(cmd));
@@ -264,6 +282,14 @@ namespace
}
}
+ if (cmdline.import_options.a_unpackaged_repository_params.specified())
+ {
+ for (args::StringSetArg::ConstIterator p(cmdline.import_options.a_unpackaged_repository_params.begin_args()),
+ p_end(cmdline.import_options.a_unpackaged_repository_params.end_args()) ;
+ p != p_end ; ++p)
+ command.append(" --" + cmdline.import_options.a_unpackaged_repository_params.long_name() + " '" + *p + "'");
+ }
+
paludis::Command cmd(command);
int retcode(run_command(cmd));
@@ -590,6 +616,8 @@ ExecuteResolutionCommand::run(
if (getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", "").empty())
throw args::DoHelp("PALUDIS_SERIALISED_RESOLUTION_FD must be provided");
+ cmdline.import_options.apply(env);
+
int fd(destringify<int>(getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", "")));
SafeIFStream deser_stream(fd);
const std::string deser_str((std::istreambuf_iterator<char>(deser_stream)), std::istreambuf_iterator<char>());
diff --git a/src/clients/cave/cmd_import.cc b/src/clients/cave/cmd_import.cc
new file mode 100644
index 0000000..5b20c7e
--- /dev/null
+++ b/src/clients/cave/cmd_import.cc
@@ -0,0 +1,242 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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 "cmd_import.hh"
+#include "exceptions.hh"
+#include "resolve_common.hh"
+#include <paludis/args/args.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/util/iterator_funcs.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/environment.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/generator.hh>
+#include <paludis/selection.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/filter.hh>
+#include <paludis/package_id.hh>
+#include <paludis/repository.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/stringify_formatter.hh>
+#include <paludis/repository_factory.hh>
+#include <paludis/package_database.hh>
+
+#include <iostream>
+#include <cstdlib>
+
+#include "command_command_line.hh"
+
+using namespace paludis;
+using namespace cave;
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct ImportCommandLine :
+ CaveCommandCommandLine
+ {
+ virtual std::string app_name() const
+ {
+ return "cave import";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Import a package from a directory containing its image.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Import a package from a directory containing its image. A named directory "
+ "is treated as holding the contents to install, and a dummy package name is "
+ "provided on the command line. Safe merge, unmerge, upgrade and replace support "
+ "is provided, as is content tracking for installed files.";
+ }
+
+ args::ArgsGroup g_contents_options;
+ args::StringArg a_location;
+ args::StringArg a_install_under;
+ args::IntegerArg a_rewrite_ids_over_to_root;
+
+ args::ArgsGroup g_metadata_options;
+ args::StringArg a_description;
+ args::StringSetArg a_build_dependency;
+ args::StringSetArg a_run_dependency;
+ args::StringArg a_preserve_metadata;
+
+ ResolveCommandLineResolutionOptions resolution_options;
+ ResolveCommandLineExecutionOptions execution_options;
+ ResolveCommandLineDisplayOptions display_options;
+ ResolveCommandLineProgramOptions program_options;
+
+ ImportCommandLine() :
+ g_contents_options(main_options_section(), "Contents Options",
+ "Options controlling the content to install"),
+ a_location(&g_contents_options, "location", 'l',
+ "Specify the directory containing the image to install (default: current directory)"),
+ a_install_under(&g_contents_options, "install-under", 'u',
+ "Install under the specified directory, rather than /"),
+ a_rewrite_ids_over_to_root(&g_contents_options, "rewrite-ids-over-to-root", 'r',
+ "Change any UID or GID over this value to 0 (-1 disables, default)"),
+
+ g_metadata_options(main_options_section(), "Metadata Options",
+ "Options specifying metadata for the package being installed"),
+ a_description(&g_metadata_options, "description", 'D',
+ "Specify a description for the package"),
+ a_build_dependency(&g_metadata_options, "build-dependency", 'B',
+ "Specify a build dependency. May be specified multiple times."),
+ a_run_dependency(&g_metadata_options, "run-dependency", 'R',
+ "Specify a run dependency. May be specified multiple times."),
+ a_preserve_metadata(&g_metadata_options, "preserve-metadata", 'P',
+ "If replacing a package previously installed using this command, copy its description "
+ "and dependencies"),
+ resolution_options(this),
+ execution_options(this),
+ display_options(this),
+ program_options(this)
+ {
+ add_usage_line("[ --location blah ] cat/pkg [ version ] [ slot ]");
+ }
+ };
+
+ std::string from_keys(const std::tr1::shared_ptr<const Map<std::string, std::string> > & m,
+ const std::string & k)
+ {
+ Map<std::string, std::string>::ConstIterator mm(m->find(k));
+ if (m->end() == mm)
+ return "";
+ else
+ return mm->second;
+ }
+}
+
+int
+ImportCommand::run(
+ const std::tr1::shared_ptr<Environment> & env,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ )
+{
+ ImportCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_IMPORT_OPTIONS", "CAVE_IMPORT_CMDLINE");
+
+ if (cmdline.a_help.specified())
+ {
+ cout << cmdline;
+ return EXIT_SUCCESS;
+ }
+
+ if (std::distance(cmdline.begin_parameters(), cmdline.end_parameters()) < 1 ||
+ std::distance(cmdline.begin_parameters(), cmdline.end_parameters()) > 3)
+ throw args::DoHelp("import takes between one and three parameters");
+
+ QualifiedPackageName package(*cmdline.begin_parameters());
+ VersionSpec version((next(cmdline.begin_parameters()) != cmdline.end_parameters()) ?
+ *next(cmdline.begin_parameters()) : "0", user_version_spec_options());
+ SlotName slot((next(cmdline.begin_parameters(), 2) != cmdline.end_parameters()) ?
+ *next(cmdline.begin_parameters(), 2) : "0");
+
+ std::string build_dependencies, run_dependencies, description;
+
+ if (cmdline.a_preserve_metadata.specified())
+ {
+ std::tr1::shared_ptr<const PackageIDSequence> old_ids((*env)[selection::AllVersionsSorted(generator::Package(package))]);
+ std::tr1::shared_ptr<const PackageID> old_id;
+ for (PackageIDSequence::ConstIterator i(old_ids->begin()), i_end(old_ids->end()) ;
+ i != i_end ; ++i)
+ {
+ if (! (*i)->repository()->format_key())
+ continue;
+ if ((*i)->repository()->format_key()->value() != "installed_unpackaged")
+ continue;
+ old_id = *i;
+ break;
+ }
+
+ if (! old_id)
+ throw args::DoHelp("--" + cmdline.a_preserve_metadata.long_name() + " specified but "
+ "no old ID available");
+
+ StringifyFormatter f;
+ if (old_id->short_description_key())
+ description = old_id->short_description_key()->value();
+ if (old_id->build_dependencies_key())
+ build_dependencies = old_id->build_dependencies_key()->pretty_print_flat(f);
+ if (old_id->run_dependencies_key())
+ run_dependencies = old_id->run_dependencies_key()->pretty_print_flat(f);
+ }
+
+ if (cmdline.a_description.specified())
+ description = cmdline.a_description.argument();
+ if (cmdline.a_build_dependency.specified())
+ build_dependencies = join(
+ cmdline.a_build_dependency.begin_args(),
+ cmdline.a_build_dependency.end_args(), ", ");
+ if (cmdline.a_run_dependency.specified())
+ run_dependencies = join(
+ cmdline.a_run_dependency.begin_args(),
+ cmdline.a_run_dependency.end_args(), ", ");
+
+ std::tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("location", stringify(
+ cmdline.a_location.specified() ?
+ FSEntry(cmdline.a_location.argument()) :
+ FSEntry::cwd()));
+ keys->insert("install_under", stringify(
+ cmdline.a_install_under.specified() ?
+ FSEntry(cmdline.a_install_under.argument()) :
+ FSEntry("/")));
+ keys->insert("rewrite_ids_over_to_root", stringify(
+ cmdline.a_rewrite_ids_over_to_root.specified() ?
+ cmdline.a_rewrite_ids_over_to_root.argument() : -1));
+ keys->insert("format", "unpackaged");
+ keys->insert("name", stringify(package));
+ keys->insert("version", stringify(version));
+ keys->insert("slot", stringify(slot));
+ keys->insert("description", description);
+ keys->insert("build_dependencies", build_dependencies);
+ keys->insert("run_dependencies", run_dependencies);
+ std::tr1::shared_ptr<Repository> repo(RepositoryFactory::get_instance()->create(env.get(),
+ std::tr1::bind(from_keys, keys, std::tr1::placeholders::_1)));
+ env->package_database()->add_repository(10, repo);
+ std::tr1::shared_ptr<const PackageIDSequence> ids(repo->package_ids(package));
+ if (1 != std::distance(ids->begin(), ids->end()))
+ throw InternalError(PALUDIS_HERE, "ids is '" + join(indirect_iterator(ids->begin()), indirect_iterator(
+ ids->end()), " ") + "'");
+
+ cmdline.resolution_options.apply_shortcuts();
+ cmdline.resolution_options.verify(env);
+
+ std::tr1::shared_ptr<Sequence<std::string> > targets(new Sequence<std::string>);
+ targets->push_back(stringify((*ids->begin())->uniquely_identifying_spec()));
+
+ return resolve_common(env, cmdline.resolution_options, cmdline.execution_options, cmdline.display_options,
+ cmdline.program_options, keys, targets);
+}
+
+std::tr1::shared_ptr<args::ArgsHandler>
+ImportCommand::make_doc_cmdline()
+{
+ return make_shared_ptr(new ImportCommandLine);
+}
+
diff --git a/src/clients/cave/cmd_import.hh b/src/clients/cave/cmd_import.hh
new file mode 100644
index 0000000..fe0562d
--- /dev/null
+++ b/src/clients/cave/cmd_import.hh
@@ -0,0 +1,43 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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_SRC_CLIENTS_CAVE_CMD_IMPORT_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_IMPORT_HH 1
+
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE ImportCommand :
+ public Command
+ {
+ public:
+ int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+#endif
diff --git a/src/clients/cave/cmd_perform.cc b/src/clients/cave/cmd_perform.cc
index 2beba54..e71d2cb 100644
--- a/src/clients/cave/cmd_perform.cc
+++ b/src/clients/cave/cmd_perform.cc
@@ -18,6 +18,7 @@
*/
#include "cmd_perform.hh"
+#include "cmd_resolve_cmdline.hh"
#include "exceptions.hh"
#include <paludis/args/args.hh>
#include <paludis/args/do_help.hh>
@@ -95,6 +96,8 @@ namespace
args::ArgsGroup g_uninstall_action_options;
args::StringArg a_config_protect;
+ ResolveCommandLineImportOptions import_options;
+
PerformCommandLine() :
g_general_options(main_options_section(), "General Options",
"General options for all actions"),
@@ -138,7 +141,9 @@ namespace
g_uninstall_action_options(main_options_section(), "Uninstall Action Options",
"Options for if the action is 'uninstall'"),
a_config_protect(&g_uninstall_action_options, "config-protect", '\0',
- "Specify additional items to include in the config protection list")
+ "Specify additional items to include in the config protection list"),
+
+ import_options(this)
{
add_usage_line("config spec");
add_usage_line("fetch | pretend-fetch [ --exclude-unmirrorable ] [ --fetch-unneeded ]"
@@ -303,6 +308,8 @@ PerformCommand::run(
if (2 != std::distance(cmdline.begin_parameters(), cmdline.end_parameters()))
throw args::DoHelp("perform takes exactly two parameters");
+ cmdline.import_options.apply(env);
+
std::string action(*cmdline.begin_parameters());
PackageDepSpec spec(parse_user_package_dep_spec(*next(cmdline.begin_parameters()), env.get(),
diff --git a/src/clients/cave/cmd_resolve.cc b/src/clients/cave/cmd_resolve.cc
index 59d273e..0002cc8 100644
--- a/src/clients/cave/cmd_resolve.cc
+++ b/src/clients/cave/cmd_resolve.cc
@@ -19,1029 +19,19 @@
#include "cmd_resolve.hh"
#include "cmd_resolve_cmdline.hh"
-#include "cmd_resolve_display_callback.hh"
-#include "cmd_resolve_dump.hh"
-#include "exceptions.hh"
-#include "command_command_line.hh"
-#include "match_qpns.hh"
+#include "resolve_common.hh"
#include <paludis/util/make_shared_ptr.hh>
-#include <paludis/util/mutex.hh>
-#include <paludis/util/stringify.hh>
-#include <paludis/util/make_named_values.hh>
-#include <paludis/util/system.hh>
-#include <paludis/util/enum_iterator.hh>
-#include <paludis/util/indirect_iterator-impl.hh>
-#include <paludis/util/wrapped_output_iterator.hh>
-#include <paludis/util/string_list_stream.hh>
-#include <paludis/util/thread.hh>
-#include <paludis/util/timestamp.hh>
-#include <paludis/args/do_help.hh>
-#include <paludis/args/escape.hh>
-#include <paludis/resolver/resolver.hh>
-#include <paludis/resolver/resolution.hh>
-#include <paludis/resolver/decision.hh>
-#include <paludis/resolver/resolver_functions.hh>
-#include <paludis/resolver/reason.hh>
-#include <paludis/resolver/suggest_restart.hh>
-#include <paludis/resolver/resolvent.hh>
-#include <paludis/resolver/constraint.hh>
-#include <paludis/resolver/sanitised_dependencies.hh>
-#include <paludis/resolver/resolutions.hh>
-#include <paludis/resolver/resolver_lists.hh>
-#include <paludis/user_dep_spec.hh>
-#include <paludis/notifier_callback.hh>
-#include <paludis/generator.hh>
-#include <paludis/filter.hh>
-#include <paludis/selection.hh>
-#include <paludis/filtered_generator.hh>
-#include <paludis/version_spec.hh>
-#include <paludis/metadata_key.hh>
-#include <paludis/environment.hh>
-#include <paludis/match_package.hh>
-#include <paludis/package_database.hh>
-#include <paludis/serialise-impl.hh>
-#include <paludis/selection_cache.hh>
-#include <algorithm>
#include <iostream>
#include <cstdlib>
-#include <map>
using namespace paludis;
-using namespace paludis::resolver;
using namespace cave;
using std::cout;
using std::endl;
-namespace
-{
- struct LabelTypesVisitor
- {
- bool is_suggestion;
- bool is_recommendation;
- bool is_requirement;
- bool seen_buildish_dep;
- bool seen_runish_dep;
- bool seen_compiled_against_dep;
-
- LabelTypesVisitor() :
- is_suggestion(false),
- is_recommendation(false),
- is_requirement(false),
- seen_buildish_dep(false),
- seen_runish_dep(false),
- seen_compiled_against_dep(false)
- {
- }
-
- void visit(const DependenciesBuildLabel &)
- {
- is_requirement = true;
- seen_buildish_dep = true;
- }
-
- void visit(const DependenciesTestLabel &)
- {
- is_requirement = true;
- seen_buildish_dep = true;
- }
-
- void visit(const DependenciesFetchLabel &)
- {
- is_requirement = true;
- seen_buildish_dep = true;
- }
-
- void visit(const DependenciesRunLabel &)
- {
- is_requirement = true;
- seen_runish_dep = true;
- }
-
- void visit(const DependenciesPostLabel &)
- {
- is_requirement = true;
- seen_runish_dep = true;
- }
-
- void visit(const DependenciesInstallLabel &)
- {
- is_requirement = true;
- seen_buildish_dep = true;
- }
-
- void visit(const DependenciesCompileAgainstLabel &)
- {
- is_requirement = true;
- seen_runish_dep = true;
- seen_buildish_dep = true;
- }
-
- void visit(const DependenciesRecommendationLabel &)
- {
- is_recommendation = true;
- seen_runish_dep = true;
- }
-
- void visit(const DependenciesSuggestionLabel &)
- {
- is_suggestion = true;
- seen_runish_dep = true;
- }
- };
-
- bool is_suggestion(const SanitisedDependency & dep)
- {
- if (dep.active_dependency_labels()->empty())
- return false;
-
- LabelTypesVisitor v;
- std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
- indirect_iterator(dep.active_dependency_labels()->end()),
- accept_visitor(v));
- return v.is_suggestion && (! v.is_recommendation) && (! v.is_requirement);
- }
-
- bool is_recommendation(const SanitisedDependency & dep)
- {
- if (dep.active_dependency_labels()->empty())
- return false;
-
- LabelTypesVisitor v;
- std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
- indirect_iterator(dep.active_dependency_labels()->end()),
- accept_visitor(v));
- return v.is_recommendation && (! v.is_requirement);
- }
-
- bool is_just_build_dep(const SanitisedDependency & dep)
- {
- if (dep.active_dependency_labels()->empty())
- throw InternalError(PALUDIS_HERE, "not implemented");
-
- LabelTypesVisitor v;
- std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
- indirect_iterator(dep.active_dependency_labels()->end()),
- accept_visitor(v));
- return v.seen_buildish_dep && ! v.seen_runish_dep;
- }
-
- bool is_compiled_against_dep(const SanitisedDependency & dep)
- {
- if (dep.active_dependency_labels()->empty())
- throw InternalError(PALUDIS_HERE, "not implemented");
-
- LabelTypesVisitor v;
- std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
- indirect_iterator(dep.active_dependency_labels()->end()),
- accept_visitor(v));
- return v.seen_compiled_against_dep;
- }
-
- bool is_buildish_dep(const SanitisedDependency & dep)
- {
- if (dep.active_dependency_labels()->empty())
- throw InternalError(PALUDIS_HERE, "not implemented");
-
- LabelTypesVisitor v;
- std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
- indirect_iterator(dep.active_dependency_labels()->end()),
- accept_visitor(v));
- return v.seen_buildish_dep;
- }
-
- bool is_runish_dep(const SanitisedDependency & dep)
- {
- if (dep.active_dependency_labels()->empty())
- throw InternalError(PALUDIS_HERE, "not implemented");
-
- LabelTypesVisitor v;
- std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
- indirect_iterator(dep.active_dependency_labels()->end()),
- accept_visitor(v));
- return v.seen_runish_dep;
- }
-
- struct DestinationTypesFinder
- {
- const Environment * const env;
- const ResolveCommandLine & cmdline;
- const std::tr1::shared_ptr<const PackageID> package_id;
-
- DestinationTypesFinder(
- const Environment * const e,
- const ResolveCommandLine & c,
- const std::tr1::shared_ptr<const PackageID> & i) :
- env(e),
- cmdline(c),
- package_id(i)
- {
- }
-
- DestinationTypes visit(const TargetReason &) const
- {
- DestinationTypes result;
-
- if (cmdline.resolution_options.a_create_binaries.specified())
- {
- bool b(true);
-
- if (cmdline.resolution_options.a_no_binaries_for.specified() && package_id)
- {
- for (args::StringSetArg::ConstIterator a(cmdline.resolution_options.a_no_binaries_for.begin_args()),
- a_end(cmdline.resolution_options.a_no_binaries_for.end_args()) ;
- a != a_end ; ++a)
- if (match_package(*env,
- parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards),
- *package_id, MatchPackageOptions()))
- {
- b = false;
- break;
- }
- }
-
- if (b)
- result += dt_create_binary;
- }
-
- if (cmdline.resolution_options.a_install_to_root.specified())
- result += dt_install_to_slash;
-
- if (result.none())
- result += dt_install_to_slash;
-
- return result;
- }
-
- DestinationTypes visit(const DependencyReason & reason) const
- {
- DestinationTypes result;
-
- bool is_buildish(is_buildish_dep(reason.sanitised_dependency())),
- is_runish(is_runish_dep(reason.sanitised_dependency()));
-
- if ((! is_buildish) && (! is_runish))
- throw InternalError(PALUDIS_HERE, "not buildish or runish. eek. labels are { "
- + join(indirect_iterator(reason.sanitised_dependency().active_dependency_labels()->begin()),
- indirect_iterator(reason.sanitised_dependency().active_dependency_labels()->end()), ", ")
- + " }");
-
- if (is_buildish)
- result += dt_install_to_slash;
- if (is_runish)
- result |= visit(TargetReason());
-
- return result;
- }
-
- DestinationTypes visit(const PresetReason &) const PALUDIS_ATTRIBUTE((noreturn))
- {
- throw InternalError(PALUDIS_HERE, "not sure what to do here yet");
- }
-
- DestinationTypes visit(const SetReason & r) const
- {
- return r.reason_for_set()->accept_returning<DestinationTypes>(*this);
- }
- };
-
- DestinationTypes get_destination_types_for_fn(
- const Environment * const env,
- const ResolveCommandLine & cmdline,
- const PackageDepSpec &,
- const std::tr1::shared_ptr<const PackageID> & id,
- const std::tr1::shared_ptr<const Reason> & reason)
- {
- DestinationTypesFinder f(env, cmdline, id);
- return reason->accept_returning<DestinationTypes>(f);
- }
-
- FilteredGenerator make_destination_filtered_generator(
- const Environment * const,
- const ResolveCommandLine & cmdline,
- const Generator & g,
- const Resolvent & r)
- {
- switch (r.destination_type())
- {
- case dt_install_to_slash:
- return g | filter::InstalledAtRoot(FSEntry("/"));
-
- case dt_create_binary:
- {
- std::tr1::shared_ptr<Generator> generator;
- for (args::StringSetArg::ConstIterator a(cmdline.resolution_options.a_create_binaries.begin_args()),
- a_end(cmdline.resolution_options.a_create_binaries.end_args()) ;
- a != a_end ; ++a)
- {
- if (! generator)
- generator.reset(new generator::InRepository(RepositoryName(*a)));
- else
- generator.reset(new generator::Intersection(*generator, generator::InRepository(RepositoryName(*a))));
- }
-
- if (! generator)
- throw args::DoHelp("No binary destinations were specified");
- else
- return g & *generator;
- }
-
- case last_dt:
- break;
- }
-
- throw InternalError(PALUDIS_HERE, stringify(r.destination_type()));
- }
-
- void add_resolver_targets(
- const std::tr1::shared_ptr<Environment> & env,
- const std::tr1::shared_ptr<Resolver> & resolver,
- const ResolveCommandLine & cmdline,
- bool & is_set)
- {
- Context context("When adding targets from commandline:");
-
- if (cmdline.begin_parameters() == cmdline.end_parameters())
- throw args::DoHelp("Must specify at least one target");
-
- bool seen_sets(false), seen_packages(false);
- for (ResolveCommandLine::ParametersConstIterator p(cmdline.begin_parameters()), p_end(cmdline.end_parameters()) ;
- p != p_end ; ++p)
- {
- try
- {
- resolver->add_target(parse_user_package_dep_spec(*p, env.get(),
- UserPackageDepSpecOptions() + updso_throw_if_set));
- if (seen_sets)
- throw args::DoHelp("Cannot specify both set and package targets");
- seen_packages = true;
- }
- catch (const GotASetNotAPackageDepSpec &)
- {
- if (seen_packages)
- throw args::DoHelp("Cannot specify both set and package targets");
- if (seen_sets)
- throw args::DoHelp("Cannot specify multiple set targets");
-
- resolver->add_target(SetName(*p));
- seen_sets = true;
- }
- }
-
- if (seen_sets)
- is_set = true;
- }
-
- UseExisting use_existing_from_cmdline(const args::EnumArg & a, const bool is_set)
- {
- if (a.argument() == "auto")
- return is_set ? ue_if_same : ue_never;
- else if (a.argument() == "never")
- return ue_never;
- else if (a.argument() == "if-transient")
- return ue_only_if_transient;
- else if (a.argument() == "if-same")
- return ue_if_same;
- else if (a.argument() == "if-same-version")
- return ue_if_same_version;
- else if (a.argument() == "if-possible")
- return ue_if_possible;
- else
- throw args::DoHelp("Don't understand argument '" + a.argument() + "' to '--" + a.long_name() + "'");
- }
-
- struct UseExistingVisitor
- {
- const ResolveCommandLine & cmdline;
- const bool from_set;
-
- UseExistingVisitor(const ResolveCommandLine & c, const bool f) :
- cmdline(c),
- from_set(f)
- {
- }
-
- UseExisting visit(const DependencyReason &) const
- {
- return use_existing_from_cmdline(cmdline.resolution_options.a_keep, false);
- }
-
- UseExisting visit(const TargetReason &) const
- {
- return use_existing_from_cmdline(cmdline.resolution_options.a_keep_targets, from_set);
- }
-
- UseExisting visit(const PresetReason &) const
- {
- return ue_if_possible;
- }
-
- UseExisting visit(const SetReason & r) const
- {
- UseExistingVisitor v(cmdline, true);
- return r.reason_for_set()->accept_returning<UseExisting>(v);
- }
- };
-
- UseExisting use_existing_fn(const ResolveCommandLine & cmdline,
- const Resolvent &,
- const PackageDepSpec &,
- const std::tr1::shared_ptr<const Reason> & reason)
- {
- UseExistingVisitor v(cmdline, false);
- return reason->accept_returning<UseExisting>(v);
- }
-
- int reinstall_scm_days(const ResolveCommandLine & cmdline)
- {
- if (cmdline.resolution_options.a_reinstall_scm.argument() == "always")
- return 0;
- else if (cmdline.resolution_options.a_reinstall_scm.argument() == "daily")
- return 1;
- else if (cmdline.resolution_options.a_reinstall_scm.argument() == "weekly")
- return 7;
- else if (cmdline.resolution_options.a_reinstall_scm.argument() == "never")
- return -1;
- else
- throw args::DoHelp("Don't understand argument '" + cmdline.resolution_options.a_reinstall_scm.argument() + "' to '--"
- + cmdline.resolution_options.a_reinstall_scm.long_name() + "'");
- }
-
- bool is_scm_name(const QualifiedPackageName & n)
- {
- std::string pkg(stringify(n.package()));
- switch (pkg.length())
- {
- case 0:
- case 1:
- case 2:
- case 3:
- return false;
-
- default:
- if (0 == pkg.compare(pkg.length() - 6, 6, "-darcs"))
- return true;
-
- case 5:
- if (0 == pkg.compare(pkg.length() - 5, 5, "-live"))
- return true;
-
- case 4:
- if (0 == pkg.compare(pkg.length() - 4, 4, "-cvs"))
- return true;
- if (0 == pkg.compare(pkg.length() - 4, 4, "-svn"))
- return true;
- return false;
- }
- }
-
- bool is_scm_older_than(const std::tr1::shared_ptr<const PackageID> & id, const int n)
- {
- if (id->version().is_scm() || is_scm_name(id->name()))
- {
- static Timestamp current_time(Timestamp::now()); /* static to avoid weirdness */
- time_t installed_time(current_time.seconds());
- if (id->installed_time_key())
- installed_time = id->installed_time_key()->value().seconds();
-
- return (current_time.seconds() - installed_time) > (24 * 60 * 60 * n);
- }
- else
- return false;
- }
-
- bool installed_is_scm_older_than(const Environment * const env, const ResolveCommandLine & cmdline,
- const Resolvent & q, const int n)
- {
- Context context("When working out whether '" + stringify(q) + "' has installed SCM packages:");
-
- const std::tr1::shared_ptr<const PackageIDSequence> ids((*env)[selection::AllVersionsUnsorted(
- make_destination_filtered_generator(env, cmdline, generator::Package(q.package()), q) |
- make_slot_filter(q)
- )]);
-
- for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
- i != i_end ; ++i)
- {
- if (is_scm_older_than(*i, n))
- return true;
- }
-
- return false;
- }
-
- typedef std::map<Resolvent, std::tr1::shared_ptr<Constraints> > InitialConstraints;
-
- const std::tr1::shared_ptr<Constraints> make_initial_constraints_for(
- const Environment * const env,
- const ResolveCommandLine & cmdline,
- const Resolvent & resolvent)
- {
- const std::tr1::shared_ptr<Constraints> result(new Constraints);
-
- int n(reinstall_scm_days(cmdline));
- if ((-1 != n) && installed_is_scm_older_than(env, cmdline, resolvent, n))
- {
- result->add(make_shared_ptr(new Constraint(make_named_values<Constraint>(
- value_for<n::destination_type>(resolvent.destination_type()),
- value_for<n::nothing_is_fine_too>(false),
- value_for<n::reason>(make_shared_ptr(new PresetReason)),
- value_for<n::spec>(make_package_dep_spec(PartiallyMadePackageDepSpecOptions()).package(resolvent.package())),
- value_for<n::untaken>(false),
- value_for<n::use_existing>(ue_only_if_transient)
- ))));
- }
-
- return result;
- }
-
- const std::tr1::shared_ptr<Constraints> initial_constraints_for_fn(
- const Environment * const env,
- const ResolveCommandLine & cmdline,
- const InitialConstraints & initial_constraints,
- const Resolvent & resolvent)
- {
- InitialConstraints::const_iterator i(initial_constraints.find(resolvent));
- if (i == initial_constraints.end())
- return make_initial_constraints_for(env, cmdline, resolvent);
- else
- return i->second;
- }
-
- struct IsTargetVisitor
- {
- bool visit(const DependencyReason &) const
- {
- return false;
- }
-
- bool visit(const PresetReason &) const
- {
- return false;
- }
-
- bool visit(const TargetReason &) const
- {
- return true;
- }
-
- bool visit(const SetReason & r) const
- {
- return r.reason_for_set()->accept_returning<bool>(*this);
- }
- };
-
- bool is_target(const std::tr1::shared_ptr<const Reason> & reason)
- {
- IsTargetVisitor v;
- return reason->accept_returning<bool>(v);
- }
-
- const std::tr1::shared_ptr<Resolvents>
- get_resolvents_for_fn(const Environment * const env,
- const ResolveCommandLine & cmdline,
- const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const SlotName> & maybe_slot,
- const std::tr1::shared_ptr<const Reason> & reason)
- {
- std::tr1::shared_ptr<PackageIDSequence> result_ids(new PackageIDSequence);
- std::tr1::shared_ptr<const PackageID> best;
-
- const std::tr1::shared_ptr<const PackageIDSequence> ids((*env)[selection::BestVersionOnly(
- generator::Matches(spec, MatchPackageOptions() + mpo_ignore_additional_requirements) |
- filter::SupportsAction<InstallAction>() |
- filter::NotMasked() |
- (maybe_slot ? Filter(filter::Slot(*maybe_slot)) : Filter(filter::All())))]);
-
- if (! ids->empty())
- best = *ids->begin();
-
- const std::tr1::shared_ptr<const PackageIDSequence> installed_ids((*env)[selection::BestVersionInEachSlot(
- generator::Matches(spec, MatchPackageOptions()) |
- filter::InstalledAtRoot(FSEntry("/")))]);
-
- const args::EnumArg & arg(is_target(reason) ? cmdline.resolution_options.a_target_slots : cmdline.resolution_options.a_slots);
-
- if (! best)
- std::copy(installed_ids->begin(), installed_ids->end(), result_ids->back_inserter());
- else if (arg.argument() == "best-or-installed")
- {
- if (indirect_iterator(installed_ids->end()) == std::find(indirect_iterator(installed_ids->begin()),
- indirect_iterator(installed_ids->end()), *best))
- result_ids->push_back(best);
- else
- std::copy(installed_ids->begin(), installed_ids->end(), result_ids->back_inserter());
- }
- else if (arg.argument() == "installed-or-best")
- {
- if (installed_ids->empty())
- result_ids->push_back(best);
- else
- std::copy(installed_ids->begin(), installed_ids->end(), result_ids->back_inserter());
- }
- else if (arg.argument() == "all")
- {
- if (indirect_iterator(installed_ids->end()) == std::find(indirect_iterator(installed_ids->begin()),
- indirect_iterator(installed_ids->end()), *best))
- result_ids->push_back(best);
- std::copy(installed_ids->begin(), installed_ids->end(), result_ids->back_inserter());
- }
- else if (arg.argument() == "best")
- result_ids->push_back(best);
- else
- throw args::DoHelp("Don't understand argument '" + arg.argument() + "' to '--"
- + arg.long_name() + "'");
-
- std::tr1::shared_ptr<Resolvents> result(new Resolvents);
- for (PackageIDSequence::ConstIterator i(result_ids->begin()), i_end(result_ids->end()) ;
- i != i_end ; ++i)
- {
- DestinationTypes destination_types(get_destination_types_for_fn(env, cmdline, spec, *i, reason));
- for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
- if (destination_types[*t])
- result->push_back(Resolvent(*i, *t));
- }
-
- return result;
- }
-
- struct CareAboutDepFnVisitor
- {
- const ResolveCommandLine & cmdline;
- const SanitisedDependency dep;
-
- CareAboutDepFnVisitor(const ResolveCommandLine & c, const SanitisedDependency & d) :
- cmdline(c),
- dep(d)
- {
- }
-
- bool visit(const ExistingNoChangeDecision &) const
- {
- if (! cmdline.resolution_options.a_follow_installed_build_dependencies.specified())
- if (is_just_build_dep(dep))
- return false;
- if (cmdline.resolution_options.a_ignore_installed_dependencies.specified())
- if (! is_compiled_against_dep(dep))
- return false;
-
- if (is_suggestion(dep) || is_recommendation(dep))
- {
- /* should only return false if the dep's not already installedish */
- return false;
- }
-
- return true;
- }
-
- bool visit(const NothingNoChangeDecision &) const
- {
- return true;
- }
-
- bool visit(const UnableToMakeDecision &) const
- {
- return true;
- }
-
- bool visit(const ChangesToMakeDecision &) const
- {
- return true;
- }
- };
-
- bool care_about_dep_fn(const Environment * const, const ResolveCommandLine & cmdline,
- const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
- const SanitisedDependency & dep)
- {
- CareAboutDepFnVisitor v(cmdline, dep);
- return resolution->decision()->accept_returning<bool>(v);
- }
-
- bool
- take_dependency_fn(const Environment * const env,
- const ResolveCommandLine & cmdline,
- const Resolvent & resolvent,
- const SanitisedDependency & dep,
- const std::tr1::shared_ptr<const Reason> &)
- {
- bool suggestion(is_suggestion(dep)), recommendation(is_recommendation(dep));
-
- if (suggestion || recommendation)
- {
- for (args::StringSetArg::ConstIterator a(cmdline.resolution_options.a_take.begin_args()),
- a_end(cmdline.resolution_options.a_take.end_args()) ;
- a != a_end ; ++a)
- {
- PackageDepSpec user_spec(parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards));
- PackageDepSpec spec(*dep.spec().if_package());
- if (match_qpns(*env, user_spec, *spec.package_ptr()))
- return true;
- }
-
- for (args::StringSetArg::ConstIterator a(cmdline.resolution_options.a_take_from.begin_args()),
- a_end(cmdline.resolution_options.a_take_from.end_args()) ;
- a != a_end ; ++a)
- {
- PackageDepSpec user_spec(parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards));
- if (match_qpns(*env, user_spec, resolvent.package()))
- return true;
- }
-
- for (args::StringSetArg::ConstIterator a(cmdline.resolution_options.a_discard.begin_args()),
- a_end(cmdline.resolution_options.a_discard.end_args()) ;
- a != a_end ; ++a)
- {
- PackageDepSpec user_spec(parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards));
- PackageDepSpec spec(*dep.spec().if_package());
- if (match_qpns(*env, user_spec, *spec.package_ptr()))
- return false;
- }
-
- for (args::StringSetArg::ConstIterator a(cmdline.resolution_options.a_discard_from.begin_args()),
- a_end(cmdline.resolution_options.a_discard_from.end_args()) ;
- a != a_end ; ++a)
- {
- PackageDepSpec user_spec(parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards));
- if (match_qpns(*env, user_spec, resolvent.package()))
- return false;
- }
- }
- if (suggestion)
- {
- if (cmdline.resolution_options.a_suggestions.argument() == "take")
- {
- return true;
- }
- return false;
- }
- if (recommendation)
- {
- if (cmdline.resolution_options.a_recommendations.argument() == "take")
- {
- return true;
- }
- return false;
- }
-
- return true;
- }
-
- const std::tr1::shared_ptr<const Repository>
- find_repository_for_fn(const Environment * const env,
- const ResolveCommandLine & cmdline,
- const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> &,
- const ChangesToMakeDecision & decision)
- {
- std::tr1::shared_ptr<const Repository> result;
- for (PackageDatabase::RepositoryConstIterator r(env->package_database()->begin_repositories()),
- r_end(env->package_database()->end_repositories()) ;
- r != r_end ; ++r)
- {
- switch (resolvent.destination_type())
- {
- case dt_install_to_slash:
- if ((! (*r)->installed_root_key()) || ((*r)->installed_root_key()->value() != FSEntry("/")))
- continue;
- break;
-
- case dt_create_binary:
- if (cmdline.resolution_options.a_create_binaries.end_args() == std::find(
- cmdline.resolution_options.a_create_binaries.begin_args(),
- cmdline.resolution_options.a_create_binaries.end_args(),
- stringify((*r)->name())))
- continue;
- break;
-
- case last_dt:
- break;
- }
-
- if ((*r)->destination_interface() &&
- (*r)->destination_interface()->is_suitable_destination_for(*decision.origin_id()))
- {
- if (result)
- throw ConfigurationError("For '" + stringify(*decision.origin_id())
- + "' with destination type " + stringify(resolvent.destination_type())
- + ", don't know whether to install to ::" + stringify(result->name())
- + " or ::" + stringify((*r)->name()));
- else
- result = *r;
- }
- }
-
- if (! result)
- throw ConfigurationError("No repository suitable for '" + stringify(*decision.origin_id())
- + "' with destination type " + stringify(resolvent.destination_type()) + " has been configured");
- return result;
- }
-
- Filter make_destination_filter_fn(const Resolvent & resolvent)
- {
- switch (resolvent.destination_type())
- {
- case dt_install_to_slash:
- return filter::InstalledAtRoot(FSEntry("/"));
-
- case dt_create_binary:
- throw InternalError(PALUDIS_HERE, "no dt_create_binary yet");
-
- case last_dt:
- break;
- }
-
- throw InternalError(PALUDIS_HERE, "unhandled dt");
- }
-
- void ser_thread_func(StringListStream & ser_stream, const ResolverLists & resolution_lists)
- {
- Serialiser ser(ser_stream);
- resolution_lists.serialise(ser);
- ser_stream.nothing_more_to_write();
- }
-
- int display_resolution(
- const std::tr1::shared_ptr<Environment> &,
- const ResolverLists & resolution_lists,
- const ResolveCommandLine & cmdline)
- {
- Context context("When displaying chosen resolution:");
-
- StringListStream ser_stream;
- Thread ser_thread(std::tr1::bind(&ser_thread_func,
- std::tr1::ref(ser_stream),
- std::tr1::cref(resolution_lists)));
-
- std::string command(cmdline.program_options.a_display_resolution_program.argument());
- if (command.empty())
- command = "$CAVE display-resolution";
-
- for (args::ArgsSection::GroupsConstIterator g(cmdline.display_options.begin()), g_end(cmdline.display_options.end()) ;
- g != g_end ; ++g)
- {
- for (args::ArgsGroup::ConstIterator o(g->begin()), o_end(g->end()) ;
- o != o_end ; ++o)
- if ((*o)->specified())
- command = command + " " + (*o)->forwardable_string();
- }
-
- for (ResolveCommandLine::ParametersConstIterator p(cmdline.begin_parameters()), p_end(cmdline.end_parameters()) ;
- p != p_end ; ++p)
- command = command + " " + args::escape(*p);
-
- paludis::Command cmd(command);
- cmd
- .with_input_stream(&ser_stream, -1, "PALUDIS_SERIALISED_RESOLUTION_FD");
-
- return run_command(cmd);
- }
-
- void perform_resolution(
- const std::tr1::shared_ptr<Environment> &,
- const ResolverLists & resolution_lists,
- const ResolveCommandLine & cmdline,
- const bool is_set) PALUDIS_ATTRIBUTE((noreturn));
-
- void perform_resolution(
- const std::tr1::shared_ptr<Environment> &,
- const ResolverLists & resolution_lists,
- const ResolveCommandLine & cmdline,
- const bool is_set)
- {
- Context context("When performing chosen resolution:");
-
- StringListStream ser_stream;
- Serialiser ser(ser_stream);
- resolution_lists.serialise(ser);
-
- /* backgrounding this barfs with become_command. working out why could
- * be a fun exercise for someone with way too much time on their hands.
- * */
- ser_thread_func(ser_stream, resolution_lists);
-
- std::string command(cmdline.program_options.a_execute_resolution_program.argument());
- if (command.empty())
- command = "$CAVE execute-resolution";
-
- for (args::ArgsSection::GroupsConstIterator g(cmdline.execution_options.begin()),
- g_end(cmdline.execution_options.end()) ;
- g != g_end ; ++g)
- {
- for (args::ArgsGroup::ConstIterator o(g->begin()), o_end(g->end()) ;
- o != o_end ; ++o)
- if ((*o)->specified())
- command = command + " " + (*o)->forwardable_string();
- }
-
- if (is_set)
- command.append(" --set");
-
- for (args::ArgsSection::GroupsConstIterator g(cmdline.program_options.begin()),
- g_end(cmdline.program_options.end()) ;
- g != g_end ; ++g)
- {
- for (args::ArgsGroup::ConstIterator o(g->begin()), o_end(g->end()) ;
- o != o_end ; ++o)
- if ((*o)->specified())
- command = command + " " + (*o)->forwardable_string();
- }
-
- if (! cmdline.resolution_options.a_execute.specified())
- command = command + " --pretend";
-
- for (ResolveCommandLine::ParametersConstIterator p(cmdline.begin_parameters()), p_end(cmdline.end_parameters()) ;
- p != p_end ; ++p)
- command = command + " " + args::escape(*p);
-
- paludis::Command cmd(command);
- cmd
- .with_input_stream(&ser_stream, -1, "PALUDIS_SERIALISED_RESOLUTION_FD");
-
- become_command(cmd);
- }
-
- struct ChosenIDVisitor
- {
- const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
- {
- return decision.origin_id();
- }
-
- const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
- {
- return decision.existing_id();
- }
-
- const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
- {
- return make_null_shared_ptr();
- }
-
- const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
- {
- return make_null_shared_ptr();
- }
- };
-
- struct KindNameVisitor
- {
- const std::string visit(const UnableToMakeDecision &) const
- {
- return "unable_to_make_decision";
- }
-
- const std::string visit(const NothingNoChangeDecision &) const
- {
- return "nothing_no_change";
- }
-
- const std::string visit(const ExistingNoChangeDecision &) const
- {
- return "existing_no_change";
- }
-
- const std::string visit(const ChangesToMakeDecision &) const
- {
- return "changes_to_make";
- }
- };
-
- void display_restarts_if_requested(const std::list<SuggestRestart> & restarts,
- const ResolveCommandLine & cmdline)
- {
- if (! cmdline.resolution_options.a_dump_restarts.specified())
- return;
-
- std::cout << "Dumping restarts:" << std::endl << std::endl;
-
- for (std::list<SuggestRestart>::const_iterator r(restarts.begin()), r_end(restarts.end()) ;
- r != r_end ; ++r)
- {
- std::cout << "* " << r->resolvent() << std::endl;
-
- std::cout << " Had decided upon ";
- const std::tr1::shared_ptr<const PackageID> id(r->previous_decision()->accept_returning<
- std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
- if (id)
- std::cout << *id;
- else
- std::cout << r->previous_decision()->accept_returning<std::string>(KindNameVisitor());
- std::cout << std::endl;
-
- std::cout << " Which did not satisfy " << r->problematic_constraint()->spec()
- << ", use existing " << r->problematic_constraint()->use_existing();
- if (r->problematic_constraint()->nothing_is_fine_too())
- std::cout << ", nothing is fine too";
- std::cout << std::endl;
- }
-
- std::cout << std::endl;
- }
-}
-
bool
ResolveCommand::important() const
{
@@ -1063,145 +53,16 @@ ResolveCommand::run(
return EXIT_SUCCESS;
}
- if (cmdline.resolution_options.a_lazy.specified() +
- cmdline.resolution_options.a_complete.specified() +
- cmdline.resolution_options.a_everything.specified() > 1)
- throw args::DoHelp("At most one of '--" + cmdline.resolution_options.a_lazy.long_name() + "', '--" + cmdline.resolution_options.a_complete.long_name()
- + "' or '--" + cmdline.resolution_options.a_everything.long_name() + "' may be specified");
-
- if (cmdline.resolution_options.a_lazy.specified())
- {
- if (! cmdline.resolution_options.a_target_slots.specified())
- cmdline.resolution_options.a_target_slots.set_argument("best");
- if (! cmdline.resolution_options.a_slots.specified())
- cmdline.resolution_options.a_slots.set_argument("best");
- if (! cmdline.resolution_options.a_ignore_installed_dependencies.specified())
- cmdline.resolution_options.a_ignore_installed_dependencies.set_specified(true);
- }
-
- if (cmdline.resolution_options.a_complete.specified())
- {
- if (! cmdline.resolution_options.a_keep.specified())
- cmdline.resolution_options.a_keep.set_argument("if-same");
- if (! cmdline.resolution_options.a_target_slots.specified())
- cmdline.resolution_options.a_target_slots.set_argument("all");
- if (! cmdline.resolution_options.a_slots.specified())
- cmdline.resolution_options.a_slots.set_argument("all");
- if (! cmdline.resolution_options.a_follow_installed_build_dependencies.specified())
- cmdline.resolution_options.a_follow_installed_build_dependencies.set_specified(true);
- if (! cmdline.resolution_options.a_reinstall_scm.specified())
- cmdline.resolution_options.a_reinstall_scm.set_argument("weekly");
- }
-
- if (cmdline.resolution_options.a_everything.specified())
- {
- if (! cmdline.resolution_options.a_keep.specified())
- cmdline.resolution_options.a_keep.set_argument("if-transient");
- if (! cmdline.resolution_options.a_keep_targets.specified())
- cmdline.resolution_options.a_keep_targets.set_argument("if-transient");
- if (! cmdline.resolution_options.a_target_slots.specified())
- cmdline.resolution_options.a_target_slots.set_argument("all");
- if (! cmdline.resolution_options.a_slots.specified())
- cmdline.resolution_options.a_slots.set_argument("all");
- if (! cmdline.resolution_options.a_follow_installed_build_dependencies.specified())
- cmdline.resolution_options.a_follow_installed_build_dependencies.set_specified(true);
- }
-
- if (cmdline.resolution_options.a_create_binaries.specified())
- {
- for (args::StringSetArg::ConstIterator a(cmdline.resolution_options.a_create_binaries.begin_args()),
- a_end(cmdline.resolution_options.a_create_binaries.end_args()) ;
- a != a_end ; ++a)
- {
- std::tr1::shared_ptr<const Repository> repo(env->package_database()->fetch_repository(RepositoryName(*a)));
- if (repo->installed_root_key() || ! repo->destination_interface())
- throw args::DoHelp("Repository '" + *a + "' not suitable for --" + cmdline.resolution_options.a_create_binaries.long_name());
- }
- }
-
- int retcode(0);
-
- InitialConstraints initial_constraints;
+ cmdline.resolution_options.apply_shortcuts();
+ cmdline.resolution_options.verify(env);
- ResolverFunctions resolver_functions(make_named_values<ResolverFunctions>(
- value_for<n::care_about_dep_fn>(std::tr1::bind(&care_about_dep_fn,
- env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1,
- std::tr1::placeholders::_2, std::tr1::placeholders::_3)),
- value_for<n::find_repository_for_fn>(std::tr1::bind(&find_repository_for_fn,
- env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2,
- std::tr1::placeholders::_3)),
- value_for<n::get_destination_types_for_fn>(std::tr1::bind(&get_destination_types_for_fn,
- env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2,
- std::tr1::placeholders::_3)),
- value_for<n::get_initial_constraints_for_fn>(std::tr1::bind(&initial_constraints_for_fn,
- env.get(), std::tr1::cref(cmdline), std::tr1::cref(initial_constraints), std::tr1::placeholders::_1)),
- value_for<n::get_resolvents_for_fn>(std::tr1::bind(&get_resolvents_for_fn,
- env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2,
- std::tr1::placeholders::_3)),
- value_for<n::get_use_existing_fn>(std::tr1::bind(&use_existing_fn,
- std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2, std::tr1::placeholders::_3)),
- value_for<n::make_destination_filtered_generator_fn>(std::tr1::bind(&make_destination_filtered_generator,
- env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2)),
- value_for<n::take_dependency_fn>(std::tr1::bind(&take_dependency_fn, env.get(),
- std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2, std::tr1::placeholders::_3))
-
- ));
-
- ScopedSelectionCache selection_cache(env.get());
- std::tr1::shared_ptr<Resolver> resolver(new Resolver(env.get(), resolver_functions));
- bool is_set(false);
- std::list<SuggestRestart> restarts;
-
- try
- {
- {
- DisplayCallback display_callback;
- ScopedNotifierCallback display_callback_holder(env.get(),
- NotifierCallbackFunction(std::tr1::cref(display_callback)));
-
- while (true)
- {
- try
- {
- add_resolver_targets(env, resolver, cmdline, is_set);
- resolver->resolve();
- break;
- }
- catch (const SuggestRestart & e)
- {
- restarts.push_back(e);
- display_callback(ResolverRestart());
- initial_constraints.insert(std::make_pair(e.resolvent(), make_initial_constraints_for(
- env.get(), cmdline, e.resolvent()))).first->second->add(
- e.suggested_preset());
- resolver = make_shared_ptr(new Resolver(env.get(), resolver_functions));
- }
- }
- }
-
- if (! restarts.empty())
- display_restarts_if_requested(restarts, cmdline);
-
- dump_if_requested(env, resolver, cmdline);
-
- retcode |= display_resolution(env, *resolver->lists(), cmdline);
-
- if (! resolver->lists()->error_resolutions()->empty())
- retcode |= 1;
-
- if (0 == retcode)
- perform_resolution(env, *resolver->lists(), cmdline, is_set);
- }
- catch (...)
- {
- if (! restarts.empty())
- display_restarts_if_requested(restarts, cmdline);
-
- dump_if_requested(env, resolver, cmdline);
- throw;
- }
+ std::tr1::shared_ptr<Sequence<std::string> > targets(new Sequence<std::string>);
+ for (ResolveCommandLine::ParametersConstIterator p(cmdline.begin_parameters()), p_end(cmdline.end_parameters()) ;
+ p != p_end ; ++p)
+ targets->push_back(*p);
- return retcode;
+ return resolve_common(env, cmdline.resolution_options, cmdline.execution_options, cmdline.display_options,
+ cmdline.program_options, make_null_shared_ptr(), targets);
}
std::tr1::shared_ptr<args::ArgsHandler>
diff --git a/src/clients/cave/cmd_resolve_cmdline.cc b/src/clients/cave/cmd_resolve_cmdline.cc
index 6d0975b..3b186e6 100644
--- a/src/clients/cave/cmd_resolve_cmdline.cc
+++ b/src/clients/cave/cmd_resolve_cmdline.cc
@@ -18,10 +18,30 @@
*/
#include "cmd_resolve_cmdline.hh"
+#include <paludis/args/do_help.hh>
+#include <paludis/repository.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/map.hh>
+#include <paludis/repository_factory.hh>
+#include <tr1/memory>
using namespace paludis;
using namespace cave;
+namespace
+{
+ std::string from_keys(const std::tr1::shared_ptr<const Map<std::string, std::string> > & m,
+ const std::string & k)
+ {
+ Map<std::string, std::string>::ConstIterator mm(m->find(k));
+ if (m->end() == mm)
+ return "";
+ else
+ return mm->second;
+ }
+}
+
ResolveCommandLineResolutionOptions::ResolveCommandLineResolutionOptions(args::ArgsHandler * const h) :
ArgsSection(h, "Resolution Options"),
g_execution_options(this, "Execution Options", "Control execution."),
@@ -259,6 +279,37 @@ ResolveCommandLineProgramOptions::ResolveCommandLineProgramOptions(args::ArgsHan
{
}
+ResolveCommandLineImportOptions::ResolveCommandLineImportOptions(args::ArgsHandler * const h) :
+ ArgsSection(h, "Import Options"),
+ g_import_options(this, "Import Options", "Options controlling additional imported packages. These options "
+ "should not be specified manually; they are for use by 'cave import'."),
+ a_unpackaged_repository_params(&g_import_options, "unpackaged-repository-params", '\0', "Specifies "
+ "the parameters used to construct an unpackaged repository, for use by 'cave import'.")
+{
+}
+
+void
+ResolveCommandLineImportOptions::apply(const std::tr1::shared_ptr<Environment> & env) const
+{
+ if (! a_unpackaged_repository_params.specified())
+ return;
+
+ std::tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ for (args::StringSetArg::ConstIterator a(a_unpackaged_repository_params.begin_args()),
+ a_end(a_unpackaged_repository_params.end_args()) ;
+ a != a_end ; ++a)
+ {
+ std::string::size_type p(a->find('='));
+ if (std::string::npos == p)
+ throw InternalError(PALUDIS_HERE, "no = in '" + stringify(*a));
+ keys->insert(a->substr(0, p), a->substr(p + 1));
+ }
+
+ std::tr1::shared_ptr<Repository> repo(RepositoryFactory::get_instance()->create(env.get(),
+ std::tr1::bind(from_keys, keys, std::tr1::placeholders::_1)));
+ env->package_database()->add_repository(10, repo);
+}
+
ResolveCommandLine::ResolveCommandLine() :
resolution_options(this),
execution_options(this),
@@ -290,3 +341,67 @@ ResolveCommandLine::app_description() const
"resolution.";
}
+void
+ResolveCommandLineResolutionOptions::apply_shortcuts()
+{
+ if (a_lazy.specified() +
+ a_complete.specified() +
+ a_everything.specified() > 1)
+ throw args::DoHelp("At most one of '--" + a_lazy.long_name() + "', '--" + a_complete.long_name()
+ + "' or '--" + a_everything.long_name() + "' may be specified");
+
+ if (a_lazy.specified())
+ {
+ if (! a_target_slots.specified())
+ a_target_slots.set_argument("best");
+ if (! a_slots.specified())
+ a_slots.set_argument("best");
+ if (! a_ignore_installed_dependencies.specified())
+ a_ignore_installed_dependencies.set_specified(true);
+ }
+
+ if (a_complete.specified())
+ {
+ if (! a_keep.specified())
+ a_keep.set_argument("if-same");
+ if (! a_target_slots.specified())
+ a_target_slots.set_argument("all");
+ if (! a_slots.specified())
+ a_slots.set_argument("all");
+ if (! a_follow_installed_build_dependencies.specified())
+ a_follow_installed_build_dependencies.set_specified(true);
+ if (! a_reinstall_scm.specified())
+ a_reinstall_scm.set_argument("weekly");
+ }
+
+ if (a_everything.specified())
+ {
+ if (! a_keep.specified())
+ a_keep.set_argument("if-transient");
+ if (! a_keep_targets.specified())
+ a_keep_targets.set_argument("if-transient");
+ if (! a_target_slots.specified())
+ a_target_slots.set_argument("all");
+ if (! a_slots.specified())
+ a_slots.set_argument("all");
+ if (! a_follow_installed_build_dependencies.specified())
+ a_follow_installed_build_dependencies.set_specified(true);
+ }
+}
+
+void
+ResolveCommandLineResolutionOptions::verify(const std::tr1::shared_ptr<const Environment> & env)
+{
+ if (a_create_binaries.specified())
+ {
+ for (args::StringSetArg::ConstIterator a(a_create_binaries.begin_args()),
+ a_end(a_create_binaries.end_args()) ;
+ a != a_end ; ++a)
+ {
+ std::tr1::shared_ptr<const Repository> repo(env->package_database()->fetch_repository(RepositoryName(*a)));
+ if (repo->installed_root_key() || ! repo->destination_interface())
+ throw args::DoHelp("Repository '" + *a + "' not suitable for --" + a_create_binaries.long_name());
+ }
+ }
+}
+
diff --git a/src/clients/cave/cmd_resolve_cmdline.hh b/src/clients/cave/cmd_resolve_cmdline.hh
index 9661228..6cd8b24 100644
--- a/src/clients/cave/cmd_resolve_cmdline.hh
+++ b/src/clients/cave/cmd_resolve_cmdline.hh
@@ -21,6 +21,8 @@
#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_RESOLVE_CMDLINE_HH 1
#include "command_command_line.hh"
+#include <paludis/environment-fwd.hh>
+#include <tr1/memory>
namespace paludis
{
@@ -99,6 +101,9 @@ namespace paludis
args::ArgsGroup g_dump_options;
args::SwitchArg a_dump;
args::SwitchArg a_dump_restarts;
+
+ void apply_shortcuts();
+ void verify(const std::tr1::shared_ptr<const Environment> & env);
};
struct ResolveCommandLineExecutionOptions :
@@ -145,6 +150,17 @@ namespace paludis
args::StringArg a_update_world_program;
};
+ struct ResolveCommandLineImportOptions :
+ args::ArgsSection
+ {
+ ResolveCommandLineImportOptions(args::ArgsHandler * const);
+
+ args::ArgsGroup g_import_options;
+ args::StringSetArg a_unpackaged_repository_params;
+
+ void apply(const std::tr1::shared_ptr<Environment> & env) const;
+ };
+
struct ResolveCommandLine :
CaveCommandCommandLine
{
diff --git a/src/clients/cave/cmd_resolve_dump.cc b/src/clients/cave/cmd_resolve_dump.cc
index df8fbda..fe8f0c3 100644
--- a/src/clients/cave/cmd_resolve_dump.cc
+++ b/src/clients/cave/cmd_resolve_dump.cc
@@ -222,7 +222,7 @@ namespace
void dump(
const std::tr1::shared_ptr<Environment> &,
const std::tr1::shared_ptr<Resolver> & resolver,
- const ResolveCommandLine &)
+ const ResolveCommandLineResolutionOptions &)
{
std::cout << "Dumping resolutions by QPN:S:" << std::endl << std::endl;
@@ -242,13 +242,13 @@ void
paludis::cave::dump_if_requested(
const std::tr1::shared_ptr<Environment> & env,
const std::tr1::shared_ptr<Resolver> & resolver,
- const ResolveCommandLine & cmdline)
+ const ResolveCommandLineResolutionOptions & resolution_options)
{
Context context("When dumping the resolver:");
- if (! cmdline.resolution_options.a_dump.specified())
+ if (! resolution_options.a_dump.specified())
return;
- dump(env, resolver, cmdline);
+ dump(env, resolver, resolution_options);
}
diff --git a/src/clients/cave/cmd_resolve_dump.hh b/src/clients/cave/cmd_resolve_dump.hh
index 8e7b8db..eb25404 100644
--- a/src/clients/cave/cmd_resolve_dump.hh
+++ b/src/clients/cave/cmd_resolve_dump.hh
@@ -31,7 +31,7 @@ namespace paludis
void dump_if_requested(
const std::tr1::shared_ptr<Environment> &,
const std::tr1::shared_ptr<resolver::Resolver> & resolver,
- const ResolveCommandLine & cmdline);
+ const ResolveCommandLineResolutionOptions & resolution_options);
}
}
diff --git a/src/clients/cave/command_factory.cc b/src/clients/cave/command_factory.cc
index 26e2fc0..9ee1dea 100644
--- a/src/clients/cave/command_factory.cc
+++ b/src/clients/cave/command_factory.cc
@@ -29,6 +29,7 @@
#include "cmd_display_resolution.hh"
#include "cmd_execute_resolution.hh"
#include "cmd_help.hh"
+#include "cmd_import.hh"
#include "cmd_perform.hh"
#include "cmd_print_categories.hh"
#include "cmd_print_commands.hh"
@@ -83,6 +84,7 @@ CommandFactory::CommandFactory() :
_imp->handlers.insert(std::make_pair("display-resolution", std::tr1::bind(&make_command<DisplayResolutionCommand>)));
_imp->handlers.insert(std::make_pair("execute-resolution", std::tr1::bind(&make_command<ExecuteResolutionCommand>)));
_imp->handlers.insert(std::make_pair("help", std::tr1::bind(&make_command<HelpCommand>)));
+ _imp->handlers.insert(std::make_pair("import", std::tr1::bind(&make_command<ImportCommand>)));
_imp->handlers.insert(std::make_pair("perform", std::tr1::bind(&make_command<PerformCommand>)));
_imp->handlers.insert(std::make_pair("print-categories", std::tr1::bind(&make_command<PrintCategoriesCommand>)));
_imp->handlers.insert(std::make_pair("print-commands", std::tr1::bind(&make_command<PrintCommandsCommand>)));
diff --git a/src/clients/cave/resolve_common.cc b/src/clients/cave/resolve_common.cc
new file mode 100644
index 0000000..641bff8
--- /dev/null
+++ b/src/clients/cave/resolve_common.cc
@@ -0,0 +1,1164 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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 "resolve_common.hh"
+#include "cmd_resolve_display_callback.hh"
+#include "cmd_resolve_dump.hh"
+#include "exceptions.hh"
+#include "command_command_line.hh"
+#include "match_qpns.hh"
+
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/enum_iterator.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/wrapped_output_iterator.hh>
+#include <paludis/util/string_list_stream.hh>
+#include <paludis/util/thread.hh>
+#include <paludis/util/timestamp.hh>
+#include <paludis/util/map.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/args/escape.hh>
+#include <paludis/resolver/resolver.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/resolver_functions.hh>
+#include <paludis/resolver/reason.hh>
+#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/resolvent.hh>
+#include <paludis/resolver/constraint.hh>
+#include <paludis/resolver/sanitised_dependencies.hh>
+#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/resolver_lists.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/notifier_callback.hh>
+#include <paludis/generator.hh>
+#include <paludis/filter.hh>
+#include <paludis/selection.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/environment.hh>
+#include <paludis/match_package.hh>
+#include <paludis/package_database.hh>
+#include <paludis/serialise-impl.hh>
+#include <paludis/selection_cache.hh>
+
+#include <algorithm>
+#include <iostream>
+#include <cstdlib>
+#include <map>
+
+using namespace paludis;
+using namespace paludis::resolver;
+using namespace cave;
+
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct LabelTypesVisitor
+ {
+ bool is_suggestion;
+ bool is_recommendation;
+ bool is_requirement;
+ bool seen_buildish_dep;
+ bool seen_runish_dep;
+ bool seen_compiled_against_dep;
+
+ LabelTypesVisitor() :
+ is_suggestion(false),
+ is_recommendation(false),
+ is_requirement(false),
+ seen_buildish_dep(false),
+ seen_runish_dep(false),
+ seen_compiled_against_dep(false)
+ {
+ }
+
+ void visit(const DependenciesBuildLabel &)
+ {
+ is_requirement = true;
+ seen_buildish_dep = true;
+ }
+
+ void visit(const DependenciesTestLabel &)
+ {
+ is_requirement = true;
+ seen_buildish_dep = true;
+ }
+
+ void visit(const DependenciesFetchLabel &)
+ {
+ is_requirement = true;
+ seen_buildish_dep = true;
+ }
+
+ void visit(const DependenciesRunLabel &)
+ {
+ is_requirement = true;
+ seen_runish_dep = true;
+ }
+
+ void visit(const DependenciesPostLabel &)
+ {
+ is_requirement = true;
+ seen_runish_dep = true;
+ }
+
+ void visit(const DependenciesInstallLabel &)
+ {
+ is_requirement = true;
+ seen_buildish_dep = true;
+ }
+
+ void visit(const DependenciesCompileAgainstLabel &)
+ {
+ is_requirement = true;
+ seen_runish_dep = true;
+ seen_buildish_dep = true;
+ }
+
+ void visit(const DependenciesRecommendationLabel &)
+ {
+ is_recommendation = true;
+ seen_runish_dep = true;
+ }
+
+ void visit(const DependenciesSuggestionLabel &)
+ {
+ is_suggestion = true;
+ seen_runish_dep = true;
+ }
+ };
+
+ bool is_suggestion(const SanitisedDependency & dep)
+ {
+ if (dep.active_dependency_labels()->empty())
+ return false;
+
+ LabelTypesVisitor v;
+ std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
+ indirect_iterator(dep.active_dependency_labels()->end()),
+ accept_visitor(v));
+ return v.is_suggestion && (! v.is_recommendation) && (! v.is_requirement);
+ }
+
+ bool is_recommendation(const SanitisedDependency & dep)
+ {
+ if (dep.active_dependency_labels()->empty())
+ return false;
+
+ LabelTypesVisitor v;
+ std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
+ indirect_iterator(dep.active_dependency_labels()->end()),
+ accept_visitor(v));
+ return v.is_recommendation && (! v.is_requirement);
+ }
+
+ bool is_just_build_dep(const SanitisedDependency & dep)
+ {
+ if (dep.active_dependency_labels()->empty())
+ throw InternalError(PALUDIS_HERE, "not implemented");
+
+ LabelTypesVisitor v;
+ std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
+ indirect_iterator(dep.active_dependency_labels()->end()),
+ accept_visitor(v));
+ return v.seen_buildish_dep && ! v.seen_runish_dep;
+ }
+
+ bool is_compiled_against_dep(const SanitisedDependency & dep)
+ {
+ if (dep.active_dependency_labels()->empty())
+ throw InternalError(PALUDIS_HERE, "not implemented");
+
+ LabelTypesVisitor v;
+ std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
+ indirect_iterator(dep.active_dependency_labels()->end()),
+ accept_visitor(v));
+ return v.seen_compiled_against_dep;
+ }
+
+ bool is_buildish_dep(const SanitisedDependency & dep)
+ {
+ if (dep.active_dependency_labels()->empty())
+ throw InternalError(PALUDIS_HERE, "not implemented");
+
+ LabelTypesVisitor v;
+ std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
+ indirect_iterator(dep.active_dependency_labels()->end()),
+ accept_visitor(v));
+ return v.seen_buildish_dep;
+ }
+
+ bool is_runish_dep(const SanitisedDependency & dep)
+ {
+ if (dep.active_dependency_labels()->empty())
+ throw InternalError(PALUDIS_HERE, "not implemented");
+
+ LabelTypesVisitor v;
+ std::for_each(indirect_iterator(dep.active_dependency_labels()->begin()),
+ indirect_iterator(dep.active_dependency_labels()->end()),
+ accept_visitor(v));
+ return v.seen_runish_dep;
+ }
+
+ struct DestinationTypesFinder
+ {
+ const Environment * const env;
+ const ResolveCommandLineResolutionOptions & resolution_options;
+ const std::tr1::shared_ptr<const PackageID> package_id;
+
+ DestinationTypesFinder(
+ const Environment * const e,
+ const ResolveCommandLineResolutionOptions & c,
+ const std::tr1::shared_ptr<const PackageID> & i) :
+ env(e),
+ resolution_options(c),
+ package_id(i)
+ {
+ }
+
+ DestinationTypes visit(const TargetReason &) const
+ {
+ DestinationTypes result;
+
+ if (resolution_options.a_create_binaries.specified())
+ {
+ bool b(true);
+
+ if (resolution_options.a_no_binaries_for.specified() && package_id)
+ {
+ for (args::StringSetArg::ConstIterator a(resolution_options.a_no_binaries_for.begin_args()),
+ a_end(resolution_options.a_no_binaries_for.end_args()) ;
+ a != a_end ; ++a)
+ if (match_package(*env,
+ parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards),
+ *package_id, MatchPackageOptions()))
+ {
+ b = false;
+ break;
+ }
+ }
+
+ if (b)
+ result += dt_create_binary;
+ }
+
+ if (resolution_options.a_install_to_root.specified())
+ result += dt_install_to_slash;
+
+ if (result.none())
+ result += dt_install_to_slash;
+
+ return result;
+ }
+
+ DestinationTypes visit(const DependencyReason & reason) const
+ {
+ DestinationTypes result;
+
+ bool is_buildish(is_buildish_dep(reason.sanitised_dependency())),
+ is_runish(is_runish_dep(reason.sanitised_dependency()));
+
+ if ((! is_buildish) && (! is_runish))
+ throw InternalError(PALUDIS_HERE, "not buildish or runish. eek. labels are { "
+ + join(indirect_iterator(reason.sanitised_dependency().active_dependency_labels()->begin()),
+ indirect_iterator(reason.sanitised_dependency().active_dependency_labels()->end()), ", ")
+ + " }");
+
+ if (is_buildish)
+ result += dt_install_to_slash;
+ if (is_runish)
+ result |= visit(TargetReason());
+
+ return result;
+ }
+
+ DestinationTypes visit(const PresetReason &) const PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw InternalError(PALUDIS_HERE, "not sure what to do here yet");
+ }
+
+ DestinationTypes visit(const SetReason & r) const
+ {
+ return r.reason_for_set()->accept_returning<DestinationTypes>(*this);
+ }
+ };
+
+ DestinationTypes get_destination_types_for_fn(
+ const Environment * const env,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const PackageDepSpec &,
+ const std::tr1::shared_ptr<const PackageID> & id,
+ const std::tr1::shared_ptr<const Reason> & reason)
+ {
+ DestinationTypesFinder f(env, resolution_options, id);
+ return reason->accept_returning<DestinationTypes>(f);
+ }
+
+ FilteredGenerator make_destination_filtered_generator(
+ const Environment * const,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const Generator & g,
+ const Resolvent & r)
+ {
+ switch (r.destination_type())
+ {
+ case dt_install_to_slash:
+ return g | filter::InstalledAtRoot(FSEntry("/"));
+
+ case dt_create_binary:
+ {
+ std::tr1::shared_ptr<Generator> generator;
+ for (args::StringSetArg::ConstIterator a(resolution_options.a_create_binaries.begin_args()),
+ a_end(resolution_options.a_create_binaries.end_args()) ;
+ a != a_end ; ++a)
+ {
+ if (! generator)
+ generator.reset(new generator::InRepository(RepositoryName(*a)));
+ else
+ generator.reset(new generator::Intersection(*generator, generator::InRepository(RepositoryName(*a))));
+ }
+
+ if (! generator)
+ throw args::DoHelp("No binary destinations were specified");
+ else
+ return g & *generator;
+ }
+
+ case last_dt:
+ break;
+ }
+
+ throw InternalError(PALUDIS_HERE, stringify(r.destination_type()));
+ }
+
+ void add_resolver_targets(
+ const std::tr1::shared_ptr<Environment> & env,
+ const std::tr1::shared_ptr<Resolver> & resolver,
+ const ResolveCommandLineResolutionOptions &,
+ const std::tr1::shared_ptr<const Sequence<std::string> > & targets,
+ bool & is_set)
+ {
+ Context context("When adding targets from commandline:");
+
+ if (targets->empty())
+ throw args::DoHelp("Must specify at least one target");
+
+ bool seen_sets(false), seen_packages(false);
+ for (Sequence<std::string>::ConstIterator p(targets->begin()), p_end(targets->end()) ;
+ p != p_end ; ++p)
+ {
+ try
+ {
+ resolver->add_target(parse_user_package_dep_spec(*p, env.get(),
+ UserPackageDepSpecOptions() + updso_throw_if_set));
+ if (seen_sets)
+ throw args::DoHelp("Cannot specify both set and package targets");
+ seen_packages = true;
+ }
+ catch (const GotASetNotAPackageDepSpec &)
+ {
+ if (seen_packages)
+ throw args::DoHelp("Cannot specify both set and package targets");
+ if (seen_sets)
+ throw args::DoHelp("Cannot specify multiple set targets");
+
+ resolver->add_target(SetName(*p));
+ seen_sets = true;
+ }
+ }
+
+ if (seen_sets)
+ is_set = true;
+ }
+
+ UseExisting use_existing_from_cmdline(const args::EnumArg & a, const bool is_set)
+ {
+ if (a.argument() == "auto")
+ return is_set ? ue_if_same : ue_never;
+ else if (a.argument() == "never")
+ return ue_never;
+ else if (a.argument() == "if-transient")
+ return ue_only_if_transient;
+ else if (a.argument() == "if-same")
+ return ue_if_same;
+ else if (a.argument() == "if-same-version")
+ return ue_if_same_version;
+ else if (a.argument() == "if-possible")
+ return ue_if_possible;
+ else
+ throw args::DoHelp("Don't understand argument '" + a.argument() + "' to '--" + a.long_name() + "'");
+ }
+
+ struct UseExistingVisitor
+ {
+ const ResolveCommandLineResolutionOptions & resolution_options;
+ const bool from_set;
+
+ UseExistingVisitor(const ResolveCommandLineResolutionOptions & c, const bool f) :
+ resolution_options(c),
+ from_set(f)
+ {
+ }
+
+ UseExisting visit(const DependencyReason &) const
+ {
+ return use_existing_from_cmdline(resolution_options.a_keep, false);
+ }
+
+ UseExisting visit(const TargetReason &) const
+ {
+ return use_existing_from_cmdline(resolution_options.a_keep_targets, from_set);
+ }
+
+ UseExisting visit(const PresetReason &) const
+ {
+ return ue_if_possible;
+ }
+
+ UseExisting visit(const SetReason & r) const
+ {
+ UseExistingVisitor v(resolution_options, true);
+ return r.reason_for_set()->accept_returning<UseExisting>(v);
+ }
+ };
+
+ UseExisting use_existing_fn(const ResolveCommandLineResolutionOptions & resolution_options,
+ const Resolvent &,
+ const PackageDepSpec &,
+ const std::tr1::shared_ptr<const Reason> & reason)
+ {
+ UseExistingVisitor v(resolution_options, false);
+ return reason->accept_returning<UseExisting>(v);
+ }
+
+ int reinstall_scm_days(const ResolveCommandLineResolutionOptions & resolution_options)
+ {
+ if (resolution_options.a_reinstall_scm.argument() == "always")
+ return 0;
+ else if (resolution_options.a_reinstall_scm.argument() == "daily")
+ return 1;
+ else if (resolution_options.a_reinstall_scm.argument() == "weekly")
+ return 7;
+ else if (resolution_options.a_reinstall_scm.argument() == "never")
+ return -1;
+ else
+ throw args::DoHelp("Don't understand argument '" + resolution_options.a_reinstall_scm.argument() + "' to '--"
+ + resolution_options.a_reinstall_scm.long_name() + "'");
+ }
+
+ bool is_scm_name(const QualifiedPackageName & n)
+ {
+ std::string pkg(stringify(n.package()));
+ switch (pkg.length())
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ return false;
+
+ default:
+ if (0 == pkg.compare(pkg.length() - 6, 6, "-darcs"))
+ return true;
+
+ case 5:
+ if (0 == pkg.compare(pkg.length() - 5, 5, "-live"))
+ return true;
+
+ case 4:
+ if (0 == pkg.compare(pkg.length() - 4, 4, "-cvs"))
+ return true;
+ if (0 == pkg.compare(pkg.length() - 4, 4, "-svn"))
+ return true;
+ return false;
+ }
+ }
+
+ bool is_scm_older_than(const std::tr1::shared_ptr<const PackageID> & id, const int n)
+ {
+ if (id->version().is_scm() || is_scm_name(id->name()))
+ {
+ static Timestamp current_time(Timestamp::now()); /* static to avoid weirdness */
+ time_t installed_time(current_time.seconds());
+ if (id->installed_time_key())
+ installed_time = id->installed_time_key()->value().seconds();
+
+ return (current_time.seconds() - installed_time) > (24 * 60 * 60 * n);
+ }
+ else
+ return false;
+ }
+
+ bool installed_is_scm_older_than(const Environment * const env, const ResolveCommandLineResolutionOptions & resolution_options,
+ const Resolvent & q, const int n)
+ {
+ Context context("When working out whether '" + stringify(q) + "' has installed SCM packages:");
+
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*env)[selection::AllVersionsUnsorted(
+ make_destination_filtered_generator(env, resolution_options, generator::Package(q.package()), q) |
+ make_slot_filter(q)
+ )]);
+
+ for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
+ i != i_end ; ++i)
+ {
+ if (is_scm_older_than(*i, n))
+ return true;
+ }
+
+ return false;
+ }
+
+ typedef std::map<Resolvent, std::tr1::shared_ptr<Constraints> > InitialConstraints;
+
+ const std::tr1::shared_ptr<Constraints> make_initial_constraints_for(
+ const Environment * const env,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const Resolvent & resolvent)
+ {
+ const std::tr1::shared_ptr<Constraints> result(new Constraints);
+
+ int n(reinstall_scm_days(resolution_options));
+ if ((-1 != n) && installed_is_scm_older_than(env, resolution_options, resolvent, n))
+ {
+ result->add(make_shared_ptr(new Constraint(make_named_values<Constraint>(
+ value_for<n::destination_type>(resolvent.destination_type()),
+ value_for<n::nothing_is_fine_too>(false),
+ value_for<n::reason>(make_shared_ptr(new PresetReason)),
+ value_for<n::spec>(make_package_dep_spec(PartiallyMadePackageDepSpecOptions()).package(resolvent.package())),
+ value_for<n::untaken>(false),
+ value_for<n::use_existing>(ue_only_if_transient)
+ ))));
+ }
+
+ return result;
+ }
+
+ const std::tr1::shared_ptr<Constraints> initial_constraints_for_fn(
+ const Environment * const env,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const InitialConstraints & initial_constraints,
+ const Resolvent & resolvent)
+ {
+ InitialConstraints::const_iterator i(initial_constraints.find(resolvent));
+ if (i == initial_constraints.end())
+ return make_initial_constraints_for(env, resolution_options, resolvent);
+ else
+ return i->second;
+ }
+
+ struct IsTargetVisitor
+ {
+ bool visit(const DependencyReason &) const
+ {
+ return false;
+ }
+
+ bool visit(const PresetReason &) const
+ {
+ return false;
+ }
+
+ bool visit(const TargetReason &) const
+ {
+ return true;
+ }
+
+ bool visit(const SetReason & r) const
+ {
+ return r.reason_for_set()->accept_returning<bool>(*this);
+ }
+ };
+
+ bool is_target(const std::tr1::shared_ptr<const Reason> & reason)
+ {
+ IsTargetVisitor v;
+ return reason->accept_returning<bool>(v);
+ }
+
+ const std::tr1::shared_ptr<Resolvents>
+ get_resolvents_for_fn(const Environment * const env,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const SlotName> & maybe_slot,
+ const std::tr1::shared_ptr<const Reason> & reason)
+ {
+ std::tr1::shared_ptr<PackageIDSequence> result_ids(new PackageIDSequence);
+ std::tr1::shared_ptr<const PackageID> best;
+
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*env)[selection::BestVersionOnly(
+ generator::Matches(spec, MatchPackageOptions() + mpo_ignore_additional_requirements) |
+ filter::SupportsAction<InstallAction>() |
+ filter::NotMasked() |
+ (maybe_slot ? Filter(filter::Slot(*maybe_slot)) : Filter(filter::All())))]);
+
+ if (! ids->empty())
+ best = *ids->begin();
+
+ const std::tr1::shared_ptr<const PackageIDSequence> installed_ids((*env)[selection::BestVersionInEachSlot(
+ generator::Matches(spec, MatchPackageOptions()) |
+ filter::InstalledAtRoot(FSEntry("/")))]);
+
+ const args::EnumArg & arg(is_target(reason) ? resolution_options.a_target_slots : resolution_options.a_slots);
+
+ if (! best)
+ std::copy(installed_ids->begin(), installed_ids->end(), result_ids->back_inserter());
+ else if (arg.argument() == "best-or-installed")
+ {
+ if (indirect_iterator(installed_ids->end()) == std::find(indirect_iterator(installed_ids->begin()),
+ indirect_iterator(installed_ids->end()), *best))
+ result_ids->push_back(best);
+ else
+ std::copy(installed_ids->begin(), installed_ids->end(), result_ids->back_inserter());
+ }
+ else if (arg.argument() == "installed-or-best")
+ {
+ if (installed_ids->empty())
+ result_ids->push_back(best);
+ else
+ std::copy(installed_ids->begin(), installed_ids->end(), result_ids->back_inserter());
+ }
+ else if (arg.argument() == "all")
+ {
+ if (indirect_iterator(installed_ids->end()) == std::find(indirect_iterator(installed_ids->begin()),
+ indirect_iterator(installed_ids->end()), *best))
+ result_ids->push_back(best);
+ std::copy(installed_ids->begin(), installed_ids->end(), result_ids->back_inserter());
+ }
+ else if (arg.argument() == "best")
+ result_ids->push_back(best);
+ else
+ throw args::DoHelp("Don't understand argument '" + arg.argument() + "' to '--"
+ + arg.long_name() + "'");
+
+ std::tr1::shared_ptr<Resolvents> result(new Resolvents);
+ for (PackageIDSequence::ConstIterator i(result_ids->begin()), i_end(result_ids->end()) ;
+ i != i_end ; ++i)
+ {
+ DestinationTypes destination_types(get_destination_types_for_fn(env, resolution_options, spec, *i, reason));
+ for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
+ if (destination_types[*t])
+ result->push_back(Resolvent(*i, *t));
+ }
+
+ return result;
+ }
+
+ struct CareAboutDepFnVisitor
+ {
+ const ResolveCommandLineResolutionOptions & resolution_options;
+ const SanitisedDependency dep;
+
+ CareAboutDepFnVisitor(const ResolveCommandLineResolutionOptions & c, const SanitisedDependency & d) :
+ resolution_options(c),
+ dep(d)
+ {
+ }
+
+ bool visit(const ExistingNoChangeDecision &) const
+ {
+ if (! resolution_options.a_follow_installed_build_dependencies.specified())
+ if (is_just_build_dep(dep))
+ return false;
+ if (resolution_options.a_ignore_installed_dependencies.specified())
+ if (! is_compiled_against_dep(dep))
+ return false;
+
+ if (is_suggestion(dep) || is_recommendation(dep))
+ {
+ /* should only return false if the dep's not already installedish */
+ return false;
+ }
+
+ return true;
+ }
+
+ bool visit(const NothingNoChangeDecision &) const
+ {
+ return true;
+ }
+
+ bool visit(const UnableToMakeDecision &) const
+ {
+ return true;
+ }
+
+ bool visit(const ChangesToMakeDecision &) const
+ {
+ return true;
+ }
+ };
+
+ bool care_about_dep_fn(const Environment * const, const ResolveCommandLineResolutionOptions & resolution_options,
+ const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
+ const SanitisedDependency & dep)
+ {
+ CareAboutDepFnVisitor v(resolution_options, dep);
+ return resolution->decision()->accept_returning<bool>(v);
+ }
+
+ bool
+ take_dependency_fn(const Environment * const env,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const Resolvent & resolvent,
+ const SanitisedDependency & dep,
+ const std::tr1::shared_ptr<const Reason> &)
+ {
+ bool suggestion(is_suggestion(dep)), recommendation(is_recommendation(dep));
+
+ if (suggestion || recommendation)
+ {
+ for (args::StringSetArg::ConstIterator a(resolution_options.a_take.begin_args()),
+ a_end(resolution_options.a_take.end_args()) ;
+ a != a_end ; ++a)
+ {
+ PackageDepSpec user_spec(parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ PackageDepSpec spec(*dep.spec().if_package());
+ if (match_qpns(*env, user_spec, *spec.package_ptr()))
+ return true;
+ }
+
+ for (args::StringSetArg::ConstIterator a(resolution_options.a_take_from.begin_args()),
+ a_end(resolution_options.a_take_from.end_args()) ;
+ a != a_end ; ++a)
+ {
+ PackageDepSpec user_spec(parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ if (match_qpns(*env, user_spec, resolvent.package()))
+ return true;
+ }
+
+ for (args::StringSetArg::ConstIterator a(resolution_options.a_discard.begin_args()),
+ a_end(resolution_options.a_discard.end_args()) ;
+ a != a_end ; ++a)
+ {
+ PackageDepSpec user_spec(parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ PackageDepSpec spec(*dep.spec().if_package());
+ if (match_qpns(*env, user_spec, *spec.package_ptr()))
+ return false;
+ }
+
+ for (args::StringSetArg::ConstIterator a(resolution_options.a_discard_from.begin_args()),
+ a_end(resolution_options.a_discard_from.end_args()) ;
+ a != a_end ; ++a)
+ {
+ PackageDepSpec user_spec(parse_user_package_dep_spec(*a, env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ if (match_qpns(*env, user_spec, resolvent.package()))
+ return false;
+ }
+ }
+ if (suggestion)
+ {
+ if (resolution_options.a_suggestions.argument() == "take")
+ {
+ return true;
+ }
+ return false;
+ }
+ if (recommendation)
+ {
+ if (resolution_options.a_recommendations.argument() == "take")
+ {
+ return true;
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ const std::tr1::shared_ptr<const Repository>
+ find_repository_for_fn(const Environment * const env,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision & decision)
+ {
+ std::tr1::shared_ptr<const Repository> result;
+ for (PackageDatabase::RepositoryConstIterator r(env->package_database()->begin_repositories()),
+ r_end(env->package_database()->end_repositories()) ;
+ r != r_end ; ++r)
+ {
+ switch (resolvent.destination_type())
+ {
+ case dt_install_to_slash:
+ if ((! (*r)->installed_root_key()) || ((*r)->installed_root_key()->value() != FSEntry("/")))
+ continue;
+ break;
+
+ case dt_create_binary:
+ if (resolution_options.a_create_binaries.end_args() == std::find(
+ resolution_options.a_create_binaries.begin_args(),
+ resolution_options.a_create_binaries.end_args(),
+ stringify((*r)->name())))
+ continue;
+ break;
+
+ case last_dt:
+ break;
+ }
+
+ if ((*r)->destination_interface() &&
+ (*r)->destination_interface()->is_suitable_destination_for(*decision.origin_id()))
+ {
+ if (result)
+ throw ConfigurationError("For '" + stringify(*decision.origin_id())
+ + "' with destination type " + stringify(resolvent.destination_type())
+ + ", don't know whether to install to ::" + stringify(result->name())
+ + " or ::" + stringify((*r)->name()));
+ else
+ result = *r;
+ }
+ }
+
+ if (! result)
+ throw ConfigurationError("No repository suitable for '" + stringify(*decision.origin_id())
+ + "' with destination type " + stringify(resolvent.destination_type()) + " has been configured");
+ return result;
+ }
+
+ Filter make_destination_filter_fn(const Resolvent & resolvent)
+ {
+ switch (resolvent.destination_type())
+ {
+ case dt_install_to_slash:
+ return filter::InstalledAtRoot(FSEntry("/"));
+
+ case dt_create_binary:
+ throw InternalError(PALUDIS_HERE, "no dt_create_binary yet");
+
+ case last_dt:
+ break;
+ }
+
+ throw InternalError(PALUDIS_HERE, "unhandled dt");
+ }
+
+ void ser_thread_func(StringListStream & ser_stream, const ResolverLists & resolution_lists)
+ {
+ Serialiser ser(ser_stream);
+ resolution_lists.serialise(ser);
+ ser_stream.nothing_more_to_write();
+ }
+
+ int display_resolution(
+ const std::tr1::shared_ptr<Environment> &,
+ const ResolverLists & resolution_lists,
+ const ResolveCommandLineResolutionOptions &,
+ const ResolveCommandLineDisplayOptions & display_options,
+ const ResolveCommandLineProgramOptions & program_options,
+ const std::tr1::shared_ptr<const Map<std::string, std::string> > & keys_if_import,
+ const std::tr1::shared_ptr<const Sequence<std::string> > & targets)
+ {
+ Context context("When displaying chosen resolution:");
+
+ StringListStream ser_stream;
+ Thread ser_thread(std::tr1::bind(&ser_thread_func,
+ std::tr1::ref(ser_stream),
+ std::tr1::cref(resolution_lists)));
+
+ std::string command(program_options.a_display_resolution_program.argument());
+ if (command.empty())
+ command = "$CAVE display-resolution";
+
+ for (args::ArgsSection::GroupsConstIterator g(display_options.begin()), g_end(display_options.end()) ;
+ g != g_end ; ++g)
+ {
+ for (args::ArgsGroup::ConstIterator o(g->begin()), o_end(g->end()) ;
+ o != o_end ; ++o)
+ if ((*o)->specified())
+ command = command + " " + (*o)->forwardable_string();
+ }
+
+ for (Sequence<std::string>::ConstIterator p(targets->begin()), p_end(targets->end()) ;
+ p != p_end ; ++p)
+ command = command + " " + args::escape(*p);
+
+ if (keys_if_import)
+ for (Map<std::string, std::string>::ConstIterator k(keys_if_import->begin()),
+ k_end(keys_if_import->end()) ;
+ k != k_end ; ++k)
+ command = command + " --unpackaged-repository-params '" + k->first + "=" + k->second + "'";
+
+ paludis::Command cmd(command);
+ cmd
+ .with_input_stream(&ser_stream, -1, "PALUDIS_SERIALISED_RESOLUTION_FD");
+
+ return run_command(cmd);
+ }
+
+ void perform_resolution(
+ const std::tr1::shared_ptr<Environment> &,
+ const ResolverLists & resolution_lists,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const ResolveCommandLineExecutionOptions & execution_options,
+ const ResolveCommandLineProgramOptions & program_options,
+ const std::tr1::shared_ptr<const Map<std::string, std::string> > & keys_if_import,
+ const std::tr1::shared_ptr<const Sequence<std::string> > & targets,
+ const bool is_set) PALUDIS_ATTRIBUTE((noreturn));
+
+ void perform_resolution(
+ const std::tr1::shared_ptr<Environment> &,
+ const ResolverLists & resolution_lists,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const ResolveCommandLineExecutionOptions & execution_options,
+ const ResolveCommandLineProgramOptions & program_options,
+ const std::tr1::shared_ptr<const Map<std::string, std::string> > & keys_if_import,
+ const std::tr1::shared_ptr<const Sequence<std::string> > & targets,
+ const bool is_set)
+ {
+ Context context("When performing chosen resolution:");
+
+ StringListStream ser_stream;
+ Serialiser ser(ser_stream);
+ resolution_lists.serialise(ser);
+
+ /* backgrounding this barfs with become_command. working out why could
+ * be a fun exercise for someone with way too much time on their hands.
+ * */
+ ser_thread_func(ser_stream, resolution_lists);
+
+ std::string command(program_options.a_execute_resolution_program.argument());
+ if (command.empty())
+ command = "$CAVE execute-resolution";
+
+ for (args::ArgsSection::GroupsConstIterator g(execution_options.begin()), g_end(execution_options.end()) ;
+ g != g_end ; ++g)
+ {
+ for (args::ArgsGroup::ConstIterator o(g->begin()), o_end(g->end()) ;
+ o != o_end ; ++o)
+ if ((*o)->specified())
+ command = command + " " + (*o)->forwardable_string();
+ }
+
+ if (is_set)
+ command.append(" --set");
+
+ for (args::ArgsSection::GroupsConstIterator g(program_options.begin()), g_end(program_options.end()) ;
+ g != g_end ; ++g)
+ {
+ for (args::ArgsGroup::ConstIterator o(g->begin()), o_end(g->end()) ;
+ o != o_end ; ++o)
+ if ((*o)->specified())
+ command = command + " " + (*o)->forwardable_string();
+ }
+
+ if (! resolution_options.a_execute.specified())
+ command = command + " --pretend";
+
+ for (Sequence<std::string>::ConstIterator p(targets->begin()), p_end(targets->end()) ;
+ p != p_end ; ++p)
+ command = command + " " + args::escape(*p);
+
+ if (keys_if_import)
+ for (Map<std::string, std::string>::ConstIterator k(keys_if_import->begin()),
+ k_end(keys_if_import->end()) ;
+ k != k_end ; ++k)
+ command = command + " --unpackaged-repository-params '" + k->first + "=" + k->second + "'";
+
+ paludis::Command cmd(command);
+ cmd
+ .with_input_stream(&ser_stream, -1, "PALUDIS_SERIALISED_RESOLUTION_FD");
+
+ become_command(cmd);
+ }
+
+ struct ChosenIDVisitor
+ {
+ const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
+ {
+ return decision.origin_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
+ {
+ return decision.existing_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+ };
+
+ struct KindNameVisitor
+ {
+ const std::string visit(const UnableToMakeDecision &) const
+ {
+ return "unable_to_make_decision";
+ }
+
+ const std::string visit(const NothingNoChangeDecision &) const
+ {
+ return "nothing_no_change";
+ }
+
+ const std::string visit(const ExistingNoChangeDecision &) const
+ {
+ return "existing_no_change";
+ }
+
+ const std::string visit(const ChangesToMakeDecision &) const
+ {
+ return "changes_to_make";
+ }
+ };
+
+ void display_restarts_if_requested(const std::list<SuggestRestart> & restarts,
+ const ResolveCommandLineResolutionOptions & resolution_options)
+ {
+ if (! resolution_options.a_dump_restarts.specified())
+ return;
+
+ std::cout << "Dumping restarts:" << std::endl << std::endl;
+
+ for (std::list<SuggestRestart>::const_iterator r(restarts.begin()), r_end(restarts.end()) ;
+ r != r_end ; ++r)
+ {
+ std::cout << "* " << r->resolvent() << std::endl;
+
+ std::cout << " Had decided upon ";
+ const std::tr1::shared_ptr<const PackageID> id(r->previous_decision()->accept_returning<
+ std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
+ if (id)
+ std::cout << *id;
+ else
+ std::cout << r->previous_decision()->accept_returning<std::string>(KindNameVisitor());
+ std::cout << std::endl;
+
+ std::cout << " Which did not satisfy " << r->problematic_constraint()->spec()
+ << ", use existing " << r->problematic_constraint()->use_existing();
+ if (r->problematic_constraint()->nothing_is_fine_too())
+ std::cout << ", nothing is fine too";
+ std::cout << std::endl;
+ }
+
+ std::cout << std::endl;
+ }
+}
+
+int
+paludis::cave::resolve_common(
+ const std::tr1::shared_ptr<Environment> & env,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const ResolveCommandLineExecutionOptions & execution_options,
+ const ResolveCommandLineDisplayOptions & display_options,
+ const ResolveCommandLineProgramOptions & program_options,
+ const std::tr1::shared_ptr<const Map<std::string, std::string> > & keys_if_import,
+ const std::tr1::shared_ptr<const Sequence<std::string> > & targets)
+{
+ int retcode(0);
+
+ InitialConstraints initial_constraints;
+
+ ResolverFunctions resolver_functions(make_named_values<ResolverFunctions>(
+ value_for<n::care_about_dep_fn>(std::tr1::bind(&care_about_dep_fn,
+ env.get(), std::tr1::cref(resolution_options), std::tr1::placeholders::_1,
+ std::tr1::placeholders::_2, std::tr1::placeholders::_3)),
+ value_for<n::find_repository_for_fn>(std::tr1::bind(&find_repository_for_fn,
+ env.get(), std::tr1::cref(resolution_options), std::tr1::placeholders::_1, std::tr1::placeholders::_2,
+ std::tr1::placeholders::_3)),
+ value_for<n::get_destination_types_for_fn>(std::tr1::bind(&get_destination_types_for_fn,
+ env.get(), std::tr1::cref(resolution_options), std::tr1::placeholders::_1, std::tr1::placeholders::_2,
+ std::tr1::placeholders::_3)),
+ value_for<n::get_initial_constraints_for_fn>(std::tr1::bind(&initial_constraints_for_fn,
+ env.get(), std::tr1::cref(resolution_options), std::tr1::cref(initial_constraints), std::tr1::placeholders::_1)),
+ value_for<n::get_resolvents_for_fn>(std::tr1::bind(&get_resolvents_for_fn,
+ env.get(), std::tr1::cref(resolution_options), std::tr1::placeholders::_1, std::tr1::placeholders::_2,
+ std::tr1::placeholders::_3)),
+ value_for<n::get_use_existing_fn>(std::tr1::bind(&use_existing_fn,
+ std::tr1::cref(resolution_options), std::tr1::placeholders::_1, std::tr1::placeholders::_2, std::tr1::placeholders::_3)),
+ value_for<n::make_destination_filtered_generator_fn>(std::tr1::bind(&make_destination_filtered_generator,
+ env.get(), std::tr1::cref(resolution_options), std::tr1::placeholders::_1, std::tr1::placeholders::_2)),
+ value_for<n::take_dependency_fn>(std::tr1::bind(&take_dependency_fn, env.get(),
+ std::tr1::cref(resolution_options), std::tr1::placeholders::_1, std::tr1::placeholders::_2, std::tr1::placeholders::_3))
+
+ ));
+
+ ScopedSelectionCache selection_cache(env.get());
+ std::tr1::shared_ptr<Resolver> resolver(new Resolver(env.get(), resolver_functions));
+ bool is_set(false);
+ std::list<SuggestRestart> restarts;
+
+ try
+ {
+ {
+ DisplayCallback display_callback;
+ ScopedNotifierCallback display_callback_holder(env.get(),
+ NotifierCallbackFunction(std::tr1::cref(display_callback)));
+
+ while (true)
+ {
+ try
+ {
+ add_resolver_targets(env, resolver, resolution_options, targets, is_set);
+ resolver->resolve();
+ break;
+ }
+ catch (const SuggestRestart & e)
+ {
+ restarts.push_back(e);
+ display_callback(ResolverRestart());
+ initial_constraints.insert(std::make_pair(e.resolvent(), make_initial_constraints_for(
+ env.get(), resolution_options, e.resolvent()))).first->second->add(
+ e.suggested_preset());
+ resolver = make_shared_ptr(new Resolver(env.get(), resolver_functions));
+ }
+ }
+ }
+
+ if (! restarts.empty())
+ display_restarts_if_requested(restarts, resolution_options);
+
+ dump_if_requested(env, resolver, resolution_options);
+
+ retcode |= display_resolution(env, *resolver->lists(), resolution_options,
+ display_options, program_options, keys_if_import, targets);
+
+ if (! resolver->lists()->error_resolutions()->empty())
+ retcode |= 1;
+
+ if (0 == retcode)
+ perform_resolution(env, *resolver->lists(), resolution_options,
+ execution_options, program_options, keys_if_import, targets, is_set);
+ }
+ catch (...)
+ {
+ if (! restarts.empty())
+ display_restarts_if_requested(restarts, resolution_options);
+
+ dump_if_requested(env, resolver, resolution_options);
+ throw;
+ }
+
+ return EXIT_FAILURE;
+}
+
diff --git a/src/clients/cave/resolve_common.hh b/src/clients/cave/resolve_common.hh
new file mode 100644
index 0000000..b43d6da
--- /dev/null
+++ b/src/clients/cave/resolve_common.hh
@@ -0,0 +1,45 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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_SRC_CLIENTS_CAVE_RESOLVE_COMMON_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_RESOLVE_COMMON_HH 1
+
+#include <paludis/environment-fwd.hh>
+#include <paludis/util/sequence-fwd.hh>
+#include <paludis/util/map-fwd.hh>
+#include <tr1/memory>
+#include "cmd_resolve_cmdline.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ int resolve_common(
+ const std::tr1::shared_ptr<Environment> & env,
+ const ResolveCommandLineResolutionOptions & resolution_options,
+ const ResolveCommandLineExecutionOptions & execution_options,
+ const ResolveCommandLineDisplayOptions & display_options,
+ const ResolveCommandLineProgramOptions & program_options,
+ const std::tr1::shared_ptr<const Map<std::string, std::string> > & keys_if_import,
+ const std::tr1::shared_ptr<const Sequence<std::string> > & targets
+ ) PALUDIS_ATTRIBUTE((warn_unused_result));
+ }
+}
+
+#endif