aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-09-02 13:55:32 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-09-02 13:55:32 +0100
commitfd46198d52e3d3c955f1c9cc11a2040b908185e9 (patch)
tree39b37cbe11196aeb08de5cbe78d0b91992585d97
parent5478723fe66236f70308e9feaa1d6262b4126d9c (diff)
downloadpaludis-fd46198d52e3d3c955f1c9cc11a2040b908185e9.tar.gz
paludis-fd46198d52e3d3c955f1c9cc11a2040b908185e9.tar.xz
cave resolve --graph-jobs
-rw-r--r--.gitignore1
-rw-r--r--doc/clients/Makefile.am1
-rw-r--r--src/clients/cave/Makefile.am9
-rw-r--r--src/clients/cave/cmd_fix_linkage.cc3
-rw-r--r--src/clients/cave/cmd_graph_jobs.cc258
-rw-r--r--src/clients/cave/cmd_graph_jobs.hh52
-rw-r--r--src/clients/cave/cmd_import.cc3
-rw-r--r--src/clients/cave/cmd_purge.cc4
-rw-r--r--src/clients/cave/cmd_resolve.cc4
-rw-r--r--src/clients/cave/cmd_resolve_cmdline.cc27
-rw-r--r--src/clients/cave/cmd_resolve_cmdline.hh16
-rw-r--r--src/clients/cave/cmd_uninstall.cc4
-rw-r--r--src/clients/cave/command_factory.cc2
-rw-r--r--src/clients/cave/resolve_common.cc82
-rw-r--r--src/clients/cave/resolve_common.hh1
15 files changed, 461 insertions, 6 deletions
diff --git a/.gitignore b/.gitignore
index d09dba3..813dc9d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,6 +90,7 @@ paludis-*.*.*.tar.bz2
/doc/clients/cave-find-candidates.html
/doc/clients/cave-fix-cache.html
/doc/clients/cave-fix-linkage.html
+/doc/clients/cave-graph-jobs.html
/doc/clients/cave-help.html
/doc/clients/cave-import.html
/doc/clients/cave-info.html
diff --git a/doc/clients/Makefile.am b/doc/clients/Makefile.am
index 05eac7c..4b1d7ee 100644
--- a/doc/clients/Makefile.am
+++ b/doc/clients/Makefile.am
@@ -35,6 +35,7 @@ CAVE_COMMANDS_HTML = \
cave-find-candidates.html \
cave-fix-cache.html \
cave-fix-linkage.html \
+ cave-graph-jobs.html \
cave-help.html \
cave-import.html \
cave-info.html \
diff --git a/src/clients/cave/Makefile.am b/src/clients/cave/Makefile.am
index 49518b2..5ab0566 100644
--- a/src/clients/cave/Makefile.am
+++ b/src/clients/cave/Makefile.am
@@ -17,7 +17,10 @@ bin_PROGRAMS = cave
noinst_PROGRAMS = man-cave
-# Also update doc/clients/Makefile.am when adding here:
+# When adding commands, you need to add to both command_MANS and
+# libcave_a_SOURCES. You should also update command_factory.cc,
+# doc/clients/Makefile.am and .gitignore.
+
command_MANS = \
cave-config.1 \
cave-contents.1 \
@@ -28,6 +31,7 @@ command_MANS = \
cave-find-candidates.1 \
cave-fix-cache.1 \
cave-fix-linkage.1 \
+ cave-graph-jobs.1 \
cave-help.1 \
cave-import.1 \
cave-info.1 \
@@ -104,7 +108,7 @@ man_cave_LDADD = \
noinst_LIBRARIES = libcave.a
-# Also update command_MANS above when adding new commands here:
+# See note above for adding commands
libcave_a_SOURCES = \
colour_formatter.cc colour_formatter.hh colour_formatter-fmt.hh \
command.cc command.hh \
@@ -120,6 +124,7 @@ libcave_a_SOURCES = \
cmd_find_candidates.cc cmd_find_candidates.hh \
cmd_fix_cache.cc cmd_fix_cache.hh cmd_fix_cache-fmt.hh \
cmd_fix_linkage.cc cmd_fix_linkage.hh \
+ cmd_graph_jobs.cc cmd_graph_jobs.hh \
cmd_help.cc cmd_help.hh \
cmd_import.cc cmd_import.hh \
cmd_info.cc cmd_info.hh cmd_info-fmt.hh \
diff --git a/src/clients/cave/cmd_fix_linkage.cc b/src/clients/cave/cmd_fix_linkage.cc
index 936928d..01e8a11 100644
--- a/src/clients/cave/cmd_fix_linkage.cc
+++ b/src/clients/cave/cmd_fix_linkage.cc
@@ -108,12 +108,14 @@ namespace
ResolveCommandLineResolutionOptions resolution_options;
ResolveCommandLineExecutionOptions execution_options;
ResolveCommandLineDisplayOptions display_options;
+ ResolveCommandLineGraphJobsOptions graph_jobs_options;
ResolveCommandLineProgramOptions program_options;
OptionsForResolve() :
resolution_options(this),
execution_options(this),
display_options(this),
+ graph_jobs_options(this),
program_options(this)
{
}
@@ -247,6 +249,7 @@ FixLinkageCommand::run(
return resolve_common(env, resolve_cmdline.resolution_options,
resolve_cmdline.execution_options,
resolve_cmdline.display_options,
+ resolve_cmdline.graph_jobs_options,
resolve_cmdline.program_options,
make_null_shared_ptr(), targets, make_null_shared_ptr(), false);
}
diff --git a/src/clients/cave/cmd_graph_jobs.cc b/src/clients/cave/cmd_graph_jobs.cc
new file mode 100644
index 0000000..ea0e43d
--- /dev/null
+++ b/src/clients/cave/cmd_graph_jobs.cc
@@ -0,0 +1,258 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009, 2010 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_graph_jobs.hh"
+#include "cmd_resolve_cmdline.hh"
+#include "exceptions.hh"
+#include "command_command_line.hh"
+#include <paludis/args/do_help.hh>
+#include <paludis/util/safe_ifstream.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/make_shared_copy.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/destringify.hh>
+#include <paludis/util/safe_ofstream.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/process.hh>
+#include <paludis/resolver/job_list.hh>
+#include <paludis/resolver/job_lists.hh>
+#include <paludis/resolver/job.hh>
+#include <paludis/resolver/job_requirements.hh>
+#include <paludis/serialise-impl.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/name.hh>
+
+#include <iostream>
+#include <cstdlib>
+
+using namespace paludis;
+using namespace cave;
+using namespace paludis::resolver;
+
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct GraphJobsCommandLine :
+ CaveCommandCommandLine
+ {
+ ResolveCommandLineGraphJobsOptions graph_jobs_options;
+ ResolveCommandLineImportOptions import_options;
+ ResolveCommandLineProgramOptions program_options;
+
+ GraphJobsCommandLine() :
+ graph_jobs_options(this),
+ import_options(this),
+ program_options(this)
+ {
+ add_environment_variable("PALUDIS_SERIALISED_RESOLUTION_FD",
+ "The file descriptor on which the serialised resolution can be found.");
+ }
+
+ virtual std::string app_name() const
+ {
+ return "cave graph-jobs";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Creates a Graphviz graph for jobs in a resolution created using 'cave resolve'.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Creates a Graphviz graph for jobs in a resolution created using 'cave resolve'. Mostly for "
+ "internal use; most users will not use this command directly.";
+ }
+ };
+
+ std::string short_spec(const PackageDepSpec & p, bool full)
+ {
+ if (full || ! p.package_ptr())
+ return stringify(p);
+ else
+ {
+ std::string result(stringify(p.package_ptr()->package()));
+ if (p.slot_requirement_ptr())
+ result = result + stringify(*p.slot_requirement_ptr());
+ if (p.in_repository_ptr())
+ result = result + "::" + stringify(*p.in_repository_ptr());
+ return result;
+ }
+ }
+
+ struct ShowOneJobAttrs
+ {
+ std::ostream & output_stream;
+ bool full;
+
+ void visit(const FetchJob & job) const
+ {
+ output_stream << "label=\"fetch " << short_spec(job.origin_id_spec(), full) << "\", ";
+ output_stream << "shape=ellipse, ";
+ output_stream << "fillcolor=cadetblue, ";
+ output_stream << "style=filled";
+ }
+
+ void visit(const InstallJob & job) const
+ {
+ output_stream << "label=\"" << short_spec(job.origin_id_spec(), full) << " -> " << job.destination_repository_name() << "\"";
+ output_stream << "shape=box, ";
+ output_stream << "fillcolor=royalblue, ";
+ output_stream << "style=filled";
+ }
+
+ void visit(const UninstallJob & job) const
+ {
+ output_stream << "label=\"uninstall " << join(job.ids_to_remove_specs()->begin(), job.ids_to_remove_specs()->end(), ", ",
+ std::bind(&short_spec, std::placeholders::_1, full)) << "\"";
+ output_stream << "shape=hexagon, ";
+ output_stream << "fillcolor=slateblue, ";
+ output_stream << "style=filled";
+ }
+ };
+
+ void graph_jobs(
+ const std::shared_ptr<Environment> &,
+ const GraphJobsCommandLine & cmdline,
+ const std::shared_ptr<const JobList<ExecuteJob> > & execute_job_list,
+ std::ostream & output_stream)
+ {
+ output_stream << "digraph Jobs {" << endl;
+ output_stream << " graph [ splines=true ]" << endl;
+ output_stream << " node [ fontsize=8, fontname=sans, height=0, width=0 ]" << endl;
+
+ for (auto j(execute_job_list->begin()), j_end(execute_job_list->end()) ;
+ j != j_end ; ++j)
+ {
+ output_stream << " job" << execute_job_list->number(j) << " [ ";
+ (*j)->accept(ShowOneJobAttrs{output_stream, cmdline.graph_jobs_options.a_graph_jobs_full_names.specified()});
+ output_stream << " ]" << endl;
+
+ for (auto r((*j)->requirements()->begin()), r_end((*j)->requirements()->end()) ;
+ r != r_end ; ++r)
+ {
+ if (! cmdline.graph_jobs_options.a_graph_jobs_all_arrows.specified())
+ if (! (r->required_if() - jri_require_for_independent).any())
+ continue;
+
+ output_stream << " job" << execute_job_list->number(j) << " -> job" << r->job_number() << " [ ";
+ if (r->required_if()[jri_fetching])
+ output_stream << " color=cadetblue";
+ else if (r->required_if()[jri_require_always])
+ output_stream << " color=crimson";
+ else if (r->required_if()[jri_require_for_satisfied])
+ output_stream << " color=indianred";
+ else if (r->required_if()[jri_require_for_independent])
+ output_stream << " color=lightpink";
+
+ output_stream << " ]" << endl;
+ }
+
+ output_stream << endl;
+ }
+
+ output_stream << "}" << endl;
+ }
+
+ int create_graph(
+ const std::shared_ptr<Environment> &,
+ const GraphJobsCommandLine & cmdline,
+ const FSPath & src,
+ const FSPath & dst)
+ {
+ Process process(ProcessCommand({ cmdline.program_options.a_graph_jobs_program.argument(),
+ "-T", cmdline.graph_jobs_options.a_graph_jobs_format.argument(),
+ stringify(src), "-o", stringify(dst)
+ }));
+
+ return process.run().wait();
+ }
+}
+
+bool
+GraphJobsCommand::important() const
+{
+ return false;
+}
+
+int
+GraphJobsCommand::run(
+ const std::shared_ptr<Environment> & env,
+ const std::shared_ptr<const Sequence<std::string > > & args,
+ const std::shared_ptr<const Resolved> & maybe_resolved
+ )
+{
+ GraphJobsCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_GRAPH_JOBS_OPTIONS", "CAVE_GRAPH_JOBS_CMDLINE");
+
+ if (cmdline.a_help.specified())
+ {
+ cout << cmdline;
+ return EXIT_SUCCESS;
+ }
+
+ cmdline.import_options.apply(env);
+
+ std::shared_ptr<const Resolved> resolved(maybe_resolved);
+ if (! resolved)
+ {
+ if (getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", "").empty())
+ throw args::DoHelp("PALUDIS_SERIALISED_RESOLUTION_FD must be provided");
+
+ int fd(destringify<int>(getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", "")));
+ SafeIFStream deser_stream(fd);
+ Deserialiser deserialiser(env.get(), deser_stream);
+ Deserialisation deserialisation("Resolved", deserialiser);
+ resolved = make_shared_copy(Resolved::deserialise(deserialisation));
+ close(fd);
+ }
+
+ std::shared_ptr<SafeOFStream> stream_if_file;
+ if (! cmdline.graph_jobs_options.a_graph_jobs_basename.argument().empty())
+ stream_if_file = std::make_shared<SafeOFStream>(FSPath(cmdline.graph_jobs_options.a_graph_jobs_basename.argument() + ".graphviz"));
+
+ int retcode(0);
+
+ graph_jobs(env, cmdline, resolved->job_lists()->execute_job_list(), stream_if_file ? *stream_if_file : cout);
+
+ if (stream_if_file && ! cmdline.graph_jobs_options.a_graph_jobs_format.argument().empty())
+ retcode = create_graph(env, cmdline,
+ FSPath(cmdline.graph_jobs_options.a_graph_jobs_basename.argument() + ".graphviz"),
+ FSPath(cmdline.graph_jobs_options.a_graph_jobs_basename.argument() + "." + cmdline.graph_jobs_options.a_graph_jobs_format.argument()));
+
+ return retcode;
+}
+
+int
+GraphJobsCommand::run(
+ const std::shared_ptr<Environment> & env,
+ const std::shared_ptr<const Sequence<std::string > > & args)
+{
+ return run(env, args, make_null_shared_ptr());
+}
+
+std::shared_ptr<args::ArgsHandler>
+GraphJobsCommand::make_doc_cmdline()
+{
+ return std::make_shared<GraphJobsCommandLine>();
+}
+
diff --git a/src/clients/cave/cmd_graph_jobs.hh b/src/clients/cave/cmd_graph_jobs.hh
new file mode 100644
index 0000000..c1772d5
--- /dev/null
+++ b/src/clients/cave/cmd_graph_jobs.hh
@@ -0,0 +1,52 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009, 2010 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_GRAPH_JOBS_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_GRAPH_JOBS_HH 1
+
+#include "command.hh"
+#include <paludis/resolver/resolved-fwd.hh>
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE GraphJobsCommand :
+ public Command
+ {
+ public:
+ bool important() const;
+
+ int run(
+ const std::shared_ptr<Environment> &,
+ const std::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ int run(
+ const std::shared_ptr<Environment> &,
+ const std::shared_ptr<const Sequence<std::string > > & args,
+ const std::shared_ptr<const resolver::Resolved> & maybe_resolved
+ );
+
+ std::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+#endif
diff --git a/src/clients/cave/cmd_import.cc b/src/clients/cave/cmd_import.cc
index a027b35..889c89b 100644
--- a/src/clients/cave/cmd_import.cc
+++ b/src/clients/cave/cmd_import.cc
@@ -144,12 +144,14 @@ namespace
ResolveCommandLineResolutionOptions resolution_options;
ResolveCommandLineExecutionOptions execution_options;
ResolveCommandLineDisplayOptions display_options;
+ ResolveCommandLineGraphJobsOptions graph_jobs_options;
ResolveCommandLineProgramOptions program_options;
OptionsForResolve() :
resolution_options(this),
execution_options(this),
display_options(this),
+ graph_jobs_options(this),
program_options(this)
{
}
@@ -311,6 +313,7 @@ ImportCommand::run(
resolve_cmdline.resolution_options,
resolve_cmdline.execution_options,
resolve_cmdline.display_options,
+ resolve_cmdline.graph_jobs_options,
resolve_cmdline.program_options,
keys, targets, world_specs, false);
}
diff --git a/src/clients/cave/cmd_purge.cc b/src/clients/cave/cmd_purge.cc
index 7382a4e..7046015 100644
--- a/src/clients/cave/cmd_purge.cc
+++ b/src/clients/cave/cmd_purge.cc
@@ -51,12 +51,14 @@ namespace
std::shared_ptr<ResolveCommandLineResolutionOptions> resolution_options;
std::shared_ptr<ResolveCommandLineExecutionOptions> execution_options;
std::shared_ptr<ResolveCommandLineDisplayOptions> display_options;
+ std::shared_ptr<ResolveCommandLineGraphJobsOptions> graph_jobs_options;
std::shared_ptr<ResolveCommandLineProgramOptions> program_options;
PurgeCommandLine(const bool for_docs) :
resolution_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineResolutionOptions>(this)),
execution_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineExecutionOptions>(this)),
display_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineDisplayOptions>(this)),
+ graph_jobs_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineGraphJobsOptions>(this)),
program_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineProgramOptions>(this))
{
add_usage_line("[ -x|--execute ]");
@@ -112,7 +114,7 @@ PurgeCommand::run(
cmdline.resolution_options->a_purge.add_argument("*/*");
return resolve_common(env, *cmdline.resolution_options, *cmdline.execution_options, *cmdline.display_options,
- *cmdline.program_options, make_null_shared_ptr(), make_null_shared_ptr(), make_null_shared_ptr(), true);
+ *cmdline.graph_jobs_options, *cmdline.program_options, make_null_shared_ptr(), make_null_shared_ptr(), make_null_shared_ptr(), true);
}
std::shared_ptr<args::ArgsHandler>
diff --git a/src/clients/cave/cmd_resolve.cc b/src/clients/cave/cmd_resolve.cc
index b3dab40..7d01f1d 100644
--- a/src/clients/cave/cmd_resolve.cc
+++ b/src/clients/cave/cmd_resolve.cc
@@ -39,12 +39,14 @@ namespace
ResolveCommandLineResolutionOptions resolution_options;
ResolveCommandLineExecutionOptions execution_options;
ResolveCommandLineDisplayOptions display_options;
+ ResolveCommandLineGraphJobsOptions graph_jobs_options;
ResolveCommandLineProgramOptions program_options;
ResolveCommandLine() :
resolution_options(this),
execution_options(this),
display_options(this),
+ graph_jobs_options(this),
program_options(this)
{
add_usage_line("[ -x|--execute ] [ -z|--lazy or -c|--complete or -e|--everything ] spec ...");
@@ -102,7 +104,7 @@ ResolveCommand::run(
targets->push_back(std::make_pair(*p, ""));
return resolve_common(env, cmdline.resolution_options, cmdline.execution_options, cmdline.display_options,
- cmdline.program_options, make_null_shared_ptr(), targets, make_null_shared_ptr(), false);
+ cmdline.graph_jobs_options, cmdline.program_options, make_null_shared_ptr(), targets, make_null_shared_ptr(), false);
}
std::shared_ptr<args::ArgsHandler>
diff --git a/src/clients/cave/cmd_resolve_cmdline.cc b/src/clients/cave/cmd_resolve_cmdline.cc
index c58f318..a0abbc3 100644
--- a/src/clients/cave/cmd_resolve_cmdline.cc
+++ b/src/clients/cave/cmd_resolve_cmdline.cc
@@ -304,6 +304,26 @@ ResolveCommandLineDisplayOptions::ResolveCommandLineDisplayOptions(args::ArgsHan
{
}
+ResolveCommandLineGraphJobsOptions::ResolveCommandLineGraphJobsOptions(args::ArgsHandler * const h) :
+ ArgsSection(h, "Graph Jobs Options"),
+ g_graph_jobs_options(this, "Graph Jobs Options", "Options relating to creating graphs for jobs. If "
+ "--graph-jobs-basename is specified, a Graphviz graph will be created for the jobs in the resolution."),
+ a_graph_jobs_basename(&g_graph_jobs_options, "graph-jobs-basename", '\0', "Specify the basename (filename without "
+ "extension) to be used when creating job graphs. If unspecified, no jobs graph will be created."),
+ a_graph_jobs_format(&g_graph_jobs_options, "graph-jobs-format", '\0', "Specifies the desired output format for "
+ "the Graphviz graph. The argument must be a valid value for the '-T' option for Graphviz. Also determines "
+ "the file extension of the generated graph. If unspecified, only a raw graph file will be created, and it "
+ "will not be processed using Graphviz."),
+
+ g_graph_jobs_format_options(this, "Graph Jobs Format Options", "Options relating to the format of created graphs."),
+ a_graph_jobs_all_arrows(&g_graph_jobs_format_options, "graph-jobs-all-arrows", '\0', "Show all arrows. By default "
+ "dependencies required only for if-independent are not shown, since for non-trivial resolutions "
+ "Graphviz will otherwise require obscene amounts of memory.", true),
+ a_graph_jobs_full_names(&g_graph_jobs_format_options, "graph-jobs-full-names", '\0', "Show full names for graph "
+ "jobs.", true)
+{
+}
+
ResolveCommandLineExecutionOptions::ResolveCommandLineExecutionOptions(args::ArgsHandler * const h) :
ArgsSection(h, "Execution Options"),
@@ -356,13 +376,18 @@ ResolveCommandLineProgramOptions::ResolveCommandLineProgramOptions(args::ArgsHan
"instead of spawning a new process."),
a_display_resolution_program(&g_program_options, "display-resolution-program", '\0', "The program used to display "
"the resolution. Defaults to '$CAVE display-resolution'."),
+ a_graph_jobs_program(&g_program_options, "graph-jobs-resolution-program", '\0', "The program used to graph "
+ "jobs. Defaults to '$CAVE graph-jobs'."),
a_execute_resolution_program(&g_program_options, "execute-resolution-program", '\0', "The program used to execute "
"the resolution. Defaults to '$CAVE execute-resolution'."),
a_perform_program(&g_program_options, "perform-program", '\0', "The program used to perform "
"actions. Defaults to '$CAVE perform'."),
a_update_world_program(&g_program_options, "update-world-program", '\0', "The program used to perform "
- "world updates. Defaults to '$CAVE update-world'.")
+ "world updates. Defaults to '$CAVE update-world'."),
+ a_graph_program(&g_program_options, "graph-program", '\0', "The program used to create Graphviz graphs. "
+ "Defaults to 'dot'.")
{
+ a_graph_jobs_program.set_argument("dot");
}
ResolveCommandLineImportOptions::ResolveCommandLineImportOptions(args::ArgsHandler * const h) :
diff --git a/src/clients/cave/cmd_resolve_cmdline.hh b/src/clients/cave/cmd_resolve_cmdline.hh
index bda9eab..01a22e0 100644
--- a/src/clients/cave/cmd_resolve_cmdline.hh
+++ b/src/clients/cave/cmd_resolve_cmdline.hh
@@ -150,6 +150,20 @@ namespace paludis
args::StringSetArg a_explain;
};
+ struct ResolveCommandLineGraphJobsOptions :
+ args::ArgsSection
+ {
+ ResolveCommandLineGraphJobsOptions(args::ArgsHandler * const);
+
+ args::ArgsGroup g_graph_jobs_options;
+ args::StringArg a_graph_jobs_basename;
+ args::StringArg a_graph_jobs_format;
+
+ args::ArgsGroup g_graph_jobs_format_options;
+ args::SwitchArg a_graph_jobs_all_arrows;
+ args::SwitchArg a_graph_jobs_full_names;
+ };
+
struct ResolveCommandLineProgramOptions :
args::ArgsSection
{
@@ -157,9 +171,11 @@ namespace paludis
args::ArgsGroup g_program_options;
args::StringArg a_display_resolution_program;
+ args::StringArg a_graph_jobs_program;
args::StringArg a_execute_resolution_program;
args::StringArg a_perform_program;
args::StringArg a_update_world_program;
+ args::StringArg a_graph_program;
};
struct ResolveCommandLineImportOptions :
diff --git a/src/clients/cave/cmd_uninstall.cc b/src/clients/cave/cmd_uninstall.cc
index 17626a2..4510de0 100644
--- a/src/clients/cave/cmd_uninstall.cc
+++ b/src/clients/cave/cmd_uninstall.cc
@@ -57,6 +57,7 @@ namespace
std::shared_ptr<ResolveCommandLineResolutionOptions> resolution_options;
std::shared_ptr<ResolveCommandLineExecutionOptions> execution_options;
std::shared_ptr<ResolveCommandLineDisplayOptions> display_options;
+ std::shared_ptr<ResolveCommandLineGraphJobsOptions> graph_jobs_options;
std::shared_ptr<ResolveCommandLineProgramOptions> program_options;
UninstallCommandLine(const bool for_docs) :
@@ -66,6 +67,7 @@ namespace
resolution_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineResolutionOptions>(this)),
execution_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineExecutionOptions>(this)),
display_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineDisplayOptions>(this)),
+ graph_jobs_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineGraphJobsOptions>(this)),
program_options(for_docs ? make_null_shared_ptr() : std::make_shared<ResolveCommandLineProgramOptions>(this))
{
add_usage_line("[ -x|--execute ] [ --uninstalls-may-break */* ] [ --remove-if-dependent */* ] spec ...");
@@ -187,7 +189,7 @@ UninstallCommand::run(
}
return resolve_common(env, *cmdline.resolution_options, *cmdline.execution_options, *cmdline.display_options,
- *cmdline.program_options, make_null_shared_ptr(), targets, targets_cleaned_up, false);
+ *cmdline.graph_jobs_options, *cmdline.program_options, make_null_shared_ptr(), targets, targets_cleaned_up, false);
}
std::shared_ptr<args::ArgsHandler>
diff --git a/src/clients/cave/command_factory.cc b/src/clients/cave/command_factory.cc
index f7c18c1..2df3968 100644
--- a/src/clients/cave/command_factory.cc
+++ b/src/clients/cave/command_factory.cc
@@ -44,6 +44,7 @@
#include "cmd_find_candidates.hh"
#include "cmd_fix_cache.hh"
#include "cmd_fix_linkage.hh"
+#include "cmd_graph_jobs.hh"
#include "cmd_help.hh"
#include "cmd_import.hh"
#include "cmd_info.hh"
@@ -152,6 +153,7 @@ CommandFactory::CommandFactory() :
_imp->handlers.insert(std::make_pair("find-candidates", std::bind(&make_command<FindCandidatesCommand>)));
_imp->handlers.insert(std::make_pair("fix-cache", std::bind(&make_command<FixCacheCommand>)));
_imp->handlers.insert(std::make_pair("fix-linkage", std::bind(&make_command<FixLinkageCommand>)));
+ _imp->handlers.insert(std::make_pair("graph-jobs", std::bind(&make_command<GraphJobsCommand>)));
_imp->handlers.insert(std::make_pair("help", std::bind(&make_command<HelpCommand>)));
_imp->handlers.insert(std::make_pair("import", std::bind(&make_command<ImportCommand>)));
_imp->handlers.insert(std::make_pair("info", std::bind(&make_command<InfoCommand>)));
diff --git a/src/clients/cave/resolve_common.cc b/src/clients/cave/resolve_common.cc
index 3c7b02c..341f64f 100644
--- a/src/clients/cave/resolve_common.cc
+++ b/src/clients/cave/resolve_common.cc
@@ -22,6 +22,7 @@
#include "cmd_resolve_dump.hh"
#include "cmd_display_resolution.hh"
#include "cmd_execute_resolution.hh"
+#include "cmd_graph_jobs.hh"
#include "exceptions.hh"
#include "command_command_line.hh"
@@ -255,6 +256,82 @@ namespace
return DisplayResolutionCommand().run(env, args, resolved);
}
+ int graph_jobs(
+ const std::shared_ptr<Environment> & env,
+ const std::shared_ptr<const Resolved> & resolved,
+ const ResolveCommandLineResolutionOptions &,
+ const ResolveCommandLineGraphJobsOptions & graph_jobs_options,
+ const ResolveCommandLineProgramOptions & program_options,
+ const std::shared_ptr<const Map<std::string, std::string> > & keys_if_import,
+ const std::shared_ptr<const Sequence<std::pair<std::string, std::string> > > & targets)
+ {
+ Context context("When graphing jobs:");
+
+ if (! graph_jobs_options.a_graph_jobs_basename.specified())
+ return 0;
+
+ StringListStream ser_stream;
+ Thread ser_thread(std::bind(&serialise_resolved,
+ std::ref(ser_stream),
+ std::cref(*resolved)));
+
+ std::shared_ptr<Sequence<std::string> > args(std::make_shared<Sequence<std::string>>());
+
+ for (args::ArgsSection::GroupsConstIterator g(graph_jobs_options.begin()), g_end(graph_jobs_options.end()) ;
+ g != g_end ; ++g)
+ {
+ for (args::ArgsGroup::ConstIterator o(g->begin()), o_end(g->end()) ;
+ o != o_end ; ++o)
+ if ((*o)->specified())
+ {
+ const std::shared_ptr<const Sequence<std::string> > f((*o)->forwardable_args());
+ std::copy(f->begin(), f->end(), args->back_inserter());
+ }
+ }
+
+ 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())
+ {
+ const std::shared_ptr<const Sequence<std::string> > f((*o)->forwardable_args());
+ std::copy(f->begin(), f->end(), args->back_inserter());
+ }
+ }
+
+ for (Sequence<std::pair<std::string, std::string> >::ConstIterator p(targets->begin()), p_end(targets->end()) ;
+ p != p_end ; ++p)
+ args->push_back(p->first);
+
+ if (program_options.a_graph_jobs_program.specified())
+ {
+ std::string command(program_options.a_graph_jobs_program.argument());
+
+ 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)
+ {
+ args->push_back("--unpackaged-repository-params");
+ args->push_back(k->first + "=" + k->second);
+ }
+
+ for (Sequence<std::string>::ConstIterator a(args->begin()), a_end(args->end()) ;
+ a != a_end ; ++a)
+ command = command + " " + args::escape(*a);
+
+ Process process((ProcessCommand(command)));
+ process
+ .send_input_to_fd(ser_stream, -1, "PALUDIS_SERIALISED_RESOLUTION_FD");
+
+ return process.run().wait();
+ }
+ else
+ return GraphJobsCommand().run(env, args, resolved);
+ }
+
void serialise_job_lists(StringListStream & ser_stream, const JobLists & job_lists)
{
Serialiser ser(ser_stream);
@@ -569,6 +646,7 @@ paludis::cave::resolve_common(
const ResolveCommandLineResolutionOptions & resolution_options,
const ResolveCommandLineExecutionOptions & execution_options,
const ResolveCommandLineDisplayOptions & display_options,
+ const ResolveCommandLineGraphJobsOptions & graph_jobs_options,
const ResolveCommandLineProgramOptions & program_options,
const std::shared_ptr<const Map<std::string, std::string> > & keys_if_import,
const std::shared_ptr<const Sequence<std::pair<std::string, std::string> > > & targets_if_not_purge,
@@ -891,6 +969,10 @@ paludis::cave::resolve_common(
display_options, program_options, keys_if_import,
purge ? std::make_shared<const Sequence<std::pair<std::string, std::string> > >() : targets_if_not_purge);
+ retcode |= graph_jobs(env, resolver->resolved(), resolution_options,
+ graph_jobs_options, program_options, keys_if_import,
+ purge ? std::make_shared<const Sequence<std::pair<std::string, std::string> > >() : targets_if_not_purge);
+
if (! resolver->resolved()->taken_unable_to_make_decisions()->empty())
retcode |= 1;
diff --git a/src/clients/cave/resolve_common.hh b/src/clients/cave/resolve_common.hh
index 242b1ae..1a7aa8f 100644
--- a/src/clients/cave/resolve_common.hh
+++ b/src/clients/cave/resolve_common.hh
@@ -35,6 +35,7 @@ namespace paludis
const ResolveCommandLineResolutionOptions & resolution_options,
const ResolveCommandLineExecutionOptions & execution_options,
const ResolveCommandLineDisplayOptions & display_options,
+ const ResolveCommandLineGraphJobsOptions & graph_jobs_options,
const ResolveCommandLineProgramOptions & program_options,
const std::shared_ptr<const Map<std::string, std::string> > & keys_if_import,
const std::shared_ptr<const Sequence<std::pair<std::string, std::string> > > & targets_if_not_purge,